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.


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