From: Jack Lange Date: Mon, 19 May 2008 23:45:27 +0000 (+0000) Subject: added invlpg support X-Git-Tag: boot386puppy-26-to-ide~41 X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=639fdba00d36b2a60fad3d28703459354cf8744f added invlpg support --- diff --git a/palacios/include/palacios/vm_guest.h b/palacios/include/palacios/vm_guest.h index 13be2f0..89e6590 100644 --- a/palacios/include/palacios/vm_guest.h +++ b/palacios/include/palacios/vm_guest.h @@ -86,6 +86,8 @@ struct guest_info { ullong_t rip; + uint_t cpl; + struct shadow_map mem_map; diff --git a/palacios/include/palacios/vmm_paging.h b/palacios/include/palacios/vmm_paging.h index 5cbdbd3..c3b235e 100644 --- a/palacios/include/palacios/vmm_paging.h +++ b/palacios/include/palacios/vmm_paging.h @@ -112,8 +112,8 @@ the host state in the vmcs before entering the guest. /* Accessor functions for the page table structures */ -#define PDE32_T_ADDR(x) ((x.pt_base_addr) << 12) -#define PTE32_T_ADDR(x) ((x.page_base_addr) << 12) +#define PDE32_T_ADDR(x) (((x).pt_base_addr) << 12) +#define PTE32_T_ADDR(x) (((x).page_base_addr) << 12) #endif diff --git a/palacios/include/palacios/vmm_shadow_paging.h b/palacios/include/palacios/vmm_shadow_paging.h index 695e0f6..40182e5 100644 --- a/palacios/include/palacios/vmm_shadow_paging.h +++ b/palacios/include/palacios/vmm_shadow_paging.h @@ -57,4 +57,7 @@ int handle_shadow_pte32_fault(struct guest_info* info, pte32_t * guest_pte); + +int handle_shadow_invlpg(struct guest_info * info); + #endif diff --git a/palacios/src/geekos/vm.c b/palacios/src/geekos/vm.c index fe50c29..3666486 100644 --- a/palacios/src/geekos/vm.c +++ b/palacios/src/geekos/vm.c @@ -304,7 +304,7 @@ int RunVMM(struct Boot_Info * bootInfo) { print_shadow_map(&(vm_info.mem_map)); hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write, NULL); - hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial, NULL); + //hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial, NULL); hook_io_port(&(vm_info.io_map), 0x400, &IO_Read, &IO_Write_to_Serial, NULL); diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index 9983b08..7889c11 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -143,7 +143,7 @@ int start_svm_guest(struct guest_info *info) { CLGI(); //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); + //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"); @@ -327,6 +327,8 @@ void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { // guest_state->rip = vm_info.rip; guest_state->rip = 0xfff0; + guest_state->cpl = 0; + //ctrl_area->instrs.instrs.CR0 = 1; ctrl_area->cr_reads.cr0 = 1; ctrl_area->cr_writes.cr0 = 1; diff --git a/palacios/src/palacios/svm_handler.c b/palacios/src/palacios/svm_handler.c index 7ac7be2..4ab4979 100644 --- a/palacios/src/palacios/svm_handler.c +++ b/palacios/src/palacios/svm_handler.c @@ -7,7 +7,6 @@ #include - int handle_svm_exit(struct guest_info * info) { vmcb_ctrl_t * guest_ctrl = 0; vmcb_saved_state_t * guest_state = 0; @@ -22,6 +21,7 @@ int handle_svm_exit(struct guest_info * info) { info->vm_regs.rsp = guest_state->rsp; info->vm_regs.rax = guest_state->rax; + info->cpl = guest_state->cpl; info->ctrl_regs.cr0 = guest_state->cr0; @@ -36,7 +36,7 @@ int handle_svm_exit(struct guest_info * info) { exit_code = guest_ctrl->exit_code; - PrintDebug("SVM Returned: Exit Code: %x\n",exit_code); + //PrintDebug("SVM Returned: Exit Code: %x\n",exit_code); // PrintDebugVMCB((vmcb_t*)(info->vmm_data)); @@ -110,8 +110,15 @@ int handle_svm_exit(struct guest_info * info) { return -1; } + } else if (exit_code == VMEXIT_INVLPG) { + if (info->page_mode == SHADOW_PAGING) { + PrintDebug("Invlpg\n"); + if (handle_shadow_invlpg(info) == -1) { + return -1; + } + } + /* - (exit_code == VMEXIT_INVLPG) || (exit_code == VMEXIT_INVLPGA) || */ @@ -226,6 +233,8 @@ int handle_svm_exit(struct guest_info * info) { guest_state->rflags = info->ctrl_regs.rflags; + guest_state->cpl = info->cpl; + guest_state->rax = info->vm_regs.rax; guest_state->rip = info->rip; guest_state->rsp = info->vm_regs.rsp; diff --git a/palacios/src/palacios/svm_io.c b/palacios/src/palacios/svm_io.c index a4208f4..d70be6f 100644 --- a/palacios/src/palacios/svm_io.c +++ b/palacios/src/palacios/svm_io.c @@ -20,7 +20,7 @@ int handle_svm_io_in(struct guest_info * info) { return -1; } - PrintDebug("IN on port %d (0x%x)\n", io_info->port, io_info->port); + //PrintDebug("IN on port %d (0x%x)\n", io_info->port, io_info->port); if (io_info->sz8) { read_size = 1; @@ -80,7 +80,7 @@ int handle_svm_io_ins(struct guest_info * info) { return -1; } - PrintDebug("INS on port %d (0x%x)\n", io_info->port, io_info->port); + //PrintDebug("INS on port %d (0x%x)\n", io_info->port, io_info->port); if (io_info->sz8) { read_size = 1; @@ -150,7 +150,7 @@ int handle_svm_io_out(struct guest_info * info) { return -1; } - PrintDebug("OUT on port %d (0x%x)\n", io_info->port, io_info->port); + //PrintDebug("OUT on port %d (0x%x)\n", io_info->port, io_info->port); if (io_info->sz8) { write_size = 1; @@ -208,7 +208,7 @@ int handle_svm_io_outs(struct guest_info * info) { return -1; } - PrintDebug("OUTS on port %d (0x%x)\n", io_info->port, io_info->port); + //PrintDebug("OUTS on port %d (0x%x)\n", io_info->port, io_info->port); if (io_info->sz8) { write_size = 1; diff --git a/palacios/src/palacios/vm_guest_mem.c b/palacios/src/palacios/vm_guest_mem.c index 7e45c0c..7b98d83 100644 --- a/palacios/src/palacios/vm_guest_mem.c +++ b/palacios/src/palacios/vm_guest_mem.c @@ -15,9 +15,11 @@ int host_va_to_host_pa(addr_t host_va, addr_t * host_pa) { *host_pa = (addr_t)(os_hooks)->vaddr_to_paddr((void *)host_va); if (*host_pa == 0) { + PrintDebug("In HVA->HPA: Invalid HVA(%x)->HPA lookup\n", host_va); return -1; } } else { + PrintDebug("In HVA->HPA: os_hooks not defined\n"); return -1; } return 0; @@ -30,9 +32,11 @@ int host_pa_to_host_va(addr_t host_pa, addr_t * host_va) { *host_va = (addr_t)(os_hooks)->paddr_to_vaddr((void *)host_pa); if (*host_va == 0) { + PrintDebug("In HPA->HVA: Invalid HPA(%x)->HVA lookup\n", host_pa); return -1; } } else { + PrintDebug("In HPA->HVA: os_hooks not defined\n"); return -1; } return 0; @@ -43,7 +47,7 @@ int host_pa_to_host_va(addr_t host_pa, addr_t * host_va) { int guest_pa_to_host_pa(struct guest_info * guest_info, addr_t guest_pa, addr_t * host_pa) { // we use the shadow map here... if (lookup_shadow_map_addr(&(guest_info->mem_map), guest_pa, host_pa) != HOST_REGION_PHYSICAL_MEMORY) { - PrintDebug("Could not find address in shadow map (addr=%x)\n", guest_pa); + PrintDebug("In GPA->HPA: Could not find address in shadow map (addr=%x)\n", guest_pa); return -1; } @@ -57,6 +61,7 @@ int guest_pa_to_host_pa(struct guest_info * guest_info, addr_t guest_pa, addr_t // int host_pa_to_guest_pa(struct guest_info * guest_info, addr_t host_pa, addr_t * guest_pa) { *guest_pa = 0; + PrintDebug("ERROR!!! HPA->GPA currently not implemented!!!\n"); return -1; } @@ -71,14 +76,16 @@ int host_pa_to_guest_pa(struct guest_info * guest_info, addr_t host_pa, addr_t * /* !! Currently not implemented !! */ // This will return negative until we implement host_pa_to_guest_pa() int host_va_to_guest_pa(struct guest_info * guest_info, addr_t host_va, addr_t * guest_pa) { - addr_t host_pa; + addr_t host_pa = 0; *guest_pa = 0; if (host_va_to_host_pa(host_va, &host_pa) != 0) { + PrintDebug("In HVA->GPA: Invalid HVA(%x)->HPA lookup\n", host_va); return -1; } if (host_pa_to_guest_pa(guest_info, host_pa, guest_pa) != 0) { + PrintDebug("In HVA->GPA: Invalid HPA(%x)->GPA lookup\n", host_pa); return -1; } @@ -89,15 +96,17 @@ int host_va_to_guest_pa(struct guest_info * guest_info, addr_t host_va, addr_t * int guest_pa_to_host_va(struct guest_info * guest_info, addr_t guest_pa, addr_t * host_va) { - addr_t host_pa; + addr_t host_pa = 0; *host_va = 0; if (guest_pa_to_host_pa(guest_info, guest_pa, &host_pa) != 0) { + PrintDebug("In GPA->HVA: Invalid GPA(%x)->HPA lookup\n", guest_pa); return -1; } if (host_pa_to_host_va(host_pa, host_va) != 0) { + PrintDebug("In GPA->HVA: Invalid HPA(%x)->HVA lookup\n", host_pa); return -1; } @@ -117,14 +126,16 @@ int guest_va_to_guest_pa(struct guest_info * guest_info, addr_t guest_va, addr_t return 0; case PROTECTED_PG: { - addr_t tmp_pa; - pde32_t * pde; + addr_t tmp_pa = 0; + pde32_t * pde = 0; addr_t guest_pde = CR3_TO_PDE32(guest_info->shdw_pg_state.guest_cr3); if (guest_pa_to_host_va(guest_info, guest_pde, (addr_t *)&pde) == -1) { + PrintDebug("In GVA->GPA: Invalid GPA(%x)->HVA PDE32 lookup\n", guest_pde); return -1; } + switch (pde32_lookup(pde, guest_va, &tmp_pa)) { case PDE32_ENTRY_NOT_PRESENT: *guest_pa = 0; @@ -134,13 +145,19 @@ int guest_va_to_guest_pa(struct guest_info * guest_info, addr_t guest_va, addr_t return 0; case PDE32_ENTRY_PTE32: { - pte32_t * pte; + pte32_t * pte = 0; + if (guest_pa_to_host_va(guest_info, tmp_pa, (addr_t*)&pte) == -1) { + PrintDebug("In GVA->GPA: Invalid GPA(%x)->HVA PTE32 lookup\n", guest_pa); return -1; } + PrintDebug("PTE host addr=%x, GVA=%x, GPA=%x(should be 0)\n", pte, guest_va, *guest_pa); + if (pte32_lookup(pte, guest_va, guest_pa) != 0) { + PrintDebug("In GVA->GPA: PTE32 Lookup failure GVA=%x; PTE=%x\n", guest_va, pte); + // PrintPT32(PDE32_INDEX(guest_va) << 22, pte); return -1; } @@ -182,6 +199,7 @@ int guest_va_to_guest_pa(struct guest_info * guest_info, addr_t guest_va, addr_t */ int guest_pa_to_guest_va(struct guest_info * guest_info, addr_t guest_pa, addr_t * guest_va) { *guest_va = 0; + PrintDebug("ERROR!!: GPA->GVA Not Implemented!!\n"); return -1; } @@ -192,15 +210,17 @@ int guest_pa_to_guest_va(struct guest_info * guest_info, addr_t guest_pa, addr_t int guest_va_to_host_pa(struct guest_info * guest_info, addr_t guest_va, addr_t * host_pa) { - addr_t guest_pa; + addr_t guest_pa = 0; *host_pa = 0; if (guest_va_to_guest_pa(guest_info, guest_va, &guest_pa) != 0) { + PrintDebug("In GVA->HPA: Invalid GVA(%x)->GPA lookup\n", guest_va); return -1; } if (guest_pa_to_host_pa(guest_info, guest_pa, host_pa) != 0) { + PrintDebug("In GVA->HPA: Invalid GPA(%x)->HPA lookup\n", guest_pa); return -1; } @@ -209,15 +229,17 @@ int guest_va_to_host_pa(struct guest_info * guest_info, addr_t guest_va, addr_t /* !! Currently not implemented !! */ int host_pa_to_guest_va(struct guest_info * guest_info, addr_t host_pa, addr_t * guest_va) { - addr_t guest_pa; + addr_t guest_pa = 0; *guest_va = 0; if (host_pa_to_guest_pa(guest_info, host_pa, &guest_pa) != 0) { + PrintDebug("In HPA->GVA: Invalid HPA(%x)->GPA lookup\n", host_pa); return -1; } if (guest_pa_to_guest_va(guest_info, guest_pa, guest_va) != 0) { + PrintDebug("In HPA->GVA: Invalid GPA(%x)->GVA lookup\n", guest_pa); return -1; } @@ -228,20 +250,23 @@ int host_pa_to_guest_va(struct guest_info * guest_info, addr_t host_pa, addr_t * int guest_va_to_host_va(struct guest_info * guest_info, addr_t guest_va, addr_t * host_va) { - addr_t guest_pa; - addr_t host_pa; + addr_t guest_pa = 0; + addr_t host_pa = 0; *host_va = 0; if (guest_va_to_guest_pa(guest_info, guest_va, &guest_pa) != 0) { + PrintDebug("In GVA->HVA: Invalid GVA(%x)->GPA lookup\n", guest_va); return -1; } if (guest_pa_to_host_pa(guest_info, guest_pa, &host_pa) != 0) { + PrintDebug("In GVA->HVA: Invalid GPA(%x)->HPA lookup\n", guest_pa); return -1; } if (host_pa_to_host_va(host_pa, host_va) != 0) { + PrintDebug("In GVA->HVA: Invalid HPA(%x)->HVA lookup\n", host_pa); return -1; } @@ -251,20 +276,23 @@ int guest_va_to_host_va(struct guest_info * guest_info, addr_t guest_va, addr_t /* !! Currently not implemented !! */ int host_va_to_guest_va(struct guest_info * guest_info, addr_t host_va, addr_t * guest_va) { - addr_t host_pa; - addr_t guest_pa; + addr_t host_pa = 0; + addr_t guest_pa = 0; *guest_va = 0; if (host_va_to_host_pa(host_va, &host_pa) != 0) { + PrintDebug("In HVA->GVA: Invalid HVA(%x)->HPA lookup\n", host_va); return -1; } if (host_pa_to_guest_pa(guest_info, host_pa, &guest_pa) != 0) { + PrintDebug("In HVA->GVA: Invalid HPA(%x)->GPA lookup\n", host_va); return -1; } if (guest_pa_to_guest_va(guest_info, guest_pa, guest_va) != 0) { + PrintDebug("In HVA->GVA: Invalid GPA(%x)->GVA lookup\n", guest_pa); return -1; } @@ -283,12 +311,15 @@ int read_guest_va_memory(struct guest_info * guest_info, addr_t guest_va, int co addr_t cursor = guest_va; int bytes_read = 0; + + while (count > 0) { int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor; int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge; - addr_t host_addr; + addr_t host_addr = 0; if (guest_va_to_host_va(guest_info, cursor, &host_addr) != 0) { + PrintDebug("Invalid GVA(%x)->HVA lookup\n", cursor); return bytes_read; } @@ -317,7 +348,7 @@ int read_guest_pa_memory(struct guest_info * guest_info, addr_t guest_pa, int co while (count > 0) { int dist_to_pg_edge = (PAGE_ADDR(cursor) + PAGE_SIZE) - cursor; int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge; - addr_t host_addr; + addr_t host_addr = 0; if (guest_pa_to_host_va(guest_info, cursor, &host_addr) != 0) { return bytes_read; diff --git a/palacios/src/palacios/vmm_ctrl_regs.c b/palacios/src/palacios/vmm_ctrl_regs.c index d134043..a05f1b9 100644 --- a/palacios/src/palacios/vmm_ctrl_regs.c +++ b/palacios/src/palacios/vmm_ctrl_regs.c @@ -411,6 +411,8 @@ int handle_cr3_write(struct guest_info * info) { 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); if (ret != 15) { PrintDebug("Could not read instruction (ret=%d)\n", ret); diff --git a/palacios/src/palacios/vmm_paging.c b/palacios/src/palacios/vmm_paging.c index 516073a..2c6a078 100644 --- a/palacios/src/palacios/vmm_paging.c +++ b/palacios/src/palacios/vmm_paging.c @@ -41,8 +41,8 @@ void delete_page_tables_pde32(pde32_t * pde) { * The entry addresses could be pointing to either guest physical memory or host physical memory * Instead we just return the entry address, and a flag to show if it points to a pte or a large page... */ -pde32_entry_type_t pde32_lookup(pde32_t * pde, addr_t addr, addr_t * entry) { - pde32_t * pde_entry = &(pde[PDE32_INDEX(addr)]); +pde32_entry_type_t pde32_lookup(pde32_t * pd, addr_t addr, addr_t * entry) { + pde32_t * pde_entry = &(pd[PDE32_INDEX(addr)]); if (!pde_entry->present) { *entry = 0; @@ -54,6 +54,7 @@ pde32_entry_type_t pde32_lookup(pde32_t * pde, addr_t addr, addr_t * entry) { *entry += PAGE_OFFSET(addr); return PDE32_ENTRY_LARGE_PAGE; } else { + *entry = PDE32_T_ADDR(*pde_entry); return PDE32_ENTRY_PTE32; } } @@ -64,15 +65,15 @@ pde32_entry_type_t pde32_lookup(pde32_t * pde, addr_t addr, addr_t * entry) { /* Takes a virtual addr (addr) and returns the physical addr (entry) as defined in the page table */ -int pte32_lookup(pte32_t * pte, addr_t addr, addr_t * entry) { - pte32_t * pte_entry = &(pte[PTE32_INDEX(addr)]); +int pte32_lookup(pte32_t * pt, addr_t addr, addr_t * entry) { + pte32_t * pte_entry = &(pt[PTE32_INDEX(addr)]); if (!pte_entry->present) { *entry = 0; + PrintDebug("Lookup at non present page (index=%d)\n", PTE32_INDEX(addr)); return -1; } else { - *entry = PAGE_ADDR(pte_entry->page_base_addr); - *entry += PAGE_OFFSET(addr); + *entry = PTE32_T_ADDR(*pte_entry) + PT32_PAGE_OFFSET(addr); return 0; } @@ -124,7 +125,6 @@ pde32_t * create_passthrough_pde32_pts(struct guest_info * guest_info) { int i, j; struct shadow_map * map = &(guest_info->mem_map); - pde32_t * pde = os_hooks->allocate_pages(1); for (i = 0; i < MAX_PDE32_ENTRIES; i++) { diff --git a/palacios/src/palacios/vmm_shadow_paging.c b/palacios/src/palacios/vmm_shadow_paging.c index 72be8e7..69606b8 100644 --- a/palacios/src/palacios/vmm_shadow_paging.c +++ b/palacios/src/palacios/vmm_shadow_paging.c @@ -3,7 +3,7 @@ #include #include - +#include @@ -249,6 +249,72 @@ 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) { + char instr[15]; + int ret; + int index = 0; + + 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 0x%x (ret=%d)\n", info->rip, ret); + return -1; + } + + + /* Can INVLPG work with Segments?? */ + while (is_prefix_byte(instr[index])) { + index++; + } + + + if ((instr[index] == (uchar_t)0x0f) && + (instr[index + 1] == (uchar_t)0x01)) { + + addr_t first_operand; + addr_t second_operand; + operand_type_t addr_type; + + index += 2; + + addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32); + + if (addr_type == MEM_OPERAND) { + pde32_t * shadow_pd = (pde32_t *)CR3_TO_PDE32(info->shdw_pg_state.shadow_cr3); + pde32_t * shadow_pde_entry = (pde32_t *)&shadow_pd[PDE32_INDEX(first_operand)]; + + //PrintDebug("PDE Index=%d\n", PDE32_INDEX(first_operand)); + //PrintDebug("FirstOperand = %x\n", first_operand); + + if (shadow_pde_entry->large_page == 1) { + shadow_pde_entry->present = 0; + } else { + if (shadow_pde_entry->present == 1) { + pte32_t * shadow_pt = (pte32_t *)PDE32_T_ADDR((*shadow_pde_entry)); + pte32_t * shadow_pte_entry = (pte32_t *)&shadow_pt[PTE32_INDEX(first_operand)]; + + shadow_pte_entry->present = 0; + } + } + + info->rip += index; + + } else { + PrintDebug("Invalid Operand type\n"); + return -1; + } + } else { + PrintDebug("invalid Instruction Opcode\n"); + PrintTraceMemDump(instr, 15); + return -1; + } + } + + return 0; +} + + /* Deprecated */ /*