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;
38 int (*hcall_fn)(struct guest_info * info, hcall_id_t hcall_id, void * priv_data);
41 struct rb_node tree_node;
44 static int free_hypercall(struct v3_vm_info * vm, struct hypercall * hcall);
46 void v3_init_hypercall_map(struct v3_vm_info * vm) {
47 vm->hcall_map.rb_node = NULL;
49 v3_register_hypercall(vm, TEST_HCALL, hcall_test, NULL);
52 int v3_deinit_hypercall_map(struct v3_vm_info * vm) {
53 struct rb_node * node = NULL;
54 struct hypercall * hcall = NULL;
55 struct rb_node * tmp_node = NULL;
57 v3_remove_hypercall(vm, TEST_HCALL);
59 node = v3_rb_first(&(vm->hcall_map));
62 hcall = rb_entry(node, struct hypercall, tree_node);
64 node = v3_rb_next(node);
66 free_hypercall(vm, hcall);
76 static inline struct hypercall * __insert_hypercall(struct v3_vm_info * vm, struct hypercall * hcall) {
77 struct rb_node ** p = &(vm->hcall_map.rb_node);
78 struct rb_node * parent = NULL;
79 struct hypercall * tmp_hcall = NULL;
83 tmp_hcall = rb_entry(parent, struct hypercall, tree_node);
85 if (hcall->id < tmp_hcall->id) {
87 } else if (hcall->id > tmp_hcall->id) {
94 rb_link_node(&(hcall->tree_node), parent, p);
100 static inline struct hypercall * insert_hypercall(struct v3_vm_info * vm, struct hypercall * hcall) {
101 struct hypercall * ret;
103 if ((ret = __insert_hypercall(vm, hcall))) {
107 v3_rb_insert_color(&(hcall->tree_node), &(vm->hcall_map));
113 static struct hypercall * get_hypercall(struct v3_vm_info * vm, hcall_id_t id) {
114 struct rb_node * n = vm->hcall_map.rb_node;
115 struct hypercall * hcall = NULL;
118 hcall = rb_entry(n, struct hypercall, tree_node);
120 if (id < hcall->id) {
122 } else if (id > hcall->id) {
133 int v3_register_hypercall(struct v3_vm_info * vm, hcall_id_t hypercall_id,
134 int (*hypercall)(struct guest_info * info, hcall_id_t hcall_id, void * priv_data),
137 struct hypercall * hcall = (struct hypercall *)V3_Malloc(sizeof(struct hypercall));
139 hcall->id = hypercall_id;
140 hcall->priv_data = priv_data;
141 hcall->hcall_fn = hypercall;
143 if (insert_hypercall(vm, hcall)) {
153 static int free_hypercall(struct v3_vm_info * vm, struct hypercall * hcall) {
154 v3_rb_erase(&(hcall->tree_node), &(vm->hcall_map));
160 int v3_remove_hypercall(struct v3_vm_info * vm, hcall_id_t hypercall_id) {
161 struct hypercall * hcall = get_hypercall(vm, hypercall_id);
164 PrintError("Attempted to remove non existant hypercall\n");
168 free_hypercall(vm, hcall);
174 int v3_handle_hypercall(struct guest_info * info) {
175 hcall_id_t hypercall_id = *(uint_t *)&info->vm_regs.rax;
176 struct hypercall * hcall = get_hypercall(info->vm_info, hypercall_id);
179 PrintError("Invalid Hypercall (%d(0x%x) not registered)\n",
180 hypercall_id, hypercall_id);
184 if (hcall->hcall_fn(info, hypercall_id, hcall->priv_data) == 0) {
185 info->vm_regs.rax = 0;
187 info->vm_regs.rax = -1;