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.


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