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.


Merge branch 'Release-1.2' of ssh://palacios@newskysaw.cs.northwestern.edu//home...
[palacios.git] / palacios / src / palacios / vmm_hypercall.c
1 /* 
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.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
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.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <palacios/vmm_hypercall.h>
21 #include <palacios/vmm.h>
22 #include <palacios/vm_guest.h>
23
24
25 #define HYPERCALL_TEST_HCALL 0x1
26
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;
33     return 0;
34 }
35
36
37
38 void v3_init_hypercall_map(struct guest_info * info) {
39     info->hcall_map.rb_node = NULL;
40
41     v3_register_hypercall(info, HYPERCALL_TEST_HCALL, hcall_test, NULL);
42 }
43
44
45 struct hypercall {
46     uint_t id;
47   
48     int (*hcall_fn)(struct guest_info * info, uint_t hcall_id, void * priv_data);
49     void * priv_data;
50   
51     struct rb_node tree_node;
52 };
53
54
55
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;
60
61     while (*p) {
62         parent = *p;
63         tmp_hcall = rb_entry(parent, struct hypercall, tree_node);
64
65         if (hcall->id < tmp_hcall->id) {
66             p = &(*p)->rb_left;
67         } else if (hcall->id > tmp_hcall->id) {
68             p = &(*p)->rb_right;
69         } else {
70             return tmp_hcall;
71         }
72     }
73
74     rb_link_node(&(hcall->tree_node), parent, p);
75
76     return NULL;
77 }
78
79
80 static inline struct hypercall * insert_hypercall(struct guest_info * info, struct hypercall * hcall) {
81     struct hypercall * ret;
82
83     if ((ret = __insert_hypercall(info, hcall))) {
84         return ret;
85     }
86
87     v3_rb_insert_color(&(hcall->tree_node), &(info->hcall_map));
88
89     return NULL;
90 }
91
92
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;
96
97     while (n) {
98         hcall = rb_entry(n, struct hypercall, tree_node);
99     
100         if (id < hcall->id) {
101             n = n->rb_left;
102         } else if (id > hcall->id) {
103             n = n->rb_right;
104         } else {
105             return hcall;
106         }
107     }
108
109     return NULL;
110 }
111
112
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), 
115                           void * priv_data) {
116
117     struct hypercall * hcall = (struct hypercall *)V3_Malloc(sizeof(struct hypercall));
118
119     hcall->id = hypercall_id;
120     hcall->priv_data = priv_data;
121     hcall->hcall_fn = hypercall;
122
123     if (insert_hypercall(info, hcall)) {
124         V3_Free(hcall);
125         return -1;
126     }
127
128     return 0;
129 }
130
131
132 int v3_handle_hypercall(struct guest_info * info) {
133     uint_t hypercall_id = *(uint_t *)&info->vm_regs.rax;
134
135     struct hypercall * hcall = get_hypercall(info, hypercall_id);
136
137     if (!hcall) {
138         PrintError("Invalid Hypercall (%d(0x%x) not registered)\n", 
139                    hypercall_id, hypercall_id);
140         return -1;
141     }
142
143     if (hcall->hcall_fn(info, hypercall_id, hcall->priv_data) == 0) {
144         info->vm_regs.rax = 0;
145     } else {
146         info->vm_regs.rax = -1;
147     }
148
149     return 0;
150 }
151