From: Jack Lange Date: Fri, 7 Mar 2008 20:25:40 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: working-cdboot-physical-but-not-qemu~58 X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=4939ecae04ce6416f404670640620a23aee9b914 *** empty log message *** --- diff --git a/palacios/build/Makefile b/palacios/build/Makefile index a82b6cc..ab3ad93 100644 --- a/palacios/build/Makefile +++ b/palacios/build/Makefile @@ -1,6 +1,6 @@ # Makefile for GeekOS kernel, userspace, and tools # Copyright (c) 2004,2005 David H. Hovemeyer -# $Revision: 1.15 $ +# $Revision: 1.16 $ # This is free software. You are permitted to use, # redistribute, and modify it as specified in the file "COPYING". @@ -300,7 +300,7 @@ vm_kernel: force vmm_mem_test: geekos/vmm_mem.c - $(HOST_CC) -m32 -o mem_test -DVMM_MEM_TEST -I../include ../src/geekos/vmm_mem.c ../src/geekos/vmm_paging.c + $(HOST_CC) -m32 -o mem_test -DVMM_MEM_TEST -I../include ../src/geekos/vmm_mem.c # Clean build directories of generated files diff --git a/palacios/include/geekos/svm.h b/palacios/include/geekos/svm.h index 84c48dd..6bb2389 100644 --- a/palacios/include/geekos/svm.h +++ b/palacios/include/geekos/svm.h @@ -10,6 +10,7 @@ #define CPUID_SVM_REV_AND_FEATURE_IDS 0x8000000a #define CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml 0x00000004 +#define CPUID_SVM_REV_AND_FEATURE_IDS_edx_np 0x00000001 #define EFER_MSR 0xc0000080 diff --git a/palacios/include/geekos/vmcb.h b/palacios/include/geekos/vmcb.h index b17c7d9..ebcce6b 100644 --- a/palacios/include/geekos/vmcb.h +++ b/palacios/include/geekos/vmcb.h @@ -71,8 +71,8 @@ union Debug_Registers { union Exception_Vectors { uint_t bitmap PACKED; struct { - uint_t ex0 : 1 PACKED; - uint_t ex1 : 1 PACKED; + uint_t ex0 : 1 PACKED; + uint_t ex1 : 1 PACKED; uint_t ex2 : 1 PACKED; uint_t ex3 : 1 PACKED; uint_t ex4 : 1 PACKED; @@ -103,7 +103,41 @@ union Exception_Vectors { uint_t ex29 : 1 PACKED; uint_t ex30 : 1 PACKED; uint_t ex31 : 1 PACKED; - } exceptions; + } ex_numbers; + struct { + uint_t de : 1 PACKED; // divide by zero + uint_t db : 1 PACKED; // Debug + uint_t nmi : 1 PACKED; // Non-maskable interrupt + uint_t bp : 1 PACKED; // Breakpoint + uint_t of : 1 PACKED; // Overflow + uint_t br : 1 PACKED; // Bound-Range + uint_t ud : 1 PACKED; // Invalid-Opcode + uint_t nm : 1 PACKED; // Device-not-available + uint_t df : 1 PACKED; // Double Fault + uint_t ex9 : 1 PACKED; + uint_t ts : 1 PACKED; // Invalid TSS + uint_t np : 1 PACKED; // Segment-not-present + uint_t ss : 1 PACKED; // Stack + uint_t gp : 1 PACKED; // General Protection Fault + uint_t pf : 1 PACKED; // Page fault + uint_t ex15 : 1 PACKED; + uint_t mf : 1 PACKED; // Floating point exception + uint_t ac : 1 PACKED; // Alignment-check + uint_t mc : 1 PACKED; // Machine Check + uint_t xf : 1 PACKED; // SIMD floating-point + uint_t ex20 : 1 PACKED; + uint_t ex21 : 1 PACKED; + uint_t ex22 : 1 PACKED; + uint_t ex23 : 1 PACKED; + uint_t ex24 : 1 PACKED; + uint_t ex25 : 1 PACKED; + uint_t ex26 : 1 PACKED; + uint_t ex27 : 1 PACKED; + uint_t ex28 : 1 PACKED; + uint_t ex29 : 1 PACKED; + uint_t sx : 1 PACKED; // Security Exception + uint_t ex31 : 1 PACKED; + } ex_names; }; @@ -239,10 +273,12 @@ typedef struct VMCB_Control_Area { * But it does say that the EXITINTINFO field is in bits 63-1 * ALL other occurances mention a 1 bit reserved field */ - uint_t rsvd8 : 1 PACKED; - ullong_t N_CR3 : 63 PACKED; + // uint_t rsvd8 : 1 PACKED; + //ullong_t N_CR3 : 63 PACKED; + ullong_t N_CR3 PACKED; /* ** */ + uint_t LBR_VIRTUALIZATION_ENABLE : 1 PACKED; ullong_t rsvd9 : 63 PACKED; // Should be 0 diff --git a/palacios/include/geekos/vmm.h b/palacios/include/geekos/vmm.h index 8751e02..93e7211 100644 --- a/palacios/include/geekos/vmm.h +++ b/palacios/include/geekos/vmm.h @@ -6,6 +6,7 @@ #include #include +#include /* utility definitions */ @@ -76,6 +77,7 @@ typedef struct guest_info { vmm_mem_layout_t mem_layout; // device_map + vmm_pde_t * page_tables; void * vmm_data; } guest_info_t; diff --git a/palacios/include/geekos/vmm_mem.h b/palacios/include/geekos/vmm_mem.h index 75e788c..877382c 100644 --- a/palacios/include/geekos/vmm_mem.h +++ b/palacios/include/geekos/vmm_mem.h @@ -5,11 +5,17 @@ #include +/* + * The mem list is TEMPORARY, simply to lock down which pages are assigned to the VM + * We will remove it and use the host page allocation mechanism in the future + */ + + typedef unsigned long addr_t; typedef struct mem_region { - addr_t addr; + addr_t addr; uint_t num_pages; struct mem_region * next; @@ -36,8 +42,8 @@ typedef enum region_type {GUEST, UNMAPPED, SHARED} region_type_t; typedef struct layout_region { - addr_t addr; - uint_t num_pages; + addr_t start; + addr_t end; region_type_t type; @@ -51,8 +57,6 @@ typedef struct layout_region { typedef struct vmm_mem_layout { uint_t num_pages; uint_t num_regions; - - uint_t num_guest_pages; layout_region_t * head; } vmm_mem_layout_t; @@ -76,15 +80,15 @@ void print_mem_list(vmm_mem_list_t * list); void init_mem_layout(vmm_mem_layout_t * layout); void free_mem_layout(vmm_mem_layout_t * layout); -layout_region_t * get_layout_cursor(vmm_mem_layout_t * layout, addr_t addr); int add_mem_range(vmm_mem_layout_t * layout, layout_region_t * region); -int add_shared_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_pages, addr_t host_addr); -int add_unmapped_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_pages); -int add_guest_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_pages); +int add_shared_mem_range(vmm_mem_layout_t * layout, addr_t start, addr_t end, addr_t host_addr); +int add_unmapped_mem_range(vmm_mem_layout_t * layout, addr_t start, addr_t end); +int add_guest_mem_range(vmm_mem_layout_t * layout, addr_t start, addr_t end); -addr_t get_mem_layout_addr(vmm_mem_layout_t * list, uint_t index); +addr_t get_mem_layout_addr(vmm_mem_layout_t * layout, uint_t index); +layout_region_t * get_mem_layout_region(vmm_mem_layout_t * layout, addr_t addr); void print_mem_layout(vmm_mem_layout_t * layout); diff --git a/palacios/include/geekos/vmm_paging.h b/palacios/include/geekos/vmm_paging.h index 5d41452..b97d835 100644 --- a/palacios/include/geekos/vmm_paging.h +++ b/palacios/include/geekos/vmm_paging.h @@ -2,7 +2,7 @@ #define __VMM_PAGING_H #include -#include + #include @@ -28,6 +28,9 @@ #define VM_EXEC 0 +#define GUEST_PAGE 0x0 +#define SHARED_PAGE 0x1 + typedef struct pde { uint_t present : 1; uint_t flags : 4; @@ -37,7 +40,7 @@ typedef struct pde { uint_t global_page : 1; uint_t vmm_info : 3; uint_t pt_base_addr : 20; -} pde_t; +} vmm_pde_t; typedef struct pte { uint_t present : 1; @@ -48,13 +51,14 @@ typedef struct pte { uint_t global_page : 1; uint_t vmm_info : 3; uint_t page_base_addr : 20; -} pte_t; +} vmm_pte_t; -pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * list); +vmm_pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * list); +void free_guest_page_tables(vmm_pde_t * pde); -void PrintDebugPageTables(pde_t * pde); +void PrintDebugPageTables(vmm_pde_t * pde); diff --git a/palacios/include/geekos/vmm_util.h b/palacios/include/geekos/vmm_util.h index ae58b10..16931b4 100644 --- a/palacios/include/geekos/vmm_util.h +++ b/palacios/include/geekos/vmm_util.h @@ -1,13 +1,15 @@ #ifndef __VMM_UTIL_H #define __VMM_UTIL_H -#include -#include +#include + #ifndef PAGE_SIZE #define PAGE_SIZE 4096 #endif + + typedef union reg_ex { ullong_t r_reg; struct { diff --git a/palacios/src/geekos/int.c b/palacios/src/geekos/int.c index 70b7b70..1799cfe 100644 --- a/palacios/src/geekos/int.c +++ b/palacios/src/geekos/int.c @@ -1,7 +1,7 @@ /* * GeekOS interrupt handling data structures and functions * Copyright (c) 2001,2003 David H. Hovemeyer - * $Revision: 1.3 $ + * $Revision: 1.4 $ * * This is free software. You are permitted to use, * redistribute, and modify it as specified in the file "COPYING". @@ -318,11 +318,18 @@ static void Dummy_Interrupt_Handler(struct Interrupt_State* state) { Begin_IRQ(state); - Print("Unexpected Interrupt! Ignoring!\n"); - SerialPrint("*** Unexpected interrupt! *** Ignoring!\n"); - Dump_Interrupt_State(state); - // SerialPrint_VMCS_ALL(); - + + /* A "feature" of some chipsets is that if an interrupt is raised by mistake + * then its automatically assigned to IRQ 7(Int 39). + * Makes perfect sense... + * See: + * http://forums12.itrc.hp.com/service/forums/questionanswer.do?admit=109447627+1204759699215+28353475&threadId=1118488 + */ + if (state->intNum != 39) { + Print("Unexpected Interrupt! Ignoring!\n"); + SerialPrint("*** Unexpected interrupt! *** Ignoring!\n"); + Dump_Interrupt_State(state); + } End_IRQ(state); //STOP(); diff --git a/palacios/src/geekos/lowlevel.asm b/palacios/src/geekos/lowlevel.asm index c530a5c..9869d9f 100644 --- a/palacios/src/geekos/lowlevel.asm +++ b/palacios/src/geekos/lowlevel.asm @@ -2,7 +2,7 @@ ; Low level interrupt/thread handling code for GeekOS. ; Copyright (c) 2001,2003,2004 David H. Hovemeyer ; Copyright (c) 2003, Jeffrey K. Hollingsworth -; $Revision: 1.3 $ +; $Revision: 1.4 $ ; This is free software. You are permitted to use, ; redistribute, and modify it as specified in the file "COPYING". @@ -172,7 +172,7 @@ EXPORT Set_MSR EXPORT Get_MSR EXPORT Get_CR2 - +EXPORT Get_CR3 EXPORT Proc_test @@ -380,6 +380,11 @@ Get_CR2: align 8 +Get_CR3: + mov eax, cr3 + ret + +align 8 Proc_test: push ebp mov ebp, esp diff --git a/palacios/src/geekos/main.c b/palacios/src/geekos/main.c index 3d3ebba..5f12931 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.16 $ + * $Revision: 1.17 $ * * This is free software. You are permitted to use, * redistribute, and modify it as specified in the file "COPYING". @@ -36,19 +36,6 @@ #include -/* - static inline unsigned int cpuid_ecx(unsigned int op) - { - unsigned int eax, ecx; - - __asm__("cpuid" - : "=a" (eax), "=c" (ecx) - : "0" (op) - : "bx", "dx" ); - - return ecx; - } -*/ @@ -169,20 +156,6 @@ void Buzzer(ulong_t arg) { -void Hello(ulong_t arg) -{ - char *b="hello "; - char byte; - short port=0xe9; - int i; - while(1){ - for (i=0;i<6;i++) { - byte=b[i]; - __asm__ __volatile__ ("outb %b0, %w1" : : "a"(byte), "Nd"(port) ); - } - } -} - void Keyboard_Listener(ulong_t arg) { ulong_t * doIBuzz = (ulong_t*)arg; Keycode key_press; @@ -209,47 +182,13 @@ extern char BSS_START, BSS_END; extern char end; -/* -void VM_Thread(ulong_t arg) -{ - int ret; - struct VMDescriptor *vm = (struct VMDescriptor *) arg; - - SerialPrintLevel(100,"VM_Thread: Launching VM with (entry_ip=%x, exit_eip=%x, guest_esp=%x)\n", - vm->entry_ip, vm->exit_eip, vm->guest_esp); - - SerialPrintLevel(100,"VM_Thread: You should see nothing further from me\n"); - - - ret = VMLaunch(vm); - - - SerialPrintLevel(100,"VM_Thread: uh oh..."); - - switch (ret) { - case VMX_SUCCESS: - SerialPrintLevel(100,"Normal VMExit Occurred\n"); - break; - case VMX_FAIL_INVALID: - SerialPrintLevel(100,"Possibile invalid VMCS (%.8x)\n", ret); - break; - case VMX_FAIL_VALID: - SerialPrintLevel(100,"Valid VMCS, errorcode recorded in VMCS\n"); - break; - case VMM_ERROR: - SerialPrintLevel(100,"VMM Error\n"); - break; - default: - SerialPrintLevel(100,"VMLaunch returned unknown error (%.8x)\n", ret); - break; - } - - SerialPrintLevel(100,"VM_Thread: Spinning\n"); - while (1) {} - -} -*/ +/* This is an ugly hack to get at the VM memory */ +ulong_t vm_range_start; +ulong_t vm_range_end; +ulong_t guest_kernel_start; +ulong_t guest_kernel_end; +/* ** */ int AllocateAndMapPagesForRange(uint_t start, uint_t length, pte_t template_pte) @@ -329,6 +268,9 @@ void Main(struct Boot_Info* bootInfo) struct vmm_os_hooks os_hooks; struct vmm_ctrl_ops vmm_ops; guest_info_t vm_info; + addr_t rsp; + addr_t rip; + memset(&os_hooks, 0, sizeof(struct vmm_os_hooks)); memset(&vmm_ops, 0, sizeof(struct vmm_ctrl_ops)); memset(&vm_info, 0, sizeof(guest_info_t)); @@ -348,14 +290,21 @@ void Main(struct Boot_Info* bootInfo) init_mem_layout(&(vm_info.mem_layout)); init_mem_list(&(vm_info.mem_list)); - // add_mem_list_pages(&(vm_info.mem_list), START_OF_VM, 20); - //add_guest_mem_range(&(vm_info.mem_layout), 0, 20); + add_mem_list_pages(&(vm_info.mem_list), vm_range_start, (vm_range_end - vm_range_start) / PAGE_SIZE); + // add_unmapped_mem_range(&(vm_info.mem_layout), 0, 256); + //add_shared_mem_range(&(vm_info.mem_layout), guest_kernel_start, (guest_kernel_end - guest_kernel_start) / PAGE_SIZE, guest_kernel_start); + //add_guest_mem_range(&(vm_info.mem_layout), guest_kernel_end, 20); - vm_info.rip = (ullong_t)(void*)&BuzzVM; - vm_info.rsp = (ulong_t)Alloc_Page(); + add_shared_mem_range(&(vm_info.mem_layout), 0, 0x1000000, 0); - SerialPrint("Initializing Guest\n"); + rip = (ulong_t)(void*)&BuzzVM; + vm_info.rip = rip; + rsp = (ulong_t)Alloc_Page(); + vm_info.rsp = rsp; + + + SerialPrint("Initializing Guest (eip=0x%.8x) (esp=0x%.8x)\n", rip, rsp); (vmm_ops).init_guest(&vm_info); SerialPrint("Starting Guest\n"); (vmm_ops).start_guest(&vm_info); @@ -371,37 +320,6 @@ void Main(struct Boot_Info* bootInfo) - - - // Try to launch a real VM - - - // We now map pages of physical memory into where we are going - // to slap the vmxassist, bios, and vgabios code - /* - pte_t template_pte; - - template_pte.present=1; - template_pte.flags=VM_WRITE|VM_READ|VM_USER|VM_EXEC; - template_pte.accessed=0; - template_pte.dirty=0; - template_pte.pteAttribute=0; - template_pte.globalPage=0; - template_pte.kernelInfo=0; - - SerialPrintLevel(1000,"Allocating Pages for VM kernel\n"); - -#define SEGLEN (1024*64) - - AllocateAndMapPagesForRange(START_OF_VM+0x100000, VM_KERNEL_LENGTH / 512, template_pte); -*/ - // Now we should be copying into actual memory - - //SerialPrintLevel(1000,"Copying VM code from %x to %x (%d bytes)\n", VM_KERNEL_START, START_OF_VM+0x100000,VM_KERNEL_LENGTH); - //memcpy((char*)(START_OF_VM+0x100000),(char*)VM_KERNEL_START,VM_KERNEL_LENGTH); - - //SerialPrintLevel(1000, "VM copied\n"); - /* // jump into vmxassist vm.entry_ip=(uint_t)0x00107fd0; diff --git a/palacios/src/geekos/mem.c b/palacios/src/geekos/mem.c index 5267ee1..7772582 100644 --- a/palacios/src/geekos/mem.c +++ b/palacios/src/geekos/mem.c @@ -2,7 +2,7 @@ * Physical memory allocation * Copyright (c) 2001,2003,2004 David H. Hovemeyer * Copyright (c) 2003, Jeffrey K. Hollingsworth - * $Revision: 1.4 $ + * $Revision: 1.5 $ * * This is free software. You are permitted to use, * redistribute, and modify it as specified in the file "COPYING". @@ -22,6 +22,7 @@ #include #include + /* ---------------------------------------------------------------------- * Global data * ---------------------------------------------------------------------- */ @@ -36,6 +37,18 @@ struct Page* g_pageList; */ uint_t g_freePageCount = 0; + + +/* + * the disgusting way to get at the memory assigned to a VM + */ +extern ulong_t vm_range_start; +extern ulong_t vm_range_end; +extern ulong_t guest_kernel_start; +extern ulong_t guest_kernel_end; + + + /* ---------------------------------------------------------------------- * Private data and functions * ---------------------------------------------------------------------- */ @@ -56,6 +69,9 @@ static struct Page_List s_freeList; */ int unsigned s_numPages; + + + /* * Add a range of pages to the inventory of physical memory. */ @@ -172,7 +188,13 @@ void Init_Mem(struct Boot_Info* bootInfo) vmmMemEnd = Round_Up_To_Page(pageListEnd + VMM_AVAIL_MEM_SIZE); - + /* + * the disgusting way to get at the memory assigned to a VM + */ + vm_range_start = vmmMemEnd; + vm_range_end = endOfMem; + guest_kernel_start = ISA_HOLE_END; + guest_kernel_end = guestEnd; Add_Page_Range(0, PAGE_SIZE, PAGE_UNUSED); // BIOS area Add_Page_Range(PAGE_SIZE, PAGE_SIZE * 3, PAGE_ALLOCATED); // Intial kernel thread obj + stack diff --git a/palacios/src/geekos/svm.c b/palacios/src/geekos/svm.c index 4ba49b2..75e65f8 100644 --- a/palacios/src/geekos/svm.c +++ b/palacios/src/geekos/svm.c @@ -13,7 +13,7 @@ extern uint_t cpuid_edx(uint_t op); extern void Get_MSR(uint_t MSR, uint_t * high_byte, uint_t * low_byte); extern void Set_MSR(uint_t MSR, uint_t high_byte, uint_t low_byte); extern uint_t launch_svm(vmcb_t * vmcb_addr); - +extern uint_t Get_CR3(); /* Checks machine SVM capability */ /* Implemented from: AMD Arch Manual 3, sect 15.4 */ @@ -35,6 +35,11 @@ int is_svm_capable() { ret = cpuid_edx(CPUID_SVM_REV_AND_FEATURE_IDS); + + if ((ret & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 0) { + PrintDebug("Nested Paging not supported\n"); + } + if ((ret & CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml) == 0) { PrintDebug("SVM BIOS Disabled, not unlockable\n"); } else { @@ -81,8 +86,7 @@ void Init_SVM(struct vmm_ctrl_ops * vmm_ops) { int init_svm_guest(struct guest_info *info) { - pde_t * pde; - + PrintDebug("Allocating VMCB\n"); info->vmm_data = (void*)Allocate_VMCB(); @@ -90,9 +94,10 @@ int init_svm_guest(struct guest_info *info) { PrintDebug("Generating Guest nested page tables\n"); print_mem_list(&(info->mem_list)); print_mem_layout(&(info->mem_layout)); - pde = generate_guest_page_tables(&(info->mem_layout), &(info->mem_list)); - PrintDebugPageTables(pde); + info->page_tables = generate_guest_page_tables(&(info->mem_layout), &(info->mem_list)); + //PrintDebugPageTables(info->page_tables); + PrintDebug("Initializing VMCB (addr=%x)\n", info->vmm_data); Init_VMCB((vmcb_t*)(info->vmm_data), *info); @@ -185,16 +190,50 @@ void Init_VMCB(vmcb_t *vmcb, guest_info_t vm_info) { seg->base = 0; } + /* ** */ + guest_state->efer |= EFER_MSR_svm_enable; - guest_state->cr0 = 0x00000001; // PE guest_state->rflags = 0x00000002; // The reserved bit is always 1 ctrl_area->svm_instrs.instrs.VMRUN = 1; + guest_state->cr0 = 0x00000001; // PE ctrl_area->guest_ASID = 1; + // Setup exits + + + ctrl_area->exceptions.ex_names.de = 1; + ctrl_area->exceptions.ex_names.df = 1; + ctrl_area->exceptions.ex_names.pf = 1; + ctrl_area->exceptions.ex_names.ts = 1; + ctrl_area->exceptions.ex_names.ss = 1; + ctrl_area->exceptions.ex_names.ac = 1; + ctrl_area->exceptions.ex_names.mc = 1; + ctrl_area->exceptions.ex_names.gp = 1; + ctrl_area->exceptions.ex_names.ud = 1; + ctrl_area->exceptions.ex_names.np = 1; + ctrl_area->exceptions.ex_names.of = 1; + + // also determine if CPU supports nested paging + if (vm_info.page_tables) { + // Flush the TLB on entries/exits + ctrl_area->TLB_CONTROL = 1; + + // Enable Nested Paging + ctrl_area->NP_ENABLE = 1; + + // Set the Nested Page Table pointer + ctrl_area->N_CR3 |= ((addr_t)vm_info.page_tables & 0xfffff000); + + guest_state->cr3 = Get_CR3(); + + PrintDebug("Set Nested CR3: lo: 0x%x hi: 0x%x\n", (uint_t)*(&(ctrl_area->N_CR3)), (uint_t)*(&(ctrl_area->N_CR3) + 4)); + PrintDebug("Set Guest CR3: lo: 0x%x hi: 0x%x\n", (uint_t)*(&(guest_state->cr3)), (uint_t)*(&(guest_state->cr3) + 4)); + // Enable Paging + guest_state->cr0 |= 0x80000000; + } - /* ** */ } diff --git a/palacios/src/geekos/vmcs.c b/palacios/src/geekos/vmcs.c index fdb962f..68faebd 100644 --- a/palacios/src/geekos/vmcs.c +++ b/palacios/src/geekos/vmcs.c @@ -1,5 +1,5 @@ #include -#include + diff --git a/palacios/src/geekos/vmm_mem.c b/palacios/src/geekos/vmm_mem.c index b2721eb..1071b74 100644 --- a/palacios/src/geekos/vmm_mem.c +++ b/palacios/src/geekos/vmm_mem.c @@ -216,96 +216,71 @@ void free_mem_layout(vmm_mem_layout_t * layout) { } -/* this function returns a pointer to the location in the layout list that - * corresponds to addr. - * Rules: - * IF addr is in a region, a ptr to that region is returned - * IF addr is not in a region, a ptr to the previous region is returned - * IF addr is before all regions, returns NULL - * IF list is empty, returns NULL - */ -layout_region_t * get_layout_cursor(vmm_mem_layout_t * layout, addr_t addr) { - layout_region_t * prev_region = layout->head; - - - while (prev_region != NULL) { - if ( (addr >= prev_region->addr) && - (addr < (prev_region->addr + (prev_region->num_pages * PAGE_SIZE))) ) { - return prev_region; - } else if (addr < prev_region->addr) { - // If this region is the current head, then this should return NULL - return prev_region->prev; - } else if (addr >= (prev_region->addr + (prev_region->num_pages * PAGE_SIZE))) { - if (prev_region->next) { - prev_region = prev_region->next; - } else { - return prev_region; - } - } - } - - return prev_region; -} - /* This is slightly different semantically from the mem list, in that we don't allow overlaps * we could probably allow overlappig regions of the same type... but I'll let someone else deal with that */ int add_mem_range(vmm_mem_layout_t * layout, layout_region_t * region) { - - layout_region_t * cursor = get_layout_cursor(layout, region->addr); - - if (cursor == NULL) { - if (layout->head) { - if (layout->head->addr < region->addr + (region->num_pages * PAGE_SIZE) - 1) { - // overlaps not allowed - return -1; - } - layout->head->prev = region; - } + layout_region_t * cursor = layout->head; + if ((!cursor) || (cursor->start >= region->end)) { region->prev = NULL; - region->next = layout->head; - layout->head = region; - + region->next = cursor; + layout->num_pages += (region->end - region->start) / PAGE_SIZE; layout->num_regions++; - layout->num_pages += region->num_pages; - } else if ((region->addr >= cursor->addr) && - (region->addr <= cursor->addr + (cursor->num_pages * PAGE_SIZE) - 1)) { - // overlaps not allowed - return -1; - } else if (region->addr > cursor->addr + (cursor->num_pages * PAGE_SIZE) - 1) { - // add region to layout - region->next = cursor->next; - region->prev = cursor; - - if (region->next) { - region->next->prev = region; - } - cursor->next = region; + layout->head = region; - layout->num_regions++; - layout->num_pages += region->num_pages; - } else { - return -1; + return 0; } + while (cursor) { + // Check if it overlaps with the current cursor + if ((cursor->end > region->start) && (cursor->start < region->start)) { + // overlaps not allowed + return -1; + } + + // add to the end of the list + if (!(cursor->next)) { + cursor->next = region; + region->prev = cursor; + layout->num_regions++; + layout->num_pages += (region->end - region->start) / PAGE_SIZE; + return 0; + } else if (cursor->next->start >= region->end) { + // add here + region->next = cursor->next; + region->prev = cursor; + + cursor->next->prev = region; + cursor->next = region; + + layout->num_regions++; + layout->num_pages += (region->end - region->start) / PAGE_SIZE; + + return 0; + } else if (cursor->next->end < region->start) { + cursor = cursor->next; + } else { + return -1; + } + } - return 0; + return -1; } -int add_shared_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_pages, addr_t host_addr) { +int add_shared_mem_range(vmm_mem_layout_t * layout, addr_t start, addr_t end, addr_t host_addr) { layout_region_t * shared_region = os_hooks->malloc(sizeof(layout_region_t)); int ret; shared_region->next = NULL; shared_region->prev = NULL; - shared_region->addr = addr; - shared_region->num_pages = num_pages; + shared_region->start = start; + shared_region->end = end; shared_region->type = SHARED; shared_region->host_addr = host_addr; @@ -318,14 +293,14 @@ int add_shared_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_page return ret; } -int add_unmapped_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_pages) { +int add_unmapped_mem_range(vmm_mem_layout_t * layout, addr_t start, addr_t end) { layout_region_t * unmapped_region = os_hooks->malloc(sizeof(layout_region_t)); int ret; unmapped_region->next = NULL; unmapped_region->prev = NULL; - unmapped_region->addr = addr; - unmapped_region->num_pages = num_pages; + unmapped_region->start = start; + unmapped_region->end = end; unmapped_region->type = UNMAPPED; unmapped_region->host_addr = 0; @@ -338,22 +313,20 @@ int add_unmapped_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_pa return ret; } -int add_guest_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_pages) { +int add_guest_mem_range(vmm_mem_layout_t * layout, addr_t start, addr_t end) { layout_region_t * guest_region = os_hooks->malloc(sizeof(layout_region_t)); int ret; guest_region->next = NULL; guest_region->prev = NULL; - guest_region->addr = addr; - guest_region->num_pages = num_pages; + guest_region->start = start; + guest_region->end = end; guest_region->type = GUEST; guest_region->host_addr = 0; ret = add_mem_range(layout, guest_region); - if (ret == 0) { - layout->num_guest_pages += num_pages; - } else { + if (ret != 0) { VMMFree(guest_region); } @@ -379,17 +352,36 @@ addr_t get_mem_layout_addr(vmm_mem_layout_t * layout, uint_t index) { return -1; } - if (reg->num_pages <= index) { - i -= reg->num_pages; + int num_reg_pages = reg->end - reg->start; + + if (num_reg_pages <= index) { + i -= num_reg_pages; reg = reg->next; } else { - return reg->addr + (i * PAGE_SIZE); + return reg->start + (i * PAGE_SIZE); } } return -1; } +layout_region_t * get_mem_layout_region(vmm_mem_layout_t * layout, addr_t addr) { + layout_region_t * tmp_reg = layout->head; + + + while (tmp_reg) { + if ((tmp_reg->start <= addr) && (tmp_reg->end > addr)) { + return tmp_reg; + } else if (tmp_reg->start > addr) { + return NULL; + } else { + tmp_reg = tmp_reg->next; + } + } + + return NULL; +} + @@ -416,7 +408,7 @@ void print_mem_layout(vmm_mem_layout_t * layout) { PrintDebug("Memory Layout (regions: %d) (pages: %d)\n", layout->num_regions, layout->num_pages); while (cur) { - PrintDebug("%d: 0x%x - 0x%x\n", i, cur->addr, cur->addr + (cur->num_pages * PAGE_SIZE) - 1); + PrintDebug("%d: 0x%x - 0x%x\n", i, cur->start, cur->end -1); cur = cur->next; i++; } @@ -433,7 +425,6 @@ void print_mem_layout(vmm_mem_layout_t * layout) { - #ifdef VMM_MEM_TEST @@ -441,7 +432,7 @@ void print_mem_layout(vmm_mem_layout_t * layout) { #include #include -#include + @@ -513,39 +504,44 @@ int mem_list_add_test_1( vmm_mem_list_t * list) { int mem_layout_add_test_1(vmm_mem_layout_t *layout) { - uint_t offset = 0; + + uint_t start = 0; + uint_t end = 0; PrintDebug("\n\nTesting Memory Layout\n"); init_mem_layout(layout); - offset = PAGE_SIZE * 6; - PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 10)); - add_guest_mem_range(layout, offset, 10); + start = 0x6000; + end = 0x10000;; + PrintDebug("Adding 0x%x - 0x%x\n", start, end); + add_guest_mem_range(layout, start, end); print_mem_layout(layout); - offset = PAGE_SIZE * 20; - PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 1)); - add_guest_mem_range(layout, offset, 1); + start = 0x1000; + end = 0x3000; + PrintDebug("Adding 0x%x - 0x%x\n", start, end); + add_guest_mem_range(layout, start, end); print_mem_layout(layout); - - offset = PAGE_SIZE * 16; - PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + PAGE_SIZE * 4); - add_guest_mem_range(layout, offset, 4); + start = 0x2000; + end = 0x6000; + PrintDebug("Adding 0x%x - 0x%x\n", start, end); + add_guest_mem_range(layout, start, end); print_mem_layout(layout); - - offset = PAGE_SIZE * 10; - PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 30)); - add_guest_mem_range(layout, offset, 30); + start = 0x4000; + end = 0x5000; + PrintDebug("Adding 0x%x - 0x%x\n", start, end); + add_guest_mem_range(layout, start, end); print_mem_layout(layout); - offset = 0; - PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 1)); - add_guest_mem_range(layout, offset, 1); + start = 0x5000; + end = 0x7000; + PrintDebug("Adding 0x%x - 0x%x\n", start, end); + add_guest_mem_range(layout, start, end); print_mem_layout(layout); @@ -573,10 +569,6 @@ int main(int argc, char ** argv) { printf("mem_list_add_test_1: %d\n", mem_list_add_test_1(&list)); printf("layout_add_test_1: %d\n", mem_layout_add_test_1(&layout)); - - pde_t * pde = generate_guest_page_tables(&layout, &list); - PrintDebugPageTables(pde); - return 0; } #endif diff --git a/palacios/src/geekos/vmm_paging.c b/palacios/src/geekos/vmm_paging.c index 81719a4..879d68a 100644 --- a/palacios/src/geekos/vmm_paging.c +++ b/palacios/src/geekos/vmm_paging.c @@ -1,6 +1,6 @@ #include - +#include @@ -13,7 +13,7 @@ extern struct vmm_os_hooks * os_hooks; * pulling pages from the mem_list when necessary * If there are any gaps in the layout, we add them as unmapped pages */ -pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * list) { +vmm_pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * list) { ullong_t current_page_addr = 0; uint_t layout_index = 0; uint_t list_index = 0; @@ -24,7 +24,7 @@ pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * l - pde_t * pde = os_hooks->allocate_pages(1); + vmm_pde_t * pde = os_hooks->allocate_pages(1); for (i = 0; i < MAX_PAGE_DIR_ENTRIES; i++) { if (num_entries == 0) { @@ -37,7 +37,7 @@ pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * l pde[i].vmm_info = 0; pde[i].pt_base_addr = 0; } else { - pte_t * pte = os_hooks->allocate_pages(1); + vmm_pte_t * pte = os_hooks->allocate_pages(1); pde[i].present = 1; pde[i].flags = VM_READ | VM_WRITE | VM_EXEC | VM_USER; @@ -67,7 +67,7 @@ pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * l current_page_addr += PAGE_SIZE; } else if (current_page_addr == layout_addr) { // Set up the Table entry to map correctly to the layout region - layout_region_t * page_region = get_layout_cursor(layout, layout_addr); + layout_region_t * page_region = get_mem_layout_region(layout, layout_addr); if (page_region->type == UNMAPPED) { pte[j].present = 0; @@ -86,17 +86,25 @@ pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * l if (page_region->type == UNMAPPED) { pte[j].page_base_addr = 0; } else if (page_region->type == SHARED) { - pte[j].page_base_addr = page_region->host_addr >> 12; + addr_t host_addr = page_region->host_addr + (layout_addr - page_region->start); + + pte[j].page_base_addr = host_addr >> 12; + pte[j].vmm_info = SHARED_PAGE; } else if (page_region->type == GUEST) { addr_t list_addr = get_mem_list_addr(list, list_index++); if (list_addr == -1) { // error - // cleanup.... + // cleanup... + free_guest_page_tables(pde); return NULL; } PrintDebug("Adding guest page (%x)\n", list_addr); pte[j].page_base_addr = list_addr >> 12; + + // Reset this when we move over to dynamic page allocation + // pte[j].vmm_info = GUEST_PAGE; + pte[j].vmm_info = SHARED_PAGE; } num_entries--; @@ -106,6 +114,7 @@ pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * l // error PrintDebug("Error creating page table...\n"); // cleanup + free_guest_page_tables(pde); return NULL; } } @@ -116,9 +125,31 @@ pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * l } +void free_guest_page_tables(vmm_pde_t * pde) { + int i, j; + + + for (i = 0; (i < MAX_PAGE_DIR_ENTRIES); i++) { + if (pde[i].present) { + vmm_pte_t * pte = (vmm_pte_t *)(pde[i].pt_base_addr << PAGE_POWER); + + for (j = 0; (j < MAX_PAGE_TABLE_ENTRIES); j++) { + if ((pte[j].present) && (pte[j].vmm_info & GUEST_PAGE)){ + os_hooks->free_page((void *)(pte[j].page_base_addr << PAGE_POWER)); + } + } + + os_hooks->free_page(pte); + } + } + + os_hooks->free_page(pde); +} + + -void PrintPDE(void * virtual_address, pde_t * pde) +void PrintPDE(void * virtual_address, vmm_pde_t * pde) { PrintDebug("PDE %p -> %p : present=%x, flags=%x, accessed=%x, reserved=%x, largePages=%x, globalPage=%x, kernelInfo=%x\n", virtual_address, @@ -132,7 +163,7 @@ void PrintPDE(void * virtual_address, pde_t * pde) pde->vmm_info); } -void PrintPTE(void * virtual_address, pte_t * pte) +void PrintPTE(void * virtual_address, vmm_pte_t * pte) { PrintDebug("PTE %p -> %p : present=%x, flags=%x, accessed=%x, dirty=%x, pteAttribute=%x, globalPage=%x, vmm_info=%x\n", virtual_address, @@ -148,7 +179,7 @@ void PrintPTE(void * virtual_address, pte_t * pte) -void PrintPD(pde_t * pde) +void PrintPD(vmm_pde_t * pde) { int i; @@ -158,11 +189,11 @@ void PrintPD(pde_t * pde) } } -void PrintPT(void * starting_address, pte_t * pte) +void PrintPT(void * starting_address, vmm_pte_t * pte) { int i; - // PrintDebug("Page Table at %p:\n", pte); + PrintDebug("Page Table at %p:\n", pte); for (i = 0; (i < MAX_PAGE_TABLE_ENTRIES) && pte[i].present; i++) { PrintPTE(starting_address + (PAGE_SIZE * i), &(pte[i])); } @@ -172,7 +203,7 @@ void PrintPT(void * starting_address, pte_t * pte) -void PrintDebugPageTables(pde_t * pde) +void PrintDebugPageTables(vmm_pde_t * pde) { int i; diff --git a/palacios/src/geekos/vmm_util.c b/palacios/src/geekos/vmm_util.c index 4aa4d34..3164e69 100644 --- a/palacios/src/geekos/vmm_util.c +++ b/palacios/src/geekos/vmm_util.c @@ -1,5 +1,6 @@ #include +#include extern struct vmm_os_hooks * os_hooks; diff --git a/palacios/src/geekos/vmx.c b/palacios/src/geekos/vmx.c index 8aa8b2f..2278da9 100644 --- a/palacios/src/geekos/vmx.c +++ b/palacios/src/geekos/vmx.c @@ -1,8 +1,5 @@ /* Eventually we want to get rid of these */ -#include -#include -#include -#include + #include #include /* ** */ @@ -30,6 +27,8 @@ extern int Launch_VM(ullong_t vmcsPtr, uint_t eip); #define ROMBIOS_DEBUG_PORT 0x403 +extern struct vmm_os_hooks * os_hooks; + static struct VM theVM; @@ -884,7 +883,7 @@ int VMLaunch(struct VMDescriptor *vm) VmxOnRegion * CreateVmxOnRegion() { union VMX_MSR basicMSR; - VmxOnRegion * region = (VmxOnRegion *)Alloc_Page(); + VmxOnRegion * region = (VmxOnRegion *)(os_hooks)->allocate_pages(1); Get_MSR(IA32_VMX_BASIC_MSR, &basicMSR.regs.high, &basicMSR.regs.low); // memcpy(region, &basicMSR.vmxBasic.revision, sizeof(uint_t)); @@ -898,7 +897,7 @@ VmxOnRegion * CreateVmxOnRegion() { VMCS * CreateVMCS() { union VMX_MSR basicMSR; - VMCS * vmcs = (VMCS *)Alloc_Page(); + VMCS * vmcs = (VMCS *)(os_hooks)->allocate_pages(1); Get_MSR(IA32_VMX_BASIC_MSR, &basicMSR.regs.high, &basicMSR.regs.low); *(ulong_t *)vmcs = basicMSR.vmxBasic.revision;