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