Date: Mon, 19 May 2014 03:50:07 +0000 (UTC) From: Neel Natu <neel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r266424 - in head/sys/amd64: include vmm vmm/intel Message-ID: <201405190350.s4J3o7VL064868@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: neel Date: Mon May 19 03:50:07 2014 New Revision: 266424 URL: http://svnweb.freebsd.org/changeset/base/266424 Log: Add PG_U (user/supervisor) checks when translating a guest linear address to a guest physical address. PG_PS (page size) field is valid only in a PDE or a PDPTE so it is now checked only in non-terminal paging entries. Ignore the upper 32-bits of the CR3 for PAE paging. Modified: head/sys/amd64/include/vmm.h head/sys/amd64/include/vmm_instruction_emul.h head/sys/amd64/vmm/intel/vmx.c head/sys/amd64/vmm/vmm.c head/sys/amd64/vmm/vmm_instruction_emul.c Modified: head/sys/amd64/include/vmm.h ============================================================================== --- head/sys/amd64/include/vmm.h Mon May 19 01:21:02 2014 (r266423) +++ head/sys/amd64/include/vmm.h Mon May 19 03:50:07 2014 (r266424) @@ -361,6 +361,7 @@ struct vm_exit { uint64_t cr3; enum vie_cpu_mode cpu_mode; enum vie_paging_mode paging_mode; + int cpl; struct vie vie; } inst_emul; /* Modified: head/sys/amd64/include/vmm_instruction_emul.h ============================================================================== --- head/sys/amd64/include/vmm_instruction_emul.h Mon May 19 01:21:02 2014 (r266423) +++ head/sys/amd64/include/vmm_instruction_emul.h Mon May 19 03:50:07 2014 (r266424) @@ -119,7 +119,8 @@ int vmm_emulate_instruction(void *vm, in */ int vmm_fetch_instruction(struct vm *vm, int cpuid, uint64_t rip, int inst_length, uint64_t cr3, - enum vie_paging_mode paging_mode, struct vie *vie); + enum vie_paging_mode paging_mode, int cpl, + struct vie *vie); void vie_init(struct vie *vie); Modified: head/sys/amd64/vmm/intel/vmx.c ============================================================================== --- head/sys/amd64/vmm/intel/vmx.c Mon May 19 01:21:02 2014 (r266423) +++ head/sys/amd64/vmm/intel/vmx.c Mon May 19 03:50:07 2014 (r266424) @@ -1492,6 +1492,18 @@ vmx_emulate_cr_access(struct vmx *vmx, i return (HANDLED); } +/* + * From section "Guest Register State" in the Intel SDM: CPL = SS.DPL + */ +static int +vmx_cpl(void) +{ + uint32_t ssar; + + ssar = vmcs_read(VMCS_GUEST_SS_ACCESS_RIGHTS); + return ((ssar >> 5) & 0x3); +} + static enum vie_cpu_mode vmx_cpu_mode(void) { @@ -1516,6 +1528,18 @@ vmx_paging_mode(void) return (PAGING_MODE_PAE); } +static void +vmexit_inst_emul(struct vm_exit *vmexit, uint64_t gpa, uint64_t gla) +{ + vmexit->exitcode = VM_EXITCODE_INST_EMUL; + vmexit->u.inst_emul.gpa = gpa; + vmexit->u.inst_emul.gla = gla; + vmexit->u.inst_emul.cr3 = vmcs_guest_cr3(); + vmexit->u.inst_emul.cpu_mode = vmx_cpu_mode(); + vmexit->u.inst_emul.paging_mode = vmx_paging_mode(); + vmexit->u.inst_emul.cpl = vmx_cpl(); +} + static int ept_fault_type(uint64_t ept_qual) { @@ -1707,12 +1731,8 @@ vmx_handle_apic_access(struct vmx *vmx, } if (allowed) { - vmexit->exitcode = VM_EXITCODE_INST_EMUL; - vmexit->u.inst_emul.gpa = DEFAULT_APIC_BASE + offset; - vmexit->u.inst_emul.gla = VIE_INVALID_GLA; - vmexit->u.inst_emul.cr3 = vmcs_guest_cr3(); - vmexit->u.inst_emul.cpu_mode = vmx_cpu_mode(); - vmexit->u.inst_emul.paging_mode = vmx_paging_mode(); + vmexit_inst_emul(vmexit, DEFAULT_APIC_BASE + offset, + VIE_INVALID_GLA); } /* @@ -1943,12 +1963,7 @@ vmx_exit_process(struct vmx *vmx, int vc vmexit->u.paging.fault_type = ept_fault_type(qual); vmm_stat_incr(vmx->vm, vcpu, VMEXIT_NESTED_FAULT, 1); } else if (ept_emulation_fault(qual)) { - vmexit->exitcode = VM_EXITCODE_INST_EMUL; - vmexit->u.inst_emul.gpa = gpa; - vmexit->u.inst_emul.gla = vmcs_gla(); - vmexit->u.inst_emul.cr3 = vmcs_guest_cr3(); - vmexit->u.inst_emul.cpu_mode = vmx_cpu_mode(); - vmexit->u.inst_emul.paging_mode = vmx_paging_mode(); + vmexit_inst_emul(vmexit, gpa, vmcs_gla()); vmm_stat_incr(vmx->vm, vcpu, VMEXIT_INST_EMUL, 1); } /* Modified: head/sys/amd64/vmm/vmm.c ============================================================================== --- head/sys/amd64/vmm/vmm.c Mon May 19 01:21:02 2014 (r266423) +++ head/sys/amd64/vmm/vmm.c Mon May 19 03:50:07 2014 (r266424) @@ -1131,7 +1131,7 @@ vm_handle_inst_emul(struct vm *vm, int v struct vie *vie; struct vcpu *vcpu; struct vm_exit *vme; - int error, inst_length; + int cpl, error, inst_length; uint64_t rip, gla, gpa, cr3; enum vie_cpu_mode cpu_mode; enum vie_paging_mode paging_mode; @@ -1147,6 +1147,7 @@ vm_handle_inst_emul(struct vm *vm, int v gla = vme->u.inst_emul.gla; gpa = vme->u.inst_emul.gpa; cr3 = vme->u.inst_emul.cr3; + cpl = vme->u.inst_emul.cpl; cpu_mode = vme->u.inst_emul.cpu_mode; paging_mode = vme->u.inst_emul.paging_mode; vie = &vme->u.inst_emul.vie; @@ -1155,7 +1156,7 @@ vm_handle_inst_emul(struct vm *vm, int v /* Fetch, decode and emulate the faulting instruction */ if (vmm_fetch_instruction(vm, vcpuid, rip, inst_length, cr3, - paging_mode, vie) != 0) + paging_mode, cpl, vie) != 0) return (EFAULT); if (vmm_decode_instruction(vm, vcpuid, gla, cpu_mode, vie) != 0) Modified: head/sys/amd64/vmm/vmm_instruction_emul.c ============================================================================== --- head/sys/amd64/vmm/vmm_instruction_emul.c Mon May 19 01:21:02 2014 (r266423) +++ head/sys/amd64/vmm/vmm_instruction_emul.c Mon May 19 03:50:07 2014 (r266424) @@ -572,14 +572,16 @@ vie_init(struct vie *vie) } static int -gla2gpa(struct vm *vm, uint64_t gla, uint64_t ptpphys, - uint64_t *gpa, enum vie_paging_mode paging_mode) +gla2gpa(struct vm *vm, uint64_t gla, uint64_t ptpphys, uint64_t *gpa, + enum vie_paging_mode paging_mode, int cpl) { - int nlevels, ptpshift, ptpindex; + int nlevels, ptpshift, ptpindex, usermode; uint64_t *ptpbase, pte, pgsize; uint32_t *ptpbase32, pte32; void *cookie; + usermode = (cpl == 3 ? 1 : 0); + if (paging_mode == PAGING_MODE_FLAT) { *gpa = gla; return (0); @@ -593,7 +595,7 @@ gla2gpa(struct vm *vm, uint64_t gla, uin ptpbase32 = vm_gpa_hold(vm, ptpphys, PAGE_SIZE, VM_PROT_READ, &cookie); - + if (ptpbase32 == NULL) goto error; @@ -608,7 +610,11 @@ gla2gpa(struct vm *vm, uint64_t gla, uin if ((pte32 & PG_V) == 0) goto error; - if (pte32 & PG_PS) + if (usermode && (pte32 & PG_U) == 0) + goto error; + + /* XXX must be ignored if CR4.PSE=0 */ + if (nlevels > 0 && (pte32 & PG_PS) != 0) break; ptpphys = pte32; @@ -621,8 +627,8 @@ gla2gpa(struct vm *vm, uint64_t gla, uin } if (paging_mode == PAGING_MODE_PAE) { - /* Zero out the lower 5 bits and the upper 12 bits */ - ptpphys >>= 5; ptpphys <<= 17; ptpphys >>= 12; + /* Zero out the lower 5 bits and the upper 32 bits */ + ptpphys &= 0xffffffe0UL; ptpbase = vm_gpa_hold(vm, ptpphys, sizeof(*ptpbase) * 4, VM_PROT_READ, &cookie); @@ -663,7 +669,10 @@ gla2gpa(struct vm *vm, uint64_t gla, uin if ((pte & PG_V) == 0) goto error; - if (pte & PG_PS) { + if (usermode && (pte & PG_U) == 0) + goto error; + + if (nlevels > 0 && (pte & PG_PS) != 0) { if (pgsize > 1 * GB) goto error; else @@ -684,7 +693,7 @@ error: int vmm_fetch_instruction(struct vm *vm, int cpuid, uint64_t rip, int inst_length, - uint64_t cr3, enum vie_paging_mode paging_mode, + uint64_t cr3, enum vie_paging_mode paging_mode, int cpl, struct vie *vie) { int n, err, prot; @@ -701,7 +710,7 @@ vmm_fetch_instruction(struct vm *vm, int /* Copy the instruction into 'vie' */ while (vie->num_valid < inst_length) { - err = gla2gpa(vm, rip, cr3, &gpa, paging_mode); + err = gla2gpa(vm, rip, cr3, &gpa, paging_mode, cpl); if (err) break;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201405190350.s4J3o7VL064868>