2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
11 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #include <palacios/vmm_hypercall.h>
21 #include <palacios/vmm.h>
22 #include <palacios/vm_guest.h>
25 static int hcall_test(struct guest_info * info, hcall_id_t hcall_id, void * private_data) {
26 info->vm_regs.rbx = 0x1111;
27 info->vm_regs.rcx = 0x2222;
28 info->vm_regs.rdx = 0x3333;
29 info->vm_regs.rsi = 0x4444;
30 info->vm_regs.rdi = 0x5555;
36 void v3_init_hypercall_map(struct v3_vm_info * vm) {
37 vm->hcall_map.rb_node = NULL;
39 v3_register_hypercall(vm, TEST_HCALL, hcall_test, NULL);
46 int (*hcall_fn)(struct guest_info * info, hcall_id_t hcall_id, void * priv_data);
49 struct rb_node tree_node;
54 static inline struct hypercall * __insert_hypercall(struct v3_vm_info * vm, struct hypercall * hcall) {
55 struct rb_node ** p = &(vm->hcall_map.rb_node);
56 struct rb_node * parent = NULL;
57 struct hypercall * tmp_hcall = NULL;
61 tmp_hcall = rb_entry(parent, struct hypercall, tree_node);
63 if (hcall->id < tmp_hcall->id) {
65 } else if (hcall->id > tmp_hcall->id) {
72 rb_link_node(&(hcall->tree_node), parent, p);
78 static inline struct hypercall * insert_hypercall(struct v3_vm_info * vm, struct hypercall * hcall) {
79 struct hypercall * ret;
81 if ((ret = __insert_hypercall(vm, hcall))) {
85 v3_rb_insert_color(&(hcall->tree_node), &(vm->hcall_map));
91 static struct hypercall * get_hypercall(struct v3_vm_info * vm, hcall_id_t id) {
92 struct rb_node * n = vm->hcall_map.rb_node;
93 struct hypercall * hcall = NULL;
96 hcall = rb_entry(n, struct hypercall, tree_node);
100 } else if (id > hcall->id) {
111 int v3_register_hypercall(struct v3_vm_info * vm, hcall_id_t hypercall_id,
112 int (*hypercall)(struct guest_info * info, hcall_id_t hcall_id, void * priv_data),
115 struct hypercall * hcall = (struct hypercall *)V3_Malloc(sizeof(struct hypercall));
117 hcall->id = hypercall_id;
118 hcall->priv_data = priv_data;
119 hcall->hcall_fn = hypercall;
121 if (insert_hypercall(vm, hcall)) {
130 int v3_handle_hypercall(struct guest_info * info) {
131 hcall_id_t hypercall_id = *(uint_t *)&info->vm_regs.rax;
132 struct hypercall * hcall = get_hypercall(info->vm_info, hypercall_id);
135 PrintError("Invalid Hypercall (%d(0x%x) not registered)\n",
136 hypercall_id, hypercall_id);
140 if (hcall->hcall_fn(info, hypercall_id, hcall->priv_data) == 0) {
141 info->vm_regs.rax = 0;
143 info->vm_regs.rax = -1;