Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


added hypercall registration and handler
Jack Lange [Mon, 16 Feb 2009 23:57:52 +0000 (17:57 -0600)]
palacios/build/Makefile
palacios/include/palacios/vm_guest.h
palacios/include/palacios/vmm_hypercall.h [new file with mode: 0644]
palacios/src/palacios/svm_handler.c
palacios/src/palacios/vmm_config.c
palacios/src/palacios/vmm_hypercall.c [new file with mode: 0644]

index 8e9d972..992dcfe 100644 (file)
@@ -279,6 +279,7 @@ VMM_OBJS := \
        palacios/vmm_profiler.o \
        palacios/vmm_direct_paging.o \
        palacios/vmm_ringbuffer.o \
+       palacios/vmm_hypercall.o \
        $(OBJ_FILES)
 
 #              vmx.c vmcs_gen.c vmcs.c
index 1eb4de6..64b5a71 100644 (file)
@@ -32,6 +32,7 @@
 #include <palacios/vmm_host_events.h>
 #include <palacios/vmm_msr.h>
 #include <palacios/vmm_profiler.h>
+#include <palacios/vmm_hypercall.h>
 
 
 
@@ -138,6 +139,9 @@ struct guest_info {
 
   struct v3_msr_map msr_map;
 
+
+  v3_hypercall_map_t hcall_map;
+
   // device_map
   struct vmm_dev_mgr  dev_mgr;
 
diff --git a/palacios/include/palacios/vmm_hypercall.h b/palacios/include/palacios/vmm_hypercall.h
new file mode 100644 (file)
index 0000000..6ec1462
--- /dev/null
@@ -0,0 +1,47 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+
+#ifndef __VMM_HYPERCALL_H__
+#define __VMM_HYPERCALL_H__
+
+#ifdef __V3VEE__
+#include <palacios/vmm_types.h>
+#include <palacios/vmm_rbtree.h>
+
+typedef struct rb_root v3_hypercall_map_t;
+
+struct guest_info;
+
+void v3_init_hypercall_map(struct guest_info * info);
+
+
+int v3_register_hypercall(struct guest_info * info, uint_t hypercall_id, 
+                         int (*hypercall)(struct guest_info * info, uint_t hcall_id, void * priv_data),
+                         void * priv_data);
+
+
+
+int v3_handle_hypercall(struct guest_info * info);
+
+
+
+#endif
+
+#endif
index a4b0597..91c0440 100644 (file)
@@ -31,6 +31,7 @@
 #include <palacios/vmm_emulator.h>
 #include <palacios/svm_msr.h>
 #include <palacios/vmm_profiler.h>
+#include <palacios/vmm_hypercall.h>
 
 
 
@@ -271,6 +272,22 @@ int v3_handle_svm_exit(struct guest_info * info) {
       */
       break;
     }
+
+
+
+  case VMEXIT_VMMCALL: 
+    { 
+      /* 
+       * Hypercall 
+       */
+
+      if (v3_handle_hypercall(info) == -1) {
+       return -1;
+      }
+      break;
+    } 
+
+
   case VMEXIT_INTR: 
     {
       // handled by interrupt dispatch earlier
@@ -300,56 +317,6 @@ int v3_handle_svm_exit(struct guest_info * info) {
     break;
 
 
-#if 0
-    // Emulation handlers currently not used
-  case VMEXIT_EXCP1: 
-    {
-#ifdef DEBUG_EMULATOR
-      PrintDebug("DEBUG EXCEPTION\n");
-#endif
-      if (info->run_state == VM_EMULATING) {
-       if (v3_emulation_exit_handler(info) == -1) {
-         return -1;
-       }
-      } else {
-       PrintError("VMMCALL with not emulator...\n");
-       return -1;
-      }
-      break;
-    } 
-    
-
-  case VMEXIT_VMMCALL: 
-    {
-#ifdef DEBUG_EMULATOR
-      PrintDebug("VMMCALL\n");
-#endif
-      if (info->run_state == VM_EMULATING) {
-       if (v3_emulation_exit_handler(info) == -1) {
-         return -1;
-       }
-      } else {
-       /*
-       ulong_t tsc_spread = 0;
-       ullong_t exit_tsc = 0;
-
-       ulong_t rax = (ulong_t)info->vm_regs.rbx;
-       ulong_t rdx = (ulong_t)info->vm_regs.rcx;
-
-       *(ulong_t *)(&exit_tsc) = rax;
-       *(((ulong_t *)(&exit_tsc)) + 1) = rdx; 
-
-       tsc_spread = info->exit_tsc - exit_tsc;
-
-       PrintError("VMMCALL tsc diff = %lu\n",tsc_spread); 
-       info->rip += 3;
-       */
-       PrintError("VMMCALL with not emulator...\n");
-       return -1;
-      }
-      break;
-    } 
-#endif
 
 
   case VMEXIT_WBINVD: 
index b713975..5e0defc 100644 (file)
@@ -24,6 +24,7 @@
 #include <palacios/vmm_decoder.h>
 #include <palacios/vmm_profiler.h>
 #include <palacios/vmm_mem.h>
+#include <palacios/vmm_hypercall.h>
 
 
 #include <devices/serial.h>
@@ -85,6 +86,9 @@ int v3_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr)
   
   v3_init_shadow_map(info);
   
+  v3_init_hypercall_map(info);
+
+  
   if (v3_cpu_type == V3_SVM_REV3_CPU) {
     info->shdw_pg_mode = NESTED_PAGING;
   } else {
diff --git a/palacios/src/palacios/vmm_hypercall.c b/palacios/src/palacios/vmm_hypercall.c
new file mode 100644 (file)
index 0000000..3c570a3
--- /dev/null
@@ -0,0 +1,127 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm_hypercall.h>
+#include <palacios/vmm.h>
+
+
+void v3_init_hypercall_map(struct guest_info * info) {
+  info->hcall_map.rb_node = NULL;
+}
+
+
+struct hypercall {
+  uint_t id;
+  
+  int (*hcall_fn)(struct guest_info * info, uint_t hcall_id, void * priv_data);
+  void * priv_data;
+  
+  struct rb_node tree_node;
+};
+
+
+
+static inline struct hypercall * __insert_hypercall(struct guest_info * info, struct hypercall * hcall) {
+  struct rb_node ** p = &(info->hcall_map.rb_node);
+  struct rb_node * parent = NULL;
+  struct hypercall * tmp_hcall = NULL;
+
+  while (*p) {
+    parent = *p;
+    tmp_hcall = rb_entry(parent, struct hypercall, tree_node);
+
+    if (hcall->id < tmp_hcall->id) {
+      p = &(*p)->rb_left;
+    } else if (hcall->id > tmp_hcall->id) {
+      p = &(*p)->rb_right;
+    } else {
+      return tmp_hcall;
+    }
+  }
+
+  rb_link_node(&(hcall->tree_node), parent, p);
+
+  return NULL;
+}
+
+
+static inline struct hypercall * insert_hypercall(struct guest_info * info, struct hypercall * hcall) {
+  struct hypercall * ret;
+
+  if ((ret = __insert_hypercall(info, hcall))) {
+    return ret;
+  }
+
+  v3_rb_insert_color(&(hcall->tree_node), &(info->hcall_map));
+
+  return NULL;
+}
+
+
+static struct hypercall * get_hypercall(struct guest_info * info, uint_t id) {
+  struct rb_node * n = info->hcall_map.rb_node;
+  struct hypercall * hcall = NULL;
+
+  while (n) {
+    hcall = rb_entry(n, struct hypercall, tree_node);
+    
+    if (id < hcall->id) {
+      n = n->rb_left;
+    } else if (id > hcall->id) {
+      n = n->rb_right;
+    } else {
+      return hcall;
+    }
+  }
+
+  return NULL;
+}
+
+
+int v3_register_hypercall(struct guest_info * info, uint_t hypercall_id, 
+                         int (*hypercall)(struct guest_info * info, uint_t hcall_id, void * priv_data), 
+                         void * priv_data) {
+
+  struct hypercall * hcall = (struct hypercall *)V3_Malloc(sizeof(struct hypercall));
+
+  hcall->id = hypercall_id;
+  hcall->priv_data = priv_data;
+  hcall->hcall_fn = hypercall;
+
+  if (insert_hypercall(info, hcall)) {
+    V3_Free(hcall);
+    return -1;
+  }
+
+  return 0;
+}
+
+
+int v3_handle_hypercall(struct guest_info * info) {
+  uint_t hypercall_id = *(uint_t *)&info->vm_regs.rax;
+
+  struct hypercall * hcall = get_hypercall(info, hypercall_id);
+
+  if (!hcall) {
+    PrintError("Invalid Hypercall (%d not registered)\n", hypercall_id);
+    return -1;
+  }
+
+  return hcall->hcall_fn(info, hypercall_id, hcall->priv_data);
+}