493 lines
18 KiB
C
493 lines
18 KiB
C
/*********************************************************
|
|
* Copyright (C) 2005-2014,2017 VMware, Inc. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation version 2 and no later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*********************************************************/
|
|
|
|
/*
|
|
* x86svm.h --
|
|
*
|
|
* This header file contains basic definitions related to
|
|
* AMD's hardware virtualization implementation, which you
|
|
* may see referred to as SVM, AMD-V, or Pacifica.
|
|
*/
|
|
|
|
|
|
#ifndef _X86SVM_H_
|
|
#define _X86SVM_H_
|
|
|
|
#define INCLUDE_ALLOW_USERLEVEL
|
|
#define INCLUDE_ALLOW_VMX
|
|
|
|
#define INCLUDE_ALLOW_MODULE
|
|
#define INCLUDE_ALLOW_VMK_MODULE
|
|
#define INCLUDE_ALLOW_VMKERNEL
|
|
#define INCLUDE_ALLOW_DISTRIBUTE
|
|
#define INCLUDE_ALLOW_VMCORE
|
|
#define INCLUDE_ALLOW_VMMON
|
|
#include "includeCheck.h"
|
|
|
|
#include "x86msr.h"
|
|
#if defined(USERLEVEL) || defined(MONITOR_APP)
|
|
#include "vm_basic_asm.h"
|
|
#else
|
|
#include "vm_asm.h"
|
|
#endif
|
|
#include "x86cpuid_asm.h"
|
|
|
|
#define SVM_VMCB_IO_BITMAP_SIZE (3 * PAGE_SIZE)
|
|
#define SVM_VMCB_MSR_BITMAP_SIZE (2 * PAGE_SIZE)
|
|
|
|
/* Exit controls for the CR/DR access and hardware exceptions */
|
|
#define SVM_CR_RD_CTL(num) (0x1 << (num))
|
|
#define SVM_CR_RD_CTL_ALL 0x0000ffff
|
|
#define SVM_CR_WR_CTL(num) (0x10000 << (num))
|
|
#define SVM_CR_WR_CTL_ALL 0xffff0000
|
|
#define SVM_DR_RD_CTL(num) (0x1 << (num))
|
|
#define SVM_DR_RD_CTL_ALL 0x0000ffff
|
|
#define SVM_DR_WR_CTL(num) (0x10000 << (num))
|
|
#define SVM_DR_WR_CTL_ALL 0xffff0000
|
|
#define SVM_XCP_CTL(vector) (0x1 << (vector))
|
|
#define SVM_XCP_CTL_ALL 0xffffffff
|
|
|
|
/* Execution intercept controls */
|
|
/* VMCB.exitCtl */
|
|
#define SVM_VMCB_EXEC_CTL_INTR 0x0000000000000001ULL
|
|
#define SVM_VMCB_EXEC_CTL_NMI 0x0000000000000002ULL
|
|
#define SVM_VMCB_EXEC_CTL_SMI 0x0000000000000004ULL
|
|
#define SVM_VMCB_EXEC_CTL_INIT 0x0000000000000008ULL
|
|
#define SVM_VMCB_EXEC_CTL_VINTR 0x0000000000000010ULL
|
|
#define SVM_VMCB_EXEC_CTL_CR0_SEL_WR 0x0000000000000020ULL
|
|
#define SVM_VMCB_EXEC_CTL_SIDT 0x0000000000000040ULL
|
|
#define SVM_VMCB_EXEC_CTL_SGDT 0x0000000000000080ULL
|
|
#define SVM_VMCB_EXEC_CTL_SLDT 0x0000000000000100ULL
|
|
#define SVM_VMCB_EXEC_CTL_STR 0x0000000000000200ULL
|
|
#define SVM_VMCB_EXEC_CTL_LIDT 0x0000000000000400ULL
|
|
#define SVM_VMCB_EXEC_CTL_LGDT 0x0000000000000800ULL
|
|
#define SVM_VMCB_EXEC_CTL_LLDT 0x0000000000001000ULL
|
|
#define SVM_VMCB_EXEC_CTL_LTR 0x0000000000002000ULL
|
|
#define SVM_VMCB_EXEC_CTL_RDTSC 0x0000000000004000ULL
|
|
#define SVM_VMCB_EXEC_CTL_RDPMC 0x0000000000008000ULL
|
|
#define SVM_VMCB_EXEC_CTL_PUSHF 0x0000000000010000ULL
|
|
#define SVM_VMCB_EXEC_CTL_POPF 0x0000000000020000ULL
|
|
#define SVM_VMCB_EXEC_CTL_CPUID 0x0000000000040000ULL
|
|
#define SVM_VMCB_EXEC_CTL_RSM 0x0000000000080000ULL
|
|
#define SVM_VMCB_EXEC_CTL_IRET 0x0000000000100000ULL
|
|
#define SVM_VMCB_EXEC_CTL_SWINT 0x0000000000200000ULL
|
|
#define SVM_VMCB_EXEC_CTL_INVD 0x0000000000400000ULL
|
|
#define SVM_VMCB_EXEC_CTL_PAUSE 0x0000000000800000ULL
|
|
#define SVM_VMCB_EXEC_CTL_HLT 0x0000000001000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_INVLPG 0x0000000002000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_INVLPGA 0x0000000004000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_IOIO 0x0000000008000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_MSR 0x0000000010000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_TS 0x0000000020000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_FERR_FRZ 0x0000000040000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_SHUTDOWN 0x0000000080000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_VMRUN 0x0000000100000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_VMMCALL 0x0000000200000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_VMLOAD 0x0000000400000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_VMSAVE 0x0000000800000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_STGI 0x0000001000000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_CLGI 0x0000002000000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_SKINIT 0x0000004000000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_RDTSCP 0x0000008000000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_ICEBP 0x0000010000000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_WBINVD 0x0000020000000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_MONITOR 0x0000040000000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_MWAIT 0x0000080000000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_MWAIT_COND 0x0000100000000000ULL
|
|
#define SVM_VMCB_EXEC_CTL_XSETBV 0x0000200000000000ULL
|
|
|
|
/* VMCB.tlbCtl */
|
|
#define SVM_VMCB_TLB_CTL_FLUSH 0x01
|
|
#define SVM_VMCB_TLB_CTL_FLUSH_ONLY_CURRENT 0x02
|
|
#define SVM_VMCB_TLB_CTL_FLUSH_KEEP_GLOBALS 0x04
|
|
|
|
/* VMCB.vAPIC */
|
|
#define SVM_VMCB_APIC_VTPR_MASK 0x00000000000000ffULL
|
|
#define SVM_VMCB_APIC_VTPR_SHIFT 0
|
|
#define SVM_VMCB_APIC_VIRQ 0x0000000000000100ULL
|
|
#define SVM_VMCB_APIC_VINTR_PRIO_MASK 0x00000000000f0000ULL
|
|
#define SVM_VMCB_APIC_VINTR_PRIO_SHIFT 16
|
|
#define SVM_VMCB_APIC_VIGN_TPR 0x0000000000100000ULL
|
|
#define SVM_VMCB_APIC_VINTR_MASKING 0x0000000001000000ULL
|
|
#define SVM_VMCB_APIC_AVIC_ENABLE 0x0000000080000000ULL
|
|
#define SVM_VMCB_APIC_VINTR_VECTOR_MASK 0x000000ff00000000ULL
|
|
#define SVM_VMCB_APIC_VINTR_VECTOR_SHIFT 32
|
|
|
|
/* VMCB.intrState */
|
|
#define SVM_VMCB_INTRSTATE_INTR_SHADOW (1 << 0)
|
|
|
|
/* VMCB.nptCtl */
|
|
#define SVM_VMCB_NPTCTL_NP_ENABLE (1 << 0)
|
|
|
|
/* VMCB.debugCtl */
|
|
#define SVM_VMCB_DEBUGCTL_LBR_ENABLE (1 << 0)
|
|
|
|
/* VMCB.clean */
|
|
#define SVMCLEAN \
|
|
CLEANBIT(I, 0) \
|
|
CLEANBIT(IOPM, 1) \
|
|
CLEANBIT(ASID, 2) \
|
|
CLEANBIT(TPR, 3) \
|
|
CLEANBIT(NP, 4) \
|
|
CLEANBIT(CRX, 5) \
|
|
CLEANBIT(DRX, 6) \
|
|
CLEANBIT(DT, 7) \
|
|
CLEANBIT(SEG, 8) \
|
|
CLEANBIT(CR2, 9) \
|
|
CLEANBIT(LBR, 10) \
|
|
CLEANBIT(AVIC, 11)
|
|
|
|
#define SVM_VMCB_CLEAN_MASK ((1 << SVM_VMCB_NUM_CLEANBITS) - 1)
|
|
|
|
/* Segment attribute masks (used for conversion to unpacked format) */
|
|
#define SVM_VMCB_ATTRIB_LOW 0x000000ff
|
|
#define SVM_VMCB_ATTRIB_HI 0x00000f00
|
|
|
|
#define SVM_VMCB_AR_ACCESSED AR_ACCESSED
|
|
#define SVM_VMCB_AR_WRITE AR_WRITE
|
|
#define SVM_VMCB_AR_READ AR_READ
|
|
#define SVM_VMCB_AR_CONFORM AR_CONFORM
|
|
#define SVM_VMCB_AR_CODE AR_CODE
|
|
#define SVM_VMCB_AR_TYPE AR_TYPE
|
|
#define SVM_VMCB_AR_S AR_S
|
|
#define SVM_VMCB_AR_DPL AR_DPL
|
|
#define SVM_VMCB_AR_PRES AR_PRES
|
|
#define SVM_VMCB_AR_AVL (AR_AVL >> 4)
|
|
#define SVM_VMCB_AR_LONGMODE (AR_LONGMODE >> 4)
|
|
#define SVM_VMCB_AR_DB (AR_DB >> 4)
|
|
#define SVM_VMCB_AR_GRAN (AR_GRAN >> 4)
|
|
|
|
#define SVM_VMCB_AR_TYPE_SHIFT AR_TYPE_SHIFT
|
|
#define SVM_VMCB_AR_S_SHIFT AR_S_SHIFT
|
|
#define SVM_VMCB_AR_DPL_SHIFT AR_DPL_SHIFT
|
|
#define SVM_VMCB_AR_PRES_SHIFT AR_PRES_SHIFT
|
|
#define SVM_VMCB_AR_AVL_SHIFT (AR_AVL_SHIFT - 4)
|
|
#define SVM_VMCB_AR_LONGMODE_SHIFT (AR_LONGMODE_SHIFT - 4)
|
|
#define SVM_VMCB_AR_DB_SHIFT (AR_DB_SHIFT - 4)
|
|
#define SVM_VMCB_AR_GRAN_SHIFT (AR_GRAN_SHIFT - 4)
|
|
|
|
/* Unique Exit Codes */
|
|
#define SVM_EXITCODE_CR_READ(n) (0 + (n))
|
|
#define SVM_EXITCODE_CR_WRITE(n) (16 + (n))
|
|
#define SVM_EXITCODE_DR_READ(n) (32 + (n))
|
|
#define SVM_EXITCODE_DR_WRITE(n) (48 + (n))
|
|
#define SVM_EXITCODE_XCP(n) (64 + (n))
|
|
#define SVM_EXITCODE_INTR 96
|
|
#define SVM_EXITCODE_NMI 97
|
|
#define SVM_EXITCODE_SMI 98
|
|
#define SVM_EXITCODE_INIT 99
|
|
#define SVM_EXITCODE_VINTR 100
|
|
#define SVM_EXITCODE_CR0_SEL_WR 101
|
|
#define SVM_EXITCODE_SIDT 102
|
|
#define SVM_EXITCODE_SGDT 103
|
|
#define SVM_EXITCODE_SLDT 104
|
|
#define SVM_EXITCODE_STR 105
|
|
#define SVM_EXITCODE_LIDT 106
|
|
#define SVM_EXITCODE_LGDT 107
|
|
#define SVM_EXITCODE_LLDT 108
|
|
#define SVM_EXITCODE_LTR 109
|
|
#define SVM_EXITCODE_RDTSC 110
|
|
#define SVM_EXITCODE_RDPMC 111
|
|
#define SVM_EXITCODE_PUSHF 112
|
|
#define SVM_EXITCODE_POPF 113
|
|
#define SVM_EXITCODE_CPUID 114
|
|
#define SVM_EXITCODE_RSM 115
|
|
#define SVM_EXITCODE_IRET 116
|
|
#define SVM_EXITCODE_SWINT 117
|
|
#define SVM_EXITCODE_INVD 118
|
|
#define SVM_EXITCODE_PAUSE 119
|
|
#define SVM_EXITCODE_HLT 120
|
|
#define SVM_EXITCODE_INVLPG 121
|
|
#define SVM_EXITCODE_INVLPGA 122
|
|
#define SVM_EXITCODE_IOIO 123
|
|
#define SVM_EXITCODE_MSR 124
|
|
#define SVM_EXITCODE_TS 125
|
|
#define SVM_EXITCODE_FERR_FRZ 126
|
|
#define SVM_EXITCODE_SHUTDOWN 127
|
|
#define SVM_EXITCODE_VMRUN 128
|
|
#define SVM_EXITCODE_VMMCALL 129
|
|
#define SVM_EXITCODE_VMLOAD 130
|
|
#define SVM_EXITCODE_VMSAVE 131
|
|
#define SVM_EXITCODE_STGI 132
|
|
#define SVM_EXITCODE_CLGI 133
|
|
#define SVM_EXITCODE_SKINIT 134
|
|
#define SVM_EXITCODE_RDTSCP 135
|
|
#define SVM_EXITCODE_ICEBP 136
|
|
#define SVM_EXITCODE_WBINVD 137
|
|
#define SVM_EXITCODE_MONITOR 138
|
|
#define SVM_EXITCODE_MWAIT 139
|
|
#define SVM_EXITCODE_MWAIT_COND 140
|
|
#define SVM_EXITCODE_XSETBV 141
|
|
#define SVM_EXITCODE_NPF 1024
|
|
#define SVM_EXITCODE_AVIC_INCOMPLETE_IPI 1025
|
|
#define SVM_EXITCODE_AVIC_NOACCEL 1026
|
|
#define SVM_EXITCODE_INVALID (-1ULL)
|
|
|
|
/* ExitInfo1 for I/O exits */
|
|
#define SVM_IOEXIT_IN 0x00000001
|
|
#define SVM_IOEXIT_STR 0x00000004
|
|
#define SVM_IOEXIT_REP 0x00000008
|
|
#define SVM_IOEXIT_SIZE_MASK 0x00000070
|
|
#define SVM_IOEXIT_SIZE_SHIFT 4
|
|
#define SVM_IOEXIT_SZ8 0x00000010
|
|
#define SVM_IOEXIT_SZ16 0x00000020
|
|
#define SVM_IOEXIT_SZ32 0x00000040
|
|
#define SVM_IOEXIT_ADDR_MASK 0x00000380
|
|
#define SVM_IOEXIT_ADDR_SHIFT 7
|
|
#define SVM_IOEXIT_A16 0x00000080
|
|
#define SVM_IOEXIT_A32 0x00000100
|
|
#define SVM_IOEXIT_A64 0x00000200
|
|
#define SVM_IOEXIT_SEG_MASK 0x00001c00
|
|
#define SVM_IOEXIT_SEG_SHIFT 10
|
|
#define SVM_IOEXIT_PORT_MASK 0xffff0000
|
|
#define SVM_IOEXIT_PORT_SHIFT 16
|
|
#define SVM_IOEXIT_MBZ 0x00000002
|
|
#define SVM_IOEXIT_SBZ 0x0000e000
|
|
|
|
/* ExitInfo1 for CR exits */
|
|
#define SVM_CREXIT_MOVCR (1ull << 63)
|
|
#define SVM_CREXIT_GPR_MASK 0xf
|
|
|
|
/* ExitInfo2 for Task Switch exits */
|
|
#define SVM_TSEXIT_ERRORCODE_MASK 0x00000000ffffffffULL
|
|
#define SVM_TSEXIT_IRET 0x0000001000000000ULL
|
|
#define SVM_TSEXIT_LJMP 0x0000004000000000ULL
|
|
#define SVM_TSEXIT_EV 0x0000100000000000ULL
|
|
#define SVM_TSEXIT_RF 0x0001000000000000ULL
|
|
|
|
/* ExitInfo1 for SMI exits */
|
|
#define SVM_SMIEXIT_EXTERNAL 0x0000000000000001ULL
|
|
#define SVM_SMIEXIT_IN 0x0000000100000000ULL
|
|
#define SVM_SMIEXIT_VALID 0x0000000200000000ULL
|
|
#define SVM_SMIEXIT_STR 0x0000000400000000ULL
|
|
#define SVM_SMIEXIT_REP 0x0000000800000000ULL
|
|
#define SVM_SMIEXIT_SZ8 0x0000001000000000ULL
|
|
#define SVM_SMIEXIT_SZ16 0x0000002000000000ULL
|
|
#define SVM_SMIEXIT_SZ32 0x0000004000000000ULL
|
|
#define SVM_SMIEXIT_A16 0x0000008000000000ULL
|
|
#define SVM_SMIEXIT_A32 0x0000010000000000ULL
|
|
#define SVM_SMIEXIT_A64 0x0000020000000000ULL
|
|
#define SVM_SMIEXIT_PORT 0xffff000000000000ULL
|
|
#define SVM_SMIEXIT_MBZ 0x0000fc00fffffffeULL
|
|
|
|
/* ExitInfo1 for NPF exits */
|
|
#define SVM_NPFEXIT_P (1 << 0)
|
|
#define SVM_NPFEXIT_RW (1 << 1)
|
|
#define SVM_NPFEXIT_US (1 << 2)
|
|
#define SVM_NPFEXIT_RSVD (1 << 3)
|
|
#define SVM_NPFEXIT_ID (1 << 4)
|
|
#define SVM_NPFEXIT_FINAL_ADDR (1ULL << 32) /* Rev. C */
|
|
#define SVM_NPFEXIT_PTE_ACCESS (1ULL << 33) /* Rev. C */
|
|
|
|
/* Event Injection */
|
|
#define SVM_INTINFO_VECTOR_MASK 0x000000ff
|
|
#define SVM_INTINFO_TYPE_SHIFT 8
|
|
#define SVM_INTINFO_TYPE_MASK (7 << SVM_INTINFO_TYPE_SHIFT)
|
|
#define SVM_INTINFO_TYPE_EXTINT (0 << SVM_INTINFO_TYPE_SHIFT)
|
|
#define SVM_INTINFO_TYPE_RSVD (1 << SVM_INTINFO_TYPE_SHIFT)
|
|
#define SVM_INTINFO_TYPE_NMI (2 << SVM_INTINFO_TYPE_SHIFT)
|
|
#define SVM_INTINFO_TYPE_XCP (3 << SVM_INTINFO_TYPE_SHIFT)
|
|
#define SVM_INTINFO_TYPE_INTN (4 << SVM_INTINFO_TYPE_SHIFT)
|
|
#define SVM_INTINFO_EV 0x00000800
|
|
#define SVM_INTINFO_RSVD 0x7ffff000
|
|
#define SVM_INTINFO_VALID 0x80000000
|
|
|
|
|
|
#define SVM_EXEC_CTL_BIT(exitCode) (1ULL << (exitCode - SVM_EXITCODE_INTR))
|
|
|
|
#define VERIFY_EXEC_CTL(name) \
|
|
ASSERT_ON_COMPILE(SVM_EXEC_CTL_BIT(SVM_EXITCODE_##name) == \
|
|
SVM_VMCB_EXEC_CTL_##name);
|
|
|
|
/* Header for a secure loader block with no SL header */
|
|
#pragma pack(push, 1)
|
|
typedef struct {
|
|
uint16 entryOffs;
|
|
uint16 codeLen;
|
|
} SLB_Header;
|
|
#pragma pack(pop)
|
|
|
|
enum {
|
|
#define CLEANBIT(_name, _pos) SVM_VMCB_CLEAN_ ## _name = _pos,
|
|
|
|
SVMCLEAN
|
|
SVM_VMCB_NUM_CLEANBITS
|
|
|
|
#undef CLEANBIT
|
|
};
|
|
|
|
static INLINE uint64
|
|
SVM_ExecCtlBit(uint32 exitCode)
|
|
{
|
|
VERIFY_EXEC_CTL(INTR);
|
|
VERIFY_EXEC_CTL(NMI);
|
|
VERIFY_EXEC_CTL(SMI);
|
|
VERIFY_EXEC_CTL(INIT);
|
|
VERIFY_EXEC_CTL(VINTR);
|
|
VERIFY_EXEC_CTL(CR0_SEL_WR);
|
|
VERIFY_EXEC_CTL(SIDT);
|
|
VERIFY_EXEC_CTL(SGDT);
|
|
VERIFY_EXEC_CTL(SLDT);
|
|
VERIFY_EXEC_CTL(STR);
|
|
VERIFY_EXEC_CTL(LIDT);
|
|
VERIFY_EXEC_CTL(LGDT);
|
|
VERIFY_EXEC_CTL(LLDT);
|
|
VERIFY_EXEC_CTL(LTR);
|
|
VERIFY_EXEC_CTL(RDTSC);
|
|
VERIFY_EXEC_CTL(RDPMC);
|
|
VERIFY_EXEC_CTL(PUSHF);
|
|
VERIFY_EXEC_CTL(POPF);
|
|
VERIFY_EXEC_CTL(CPUID);
|
|
VERIFY_EXEC_CTL(RSM);
|
|
VERIFY_EXEC_CTL(IRET);
|
|
VERIFY_EXEC_CTL(SWINT);
|
|
VERIFY_EXEC_CTL(INVD);
|
|
VERIFY_EXEC_CTL(PAUSE);
|
|
VERIFY_EXEC_CTL(HLT);
|
|
VERIFY_EXEC_CTL(INVLPG);
|
|
VERIFY_EXEC_CTL(INVLPGA);
|
|
VERIFY_EXEC_CTL(IOIO);
|
|
VERIFY_EXEC_CTL(MSR);
|
|
VERIFY_EXEC_CTL(TS);
|
|
VERIFY_EXEC_CTL(FERR_FRZ);
|
|
VERIFY_EXEC_CTL(SHUTDOWN);
|
|
VERIFY_EXEC_CTL(VMRUN);
|
|
VERIFY_EXEC_CTL(VMMCALL);
|
|
VERIFY_EXEC_CTL(VMLOAD);
|
|
VERIFY_EXEC_CTL(VMSAVE);
|
|
VERIFY_EXEC_CTL(STGI);
|
|
VERIFY_EXEC_CTL(CLGI);
|
|
VERIFY_EXEC_CTL(SKINIT);
|
|
VERIFY_EXEC_CTL(RDTSCP);
|
|
VERIFY_EXEC_CTL(ICEBP);
|
|
VERIFY_EXEC_CTL(WBINVD);
|
|
VERIFY_EXEC_CTL(MONITOR);
|
|
VERIFY_EXEC_CTL(MWAIT);
|
|
VERIFY_EXEC_CTL(MWAIT_COND);
|
|
VERIFY_EXEC_CTL(XSETBV);
|
|
ASSERT(SVM_EXITCODE_INTR <= exitCode && exitCode <= SVM_EXITCODE_XSETBV);
|
|
return SVM_EXEC_CTL_BIT(exitCode);
|
|
}
|
|
|
|
|
|
/*
|
|
*----------------------------------------------------------------------
|
|
*
|
|
* SVM_EnabledFromFeatures --
|
|
*
|
|
* Returns TRUE if SVM is enabled in the given VM control MSR bits.
|
|
*
|
|
*----------------------------------------------------------------------
|
|
*/
|
|
static INLINE Bool
|
|
SVM_EnabledFromFeatures(uint64 vmCR)
|
|
{
|
|
return (vmCR & MSR_VM_CR_SVME_DISABLE) == 0;
|
|
}
|
|
|
|
|
|
/*
|
|
*----------------------------------------------------------------------
|
|
*
|
|
* SVM_LockedFromFeatures --
|
|
*
|
|
* Returns TRUE if SVM is locked in the given VM control MSR bits.
|
|
*
|
|
*----------------------------------------------------------------------
|
|
*/
|
|
static INLINE Bool
|
|
SVM_LockedFromFeatures(uint64 vmCR)
|
|
{
|
|
return (vmCR & MSR_VM_CR_SVM_LOCK) != 0;
|
|
}
|
|
|
|
|
|
#if !defined(USERLEVEL) && !defined(MONITOR_APP) /* { */
|
|
/*
|
|
*----------------------------------------------------------------------
|
|
* SVM_EnabledCPU --
|
|
*
|
|
* Returns TRUE if SVM is enabled on this CPU. This function assumes
|
|
* that the processor is SVM_Capable().
|
|
*----------------------------------------------------------------------
|
|
*/
|
|
static INLINE Bool
|
|
SVM_EnabledCPU(void)
|
|
{
|
|
return SVM_EnabledFromFeatures(__GET_MSR(MSR_VM_CR));
|
|
}
|
|
#endif /* } !defined(USERLEVEL) */
|
|
|
|
|
|
#ifndef VMM
|
|
/*
|
|
*----------------------------------------------------------------------
|
|
* SVM_CapableCPU --
|
|
*
|
|
* Verify that this CPU is SVM-capable.
|
|
*----------------------------------------------------------------------
|
|
*/
|
|
static INLINE Bool
|
|
SVM_CapableCPU(void)
|
|
{
|
|
return ((__GET_EAX_FROM_CPUID(0x80000000) >= 0x8000000a) &&
|
|
CPUID_ISSET(0x80000001, ECX, SVM,
|
|
__GET_ECX_FROM_CPUID(0x80000001)) &&
|
|
CPUID_GET(0x8000000a, EAX, SVM_REVISION,
|
|
__GET_EAX_FROM_CPUID(CPUID_SVM_FEATURES)) != 0);
|
|
}
|
|
|
|
|
|
/*
|
|
*----------------------------------------------------------------------
|
|
* SVM_SupportedVersion --
|
|
*
|
|
* Verify that a CPU has the SVM capabilities required to run the
|
|
* SVM-enabled monitor. This function assumes that the processor is
|
|
* SVM_Capable(). We only support CPUs that populate the exitIntInfo
|
|
* field of the VMCB when IDT vectoring is interrupted by a task switch
|
|
* intercept. That behavior was first introduced with Family 10H.
|
|
*----------------------------------------------------------------------
|
|
*/
|
|
static INLINE Bool
|
|
SVM_SupportedVersion(uint32 version)
|
|
{
|
|
return CPUID_EFFECTIVE_FAMILY(version) >= CPUID_FAMILY_K8L;
|
|
}
|
|
|
|
|
|
/*
|
|
*
|
|
*----------------------------------------------------------------------
|
|
* SVM_SupportedCPU --
|
|
*
|
|
* Wrapper to call SVM_SupportedVersion() with the right
|
|
* parameter(s) for the current CPU.
|
|
*----------------------------------------------------------------------
|
|
*/
|
|
static INLINE Bool
|
|
SVM_SupportedCPU(void)
|
|
{
|
|
return SVM_SupportedVersion(__GET_EAX_FROM_CPUID(1));
|
|
}
|
|
|
|
|
|
#endif /* VMM */
|
|
|
|
#endif /* _X86SVM_H_ */
|