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.


Assure that unhandled MSR reads get back zeros
[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("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("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(info, msr_num, msr_val, hook->priv_data) == -1) {
68             PrintError("Error in MSR hook Write\n");
69             return -1;
70         }
71     }
72
73     info->rip += 2;
74
75     return 0;
76 }
77
78
79 int v3_handle_msr_read(struct guest_info * info) {
80     uint32_t msr_num = info->vm_regs.rcx;
81     struct v3_msr msr_val;
82     struct v3_msr_hook * hook = NULL;
83
84     msr_val.value = 0;
85
86     hook = v3_get_msr_hook(info->vm_info, msr_num);
87     
88     if (hook == NULL) {
89         v3_msr_unhandled_read(info, msr_num, &msr_val, NULL);
90     } else {
91         if (hook->read(info, msr_num, &msr_val, hook->priv_data) == -1) {
92             PrintError("Error in MSR hook Read\n");
93             return -1;
94         }
95     }
96     
97     info->vm_regs.rax = msr_val.lo;
98     info->vm_regs.rdx = msr_val.hi;
99
100     info->rip += 2;
101     return 0;
102 }
103
104
105
106 int v3_msr_unhandled_read(struct guest_info * core, uint32_t msr, struct v3_msr * dst, void * priv_data) {
107     V3_Print("Palacios: Unhandled MSR Read (MSR=0x%x) - returning zero\n", msr);
108     dst->lo=dst->hi=0;
109     // should produce GPF for unsupported msr
110     return 0;
111 }
112
113 int v3_msr_unhandled_write(struct guest_info * core, uint32_t msr, struct v3_msr src, void * priv_data) {
114     V3_Print("Palacios: Unhandled MSR Write (MSR=0x%x) - ignored\n", msr);
115     // should produce GPF for unsupported msr
116     return 0;
117 }
118
119
120 int v3_hook_msr(struct v3_vm_info * vm, uint32_t msr, 
121                 int (*read)(struct guest_info * core, uint32_t msr, struct v3_msr * dst, void * priv_data),
122                 int (*write)(struct guest_info * core, uint32_t msr, struct v3_msr src, void * priv_data),
123                 void * priv_data) {
124
125     struct v3_msr_map * msr_map = &(vm->msr_map);
126     struct v3_msr_hook * hook = NULL;
127
128     hook = (struct v3_msr_hook *)V3_Malloc(sizeof(struct v3_msr_hook));
129
130     if (hook == NULL) {
131         PrintError("Could not allocate msr hook for MSR 0x%x\n", msr);
132         return -1;
133     }
134
135     hook->read = read;
136     hook->write = write;
137     hook->msr = msr;
138     hook->priv_data = priv_data;
139
140     msr_map->num_hooks++;
141
142     list_add(&(hook->link), &(msr_map->hook_list));
143
144     if (msr_map->update_map) {
145         msr_map->update_map(vm, msr, 
146                             (read == NULL) ? 0 : 1,
147                             (write == NULL) ? 0 : 1);
148     }
149
150     return 0;
151 }
152
153
154
155
156
157 static int free_hook(struct v3_vm_info * vm, struct v3_msr_hook * hook) {
158     list_del(&(hook->link));
159
160     if (vm->msr_map.update_map) {
161         vm->msr_map.update_map(vm, hook->msr, 0, 0);
162     }
163
164     V3_Free(hook);
165
166     return 0;
167 }
168
169
170 int v3_unhook_msr(struct v3_vm_info * vm, uint32_t msr) {
171     struct v3_msr_hook * hook = v3_get_msr_hook(vm, msr);
172
173     if (hook == NULL) {
174         PrintError("Could not find MSR to unhook %u (0x%x)\n", msr, msr);
175         return -1;
176     }
177
178     free_hook(vm, hook);
179
180     return 0;
181 }
182
183
184
185 struct v3_msr_hook * v3_get_msr_hook(struct v3_vm_info * vm, uint32_t msr) {
186     struct v3_msr_map * msr_map = &(vm->msr_map);
187     struct v3_msr_hook * hook = NULL;
188
189     list_for_each_entry(hook, &(msr_map->hook_list), link) {
190         if (hook->msr == msr) {
191             return hook;
192         }
193     }
194
195     return NULL;
196 }
197
198
199 void v3_refresh_msr_map(struct v3_vm_info * vm) {
200     struct v3_msr_map * msr_map = &(vm->msr_map);
201     struct v3_msr_hook * hook = NULL;
202
203     if (msr_map->update_map == NULL) {
204         PrintError("Trying to refresh an MSR map with no backend\n");
205         return;
206     }
207
208     list_for_each_entry(hook, &(msr_map->hook_list), link) {
209         PrintDebug("updating MSR map for msr 0x%x\n", hook->msr);
210         msr_map->update_map(vm, hook->msr,      
211                             (hook->read == NULL) ? 0 : 1,
212                             (hook->write == NULL) ? 0 : 1);
213     }
214 }
215
216 void v3_print_msr_map(struct v3_vm_info * vm) {
217     struct v3_msr_map * msr_map = &(vm->msr_map);
218     struct v3_msr_hook * hook = NULL;
219
220     list_for_each_entry(hook, &(msr_map->hook_list), link) {
221         V3_Print("MSR HOOK (MSR=0x%x) (read=0x%p) (write=0x%p)\n",
222                    hook->msr, hook->read, hook->write);
223     }
224 }