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
#include <palacios/vmm_host_events.h>
#include <palacios/vmm_msr.h>
#include <palacios/vmm_profiler.h>
+#include <palacios/vmm_hypercall.h>
struct v3_msr_map msr_map;
+
+ v3_hypercall_map_t hcall_map;
+
// device_map
struct vmm_dev_mgr dev_mgr;
--- /dev/null
+/*
+ * 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
#include <palacios/vmm_emulator.h>
#include <palacios/svm_msr.h>
#include <palacios/vmm_profiler.h>
+#include <palacios/vmm_hypercall.h>
*/
break;
}
+
+
+
+ case VMEXIT_VMMCALL:
+ {
+ /*
+ * Hypercall
+ */
+
+ if (v3_handle_hypercall(info) == -1) {
+ return -1;
+ }
+ break;
+ }
+
+
case VMEXIT_INTR:
{
// handled by interrupt dispatch earlier
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:
#include <palacios/vmm_decoder.h>
#include <palacios/vmm_profiler.h>
#include <palacios/vmm_mem.h>
+#include <palacios/vmm_hypercall.h>
#include <devices/serial.h>
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 {
--- /dev/null
+/*
+ * 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);
+}