Deleted Added
full compact
vmx.c (266550) vmx.c (266573)
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: head/sys/amd64/vmm/intel/vmx.c 266550 2014-05-22 17:22:37Z neel $
26 * $FreeBSD: head/sys/amd64/vmm/intel/vmx.c 266573 2014-05-23 05:15:17Z neel $
27 */
28
29#include <sys/cdefs.h>
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/sys/amd64/vmm/intel/vmx.c 266550 2014-05-22 17:22:37Z neel $");
30__FBSDID("$FreeBSD: head/sys/amd64/vmm/intel/vmx.c 266573 2014-05-23 05:15:17Z neel $");
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>

--- 141 unchanged lines hidden (view full) ---

180
181/*
182 * Use the last page below 4GB as the APIC access address. This address is
183 * occupied by the boot firmware so it is guaranteed that it will not conflict
184 * with a page in system memory.
185 */
186#define APIC_ACCESS_ADDRESS 0xFFFFF000
187
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>

--- 141 unchanged lines hidden (view full) ---

180
181/*
182 * Use the last page below 4GB as the APIC access address. This address is
183 * occupied by the boot firmware so it is guaranteed that it will not conflict
184 * with a page in system memory.
185 */
186#define APIC_ACCESS_ADDRESS 0xFFFFF000
187
188static int vmx_getdesc(void *arg, int vcpu, int reg, struct seg_desc *desc);
189static int vmx_getreg(void *arg, int vcpu, int reg, uint64_t *retval);
188static void vmx_inject_pir(struct vlapic *vlapic);
189
190#ifdef KTR
191static const char *
192exit_reason_to_str(int reason)
193{
194 static char reasonbuf[32];
195

--- 329 unchanged lines hidden (view full) ---

525 if (vmxon_enabled[curcpu])
526 vmxon(vmxon_region[curcpu]);
527}
528
529static int
530vmx_init(int ipinum)
531{
532 int error, use_tpr_shadow;
190static void vmx_inject_pir(struct vlapic *vlapic);
191
192#ifdef KTR
193static const char *
194exit_reason_to_str(int reason)
195{
196 static char reasonbuf[32];
197

--- 329 unchanged lines hidden (view full) ---

527 if (vmxon_enabled[curcpu])
528 vmxon(vmxon_region[curcpu]);
529}
530
531static int
532vmx_init(int ipinum)
533{
534 int error, use_tpr_shadow;
533 uint64_t fixed0, fixed1, feature_control;
535 uint64_t basic, fixed0, fixed1, feature_control;
534 uint32_t tmp, procbased2_vid_bits;
535
536 /* CPUID.1:ECX[bit 5] must be 1 for processor to support VMX */
537 if (!(cpu_feature2 & CPUID2_VMX)) {
538 printf("vmx_init: processor does not support VMX operation\n");
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);
547 if ((feature_control & IA32_FEATURE_CONTROL_LOCK) == 0 ||
548 (feature_control & IA32_FEATURE_CONTROL_VMX_EN) == 0) {
549 printf("vmx_init: VMX operation disabled by BIOS\n");
550 return (ENXIO);
551 }
552
536 uint32_t tmp, procbased2_vid_bits;
537
538 /* CPUID.1:ECX[bit 5] must be 1 for processor to support VMX */
539 if (!(cpu_feature2 & CPUID2_VMX)) {
540 printf("vmx_init: processor does not support VMX operation\n");
541 return (ENXIO);
542 }
543
544 /*
545 * Verify that MSR_IA32_FEATURE_CONTROL lock and VMXON enable bits
546 * are set (bits 0 and 2 respectively).
547 */
548 feature_control = rdmsr(MSR_IA32_FEATURE_CONTROL);
549 if ((feature_control & IA32_FEATURE_CONTROL_LOCK) == 0 ||
550 (feature_control & IA32_FEATURE_CONTROL_VMX_EN) == 0) {
551 printf("vmx_init: VMX operation disabled by BIOS\n");
552 return (ENXIO);
553 }
554
555 /*
556 * Verify capabilities MSR_VMX_BASIC:
557 * - bit 54 indicates support for INS/OUTS decoding
558 */
559 basic = rdmsr(MSR_VMX_BASIC);
560 if ((basic & (1UL << 54)) == 0) {
561 printf("vmx_init: processor does not support desired basic "
562 "capabilities\n");
563 return (EINVAL);
564 }
565
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,
556 PROCBASED_CTLS_ONE_SETTING,
557 PROCBASED_CTLS_ZERO_SETTING, &procbased_ctls);
558 if (error) {
559 printf("vmx_init: processor does not support desired primary "
560 "processor-based controls\n");

--- 962 unchanged lines hidden (view full) ---

1523 if (!(vmcs_read(VMCS_GUEST_CR4) & CR4_PAE))
1524 return (PAGING_MODE_32);
1525 if (vmcs_read(VMCS_GUEST_IA32_EFER) & EFER_LME)
1526 return (PAGING_MODE_64);
1527 else
1528 return (PAGING_MODE_PAE);
1529}
1530
566 /* Check support for primary processor-based VM-execution controls */
567 error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS,
568 MSR_VMX_TRUE_PROCBASED_CTLS,
569 PROCBASED_CTLS_ONE_SETTING,
570 PROCBASED_CTLS_ZERO_SETTING, &procbased_ctls);
571 if (error) {
572 printf("vmx_init: processor does not support desired primary "
573 "processor-based controls\n");

--- 962 unchanged lines hidden (view full) ---

1536 if (!(vmcs_read(VMCS_GUEST_CR4) & CR4_PAE))
1537 return (PAGING_MODE_32);
1538 if (vmcs_read(VMCS_GUEST_IA32_EFER) & EFER_LME)
1539 return (PAGING_MODE_64);
1540 else
1541 return (PAGING_MODE_PAE);
1542}
1543
1544static uint64_t
1545inout_str_index(struct vmx *vmx, int vcpuid, int in)
1546{
1547 uint64_t val;
1548 int error;
1549 enum vm_reg_name reg;
1550
1551 reg = in ? VM_REG_GUEST_RDI : VM_REG_GUEST_RSI;
1552 error = vmx_getreg(vmx, vcpuid, reg, &val);
1553 KASSERT(error == 0, ("%s: vmx_getreg error %d", __func__, error));
1554 return (val);
1555}
1556
1557static uint64_t
1558inout_str_count(struct vmx *vmx, int vcpuid, int rep)
1559{
1560 uint64_t val;
1561 int error;
1562
1563 if (rep) {
1564 error = vmx_getreg(vmx, vcpuid, VM_REG_GUEST_RCX, &val);
1565 KASSERT(!error, ("%s: vmx_getreg error %d", __func__, error));
1566 } else {
1567 val = 1;
1568 }
1569 return (val);
1570}
1571
1572static int
1573inout_str_addrsize(uint32_t inst_info)
1574{
1575 uint32_t size;
1576
1577 size = (inst_info >> 7) & 0x7;
1578 switch (size) {
1579 case 0:
1580 return (2); /* 16 bit */
1581 case 1:
1582 return (4); /* 32 bit */
1583 case 2:
1584 return (8); /* 64 bit */
1585 default:
1586 panic("%s: invalid size encoding %d", __func__, size);
1587 }
1588}
1589
1531static void
1590static void
1591inout_str_seginfo(struct vmx *vmx, int vcpuid, uint32_t inst_info, int in,
1592 struct vm_inout_str *vis)
1593{
1594 int error, s;
1595
1596 if (in) {
1597 vis->seg_name = VM_REG_GUEST_ES;
1598 } else {
1599 s = (inst_info >> 15) & 0x7;
1600 vis->seg_name = vm_segment_name(s);
1601 }
1602
1603 error = vmx_getdesc(vmx, vcpuid, vis->seg_name, &vis->seg_desc);
1604 KASSERT(error == 0, ("%s: vmx_getdesc error %d", __func__, error));
1605
1606 /* XXX modify svm.c to update bit 16 of seg_desc.access (unusable) */
1607}
1608
1609static void
1532vmexit_inst_emul(struct vm_exit *vmexit, uint64_t gpa, uint64_t gla)
1533{
1534 vmexit->exitcode = VM_EXITCODE_INST_EMUL;
1535 vmexit->u.inst_emul.gpa = gpa;
1536 vmexit->u.inst_emul.gla = gla;
1537 vmexit->u.inst_emul.cr3 = vmcs_guest_cr3();
1538 vmexit->u.inst_emul.cpu_mode = vmx_cpu_mode();
1539 vmexit->u.inst_emul.paging_mode = vmx_paging_mode();

--- 204 unchanged lines hidden (view full) ---

1744 * exitcode of VM_EXITCODE_VMX and will be dealt with in userland.
1745 */
1746 return (UNHANDLED);
1747}
1748
1749static int
1750vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit)
1751{
1610vmexit_inst_emul(struct vm_exit *vmexit, uint64_t gpa, uint64_t gla)
1611{
1612 vmexit->exitcode = VM_EXITCODE_INST_EMUL;
1613 vmexit->u.inst_emul.gpa = gpa;
1614 vmexit->u.inst_emul.gla = gla;
1615 vmexit->u.inst_emul.cr3 = vmcs_guest_cr3();
1616 vmexit->u.inst_emul.cpu_mode = vmx_cpu_mode();
1617 vmexit->u.inst_emul.paging_mode = vmx_paging_mode();

--- 204 unchanged lines hidden (view full) ---

1822 * exitcode of VM_EXITCODE_VMX and will be dealt with in userland.
1823 */
1824 return (UNHANDLED);
1825}
1826
1827static int
1828vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit)
1829{
1752 int error, handled;
1830 int error, handled, in;
1753 struct vmxctx *vmxctx;
1754 struct vlapic *vlapic;
1831 struct vmxctx *vmxctx;
1832 struct vlapic *vlapic;
1755 uint32_t eax, ecx, edx, idtvec_info, idtvec_err, intr_info, reason;
1833 struct vm_inout_str *vis;
1834 uint32_t eax, ecx, edx, idtvec_info, idtvec_err, intr_info, inst_info;
1835 uint32_t reason;
1756 uint64_t qual, gpa;
1757 bool retu;
1758
1759 CTASSERT((PINBASED_CTLS_ONE_SETTING & PINBASED_VIRTUAL_NMI) != 0);
1760 CTASSERT((PINBASED_CTLS_ONE_SETTING & PINBASED_NMI_EXITING) != 0);
1761
1762 handled = UNHANDLED;
1763 vmxctx = &vmx->ctx[vcpu];

--- 140 unchanged lines hidden (view full) ---

1904 vmx_inject_nmi(vmx, vcpu);
1905 vmx_clear_nmi_window_exiting(vmx, vcpu);
1906 vmm_stat_incr(vmx->vm, vcpu, VMEXIT_NMI_WINDOW, 1);
1907 return (1);
1908 case EXIT_REASON_INOUT:
1909 vmm_stat_incr(vmx->vm, vcpu, VMEXIT_INOUT, 1);
1910 vmexit->exitcode = VM_EXITCODE_INOUT;
1911 vmexit->u.inout.bytes = (qual & 0x7) + 1;
1836 uint64_t qual, gpa;
1837 bool retu;
1838
1839 CTASSERT((PINBASED_CTLS_ONE_SETTING & PINBASED_VIRTUAL_NMI) != 0);
1840 CTASSERT((PINBASED_CTLS_ONE_SETTING & PINBASED_NMI_EXITING) != 0);
1841
1842 handled = UNHANDLED;
1843 vmxctx = &vmx->ctx[vcpu];

--- 140 unchanged lines hidden (view full) ---

1984 vmx_inject_nmi(vmx, vcpu);
1985 vmx_clear_nmi_window_exiting(vmx, vcpu);
1986 vmm_stat_incr(vmx->vm, vcpu, VMEXIT_NMI_WINDOW, 1);
1987 return (1);
1988 case EXIT_REASON_INOUT:
1989 vmm_stat_incr(vmx->vm, vcpu, VMEXIT_INOUT, 1);
1990 vmexit->exitcode = VM_EXITCODE_INOUT;
1991 vmexit->u.inout.bytes = (qual & 0x7) + 1;
1912 vmexit->u.inout.in = (qual & 0x8) ? 1 : 0;
1992 vmexit->u.inout.in = in = (qual & 0x8) ? 1 : 0;
1913 vmexit->u.inout.string = (qual & 0x10) ? 1 : 0;
1914 vmexit->u.inout.rep = (qual & 0x20) ? 1 : 0;
1915 vmexit->u.inout.port = (uint16_t)(qual >> 16);
1916 vmexit->u.inout.eax = (uint32_t)(vmxctx->guest_rax);
1993 vmexit->u.inout.string = (qual & 0x10) ? 1 : 0;
1994 vmexit->u.inout.rep = (qual & 0x20) ? 1 : 0;
1995 vmexit->u.inout.port = (uint16_t)(qual >> 16);
1996 vmexit->u.inout.eax = (uint32_t)(vmxctx->guest_rax);
1917 error = emulate_ioport(vmx->vm, vcpu, vmexit);
1918 if (error == 0) {
1919 handled = 1;
1920 vmxctx->guest_rax = vmexit->u.inout.eax;
1997 if (vmexit->u.inout.string) {
1998 inst_info = vmcs_read(VMCS_EXIT_INSTRUCTION_INFO);
1999 vmexit->exitcode = VM_EXITCODE_INOUT_STR;
2000 vis = &vmexit->u.inout_str;
2001 vis->cpu_mode = vmx_cpu_mode();
2002 vis->paging_mode = vmx_paging_mode();
2003 vis->rflags = vmcs_read(VMCS_GUEST_RFLAGS);
2004 vis->cr0 = vmcs_read(VMCS_GUEST_CR0);
2005 vis->cr3 = vmcs_read(VMCS_GUEST_CR3);
2006 vis->cpl = vmx_cpl();
2007 vis->index = inout_str_index(vmx, vcpu, in);
2008 vis->count = inout_str_count(vmx, vcpu, vis->inout.rep);
2009 vis->addrsize = inout_str_addrsize(inst_info);
2010 inout_str_seginfo(vmx, vcpu, inst_info, in, vis);
2011 vis->gla = vmcs_gla();
1921 }
1922 break;
1923 case EXIT_REASON_CPUID:
1924 vmm_stat_incr(vmx->vm, vcpu, VMEXIT_CPUID, 1);
1925 handled = vmx_handle_cpuid(vmx->vm, vcpu, vmxctx);
1926 break;
1927 case EXIT_REASON_EXCEPTION:
1928 vmm_stat_incr(vmx->vm, vcpu, VMEXIT_EXCEPTION, 1);

--- 978 unchanged lines hidden ---
2012 }
2013 break;
2014 case EXIT_REASON_CPUID:
2015 vmm_stat_incr(vmx->vm, vcpu, VMEXIT_CPUID, 1);
2016 handled = vmx_handle_cpuid(vmx->vm, vcpu, vmxctx);
2017 break;
2018 case EXIT_REASON_EXCEPTION:
2019 vmm_stat_incr(vmx->vm, vcpu, VMEXIT_EXCEPTION, 1);

--- 978 unchanged lines hidden ---