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.


More detailed error handling on msr writes
[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) {
68             if (hook->write(info, msr_num, msr_val, hook->priv_data) == -1) {
69                 PrintError("Error in MSR hook Write\n");
70                 return -1;
71             }
72         } else {
73             PrintError("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("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("Palacios: Unhandled MSR Read (MSR=0x%x)\n", msr);
112     return 0;
113 }
114
115 int v3_msr_unhandled_write(struct guest_info * core, uint32_t msr, struct v3_msr src, void * priv_data) {
116     V3_Print("Palacios: Unhandled MSR Write (MSR=0x%x)\n", msr);
117     return 0;
118 }
119
120
121 int v3_hook_msr(struct v3_vm_info * vm, uint32_t msr, 
122                 int (*read)(struct guest_info * core, uint32_t msr, struct v3_msr * dst, void * priv_data),
123                 int (*write)(struct guest_info * core, uint32_t msr, struct v3_msr src, void * priv_data),
124                 void * priv_data) {
125
126     struct v3_msr_map * msr_map = &(vm->msr_map);
127     struct v3_msr_hook * hook = NULL;
128
129     hook = (struct v3_msr_hook *)V3_Malloc(sizeof(struct v3_msr_hook));
130
131     if (hook == NULL) {
132         PrintError("Could not allocate msr hook for MSR 0x%x\n", msr);
133         return -1;
134     }
135
136     hook->read = read;
137     hook->write = write;
138     hook->msr = msr;
139     hook->priv_data = priv_data;
140
141     msr_map->num_hooks++;
142
143     list_add(&(hook->link), &(msr_map->hook_list));
144
145     if (msr_map->update_map) {
146         msr_map->update_map(vm, msr, 
147                             (read == NULL) ? 0 : 1,
148                             (write == NULL) ? 0 : 1);
149     }
150
151     return 0;
152 }
153
154
155
156
157
158 static int free_hook(struct v3_vm_info * vm, struct v3_msr_hook * hook) {
159     list_del(&(hook->link));
160
161     if (vm->msr_map.update_map) {
162         vm->msr_map.update_map(vm, hook->msr, 0, 0);
163     }
164
165     V3_Free(hook);
166
167     return 0;
168 }
169
170
171 int v3_unhook_msr(struct v3_vm_info * vm, uint32_t msr) {
172     struct v3_msr_hook * hook = v3_get_msr_hook(vm, msr);
173
174     if (hook == NULL) {
175         PrintError("Could not find MSR to unhook %u (0x%x)\n", msr, msr);
176         return -1;
177     }
178
179     free_hook(vm, hook);
180
181     return 0;
182 }
183
184
185
186 struct v3_msr_hook * v3_get_msr_hook(struct v3_vm_info * vm, uint32_t msr) {
187     struct v3_msr_map * msr_map = &(vm->msr_map);
188     struct v3_msr_hook * hook = NULL;
189
190     list_for_each_entry(hook, &(msr_map->hook_list), link) {
191         if (hook->msr == msr) {
192             return hook;
193         }
194     }
195
196     return NULL;
197 }
198
199
200 void v3_refresh_msr_map(struct v3_vm_info * vm) {
201     struct v3_msr_map * msr_map = &(vm->msr_map);
202     struct v3_msr_hook * hook = NULL;
203
204     if (msr_map->update_map == NULL) {
205         PrintError("Trying to refresh an MSR map with no backend\n");
206         return;
207     }
208
209     list_for_each_entry(hook, &(msr_map->hook_list), link) {
210         PrintDebug("updating MSR map for msr 0x%x\n", hook->msr);
211         msr_map->update_map(vm, hook->msr,      
212                             (hook->read == NULL) ? 0 : 1,
213                             (hook->write == NULL) ? 0 : 1);
214     }
215 }
216
217 void v3_print_msr_map(struct v3_vm_info * vm) {
218     struct v3_msr_map * msr_map = &(vm->msr_map);
219     struct v3_msr_hook * hook = NULL;
220
221     list_for_each_entry(hook, &(msr_map->hook_list), link) {
222         V3_Print("MSR HOOK (MSR=0x%x) (read=0x%p) (write=0x%p)\n",
223                    hook->msr, hook->read, hook->write);
224     }
225 }