1 #include <palacios/svm_ctrl_regs.h>
2 #include <palacios/vmm_mem.h>
3 #include <palacios/vmm.h>
4 #include <palacios/vmcb.h>
5 #include <palacios/vmm_emulate.h>
6 #include <palacios/vm_guest_mem.h>
7 #include <palacios/vmm_ctrl_regs.h>
10 /* Segmentation is a problem here...
12 * When we get a memory operand, presumably we use the default segment (which is?)
13 * unless an alternate segment was specfied in the prefix...
17 int handle_cr0_write(struct guest_info * info) {
18 //vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data));
19 vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
23 if (info->cpu_mode == REAL) {
27 // The real rip address is actually a combination of the rip + CS base
28 ret = read_guest_pa_memory(info, get_addr_linear(info, guest_state->rip, guest_state->cs.selector), 15, instr);
30 // I think we should inject a GPF into the guest
31 PrintDebug("Could not read instruction (ret=%d)\n", ret);
35 while (is_prefix_byte(instr[index])) {
39 if ((instr[index] == cr_access_byte) &&
40 (instr[index + 1] == lmsw_byte) &&
41 (MODRM_REG(instr[index + 2]) == lmsw_reg_byte)) {
44 addr_t second_operand;
45 struct cr0_real *real_cr0;
46 struct cr0_real *new_cr0;
47 operand_type_t addr_type;
53 real_cr0 = (struct cr0_real*)&(guest_state->cr0);
55 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
58 if (addr_type == REG_OPERAND) {
59 new_cr0 = (struct cr0_real *)first_operand;
60 } else if (addr_type == MEM_OPERAND) {
63 if (guest_pa_to_host_va(info, first_operand + (guest_state->ds.base << 4), &host_addr) == -1) {
68 new_cr0 = (struct cr0_real *)host_addr;
70 // error... don't know what to do
74 if ((new_cr0->pe == 1) && (real_cr0->pe == 0)) {
75 info->cpu_mode = PROTECTED;
76 } else if ((new_cr0->pe == 0) && (real_cr0->pe == 1)) {
77 info->cpu_mode = REAL;
80 new_cr0_val = *(char*)(new_cr0) & 0x0f;
83 if (info->page_mode == SHADOW_PAGING) {
84 struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
86 PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
87 /* struct cr0_real is only 4 bits wide,
88 * so we can overwrite the real_cr0 without worrying about the shadow fields
90 *(char*)real_cr0 &= 0xf0;
91 *(char*)real_cr0 |= new_cr0_val;
93 *(char*)shadow_cr0 &= 0xf0;
94 *(char*)shadow_cr0 |= new_cr0_val;
96 PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
98 PrintDebug("Old CR0=%x\n", *real_cr0);
99 // for now we just pass through....
100 *(char*)real_cr0 &= 0xf0;
101 *(char*)real_cr0 |= new_cr0_val;
103 PrintDebug("New CR0=%x\n", *real_cr0);
109 } else if ((instr[index] == cr_access_byte) &&
110 (instr[index + 1] == clts_byte)) {
114 } else if ((instr[index] == cr_access_byte) &&
115 (instr[index + 1] = mov_to_cr_byte)) {
116 addr_t first_operand;
117 addr_t second_operand;
118 struct cr0_32 *real_cr0;
119 struct cr0_32 *new_cr0;
120 operand_type_t addr_type;
125 real_cr0 = (struct cr0_32*)&(guest_state->cr0);
127 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
129 if (addr_type != REG_OPERAND) {
130 /* Mov to CR0 Can only be a 32 bit register */
135 new_cr0 = (struct cr0_32 *)first_operand;
137 if (new_cr0->pe == 1) {
138 PrintDebug("Entering Protected Mode\n");
139 info->cpu_mode = PROTECTED;
142 if (new_cr0->pg == 1) {
147 if (info->page_mode == SHADOW_PAGING) {
148 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
150 PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
151 *real_cr0 = *new_cr0;
154 *shadow_cr0 = *new_cr0;
156 PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
158 PrintDebug("Old CR0=%x\n", *real_cr0);
159 *real_cr0 = *new_cr0;
160 PrintDebug("New CR0=%x\n", *real_cr0);
166 PrintDebug("Unsupported Instruction\n");
167 // unsupported instruction, UD the guest
172 } else if (info->cpu_mode == PROTECTED) {
176 PrintDebug("Protected Mode write to CR0\n");
178 // The real rip address is actually a combination of the rip + CS base
179 ret = read_guest_pa_memory(info, get_addr_linear(info, guest_state->rip, guest_state->cs.base), 15, instr);
181 // I think we should inject a GPF into the guest
182 PrintDebug("Could not read instruction (ret=%d)\n", ret);
186 while (is_prefix_byte(instr[index])) {
191 /* CHECK IF MOV_TO_CR CAN TAKE MEMORY OPERANDS... */
192 if ((instr[index] == cr_access_byte) &&
193 (instr[index + 1] == mov_to_cr_byte)) {
195 addr_t first_operand;
196 addr_t second_operand;
197 struct cr0_32 *real_cr0;
198 struct cr0_32 *new_cr0;
199 operand_type_t addr_type;
203 real_cr0 = (struct cr0_32*)&(guest_state->cr0);
205 addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
207 if (addr_type != REG_OPERAND) {
211 new_cr0 = (struct cr0_32 *)first_operand;
214 if (info->page_mode == SHADOW_PAGING) {
215 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
217 if (new_cr0->pg == 1){
218 info->cpu_mode = PROTECTED_PG;
220 *shadow_cr0 = *new_cr0;
221 *real_cr0 = *new_cr0;
224 // Activate Shadow Paging
227 } else if (new_cr0->pe == 0) {
228 info->cpu_mode = REAL;
230 *shadow_cr0 = *new_cr0;
231 *real_cr0 = *new_cr0;
237 *real_cr0 = *new_cr0;
244 PrintDebug("Unknown Mode write to CR0\n");
251 int handle_cr0_read(struct guest_info * info) {
252 //vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data));
253 vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
256 if (info->cpu_mode == REAL) {
260 // The real rip address is actually a combination of the rip + CS base
261 ret = read_guest_pa_memory(info, get_addr_linear(info, guest_state->rip, guest_state->cs.selector), 15, instr);
263 // I think we should inject a GPF into the guest
264 PrintDebug("Could not read Real Mode instruction (ret=%d)\n", ret);
269 while (is_prefix_byte(instr[index])) {
273 if ((instr[index] == cr_access_byte) &&
274 (instr[index + 1] == smsw_byte) &&
275 (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) {
277 addr_t first_operand;
278 addr_t second_operand;
279 struct cr0_real *cr0;
280 operand_type_t addr_type;
285 cr0 = (struct cr0_real*)&(guest_state->cr0);
288 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
290 if (addr_type == MEM_OPERAND) {
293 if (guest_pa_to_host_va(info, first_operand + (guest_state->ds.base << 4), &host_addr) == -1) {
298 first_operand = host_addr;
300 // error... don't know what to do
304 cr0_val = *(char*)cr0 & 0x0f;
306 *(char *)first_operand &= 0xf0;
307 *(char *)first_operand |= cr0_val;
309 PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip));
311 PrintDebug("new_rip = %x\n", (ulong_t)(info->rip));
312 } else if ((instr[index] == cr_access_byte) &&
313 (instr[index+1] == mov_from_cr_byte)) {
315 * This can only take a 32 bit register argument in anything less than 64 bit mode.
317 addr_t first_operand;
318 addr_t second_operand;
319 operand_type_t addr_type;
321 struct cr0_32 * real_cr0 = (struct cr0_32 *)&(guest_state->cr0);
325 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
327 struct cr0_32 * virt_cr0 = (struct cr0_32 *)first_operand;
329 if (addr_type != REG_OPERAND) {
330 // invalid opcode to guest
331 PrintDebug("Invalid operand type in mov from CR0\n");
335 if (info->page_mode == SHADOW_PAGING) {
336 *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
338 *virt_cr0 = *real_cr0;
344 PrintDebug("Unknown read instr from CR0\n");
348 } else if (info->cpu_mode == PROTECTED) {
352 // The real rip address is actually a combination of the rip + CS base
353 ret = read_guest_pa_memory(info, get_addr_linear(info, guest_state->rip, guest_state->cs.base), 15, instr);
355 // I think we should inject a GPF into the guest
356 PrintDebug("Could not read Proteced mode instruction (ret=%d)\n", ret);
360 while (is_prefix_byte(instr[index])) {
365 if ((instr[index] == cr_access_byte) &&
366 (instr[index+1] == mov_from_cr_byte)) {
367 addr_t first_operand;
368 addr_t second_operand;
369 operand_type_t addr_type;
370 struct cr0_32 * virt_cr0;
371 struct cr0_32 * real_cr0 = (struct cr0_32 *)&(guest_state->cr0);
375 addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
377 if (addr_type != REG_OPERAND) {
378 PrintDebug("Invalid operand type in mov from CR0\n");
382 virt_cr0 = (struct cr0_32 *)first_operand;
384 if (info->page_mode == SHADOW_PAGING) {
385 *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
387 *virt_cr0 = *real_cr0;
393 PrintDebug("Unknown read instruction from CR0\n");
398 PrintDebug("Unknown mode read from CR0\n");