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 #define HYPERCALL_TEST_HCALL 0x1
27 static int hcall_test(struct guest_info * info, uint_t hcall_id, void * private_data) {
28 info->vm_regs.rbx = 0x1111;
29 info->vm_regs.rcx = 0x2222;
30 info->vm_regs.rdx = 0x3333;
31 info->vm_regs.rsi = 0x4444;
32 info->vm_regs.rdi = 0x5555;
38 void v3_init_hypercall_map(struct guest_info * info) {
39 info->hcall_map.rb_node = NULL;
41 v3_register_hypercall(info, HYPERCALL_TEST_HCALL, hcall_test, NULL);
48 int (*hcall_fn)(struct guest_info * info, uint_t hcall_id, void * priv_data);
51 struct rb_node tree_node;
56 static inline struct hypercall * __insert_hypercall(struct guest_info * info, struct hypercall * hcall) {
57 struct rb_node ** p = &(info->hcall_map.rb_node);
58 struct rb_node * parent = NULL;
59 struct hypercall * tmp_hcall = NULL;
63 tmp_hcall = rb_entry(parent, struct hypercall, tree_node);
65 if (hcall->id < tmp_hcall->id) {
67 } else if (hcall->id > tmp_hcall->id) {
74 rb_link_node(&(hcall->tree_node), parent, p);
80 static inline struct hypercall * insert_hypercall(struct guest_info * info, struct hypercall * hcall) {
81 struct hypercall * ret;
83 if ((ret = __insert_hypercall(info, hcall))) {
87 v3_rb_insert_color(&(hcall->tree_node), &(info->hcall_map));
93 static struct hypercall * get_hypercall(struct guest_info * info, uint_t id) {
94 struct rb_node * n = info->hcall_map.rb_node;
95 struct hypercall * hcall = NULL;
98 hcall = rb_entry(n, struct hypercall, tree_node);
100 if (id < hcall->id) {
102 } else if (id > hcall->id) {
113 int v3_register_hypercall(struct guest_info * info, uint_t hypercall_id,
114 int (*hypercall)(struct guest_info * info, uint_t hcall_id, void * priv_data),
117 struct hypercall * hcall = (struct hypercall *)V3_Malloc(sizeof(struct hypercall));
119 hcall->id = hypercall_id;
120 hcall->priv_data = priv_data;
121 hcall->hcall_fn = hypercall;
123 if (insert_hypercall(info, hcall)) {
132 int v3_handle_hypercall(struct guest_info * info) {
133 uint_t hypercall_id = *(uint_t *)&info->vm_regs.rax;
135 struct hypercall * hcall = get_hypercall(info, hypercall_id);
138 PrintError("Invalid Hypercall (%d(0x%x) not registered)\n",
139 hypercall_id, hypercall_id);
143 if (hcall->hcall_fn(info, hypercall_id, hcall->priv_data) == 0) {
144 info->vm_regs.rax = 0;
146 info->vm_regs.rax = -1;