vmx.c (249450) | vmx.c (249879) |
---|---|
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 249450 2013-04-13 21:41:51Z neel $ | 26 * $FreeBSD: head/sys/amd64/vmm/intel/vmx.c 249879 2013-04-25 04:56:43Z grehan $ |
27 */ 28 29#include <sys/cdefs.h> | 27 */ 28 29#include <sys/cdefs.h> |
30__FBSDID("$FreeBSD: head/sys/amd64/vmm/intel/vmx.c 249450 2013-04-13 21:41:51Z neel $"); | 30__FBSDID("$FreeBSD: head/sys/amd64/vmm/intel/vmx.c 249879 2013-04-25 04:56:43Z grehan $"); |
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> --- 623 unchanged lines hidden (view full) --- 662 shadow_value = cr0_ones_mask; 663 } else { 664 mask_ident = VMCS_CR4_MASK; 665 mask_value = cr4_ones_mask | cr4_zeros_mask; 666 shadow_ident = VMCS_CR4_SHADOW; 667 shadow_value = cr4_ones_mask; 668 } 669 | 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> --- 623 unchanged lines hidden (view full) --- 662 shadow_value = cr0_ones_mask; 663 } else { 664 mask_ident = VMCS_CR4_MASK; 665 mask_value = cr4_ones_mask | cr4_zeros_mask; 666 shadow_ident = VMCS_CR4_SHADOW; 667 shadow_value = cr4_ones_mask; 668 } 669 |
670 error = vmcs_setreg(vmcs, VMCS_IDENT(mask_ident), mask_value); | 670 error = vmcs_setreg(vmcs, 0, VMCS_IDENT(mask_ident), mask_value); |
671 if (error) 672 return (error); 673 | 671 if (error) 672 return (error); 673 |
674 error = vmcs_setreg(vmcs, VMCS_IDENT(shadow_ident), shadow_value); | 674 error = vmcs_setreg(vmcs, 0, VMCS_IDENT(shadow_ident), shadow_value); |
675 if (error) 676 return (error); 677 678 return (0); 679} 680#define vmx_setup_cr0_shadow(vmcs) vmx_setup_cr_shadow(0, (vmcs)) 681#define vmx_setup_cr4_shadow(vmcs) vmx_setup_cr_shadow(4, (vmcs)) 682 --- 929 unchanged lines hidden (view full) --- 1612 return (0); 1613 } else 1614 return (EINVAL); 1615} 1616 1617static int 1618vmx_getreg(void *arg, int vcpu, int reg, uint64_t *retval) 1619{ | 675 if (error) 676 return (error); 677 678 return (0); 679} 680#define vmx_setup_cr0_shadow(vmcs) vmx_setup_cr_shadow(0, (vmcs)) 681#define vmx_setup_cr4_shadow(vmcs) vmx_setup_cr_shadow(4, (vmcs)) 682 --- 929 unchanged lines hidden (view full) --- 1612 return (0); 1613 } else 1614 return (EINVAL); 1615} 1616 1617static int 1618vmx_getreg(void *arg, int vcpu, int reg, uint64_t *retval) 1619{ |
1620 int running, hostcpu; |
|
1620 struct vmx *vmx = arg; 1621 | 1621 struct vmx *vmx = arg; 1622 |
1623 running = vcpu_is_running(vmx->vm, vcpu, &hostcpu); 1624 if (running && hostcpu != curcpu) 1625 panic("vmx_getreg: %s%d is running", vm_name(vmx->vm), vcpu); 1626 |
|
1622 if (vmxctx_getreg(&vmx->ctx[vcpu], reg, retval) == 0) 1623 return (0); 1624 | 1627 if (vmxctx_getreg(&vmx->ctx[vcpu], reg, retval) == 0) 1628 return (0); 1629 |
1625 /* 1626 * If the vcpu is running then don't mess with the VMCS. 1627 * 1628 * vmcs_getreg will VMCLEAR the vmcs when it is done which will cause 1629 * the subsequent vmlaunch/vmresume to fail. 1630 */ 1631 if (vcpu_is_running(vmx->vm, vcpu)) 1632 panic("vmx_getreg: %s%d is running", vm_name(vmx->vm), vcpu); 1633 1634 return (vmcs_getreg(&vmx->vmcs[vcpu], reg, retval)); | 1630 return (vmcs_getreg(&vmx->vmcs[vcpu], running, reg, retval)); |
1635} 1636 1637static int 1638vmx_setreg(void *arg, int vcpu, int reg, uint64_t val) 1639{ | 1631} 1632 1633static int 1634vmx_setreg(void *arg, int vcpu, int reg, uint64_t val) 1635{ |
1640 int error; | 1636 int error, hostcpu, running; |
1641 uint64_t ctls; 1642 struct vmx *vmx = arg; 1643 | 1637 uint64_t ctls; 1638 struct vmx *vmx = arg; 1639 |
1644 /* 1645 * XXX Allow caller to set contents of the guest registers saved in 1646 * the 'vmxctx' even though the vcpu might be running. We need this 1647 * specifically to support the rdmsr emulation that will set the 1648 * %eax and %edx registers during vm exit processing. 1649 */ | 1640 running = vcpu_is_running(vmx->vm, vcpu, &hostcpu); 1641 if (running && hostcpu != curcpu) 1642 panic("vmx_setreg: %s%d is running", vm_name(vmx->vm), vcpu); 1643 |
1650 if (vmxctx_setreg(&vmx->ctx[vcpu], reg, val) == 0) 1651 return (0); 1652 | 1644 if (vmxctx_setreg(&vmx->ctx[vcpu], reg, val) == 0) 1645 return (0); 1646 |
1653 /* 1654 * If the vcpu is running then don't mess with the VMCS. 1655 * 1656 * vmcs_setreg will VMCLEAR the vmcs when it is done which will cause 1657 * the subsequent vmlaunch/vmresume to fail. 1658 */ 1659 if (vcpu_is_running(vmx->vm, vcpu)) 1660 panic("vmx_setreg: %s%d is running", vm_name(vmx->vm), vcpu); | 1647 error = vmcs_setreg(&vmx->vmcs[vcpu], running, reg, val); |
1661 | 1648 |
1662 error = vmcs_setreg(&vmx->vmcs[vcpu], reg, val); 1663 | |
1664 if (error == 0) { 1665 /* 1666 * If the "load EFER" VM-entry control is 1 then the 1667 * value of EFER.LMA must be identical to "IA-32e mode guest" 1668 * bit in the VM-entry control. 1669 */ 1670 if ((entry_ctls & VM_ENTRY_LOAD_EFER) != 0 && 1671 (reg == VM_REG_GUEST_EFER)) { | 1649 if (error == 0) { 1650 /* 1651 * If the "load EFER" VM-entry control is 1 then the 1652 * value of EFER.LMA must be identical to "IA-32e mode guest" 1653 * bit in the VM-entry control. 1654 */ 1655 if ((entry_ctls & VM_ENTRY_LOAD_EFER) != 0 && 1656 (reg == VM_REG_GUEST_EFER)) { |
1672 vmcs_getreg(&vmx->vmcs[vcpu], | 1657 vmcs_getreg(&vmx->vmcs[vcpu], running, |
1673 VMCS_IDENT(VMCS_ENTRY_CTLS), &ctls); 1674 if (val & EFER_LMA) 1675 ctls |= VM_ENTRY_GUEST_LMA; 1676 else 1677 ctls &= ~VM_ENTRY_GUEST_LMA; | 1658 VMCS_IDENT(VMCS_ENTRY_CTLS), &ctls); 1659 if (val & EFER_LMA) 1660 ctls |= VM_ENTRY_GUEST_LMA; 1661 else 1662 ctls &= ~VM_ENTRY_GUEST_LMA; |
1678 vmcs_setreg(&vmx->vmcs[vcpu], | 1663 vmcs_setreg(&vmx->vmcs[vcpu], running, |
1679 VMCS_IDENT(VMCS_ENTRY_CTLS), ctls); 1680 } 1681 } 1682 1683 return (error); 1684} 1685 1686static int --- 30 unchanged lines hidden (view full) --- 1717 0x5, /* VM_PRIV_SW_EXCEPTION */ 1718 0x6, /* VM_SW_EXCEPTION */ 1719 }; 1720 1721 /* 1722 * If there is already an exception pending to be delivered to the 1723 * vcpu then just return. 1724 */ | 1664 VMCS_IDENT(VMCS_ENTRY_CTLS), ctls); 1665 } 1666 } 1667 1668 return (error); 1669} 1670 1671static int --- 30 unchanged lines hidden (view full) --- 1702 0x5, /* VM_PRIV_SW_EXCEPTION */ 1703 0x6, /* VM_SW_EXCEPTION */ 1704 }; 1705 1706 /* 1707 * If there is already an exception pending to be delivered to the 1708 * vcpu then just return. 1709 */ |
1725 error = vmcs_getreg(vmcs, VMCS_IDENT(VMCS_ENTRY_INTR_INFO), &info); | 1710 error = vmcs_getreg(vmcs, 0, VMCS_IDENT(VMCS_ENTRY_INTR_INFO), &info); |
1726 if (error) 1727 return (error); 1728 1729 if (info & VMCS_INTERRUPTION_INFO_VALID) 1730 return (EAGAIN); 1731 1732 info = vector | (type_map[type] << 8) | (code_valid ? 1 << 11 : 0); 1733 info |= VMCS_INTERRUPTION_INFO_VALID; | 1711 if (error) 1712 return (error); 1713 1714 if (info & VMCS_INTERRUPTION_INFO_VALID) 1715 return (EAGAIN); 1716 1717 info = vector | (type_map[type] << 8) | (code_valid ? 1 << 11 : 0); 1718 info |= VMCS_INTERRUPTION_INFO_VALID; |
1734 error = vmcs_setreg(vmcs, VMCS_IDENT(VMCS_ENTRY_INTR_INFO), info); | 1719 error = vmcs_setreg(vmcs, 0, VMCS_IDENT(VMCS_ENTRY_INTR_INFO), info); |
1735 if (error != 0) 1736 return (error); 1737 1738 if (code_valid) { | 1720 if (error != 0) 1721 return (error); 1722 1723 if (code_valid) { |
1739 error = vmcs_setreg(vmcs, | 1724 error = vmcs_setreg(vmcs, 0, |
1740 VMCS_IDENT(VMCS_ENTRY_EXCEPTION_ERROR), 1741 code); 1742 } 1743 return (error); 1744} 1745 1746static int 1747vmx_getcap(void *arg, int vcpu, int type, int *retval) --- 139 unchanged lines hidden --- | 1725 VMCS_IDENT(VMCS_ENTRY_EXCEPTION_ERROR), 1726 code); 1727 } 1728 return (error); 1729} 1730 1731static int 1732vmx_getcap(void *arg, int vcpu, int type, int *retval) --- 139 unchanged lines hidden --- |