From: Jack Lange Date: Mon, 30 Jun 2008 23:09:14 +0000 (+0000) Subject: large change to break apart the guest operation mode parameters X-Git-Tag: boot386puppy-26-to-ide~10 X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=41d6dcb0a638ebdc01b89a9edf427c75975b2003 large change to break apart the guest operation mode parameters --- diff --git a/palacios/include/palacios/vm_guest.h b/palacios/include/palacios/vm_guest.h index 0987f95..2582cf0 100644 --- a/palacios/include/palacios/vm_guest.h +++ b/palacios/include/palacios/vm_guest.h @@ -79,21 +79,20 @@ struct vm_ctrl_ops { -typedef enum {SHADOW_PAGING, NESTED_PAGING} vm_page_mode_t; -typedef enum {REAL, PROTECTED, PROTECTED_PG, PROTECTED_PAE, PROTECTED_PAE_PG, LONG, LONG_PG} vm_cpu_mode_t; +typedef enum {SHADOW_PAGING, NESTED_PAGING} vmm_paging_mode_t; +typedef enum {REAL, PROTECTED, PROTECTED_PAE, LONG} vm_cpu_mode_t; +typedef enum {PHYSICAL_MEM, VIRTUAL_MEM} vm_mem_mode_t; struct guest_info { ullong_t rip; - uint_t cpl; - struct shadow_map mem_map; struct vm_time time_state; - vm_page_mode_t page_mode; + vmm_paging_mode_t shdw_pg_mode; struct shadow_page_state shdw_pg_state; // nested_paging_t nested_page_state; @@ -107,6 +106,7 @@ struct guest_info { struct vmm_dev_mgr dev_mgr; vm_cpu_mode_t cpu_mode; + vm_mem_mode_t mem_mode; struct v3_gprs vm_regs; diff --git a/palacios/include/palacios/vmm_decoder.h b/palacios/include/palacios/vmm_decoder.h index fda3729..f37a205 100644 --- a/palacios/include/palacios/vmm_decoder.h +++ b/palacios/include/palacios/vmm_decoder.h @@ -154,7 +154,6 @@ static inline v3_reg_t get_gpr_mask(struct guest_info * info) { return 0xffff; break; case PROTECTED: - case PROTECTED_PG: return 0xffffffff; default: V3_ASSERT(0); @@ -169,7 +168,6 @@ static inline addr_t get_addr_linear(struct guest_info * info, addr_t addr, stru return addr + (seg->selector << 4); break; case PROTECTED: - case PROTECTED_PG: return addr + seg->base; break; default: diff --git a/palacios/include/palacios/vmm_intr.h b/palacios/include/palacios/vmm_intr.h index eccf8fc..30bb2b5 100644 --- a/palacios/include/palacios/vmm_intr.h +++ b/palacios/include/palacios/vmm_intr.h @@ -25,7 +25,7 @@ #define SX_EXCEPTION 0x1e -typedef enum {INVALID_INTR, EXTERNAL_IRQ, NMI, EXCEPTION, SOFTWARE, VIRTUAL} intr_type_t; +typedef enum {INVALID_INTR, EXTERNAL_IRQ, NMI, EXCEPTION, SOFTWARE_INTR, VIRTUAL_INTR} intr_type_t; struct guest_info; diff --git a/palacios/include/palacios/vmm_shadow_paging.h b/palacios/include/palacios/vmm_shadow_paging.h index 40182e5..bdf0114 100644 --- a/palacios/include/palacios/vmm_shadow_paging.h +++ b/palacios/include/palacios/vmm_shadow_paging.h @@ -26,9 +26,6 @@ struct shadow_page_state { - - - struct guest_info; diff --git a/palacios/src/geekos/vm.c b/palacios/src/geekos/vm.c index 0b69b6a..141eedf 100644 --- a/palacios/src/geekos/vm.c +++ b/palacios/src/geekos/vm.c @@ -203,9 +203,10 @@ int RunVMM(struct Boot_Info * bootInfo) { init_shadow_map(&(vm_info.mem_map)); init_shadow_page_state(&(vm_info.shdw_pg_state)); v3_init_time(&(vm_info.time_state)); - vm_info.page_mode = SHADOW_PAGING; + vm_info.shdw_pg_mode = SHADOW_PAGING; vm_info.cpu_mode = REAL; + vm_info.mem_mode = PHYSICAL_MEM; //init_irq_map(&(vm_info.irq_map)); init_vmm_io_map(&(vm_info.io_map)); @@ -313,7 +314,7 @@ int RunVMM(struct Boot_Info * bootInfo) { //add_shadow_region_passthrough(&vm_info, 0x100000, 0x2000000, (addr_t)Allocate_VMM_Pages(8192)); add_shadow_region_passthrough(&vm_info, 0x100000, 0x1000000, (addr_t)Allocate_VMM_Pages(4096)); - + add_shadow_region_passthrough(&vm_info, 0xc0000000, 0xffffffff, 0xc0000000); print_shadow_map(&(vm_info.mem_map)); diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index 7a81e7e..1a9f1b8 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -154,7 +154,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { ctrl_area->instrs.INTR = 1; - if (vm_info.page_mode == SHADOW_PAGING) { + if (vm_info.shdw_pg_mode == SHADOW_PAGING) { PrintDebug("Creating initial shadow page table\n"); vm_info.shdw_pg_state.shadow_cr3 |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff); PrintDebug("Created\n"); @@ -173,7 +173,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { guest_state->g_pat = 0x7040600070406ULL; guest_state->cr0 |= 0x80000000; - } else if (vm_info.page_mode == NESTED_PAGING) { + } else if (vm_info.shdw_pg_mode == NESTED_PAGING) { // Flush the TLB on entries/exits //ctrl_area->TLB_CONTROL = 1; @@ -273,7 +273,6 @@ static int start_svm_guest(struct guest_info *info) { PrintDebug("SVM ERROR!!\n"); - PrintDebug("RIP: %x\n", guest_state->rip); @@ -282,7 +281,13 @@ static int start_svm_guest(struct guest_info *info) { PrintDebug("RIP Linear: %x\n", linear_addr); - guest_pa_to_host_pa(info, linear_addr, &host_addr); + + if (info->mem_mode == PHYSICAL_MEM) { + guest_pa_to_host_pa(info, linear_addr, &host_addr); + } else if (info->mem_mode == VIRTUAL_MEM) { + guest_va_to_host_pa(info, linear_addr, &host_addr); + } + PrintDebug("Host Address of rip = 0x%x\n", host_addr); diff --git a/palacios/src/palacios/svm_handler.c b/palacios/src/palacios/svm_handler.c index 7e1a91b..fa71162 100644 --- a/palacios/src/palacios/svm_handler.c +++ b/palacios/src/palacios/svm_handler.c @@ -106,7 +106,7 @@ int handle_svm_exit(struct guest_info * info) { PrintDebug("PageFault at %x (error=%d)\n", fault_addr, *error_code); - if (info->page_mode == SHADOW_PAGING) { + if (info->shdw_pg_mode == SHADOW_PAGING) { if (handle_shadow_pagefault(info, fault_addr, *error_code) == -1) { return -1; } @@ -116,7 +116,7 @@ int handle_svm_exit(struct guest_info * info) { } } else if (exit_code == VMEXIT_INVLPG) { - if (info->page_mode == SHADOW_PAGING) { + if (info->shdw_pg_mode == SHADOW_PAGING) { PrintDebug("Invlpg\n"); if (handle_shadow_invlpg(info) == -1) { return -1; @@ -158,8 +158,18 @@ int handle_svm_exit(struct guest_info * info) { - if (guest_pa_to_host_pa(info, guest_state->rip, &host_addr) == -1) { - PrintDebug("Could not translate guest_state->rip to host address\n"); + if (info->mem_mode == PHYSICAL_MEM) { + if (guest_pa_to_host_pa(info, guest_state->rip, &host_addr) == -1) { + PrintDebug("Could not translate guest_state->rip to host address\n"); + return -1; + } + } else if (info->mem_mode == VIRTUAL_MEM) { + if (guest_va_to_host_pa(info, guest_state->rip, &host_addr) == -1) { + PrintDebug("Could not translate guest_state->rip to host address\n"); + return -1; + } + } else { + PrintDebug("Invalid memory mode\n"); return -1; } @@ -169,7 +179,11 @@ int handle_svm_exit(struct guest_info * info) { PrintDebug("Reading from 0x%x in guest\n", rip_addr); - read_guest_pa_memory(info, rip_addr, 15, buf); + if (info->mem_mode == PHYSICAL_MEM) { + read_guest_pa_memory(info, rip_addr, 15, buf); + } else { + read_guest_va_memory(info, rip_addr, 15, buf); + } PrintTraceMemDump(buf, 15); @@ -223,10 +237,10 @@ int handle_svm_exit(struct guest_info * info) { injecting_intr(info, excp, EXCEPTION); break; } - case SOFTWARE: + case SOFTWARE_INTR: guest_ctrl->EVENTINJ.type = SVM_INJECTION_SOFT_INTR; break; - case VIRTUAL: + case VIRTUAL_INTR: guest_ctrl->EVENTINJ.type = SVM_INJECTION_VIRTUAL_INTR; break; diff --git a/palacios/src/palacios/vm_guest_mem.c b/palacios/src/palacios/vm_guest_mem.c index 7b98d83..70914b4 100644 --- a/palacios/src/palacios/vm_guest_mem.c +++ b/palacios/src/palacios/vm_guest_mem.c @@ -115,16 +115,16 @@ int guest_pa_to_host_va(struct guest_info * guest_info, addr_t guest_pa, addr_t int guest_va_to_guest_pa(struct guest_info * guest_info, addr_t guest_va, addr_t * guest_pa) { - if (guest_info->page_mode == SHADOW_PAGING) { - switch (guest_info->cpu_mode) { - case REAL: - case PROTECTED: - case LONG: - case PROTECTED_PAE: + if (guest_info->shdw_pg_mode == SHADOW_PAGING) { + if (guest_info->mem_mode == PHYSICAL_MEM) { // guest virtual address is the same as the physical *guest_pa = guest_va; return 0; - case PROTECTED_PG: + } + + // Guest Is in Paged mode + switch (guest_info->cpu_mode) { + case PROTECTED: { addr_t tmp_pa = 0; pde32_t * pde = 0; @@ -167,18 +167,18 @@ int guest_va_to_guest_pa(struct guest_info * guest_info, addr_t guest_va, addr_t return -1; } } - case PROTECTED_PAE_PG: + case PROTECTED_PAE: { // Fill in } - case LONG_PG: + case LONG: { // Fill in } default: return -1; } - } else if (guest_info->page_mode == NESTED_PAGING) { + } else if (guest_info->shdw_pg_mode == NESTED_PAGING) { // Fill in diff --git a/palacios/src/palacios/vmm_ctrl_regs.c b/palacios/src/palacios/vmm_ctrl_regs.c index 245ba44..82853bc 100644 --- a/palacios/src/palacios/vmm_ctrl_regs.c +++ b/palacios/src/palacios/vmm_ctrl_regs.c @@ -85,7 +85,7 @@ int handle_cr0_write(struct guest_info * info) { new_cr0_val = *(char*)(new_cr0) & 0x0f; - if (info->page_mode == SHADOW_PAGING) { + if (info->shdw_pg_mode == SHADOW_PAGING) { struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0); PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0); @@ -153,7 +153,7 @@ int handle_cr0_write(struct guest_info * info) { return -1; } - if (info->page_mode == SHADOW_PAGING) { + if (info->shdw_pg_mode == SHADOW_PAGING) { struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0); PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0); @@ -181,24 +181,23 @@ int handle_cr0_write(struct guest_info * info) { break; case PROTECTED: - case PROTECTED_PG: { int index = 0; int ret; PrintDebug("Protected %s Mode write to CR0 at guest %s linear rip 0x%x\n", - info->cpu_mode==PROTECTED_PG ? "Paged" : "", - info->cpu_mode==PROTECTED_PG ? "virtual" : "", - get_addr_linear(info,info->rip,&(info->segments.cs))); + info->mem_mode == VIRTUAL_MEM ? "Paged" : "", + info->mem_mode == VIRTUAL_MEM ? "virtual" : "", + get_addr_linear(info, info->rip, &(info->segments.cs))); // OK, now we will read the instruction // The only difference between PROTECTED and PROTECTED_PG is whether we read // from guest_pa or guest_va - if (info->cpu_mode==PROTECTED) { + if (info->mem_mode == PHYSICAL_MEM) { // The real rip address is actually a combination of the rip + CS base ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); - } else { //PROTECTED_PG + } else { ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); } @@ -240,7 +239,7 @@ int handle_cr0_write(struct guest_info * info) { - if (info->page_mode == SHADOW_PAGING) { + if (info->shdw_pg_mode == SHADOW_PAGING) { struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0); if (new_cr0->pg == 1){ @@ -249,7 +248,7 @@ int handle_cr0_write(struct guest_info * info) { struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3); - info->cpu_mode = PROTECTED_PG; + info->mem_mode = VIRTUAL_MEM; *shadow_cr0 = *new_cr0; *real_cr0 = *new_cr0; @@ -300,18 +299,10 @@ int handle_cr0_write(struct guest_info * info) { PrintDebug("Protected PAE Mode write to CR0 is UNIMPLEMENTED\n"); return -1; - case PROTECTED_PAE_PG: - PrintDebug("Protected PAE Paged Mode write to CR0 is UNIMPLEMENTED\n"); - return -1; - case LONG: PrintDebug("Protected Long Mode write to CR0 is UNIMPLEMENTED\n"); return -1; - case LONG_PG: - PrintDebug("Protected Long Paged Mode write to CR0 is UNIMPLEMENTED\n"); - return -1; - default: { PrintDebug("Unknown Mode write to CR0 (info->cpu_mode=0x%x\n)",info->cpu_mode); @@ -418,7 +409,7 @@ int handle_cr0_read(struct guest_info * info) { return -1; } - if (info->page_mode == SHADOW_PAGING) { + if (info->shdw_pg_mode == SHADOW_PAGING) { *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0); } else { *virt_cr0 = *real_cr0; @@ -436,23 +427,22 @@ int handle_cr0_read(struct guest_info * info) { break; case PROTECTED: - case PROTECTED_PG: { int index = 0; int ret; PrintDebug("Protected %s Mode read from CR0 at guest %s linear rip 0x%x\n", - info->cpu_mode==PROTECTED_PG ? "Paged" : "", - info->cpu_mode==PROTECTED_PG ? "virtual" : "", - get_addr_linear(info,info->rip,&(info->segments.cs))); + info->mem_mode == VIRTUAL_MEM ? "Paged" : "", + info->mem_mode == VIRTUAL_MEM ? "virtual" : "", + get_addr_linear(info, info->rip, &(info->segments.cs))); // We need to read the instruction, which is at CS:IP, but that // linear address is guest physical without PG and guest virtual with PG - if (info->cpu_mode==PROTECTED) { + if (info->cpu_mode == PHYSICAL_MEM) { // The real rip address is actually a combination of the rip + CS base ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); - } else { // PROTECTED_PG + } else { // The real rip address is actually a combination of the rip + CS base ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); } @@ -460,7 +450,7 @@ int handle_cr0_read(struct guest_info * info) { if (ret != 15) { // I think we should inject a GPF into the guest PrintDebug("Could not read Protected %s mode instruction (ret=%d)\n", - info->cpu_mode==PROTECTED_PG ? "Paged" : "", ret); + info->cpu_mode == VIRTUAL_MEM ? "Paged" : "", ret); return -1; } @@ -491,7 +481,7 @@ int handle_cr0_read(struct guest_info * info) { virt_cr0 = (struct cr0_32 *)first_operand; - if (info->page_mode == SHADOW_PAGING) { + if (info->shdw_pg_mode == SHADOW_PAGING) { *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0); } else { *virt_cr0 = *real_cr0; @@ -510,17 +500,11 @@ int handle_cr0_read(struct guest_info * info) { PrintDebug("Protected PAE Mode read to CR0 is UNIMPLEMENTED\n"); return -1; - case PROTECTED_PAE_PG: - PrintDebug("Protected PAE Paged Mode read to CR0 is UNIMPLEMENTED\n"); - return -1; - case LONG: PrintDebug("Protected Long Mode read to CR0 is UNIMPLEMENTED\n"); return -1; - case LONG_PG: - PrintDebug("Protected Long Paged Mode read to CR0 is UNIMPLEMENTED\n"); - return -1; + default: { PrintDebug("Unknown Mode read from CR0 (info->cpu_mode=0x%x)\n",info->cpu_mode); @@ -537,14 +521,25 @@ int handle_cr0_read(struct guest_info * info) { int handle_cr3_write(struct guest_info * info) { - if ((info->cpu_mode == PROTECTED) || (info->cpu_mode == PROTECTED_PG)) { + if (info->cpu_mode == PROTECTED) { int index = 0; int ret; char instr[15]; - /* Isn't the RIP a Guest Virtual Address???????? */ - ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); + // We need to read the instruction, which is at CS:IP, but that + // linear address is guest physical without PG and guest virtual with PG + if (info->cpu_mode == PHYSICAL_MEM) { + // The real rip address is actually a combination of the rip + CS base + PrintDebug("Writing Guest CR3 Write (Physical Address)\n"); + ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); + } else { + PrintDebug("Writing Guest CR3 Write (Virtual Address)\n"); + // The real rip address is actually a combination of the rip + CS base + ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); + } + + if (ret != 15) { PrintDebug("Could not read instruction (ret=%d)\n", ret); return -1; @@ -574,17 +569,16 @@ int handle_cr3_write(struct guest_info * info) { new_cr3 = (struct cr3_32 *)first_operand; - if (info->page_mode == SHADOW_PAGING) { + if (info->shdw_pg_mode == SHADOW_PAGING) { addr_t shadow_pt; struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3); struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3); - PrintDebug("fooo1\n"); /* Delete the current Page Tables */ delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3)); - PrintDebug("fooo2\n"); + *guest_cr3 = *new_cr3; // Something like this @@ -597,7 +591,7 @@ int handle_cr3_write(struct guest_info * info) { shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt); - if (info->cpu_mode == PROTECTED_PG) { + if (info->mem_mode == VIRTUAL_MEM) { // If we aren't in paged mode then we have to preserve the identity mapped CR3 info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3; } @@ -621,12 +615,22 @@ int handle_cr3_write(struct guest_info * info) { int handle_cr3_read(struct guest_info * info) { - if ((info->cpu_mode == PROTECTED) || (info->cpu_mode == PROTECTED_PG)) { + if (info->cpu_mode == PROTECTED) { int index = 0; int ret; char instr[15]; - ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); + + // We need to read the instruction, which is at CS:IP, but that + // linear address is guest physical without PG and guest virtual with PG + if (info->cpu_mode == PHYSICAL_MEM) { + // The real rip address is actually a combination of the rip + CS base + ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); + } else { + // The real rip address is actually a combination of the rip + CS base + ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); + } + if (ret != 15) { PrintDebug("Could not read instruction (ret=%d)\n", ret); return -1; @@ -655,7 +659,7 @@ int handle_cr3_read(struct guest_info * info) { virt_cr3 = (struct cr3_32 *)first_operand; - if (info->page_mode == SHADOW_PAGING) { + if (info->shdw_pg_mode == SHADOW_PAGING) { *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3); } else { *virt_cr3 = *real_cr3; diff --git a/palacios/src/palacios/vmm_shadow_paging.c b/palacios/src/palacios/vmm_shadow_paging.c index 5536f04..360e532 100644 --- a/palacios/src/palacios/vmm_shadow_paging.c +++ b/palacios/src/palacios/vmm_shadow_paging.c @@ -19,23 +19,25 @@ int init_shadow_page_state(struct shadow_page_state * state) { int handle_shadow_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) { - switch (info->cpu_mode) { - case PROTECTED_PG: - return handle_shadow_pagefault32(info, fault_addr, error_code); - break; - case PROTECTED_PAE_PG: - case LONG_PG: - // currently not handled - return -1; - break; - case REAL: - case PROTECTED: - case PROTECTED_PAE: - case LONG: + if (info->mem_mode == PHYSICAL_MEM) { // If paging is not turned on we need to handle the special cases return handle_special_page_fault(info, fault_addr, error_code); - break; - default: + } else if (info->mem_mode == VIRTUAL_MEM) { + + switch (info->cpu_mode) { + case PROTECTED: + return handle_shadow_pagefault32(info, fault_addr, error_code); + break; + case PROTECTED_PAE: + case LONG: + // currently not handled + return -1; + break; + default: + return -1; + } + } else { + PrintDebug("Invalid Memory mode\n"); return -1; } } @@ -151,7 +153,7 @@ int handle_shadow_pagefault32(struct guest_info * info, addr_t fault_addr, pf_er return -1; } - PrintDebugPageTables(shadow_pde); + //PrintDebugPageTables(shadow_pde); return 0; } @@ -277,7 +279,15 @@ addr_t create_new_shadow_pt32(struct guest_info * info) { /* Currently Does not work with Segmentation!!! */ int handle_shadow_invlpg(struct guest_info * info) { - if (info->cpu_mode == PROTECTED_PG) { + if (info->mem_mode != VIRTUAL_MEM) { + // Paging must be turned on... + // should handle with some sort of fault I think + PrintDebug("ERROR: INVLPG called in non paged mode\n"); + return -1; + } + + + if (info->cpu_mode == PROTECTED) { char instr[15]; int ret; int index = 0; @@ -334,7 +344,7 @@ int handle_shadow_invlpg(struct guest_info * info) { PrintDebug("invalid Instruction Opcode\n"); PrintTraceMemDump(instr, 15); return -1; - } + } } return 0;