From owner-svn-src-projects@FreeBSD.ORG Wed Oct 3 00:46:30 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id E13A41065670; Wed, 3 Oct 2012 00:46:30 +0000 (UTC) (envelope-from neel@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id C1D288FC12; Wed, 3 Oct 2012 00:46:30 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q930kUtB030729; Wed, 3 Oct 2012 00:46:30 GMT (envelope-from neel@svn.freebsd.org) Received: (from neel@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q930kUNj030722; Wed, 3 Oct 2012 00:46:30 GMT (envelope-from neel@svn.freebsd.org) Message-Id: <201210030046.q930kUNj030722@svn.freebsd.org> From: Neel Natu Date: Wed, 3 Oct 2012 00:46:30 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r241147 - in projects/bhyve/sys/amd64: include vmm vmm/amd vmm/intel X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 03 Oct 2012 00:46:31 -0000 Author: neel Date: Wed Oct 3 00:46:30 2012 New Revision: 241147 URL: http://svn.freebsd.org/changeset/base/241147 Log: Get rid of assumptions in the hypervisor that the host physical memory associated with guest physical memory is contiguous. Rewrite vm_gpa2hpa() to get the GPA to HPA mapping by querying the nested page tables. Modified: projects/bhyve/sys/amd64/include/vmm.h projects/bhyve/sys/amd64/vmm/amd/amdv.c projects/bhyve/sys/amd64/vmm/intel/ept.c projects/bhyve/sys/amd64/vmm/intel/ept.h projects/bhyve/sys/amd64/vmm/intel/vmx.c projects/bhyve/sys/amd64/vmm/vmm.c Modified: projects/bhyve/sys/amd64/include/vmm.h ============================================================================== --- projects/bhyve/sys/amd64/include/vmm.h Wed Oct 3 00:41:46 2012 (r241146) +++ projects/bhyve/sys/amd64/include/vmm.h Wed Oct 3 00:46:30 2012 (r241147) @@ -47,9 +47,11 @@ typedef int (*vmm_cleanup_func_t)(void); typedef void * (*vmi_init_func_t)(struct vm *vm); /* instance specific apis */ typedef int (*vmi_run_func_t)(void *vmi, int vcpu, register_t rip); typedef void (*vmi_cleanup_func_t)(void *vmi); -typedef int (*vmi_mmap_func_t)(void *vmi, vm_paddr_t gpa, vm_paddr_t hpa, - size_t length, vm_memattr_t attr, - int prot, boolean_t superpages_ok); +typedef int (*vmi_mmap_set_func_t)(void *vmi, vm_paddr_t gpa, + vm_paddr_t hpa, size_t length, + vm_memattr_t attr, int prot, + boolean_t superpages_ok); +typedef vm_paddr_t (*vmi_mmap_get_func_t)(void *vmi, vm_paddr_t gpa); typedef int (*vmi_get_register_t)(void *vmi, int vcpu, int num, uint64_t *retval); typedef int (*vmi_set_register_t)(void *vmi, int vcpu, int num, @@ -72,7 +74,8 @@ struct vmm_ops { vmi_init_func_t vminit; /* vm-specific initialization */ vmi_run_func_t vmrun; vmi_cleanup_func_t vmcleanup; - vmi_mmap_func_t vmmmap; + vmi_mmap_set_func_t vmmmap_set; + vmi_mmap_get_func_t vmmmap_get; vmi_get_register_t vmgetreg; vmi_set_register_t vmsetreg; vmi_get_desc_t vmgetdesc; Modified: projects/bhyve/sys/amd64/vmm/amd/amdv.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/amd/amdv.c Wed Oct 3 00:41:46 2012 (r241146) +++ projects/bhyve/sys/amd64/vmm/amd/amdv.c Wed Oct 3 00:46:30 2012 (r241147) @@ -78,11 +78,19 @@ amdv_vmcleanup(void *arg) } static int -amdv_vmmmap(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, size_t length, +amdv_vmmmap_set(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, size_t length, vm_memattr_t attr, int prot, boolean_t spok) { - printf("amdv_vmmmap: not implemented\n"); + printf("amdv_vmmmap_set: not implemented\n"); + return (EINVAL); +} + +static vm_paddr_t +amdv_vmmmap_get(void *arg, vm_paddr_t gpa) +{ + + printf("amdv_vmmmap_get: not implemented\n"); return (EINVAL); } @@ -157,7 +165,8 @@ struct vmm_ops vmm_ops_amd = { amdv_vminit, amdv_vmrun, amdv_vmcleanup, - amdv_vmmmap, + amdv_vmmmap_set, + amdv_vmmmap_get, amdv_getreg, amdv_setreg, amdv_getdesc, Modified: projects/bhyve/sys/amd64/vmm/intel/ept.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/intel/ept.c Wed Oct 3 00:41:46 2012 (r241146) +++ projects/bhyve/sys/amd64/vmm/intel/ept.c Wed Oct 3 00:46:30 2012 (r241147) @@ -115,6 +115,40 @@ ept_init(void) return (0); } +#if 0 +static void +ept_dump(uint64_t *ptp, int nlevels) +{ + int i, t, tabs; + uint64_t *ptpnext, ptpval; + + if (--nlevels < 0) + return; + + tabs = 3 - nlevels; + for (t = 0; t < tabs; t++) + printf("\t"); + printf("PTP = %p\n", ptp); + + for (i = 0; i < 512; i++) { + ptpval = ptp[i]; + + if (ptpval == 0) + continue; + + for (t = 0; t < tabs; t++) + printf("\t"); + printf("%3d 0x%016lx\n", i, ptpval); + + if (nlevels != 0 && (ptpval & EPT_PG_SUPERPAGE) == 0) { + ptpnext = (uint64_t *) + PHYS_TO_DMAP(ptpval & EPT_ADDR_MASK); + ept_dump(ptpnext, nlevels); + } + } +} +#endif + static size_t ept_create_mapping(uint64_t *ptp, vm_paddr_t gpa, vm_paddr_t hpa, size_t length, vm_memattr_t attr, vm_prot_t prot, boolean_t spok) @@ -179,29 +213,64 @@ ept_create_mapping(uint64_t *ptp, vm_pad "mismatch\n", gpa, ptpshift); } - /* Do the mapping */ - ptp[ptpindex] = hpa; + if (prot != VM_PROT_NONE) { + /* Do the mapping */ + ptp[ptpindex] = hpa; + + /* Apply the access controls */ + if (prot & VM_PROT_READ) + ptp[ptpindex] |= EPT_PG_RD; + if (prot & VM_PROT_WRITE) + ptp[ptpindex] |= EPT_PG_WR; + if (prot & VM_PROT_EXECUTE) + ptp[ptpindex] |= EPT_PG_EX; - /* Apply the access controls */ - if (prot & VM_PROT_READ) - ptp[ptpindex] |= EPT_PG_RD; - if (prot & VM_PROT_WRITE) - ptp[ptpindex] |= EPT_PG_WR; - if (prot & VM_PROT_EXECUTE) - ptp[ptpindex] |= EPT_PG_EX; - - /* - * XXX should we enforce this memory type by setting the ignore PAT - * bit to 1. - */ - ptp[ptpindex] |= EPT_PG_MEMORY_TYPE(attr); + /* + * XXX should we enforce this memory type by setting the + * ignore PAT bit to 1. + */ + ptp[ptpindex] |= EPT_PG_MEMORY_TYPE(attr); - if (nlevels > 0) - ptp[ptpindex] |= EPT_PG_SUPERPAGE; + if (nlevels > 0) + ptp[ptpindex] |= EPT_PG_SUPERPAGE; + } else { + /* Remove the mapping */ + ptp[ptpindex] = 0; + } return (1UL << ptpshift); } +static vm_paddr_t +ept_lookup_mapping(uint64_t *ptp, vm_paddr_t gpa) +{ + int nlevels, ptpshift, ptpindex; + uint64_t ptpval, hpabase, pgmask; + + nlevels = EPT_PWLEVELS; + while (--nlevels >= 0) { + ptpshift = PAGE_SHIFT + nlevels * 9; + ptpindex = (gpa >> ptpshift) & 0x1FF; + + ptpval = ptp[ptpindex]; + + /* Cannot make progress beyond this point */ + if ((ptpval & (EPT_PG_RD | EPT_PG_WR | EPT_PG_EX)) == 0) + break; + + if (nlevels == 0 || (ptpval & EPT_PG_SUPERPAGE)) { + pgmask = (1UL << ptpshift) - 1; + hpabase = ptpval & ~pgmask; + return (hpabase | (gpa & pgmask)); + } + + /* Work our way down to the next level page table page */ + ptp = (uint64_t *)PHYS_TO_DMAP(ptpval & EPT_ADDR_MASK); + } + + return ((vm_paddr_t)-1); +} + static void ept_free_pt_entry(pt_entry_t pte) { @@ -276,8 +345,8 @@ ept_vmcleanup(struct vmx *vmx) } int -ept_vmmmap(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, size_t len, - vm_memattr_t attr, int prot, boolean_t spok) +ept_vmmmap_set(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, size_t len, + vm_memattr_t attr, int prot, boolean_t spok) { size_t n; struct vmx *vmx = arg; @@ -293,6 +362,17 @@ ept_vmmmap(void *arg, vm_paddr_t gpa, vm return (0); } +vm_paddr_t +ept_vmmmap_get(void *arg, vm_paddr_t gpa) +{ + vm_paddr_t hpa; + struct vmx *vmx; + + vmx = arg; + hpa = ept_lookup_mapping(vmx->pml4ept, gpa); + return (hpa); +} + static void invept_single_context(void *arg) { Modified: projects/bhyve/sys/amd64/vmm/intel/ept.h ============================================================================== --- projects/bhyve/sys/amd64/vmm/intel/ept.h Wed Oct 3 00:41:46 2012 (r241146) +++ projects/bhyve/sys/amd64/vmm/intel/ept.h Wed Oct 3 00:46:30 2012 (r241147) @@ -35,8 +35,9 @@ struct vmx; #define EPTP(pml4) ((pml4) | (EPT_PWLEVELS - 1) << 3 | PAT_WRITE_BACK) int ept_init(void); -int ept_vmmmap(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, size_t length, +int ept_vmmmap_set(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, size_t length, vm_memattr_t attr, int prot, boolean_t allow_superpage_mappings); +vm_paddr_t ept_vmmmap_get(void *arg, vm_paddr_t gpa); void ept_invalidate_mappings(u_long ept_pml4); void ept_vmcleanup(struct vmx *vmx); #endif Modified: projects/bhyve/sys/amd64/vmm/intel/vmx.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/intel/vmx.c Wed Oct 3 00:41:46 2012 (r241146) +++ projects/bhyve/sys/amd64/vmm/intel/vmx.c Wed Oct 3 00:46:30 2012 (r241147) @@ -1813,7 +1813,8 @@ struct vmm_ops vmm_ops_intel = { vmx_vminit, vmx_run, vmx_vmcleanup, - ept_vmmmap, + ept_vmmmap_set, + ept_vmmmap_get, vmx_getreg, vmx_setreg, vmx_getdesc, Modified: projects/bhyve/sys/amd64/vmm/vmm.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/vmm.c Wed Oct 3 00:41:46 2012 (r241146) +++ projects/bhyve/sys/amd64/vmm/vmm.c Wed Oct 3 00:46:30 2012 (r241147) @@ -115,8 +115,12 @@ static struct vmm_ops *ops; #define VMRUN(vmi, vcpu, rip) \ (ops != NULL ? (*ops->vmrun)(vmi, vcpu, rip) : ENXIO) #define VMCLEANUP(vmi) (ops != NULL ? (*ops->vmcleanup)(vmi) : NULL) -#define VMMMAP(vmi, gpa, hpa, len, attr, prot, spm) \ - (ops != NULL ? (*ops->vmmmap)(vmi, gpa, hpa, len, attr, prot, spm) : ENXIO) +#define VMMMAP_SET(vmi, gpa, hpa, len, attr, prot, spm) \ + (ops != NULL ? \ + (*ops->vmmmap_set)(vmi, gpa, hpa, len, attr, prot, spm) : \ + ENXIO) +#define VMMMAP_GET(vmi, gpa) \ + (ops != NULL ? (*ops->vmmmap_get)(vmi, gpa) : ENXIO) #define VMGETREG(vmi, vcpu, num, retval) \ (ops != NULL ? (*ops->vmgetreg)(vmi, vcpu, num, retval) : ENXIO) #define VMSETREG(vmi, vcpu, num, val) \ @@ -302,8 +306,8 @@ vm_map_mmio(struct vm *vm, vm_paddr_t gp { const boolean_t spok = TRUE; /* superpage mappings are ok */ - return (VMMMAP(vm->cookie, gpa, hpa, len, VM_MEMATTR_UNCACHEABLE, - VM_PROT_RW, spok)); + return (VMMMAP_SET(vm->cookie, gpa, hpa, len, VM_MEMATTR_UNCACHEABLE, + VM_PROT_RW, spok)); } int @@ -311,8 +315,8 @@ vm_unmap_mmio(struct vm *vm, vm_paddr_t { const boolean_t spok = TRUE; /* superpage mappings are ok */ - return (VMMMAP(vm->cookie, gpa, 0, len, VM_MEMATTR_UNCACHEABLE, - VM_PROT_NONE, spok)); + return (VMMMAP_SET(vm->cookie, gpa, 0, len, 0, + VM_PROT_NONE, spok)); } /* @@ -380,8 +384,8 @@ vm_malloc(struct vm *vm, vm_paddr_t gpa, if (hpa == 0) return (ENOMEM); - error = VMMMAP(vm->cookie, gpa, hpa, len, VM_MEMATTR_WRITE_BACK, - VM_PROT_ALL, spok); + error = VMMMAP_SET(vm->cookie, gpa, hpa, len, VM_MEMATTR_WRITE_BACK, + VM_PROT_ALL, spok); if (error) { vmm_mem_free(hpa, len); return (error); @@ -400,17 +404,8 @@ vm_malloc(struct vm *vm, vm_paddr_t gpa, vm_paddr_t vm_gpa2hpa(struct vm *vm, vm_paddr_t gpa, size_t len) { - int i; - vm_paddr_t gpabase, gpalimit, hpabase; - for (i = 0; i < vm->num_mem_segs; i++) { - hpabase = vm->mem_segs[i].hpa; - gpabase = vm->mem_segs[i].gpa; - gpalimit = gpabase + vm->mem_segs[i].len; - if (gpa >= gpabase && gpa + len <= gpalimit) - return ((gpa - gpabase) + hpabase); - } - return ((vm_paddr_t)-1); + return (VMMMAP_GET(vm->cookie, gpa)); } int