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.


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