From: Jack Lange Date: Wed, 2 Apr 2008 00:28:34 +0000 (+0000) Subject: real->protected mode switch should work now X-Git-Tag: working-cdboot-physical-but-not-qemu~47 X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=9be2a31f574121ab4aa0289b7714eefe070b0db0 real->protected mode switch should work now --- diff --git a/palacios/include/geekos/svm_ctrl_regs.h b/palacios/include/geekos/svm_ctrl_regs.h index d8b3e37..44f6b7a 100644 --- a/palacios/include/geekos/svm_ctrl_regs.h +++ b/palacios/include/geekos/svm_ctrl_regs.h @@ -19,7 +19,7 @@ static const uchar_t mov_from_cr_byte = 0x20; -int handle_cr0_write(struct guest_info * info, ullong_t * new_cr0); +int handle_cr0_write(struct guest_info * info); diff --git a/palacios/include/geekos/vmm_ctrl_regs.h b/palacios/include/geekos/vmm_ctrl_regs.h new file mode 100644 index 0000000..f0d63fe --- /dev/null +++ b/palacios/include/geekos/vmm_ctrl_regs.h @@ -0,0 +1,118 @@ +#ifndef __VMM_CTRL_REGS_H +#define __VMM_CTRL_REGS_H + + +struct cr0_real { + uint_t pe : 1; + uint_t mp : 1; + uint_t em : 1; + uint_t ts : 1; +}; + + +struct cr0_32 { + uint_t pe : 1; + uint_t mp : 1; + uint_t em : 1; + uint_t ts : 1; + uint_t et : 1; + uint_t ne : 1; + uint_t rsvd1 : 10; + uint_t wp : 1; + uint_t rsvd2 : 1; + uint_t am : 1; + uint_t rsvd3 : 10; + uint_t nw : 1; + uint_t cd : 1; + uint_t pg : 1; +}; + + +struct cr0_64 { + uint_t pe : 1; + uint_t mp : 1; + uint_t em : 1; + uint_t ts : 1; + uint_t et : 1; + uint_t ne : 1; + uint_t rsvd1 : 10; + uint_t wp : 1; + uint_t rsvd2 : 1; + uint_t am : 1; + uint_t rsvd3 : 10; + uint_t nw : 1; + uint_t cd : 1; + uint_t pg : 1; + + uint_t rsvd4; // MBZ +}; + + +struct cr2_32 { + uint_t pf_vaddr; +}; + +struct cr2_64 { + ullong_t pf_vaddr; +}; + + +struct cr3_32 { + uint_t rsvd1 : 3; + uint_t pwt : 1; + uint_t pcd : 1; + uint_t rsvd2 : 7; + uint_t pdt_base_addr : 20; +}; + + +struct cr3_32_PAE { + uint_t rsvd1 : 3; + uint_t pwt : 1; + uint_t pcd : 1; + uint_t pdpt_base_addr : 27; +}; + + +struct cr3_64 { + uint_t rsvd1 : 3; + uint_t pwt : 1; + uint_t pcd : 1; + uint_t rsvd2 : 7; + ullong_t pml4t_base_addr : 40; + uint_t rsvd3 : 12; +}; + + +struct cr4_32 { + uint_t vme : 1; + uint_t pvi : 1; + uint_t tsd : 1; + uint_t de : 1; + uint_t pse : 1; + uint_t pae : 1; + uint_t mce : 1; + uint_t pge : 1; + uint_t pce : 1; + uint_t osf_xsr : 1; + uint_t osx : 1; + uint_t rsvd1 : 21; +}; + +struct cr4_64 { + uint_t vme : 1; + uint_t pvi : 1; + uint_t tsd : 1; + uint_t de : 1; + uint_t pse : 1; + uint_t pae : 1; + uint_t mce : 1; + uint_t pge : 1; + uint_t pce : 1; + uint_t osf_xsr : 1; + uint_t osx : 1; + uint_t rsvd1 : 21; + uint_t rsvd2 : 32; +}; + +#endif diff --git a/palacios/include/geekos/vmm_shadow_paging.h b/palacios/include/geekos/vmm_shadow_paging.h index e84f72f..1817800 100644 --- a/palacios/include/geekos/vmm_shadow_paging.h +++ b/palacios/include/geekos/vmm_shadow_paging.h @@ -16,7 +16,7 @@ struct shadow_page_state { paging_mode_t guest_mode; reg_ex_t guest_cr3; // points to guest's current page table - // Should thi sbe here + // Should this be here?? reg_ex_t guest_cr0; // these two reflect the top-level page directory diff --git a/palacios/src/geekos/main.c b/palacios/src/geekos/main.c index 4f21335..85019d5 100644 --- a/palacios/src/geekos/main.c +++ b/palacios/src/geekos/main.c @@ -3,7 +3,7 @@ * Copyright (c) 2001,2003,2004 David H. Hovemeyer * Copyright (c) 2003, Jeffrey K. Hollingsworth * Copyright (c) 2004, Iulian Neamtiu - * $Revision: 1.26 $ + * $Revision: 1.27 $ * * This is free software. You are permitted to use, * redistribute, and modify it as specified in the file "COPYING". @@ -258,9 +258,9 @@ void Main(struct Boot_Info* bootInfo) -#if 0 +#if 1 SerialPrint("Dumping VM kernel Code (first 128 bytes @ 0x%x)\n", 0x100000); - SerialMemDump((unsigned char *)0xfe000, 4096); + SerialMemDump((unsigned char *)0x100000, 256); /* SerialPrint("Dumping kernel Code (first 512 bytes @ 0x%x)\n",KERNEL_START); SerialMemDump((unsigned char *)VM_KERNEL_START, 512); @@ -347,7 +347,9 @@ void Main(struct Boot_Info* bootInfo) vm_info.cs.base=0xf000; vm_info.cs.limit=0xffff; */ - vm_info.rip = 0xfff0; + //vm_info.rip = 0xfff0; + + vm_info.rip = 0; vm_info.vm_regs.rsp = 0x0; } diff --git a/palacios/src/geekos/svm.c b/palacios/src/geekos/svm.c index ad870ff..8108ddb 100644 --- a/palacios/src/geekos/svm.c +++ b/palacios/src/geekos/svm.c @@ -116,7 +116,7 @@ int init_svm_guest(struct guest_info *info) { PrintDebug("Initializing VMCB (addr=%x)\n", info->vmm_data); Init_VMCB((vmcb_t*)(info->vmm_data), *info); - info->rip = 0; + // info->rip = 0; info->vm_regs.rdi = 0; info->vm_regs.rsi = 0; @@ -140,7 +140,9 @@ int start_svm_guest(struct guest_info *info) { //PrintDebugVMCB((vmcb_t*)(info->vmm_data)); while (1) { + PrintDebug("SVM Launch Args (vmcb=%x), (info=%x), (vm_regs=%x)\n", info->vmm_data, &(info->vm_regs)); + PrintDebug("Launching to RIP: %x\n", info->rip); safe_svm_launch((vmcb_t*)(info->vmm_data), &(info->vm_regs)); //launch_svm((vmcb_t*)(info->vmm_data)); PrintDebug("SVM Returned\n"); 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; } diff --git a/palacios/src/geekos/svm_handler.c b/palacios/src/geekos/svm_handler.c index 6624da6..6cd7afe 100644 --- a/palacios/src/geekos/svm_handler.c +++ b/palacios/src/geekos/svm_handler.c @@ -21,7 +21,7 @@ int handle_svm_exit(struct guest_info * info) { info->vm_regs.rsp = guest_state->rsp; - PrintDebug("SVM Returned: (Exit Code=%x) (VMCB=%x)\n", &(guest_ctrl->exit_code), info->vmm_data); + PrintDebug("SVM Returned:(VMCB=%x)\n", info->vmm_data); PrintDebug("RIP: %x\n", guest_state->rip); @@ -30,21 +30,22 @@ int handle_svm_exit(struct guest_info * info) { // PrintDebugVMCB((vmcb_t*)(info->vmm_data)); PrintDebug("SVM Returned: Exit Code: %x\n",exit_code); + PrintDebug("io_info1 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info1)); PrintDebug("io_info1 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info1)) + 4)); PrintDebug("io_info2 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info2)); PrintDebug("io_info2 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info2)) + 4)); + if (exit_code == VMEXIT_IOIO) { handle_svm_io(info); } else if (exit_code == VMEXIT_CR0_WRITE) { PrintDebug("CR0 Write\n"); - ullong_t new_cr0 = 0; - - handle_cr0_write(info, &new_cr0); - guest_state->cr0 = new_cr0; + if (handle_cr0_write(info) == -1) { + return -1; + } } else if (( (exit_code == VMEXIT_CR3_READ) || (exit_code == VMEXIT_CR3_WRITE) ||