vmx.c (268935) | vmx.c (268953) |
---|---|
1/*- 2 * Copyright (c) 2011 NetApp, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * | 1/*- 2 * Copyright (c) 2011 NetApp, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * |
26 * $FreeBSD: stable/10/sys/amd64/vmm/intel/vmx.c 268935 2014-07-21 02:39:17Z jhb $ | 26 * $FreeBSD: stable/10/sys/amd64/vmm/intel/vmx.c 268953 2014-07-21 19:08:02Z jhb $ |
27 */ 28 29#include <sys/cdefs.h> | 27 */ 28 29#include <sys/cdefs.h> |
30__FBSDID("$FreeBSD: stable/10/sys/amd64/vmm/intel/vmx.c 268935 2014-07-21 02:39:17Z jhb $"); | 30__FBSDID("$FreeBSD: stable/10/sys/amd64/vmm/intel/vmx.c 268953 2014-07-21 19:08:02Z jhb $"); |
31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/smp.h> 35#include <sys/kernel.h> 36#include <sys/malloc.h> 37#include <sys/pcpu.h> 38#include <sys/proc.h> --- 465 unchanged lines hidden (view full) --- 504 505 return (0); 506} 507 508static void 509vmx_enable(void *arg __unused) 510{ 511 int error; | 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/smp.h> 35#include <sys/kernel.h> 36#include <sys/malloc.h> 37#include <sys/pcpu.h> 38#include <sys/proc.h> --- 465 unchanged lines hidden (view full) --- 504 505 return (0); 506} 507 508static void 509vmx_enable(void *arg __unused) 510{ 511 int error; |
512 uint64_t feature_control; |
|
512 | 513 |
514 feature_control = rdmsr(MSR_IA32_FEATURE_CONTROL); 515 if ((feature_control & IA32_FEATURE_CONTROL_LOCK) == 0 || 516 (feature_control & IA32_FEATURE_CONTROL_VMX_EN) == 0) { 517 wrmsr(MSR_IA32_FEATURE_CONTROL, 518 feature_control | IA32_FEATURE_CONTROL_VMX_EN | 519 IA32_FEATURE_CONTROL_LOCK); 520 } 521 |
|
513 load_cr4(rcr4() | CR4_VMXE); 514 515 *(uint32_t *)vmxon_region[curcpu] = vmx_revision(); 516 error = vmxon(vmxon_region[curcpu]); 517 if (error == 0) 518 vmxon_enabled[curcpu] = 1; 519} 520 --- 18 unchanged lines hidden (view full) --- 539 return (ENXIO); 540 } 541 542 /* 543 * Verify that MSR_IA32_FEATURE_CONTROL lock and VMXON enable bits 544 * are set (bits 0 and 2 respectively). 545 */ 546 feature_control = rdmsr(MSR_IA32_FEATURE_CONTROL); | 522 load_cr4(rcr4() | CR4_VMXE); 523 524 *(uint32_t *)vmxon_region[curcpu] = vmx_revision(); 525 error = vmxon(vmxon_region[curcpu]); 526 if (error == 0) 527 vmxon_enabled[curcpu] = 1; 528} 529 --- 18 unchanged lines hidden (view full) --- 548 return (ENXIO); 549 } 550 551 /* 552 * Verify that MSR_IA32_FEATURE_CONTROL lock and VMXON enable bits 553 * are set (bits 0 and 2 respectively). 554 */ 555 feature_control = rdmsr(MSR_IA32_FEATURE_CONTROL); |
547 if ((feature_control & IA32_FEATURE_CONTROL_LOCK) == 0 || | 556 if ((feature_control & IA32_FEATURE_CONTROL_LOCK) == 1 && |
548 (feature_control & IA32_FEATURE_CONTROL_VMX_EN) == 0) { 549 printf("vmx_init: VMX operation disabled by BIOS\n"); 550 return (ENXIO); 551 } 552 553 /* Check support for primary processor-based VM-execution controls */ 554 error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS, 555 MSR_VMX_TRUE_PROCBASED_CTLS, --- 302 unchanged lines hidden (view full) --- 858 * Host KGSBASE is restored before returning to userland from the pcb. 859 * There will be a window of time when we are executing in the host 860 * kernel context with a value of KGSBASE from the guest. This is ok 861 * because the value of KGSBASE is inconsequential in kernel context. 862 * 863 * MSR_EFER is saved and restored in the guest VMCS area on a 864 * VM exit and entry respectively. It is also restored from the 865 * host VMCS area on a VM exit. | 557 (feature_control & IA32_FEATURE_CONTROL_VMX_EN) == 0) { 558 printf("vmx_init: VMX operation disabled by BIOS\n"); 559 return (ENXIO); 560 } 561 562 /* Check support for primary processor-based VM-execution controls */ 563 error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS, 564 MSR_VMX_TRUE_PROCBASED_CTLS, --- 302 unchanged lines hidden (view full) --- 867 * Host KGSBASE is restored before returning to userland from the pcb. 868 * There will be a window of time when we are executing in the host 869 * kernel context with a value of KGSBASE from the guest. This is ok 870 * because the value of KGSBASE is inconsequential in kernel context. 871 * 872 * MSR_EFER is saved and restored in the guest VMCS area on a 873 * VM exit and entry respectively. It is also restored from the 874 * host VMCS area on a VM exit. |
875 * 876 * The TSC MSR is exposed read-only. Writes are disallowed as that 877 * will impact the host TSC. 878 * XXX Writes would be implemented with a wrmsr trap, and 879 * then modifying the TSC offset in the VMCS. |
|
866 */ 867 if (guest_msr_rw(vmx, MSR_GSBASE) || 868 guest_msr_rw(vmx, MSR_FSBASE) || 869 guest_msr_rw(vmx, MSR_SYSENTER_CS_MSR) || 870 guest_msr_rw(vmx, MSR_SYSENTER_ESP_MSR) || 871 guest_msr_rw(vmx, MSR_SYSENTER_EIP_MSR) || 872 guest_msr_rw(vmx, MSR_KGSBASE) || | 880 */ 881 if (guest_msr_rw(vmx, MSR_GSBASE) || 882 guest_msr_rw(vmx, MSR_FSBASE) || 883 guest_msr_rw(vmx, MSR_SYSENTER_CS_MSR) || 884 guest_msr_rw(vmx, MSR_SYSENTER_ESP_MSR) || 885 guest_msr_rw(vmx, MSR_SYSENTER_EIP_MSR) || 886 guest_msr_rw(vmx, MSR_KGSBASE) || |
873 guest_msr_rw(vmx, MSR_EFER)) | 887 guest_msr_rw(vmx, MSR_EFER) || 888 guest_msr_ro(vmx, MSR_TSC)) |
874 panic("vmx_vminit: error setting guest msr access"); 875 876 /* 877 * MSR_PAT is saved and restored in the guest VMCS are on a VM exit 878 * and entry respectively. It is also restored from the host VMCS 879 * area on a VM exit. However, if running on a system with no 880 * MSR_PAT save/restore support, leave access disabled so accesses 881 * will be trapped. --- 942 unchanged lines hidden (view full) --- 1824 case EXIT_REASON_CR_ACCESS: 1825 vmm_stat_incr(vmx->vm, vcpu, VMEXIT_CR_ACCESS, 1); 1826 handled = vmx_emulate_cr_access(vmx, vcpu, qual); 1827 break; 1828 case EXIT_REASON_RDMSR: 1829 vmm_stat_incr(vmx->vm, vcpu, VMEXIT_RDMSR, 1); 1830 retu = false; 1831 ecx = vmxctx->guest_rcx; | 889 panic("vmx_vminit: error setting guest msr access"); 890 891 /* 892 * MSR_PAT is saved and restored in the guest VMCS are on a VM exit 893 * and entry respectively. It is also restored from the host VMCS 894 * area on a VM exit. However, if running on a system with no 895 * MSR_PAT save/restore support, leave access disabled so accesses 896 * will be trapped. --- 942 unchanged lines hidden (view full) --- 1839 case EXIT_REASON_CR_ACCESS: 1840 vmm_stat_incr(vmx->vm, vcpu, VMEXIT_CR_ACCESS, 1); 1841 handled = vmx_emulate_cr_access(vmx, vcpu, qual); 1842 break; 1843 case EXIT_REASON_RDMSR: 1844 vmm_stat_incr(vmx->vm, vcpu, VMEXIT_RDMSR, 1); 1845 retu = false; 1846 ecx = vmxctx->guest_rcx; |
1847 VCPU_CTR1(vmx->vm, vcpu, "rdmsr 0x%08x", ecx); |
|
1832 error = emulate_rdmsr(vmx->vm, vcpu, ecx, &retu); 1833 if (error) { 1834 vmexit->exitcode = VM_EXITCODE_RDMSR; 1835 vmexit->u.msr.code = ecx; 1836 } else if (!retu) { 1837 handled = HANDLED; 1838 } else { 1839 /* Return to userspace with a valid exitcode */ 1840 KASSERT(vmexit->exitcode != VM_EXITCODE_BOGUS, 1841 ("emulate_wrmsr retu with bogus exitcode")); 1842 } 1843 break; 1844 case EXIT_REASON_WRMSR: 1845 vmm_stat_incr(vmx->vm, vcpu, VMEXIT_WRMSR, 1); 1846 retu = false; 1847 eax = vmxctx->guest_rax; 1848 ecx = vmxctx->guest_rcx; 1849 edx = vmxctx->guest_rdx; | 1848 error = emulate_rdmsr(vmx->vm, vcpu, ecx, &retu); 1849 if (error) { 1850 vmexit->exitcode = VM_EXITCODE_RDMSR; 1851 vmexit->u.msr.code = ecx; 1852 } else if (!retu) { 1853 handled = HANDLED; 1854 } else { 1855 /* Return to userspace with a valid exitcode */ 1856 KASSERT(vmexit->exitcode != VM_EXITCODE_BOGUS, 1857 ("emulate_wrmsr retu with bogus exitcode")); 1858 } 1859 break; 1860 case EXIT_REASON_WRMSR: 1861 vmm_stat_incr(vmx->vm, vcpu, VMEXIT_WRMSR, 1); 1862 retu = false; 1863 eax = vmxctx->guest_rax; 1864 ecx = vmxctx->guest_rcx; 1865 edx = vmxctx->guest_rdx; |
1866 VCPU_CTR2(vmx->vm, vcpu, "wrmsr 0x%08x value 0x%016lx", 1867 ecx, (uint64_t)edx << 32 | eax); |
|
1850 error = emulate_wrmsr(vmx->vm, vcpu, ecx, 1851 (uint64_t)edx << 32 | eax, &retu); 1852 if (error) { 1853 vmexit->exitcode = VM_EXITCODE_WRMSR; 1854 vmexit->u.msr.code = ecx; 1855 vmexit->u.msr.wval = (uint64_t)edx << 32 | eax; 1856 } else if (!retu) { 1857 handled = HANDLED; --- 394 unchanged lines hidden (view full) --- 2252 2253 VMCLEAR(vmcs); 2254 return (0); 2255} 2256 2257static void 2258vmx_vmcleanup(void *arg) 2259{ | 1868 error = emulate_wrmsr(vmx->vm, vcpu, ecx, 1869 (uint64_t)edx << 32 | eax, &retu); 1870 if (error) { 1871 vmexit->exitcode = VM_EXITCODE_WRMSR; 1872 vmexit->u.msr.code = ecx; 1873 vmexit->u.msr.wval = (uint64_t)edx << 32 | eax; 1874 } else if (!retu) { 1875 handled = HANDLED; --- 394 unchanged lines hidden (view full) --- 2270 2271 VMCLEAR(vmcs); 2272 return (0); 2273} 2274 2275static void 2276vmx_vmcleanup(void *arg) 2277{ |
2260 int i, error; | 2278 int i; |
2261 struct vmx *vmx = arg; 2262 2263 if (apic_access_virtualization(vmx, 0)) 2264 vm_unmap_mmio(vmx->vm, DEFAULT_APIC_BASE, PAGE_SIZE); 2265 2266 for (i = 0; i < VM_MAXCPU; i++) 2267 vpid_free(vmx->state[i].vpid); 2268 | 2279 struct vmx *vmx = arg; 2280 2281 if (apic_access_virtualization(vmx, 0)) 2282 vm_unmap_mmio(vmx->vm, DEFAULT_APIC_BASE, PAGE_SIZE); 2283 2284 for (i = 0; i < VM_MAXCPU; i++) 2285 vpid_free(vmx->state[i].vpid); 2286 |
2269 /* 2270 * XXXSMP we also need to clear the VMCS active on the other vcpus. 2271 */ 2272 error = vmclear(&vmx->vmcs[0]); 2273 if (error != 0) 2274 panic("vmx_vmcleanup: vmclear error %d on vcpu 0", error); 2275 | |
2276 free(vmx, M_VMX); 2277 2278 return; 2279} 2280 2281static register_t * 2282vmxctx_regptr(struct vmxctx *vmxctx, int reg) 2283{ --- 141 unchanged lines hidden (view full) --- 2425 } 2426 2427 return (error); 2428} 2429 2430static int 2431vmx_getdesc(void *arg, int vcpu, int reg, struct seg_desc *desc) 2432{ | 2287 free(vmx, M_VMX); 2288 2289 return; 2290} 2291 2292static register_t * 2293vmxctx_regptr(struct vmxctx *vmxctx, int reg) 2294{ --- 141 unchanged lines hidden (view full) --- 2436 } 2437 2438 return (error); 2439} 2440 2441static int 2442vmx_getdesc(void *arg, int vcpu, int reg, struct seg_desc *desc) 2443{ |
2444 int hostcpu, running; |
|
2433 struct vmx *vmx = arg; 2434 | 2445 struct vmx *vmx = arg; 2446 |
2435 return (vmcs_getdesc(&vmx->vmcs[vcpu], reg, desc)); | 2447 running = vcpu_is_running(vmx->vm, vcpu, &hostcpu); 2448 if (running && hostcpu != curcpu) 2449 panic("vmx_getdesc: %s%d is running", vm_name(vmx->vm), vcpu); 2450 2451 return (vmcs_getdesc(&vmx->vmcs[vcpu], running, reg, desc)); |
2436} 2437 2438static int 2439vmx_setdesc(void *arg, int vcpu, int reg, struct seg_desc *desc) 2440{ | 2452} 2453 2454static int 2455vmx_setdesc(void *arg, int vcpu, int reg, struct seg_desc *desc) 2456{ |
2457 int hostcpu, running; |
|
2441 struct vmx *vmx = arg; 2442 | 2458 struct vmx *vmx = arg; 2459 |
2443 return (vmcs_setdesc(&vmx->vmcs[vcpu], reg, desc)); | 2460 running = vcpu_is_running(vmx->vm, vcpu, &hostcpu); 2461 if (running && hostcpu != curcpu) 2462 panic("vmx_setdesc: %s%d is running", vm_name(vmx->vm), vcpu); 2463 2464 return (vmcs_setdesc(&vmx->vmcs[vcpu], running, reg, desc)); |
2444} 2445 2446static int 2447vmx_getcap(void *arg, int vcpu, int type, int *retval) 2448{ 2449 struct vmx *vmx = arg; 2450 int vcap; 2451 int ret; --- 466 unchanged lines hidden --- | 2465} 2466 2467static int 2468vmx_getcap(void *arg, int vcpu, int type, int *retval) 2469{ 2470 struct vmx *vmx = arg; 2471 int vcap; 2472 int ret; --- 466 unchanged lines hidden --- |