X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fgeekos%2Fsvm_ctrl_regs.c;fp=palacios%2Fsrc%2Fgeekos%2Fsvm_ctrl_regs.c;h=3929222ec31f5f28c6e17f527b8d28be6e556bcf;hb=9be2a31f574121ab4aa0289b7714eefe070b0db0;hp=a0c5e1a8311926e54013bd53864d4b7155b6dafc;hpb=959ed075fac59969a8dc299e51824166f50bb2d0;p=palacios.git diff --git a/palacios/src/geekos/svm_ctrl_regs.c b/palacios/src/geekos/svm_ctrl_regs.c index a0c5e1a..3929222 100644 --- a/palacios/src/geekos/svm_ctrl_regs.c +++ b/palacios/src/geekos/svm_ctrl_regs.c @@ -4,8 +4,10 @@ #include #include #include +#include -int handle_cr0_write(struct guest_info * info, ullong_t * new_cr0) { + +int handle_cr0_write(struct guest_info * info) { //vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data)); vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data)); char instr[15]; @@ -14,8 +16,16 @@ int handle_cr0_write(struct guest_info * info, ullong_t * new_cr0) { if (info->cpu_mode == REAL) { - read_guest_pa_memory(info, (addr_t)guest_state->rip, 15, instr); int index = 0; + int ret; + + // The real rip address is actually a combination of the rip + CS base + ret = read_guest_pa_memory(info, (addr_t)guest_state->rip, 15, instr); + if (ret != 0) { + // I think we should inject a GPF into the guest + PrintDebug("Could not read instruction (ret=%d)\n", ret); + return -1; + } while (is_prefix_byte(instr[index])) { PrintDebug("instr(%d): 0x%x\n", index, instr[index]); @@ -30,34 +40,61 @@ int handle_cr0_write(struct guest_info * info, ullong_t * new_cr0) { addr_t first_operand; addr_t second_operand; + struct cr0_real *old_cr0; + struct cr0_real *new_cr0; // LMSW // decode mod/RM index += 2; + old_cr0 = (struct cr0_real*)&(guest_state->cr0); if (decode_operands16(&(info->vm_regs), instr + index, &first_operand, &second_operand, REG16) != 0) { // error... don't know what to do return -1; } - - PrintDebug("FirstOperand addr: %x, RAX addr: %x\n", first_operand, &(info->vm_regs.rax)); + index += 3; + + new_cr0 = (struct cr0_real *)first_operand; + if ((new_cr0->pe == 1) && (old_cr0->pe == 0)) { + info->cpu_mode = PROTECTED; + } + if (info->page_mode == SHADOW_PAGING) { + struct cr0_real * virt_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0); + + /* struct cr0_real is only 4 bits wide, + * so we can overwrite the old_cr0 without worrying about the shadow fields + */ + *old_cr0 = *new_cr0; + *virt_cr0 = *new_cr0; + } else { + // for now we just pass through.... + *old_cr0 = *new_cr0; + } + + PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip)); + info->rip += index; + PrintDebug("new_rip = %x\n", (ulong_t)(info->rip)); } else if ((instr[index] == cr_access_byte) && (instr[index + 1] == clts_byte)) { // CLTS } else { - // unsupported instruction, GPF the guest + // unsupported instruction, UD the guest return -1; } + } else if (info->cpu_mode == PROTECTED) { + PrintDebug("Protected Mode write to CR0\n"); + while(1); + } else { + PrintDebug("Unknown Mode write to CR0\n"); + while(1); } - - return 0; }