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.


Allow strict MSR semantics
[palacios.git] / palacios / src / palacios / vmm_msr.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
21 #include <palacios/vmm_msr.h>
22 #include <palacios/vmm.h>
23 #include <palacios/vm_guest.h>
24
25 static int free_hook(struct v3_vm_info * vm, struct v3_msr_hook * hook);
26
27 void v3_init_msr_map(struct v3_vm_info * vm) {
28     struct v3_msr_map * msr_map  = &(vm->msr_map);
29
30     PrintDebug(vm, VCORE_NONE, "Initializing MSR map.\n");
31
32     INIT_LIST_HEAD(&(msr_map->hook_list));
33     msr_map->num_hooks = 0;
34
35     msr_map->arch_data = NULL;
36     msr_map->update_map = NULL;
37 }
38
39 int v3_deinit_msr_map(struct v3_vm_info * vm) {
40     struct v3_msr_hook * hook = NULL;
41     struct v3_msr_hook * tmp = NULL;
42
43     list_for_each_entry_safe(hook, tmp, &(vm->msr_map.hook_list), link) {
44         free_hook(vm, hook);
45     }
46
47     return 0;
48 }
49
50 int v3_handle_msr_write(struct guest_info * info) {
51     uint32_t msr_num = info->vm_regs.rcx;
52     struct v3_msr msr_val;
53     struct v3_msr_hook * hook = NULL;
54     
55     msr_val.value = 0;
56
57     PrintDebug(info->vm_info, info, "MSR write for msr 0x%x\n", msr_num);
58
59     hook = v3_get_msr_hook(info->vm_info, msr_num);
60
61     if (hook == NULL) {
62         v3_msr_unhandled_write(info, msr_num, msr_val, NULL);
63     } else {
64         msr_val.lo = info->vm_regs.rax;
65         msr_val.hi = info->vm_regs.rdx;
66         
67         if (hook->write) {
68             if (hook->write(info, msr_num, msr_val, hook->priv_data) == -1) {
69                 PrintError(info->vm_info, info, "Error in MSR hook Write\n");
70                 return -1;
71             }
72         } else {
73             PrintError(info->vm_info, info, "No write hook exists for msr 0x%x\n",msr_num);
74         }
75     }
76
77     info->rip += 2;
78
79     return 0;
80 }
81
82
83 int v3_handle_msr_read(struct guest_info * info) {
84     uint32_t msr_num = info->vm_regs.rcx;
85     struct v3_msr msr_val;
86     struct v3_msr_hook * hook = NULL;
87
88     msr_val.value = 0;
89
90     hook = v3_get_msr_hook(info->vm_info, msr_num);
91     
92     if (hook == NULL) {
93         v3_msr_unhandled_read(info, msr_num, &msr_val, NULL);
94     } else {
95         if (hook->read(info, msr_num, &msr_val, hook->priv_data) == -1) {
96             PrintError(info->vm_info, info, "Error in MSR hook Read\n");
97             return -1;
98         }
99     }
100     
101     info->vm_regs.rax = msr_val.lo;
102     info->vm_regs.rdx = msr_val.hi;
103
104     info->rip += 2;
105     return 0;
106 }
107
108
109
110 int v3_msr_unhandled_read(struct guest_info * core, uint32_t msr, struct v3_msr * dst, void * priv_data) {
111     V3_Print(core->vm_info, core, "Palacios: Unhandled MSR Read (MSR=0x%x) - returning zero\n", msr);
112
113 #ifdef V3_CONFIG_STRICT_MSR_SEMANTICS
114     v3_raise_exception(core,GPF_EXCEPTION);
115 #else
116     dst->value = 0;
117 #endif
118     
119     return 0;
120 }
121
122 int v3_msr_unhandled_write(struct guest_info * core, uint32_t msr, struct v3_msr src, void * priv_data) {
123     V3_Print(core->vm_info, core, "Palacios: Unhandled MSR Write (MSR=0x%x) - ignored\n", msr);
124
125 #ifdef V3_CONFIG_STRICT_MSR_SEMANTICS
126     v3_raise_exception(core,GPF_EXCEPTION);
127 #else
128     // write ignored
129 #endif
130
131     return 0;
132 }
133
134
135 int v3_hook_msr(struct v3_vm_info * vm, uint32_t msr, 
136                 int (*read)(struct guest_info * core, uint32_t msr, struct v3_msr * dst, void * priv_data),
137                 int (*write)(struct guest_info * core, uint32_t msr, struct v3_msr src, void * priv_data),
138                 void * priv_data) {
139
140     struct v3_msr_map * msr_map = &(vm->msr_map);
141     struct v3_msr_hook * hook = NULL;
142
143     hook = (struct v3_msr_hook *)V3_Malloc(sizeof(struct v3_msr_hook));
144
145     if (hook == NULL) {
146         PrintError(vm, VCORE_NONE,"Could not allocate msr hook for MSR 0x%x\n", msr);
147         return -1;
148     }
149
150     hook->read = read;
151     hook->write = write;
152     hook->msr = msr;
153     hook->priv_data = priv_data;
154
155     msr_map->num_hooks++;
156
157     list_add(&(hook->link), &(msr_map->hook_list));
158
159     if (msr_map->update_map) {
160         msr_map->update_map(vm, msr, 
161                             (read == NULL) ? 0 : 1,
162                             (write == NULL) ? 0 : 1);
163     }
164
165     return 0;
166 }
167
168
169
170
171
172 static int free_hook(struct v3_vm_info * vm, struct v3_msr_hook * hook) {
173     list_del(&(hook->link));
174
175     if (vm->msr_map.update_map) {
176         vm->msr_map.update_map(vm, hook->msr, 0, 0);
177     }
178
179     V3_Free(hook);
180
181     return 0;
182 }
183
184
185 int v3_unhook_msr(struct v3_vm_info * vm, uint32_t msr) {
186     struct v3_msr_hook * hook = v3_get_msr_hook(vm, msr);
187
188     if (hook == NULL) {
189         PrintError(vm, VCORE_NONE,"Could not find MSR to unhook %u (0x%x)\n", msr, msr);
190         return -1;
191     }
192
193     free_hook(vm, hook);
194
195     return 0;
196 }
197
198
199
200 struct v3_msr_hook * v3_get_msr_hook(struct v3_vm_info * vm, uint32_t msr) {
201     struct v3_msr_map * msr_map = &(vm->msr_map);
202     struct v3_msr_hook * hook = NULL;
203
204     list_for_each_entry(hook, &(msr_map->hook_list), link) {
205         if (hook->msr == msr) {
206             return hook;
207         }
208     }
209
210     return NULL;
211 }
212
213
214 void v3_refresh_msr_map(struct v3_vm_info * vm) {
215     struct v3_msr_map * msr_map = &(vm->msr_map);
216     struct v3_msr_hook * hook = NULL;
217
218     if (msr_map->update_map == NULL) {
219         PrintError(vm, VCORE_NONE, "Trying to refresh an MSR map with no backend\n");
220         return;
221     }
222
223     list_for_each_entry(hook, &(msr_map->hook_list), link) {
224         PrintDebug(vm, VCORE_NONE, "updating MSR map for msr 0x%x\n", hook->msr);
225         msr_map->update_map(vm, hook->msr,      
226                             (hook->read == NULL) ? 0 : 1,
227                             (hook->write == NULL) ? 0 : 1);
228     }
229 }
230
231 void v3_print_msr_map(struct v3_vm_info * vm) {
232     struct v3_msr_map * msr_map = &(vm->msr_map);
233     struct v3_msr_hook * hook = NULL;
234
235     list_for_each_entry(hook, &(msr_map->hook_list), link) {
236         V3_Print(vm, VCORE_NONE, "MSR HOOK (MSR=0x%x) (read=0x%p) (write=0x%p)\n",
237                    hook->msr, hook->read, hook->write);
238     }
239 }