Deleted Added
full compact
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 ---