379 lines
13 KiB
C
379 lines
13 KiB
C
/////////////////////////////////////////////////////////////////////////
|
|
// $Id$
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 2011-2012 Stanislav Shwartsman
|
|
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
|
|
//
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2 of the License, or (at your option) any later version.
|
|
//
|
|
// This library 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
|
|
// Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef _BX_SVM_AMD_H_
|
|
#define _BX_SVM_AMD_H_
|
|
|
|
#if BX_SUPPORT_SVM
|
|
|
|
#define BX_SVM_REVISION 0x01 /* FIXME: check what is real SVM revision */
|
|
|
|
enum SVM_intercept_codes {
|
|
SVM_VMEXIT_CR0_READ = 0,
|
|
SVM_VMEXIT_CR2_READ = 2,
|
|
SVM_VMEXIT_CR3_READ = 3,
|
|
SVM_VMEXIT_CR4_READ = 4,
|
|
SVM_VMEXIT_CR8_READ = 8,
|
|
SVM_VMEXIT_CR0_WRITE = 16,
|
|
SVM_VMEXIT_CR2_WRITE = 18,
|
|
SVM_VMEXIT_CR3_WRITE = 19,
|
|
SVM_VMEXIT_CR4_WRITE = 20,
|
|
SVM_VMEXIT_CR8_WRITE = 24,
|
|
SVM_VMEXIT_DR0_READ = 32,
|
|
SVM_VMEXIT_DR0_WRITE = 48,
|
|
SVM_VMEXIT_EXCEPTION = 64,
|
|
SVM_VMEXIT_INTR = 96,
|
|
SVM_VMEXIT_NMI = 97,
|
|
SVM_VMEXIT_SMI = 98,
|
|
SVM_VMEXIT_INIT = 99,
|
|
SVM_VMEXIT_VINTR = 100,
|
|
SVM_VMEXIT_CR0_SEL_WRITE = 101,
|
|
SVM_VMEXIT_IDTR_READ = 102,
|
|
SVM_VMEXIT_GDTR_READ = 103,
|
|
SVM_VMEXIT_LDTR_READ = 104,
|
|
SVM_VMEXIT_TR_READ = 105,
|
|
SVM_VMEXIT_IDTR_WRITE = 106,
|
|
SVM_VMEXIT_GDTR_WRITE = 107,
|
|
SVM_VMEXIT_LDTR_WRITE = 108,
|
|
SVM_VMEXIT_TR_WRITE = 109,
|
|
SVM_VMEXIT_RDTSC = 110,
|
|
SVM_VMEXIT_RDPMC = 111,
|
|
SVM_VMEXIT_PUSHF = 112,
|
|
SVM_VMEXIT_POPF = 113,
|
|
SVM_VMEXIT_CPUID = 114,
|
|
SVM_VMEXIT_RSM = 115,
|
|
SVM_VMEXIT_IRET = 116,
|
|
SVM_VMEXIT_SOFTWARE_INTERRUPT = 117,
|
|
SVM_VMEXIT_INVD = 118,
|
|
SVM_VMEXIT_PAUSE = 119,
|
|
SVM_VMEXIT_HLT = 120,
|
|
SVM_VMEXIT_INVLPG = 121,
|
|
SVM_VMEXIT_INVLPGA = 122,
|
|
SVM_VMEXIT_IO = 123,
|
|
SVM_VMEXIT_MSR = 124,
|
|
SVM_VMEXIT_TASK_SWITCH = 125,
|
|
SVM_VMEXIT_FERR_FREEZE = 126,
|
|
SVM_VMEXIT_SHUTDOWN = 127,
|
|
SVM_VMEXIT_VMRUN = 128,
|
|
SVM_VMEXIT_VMMCALL = 129,
|
|
SVM_VMEXIT_VMLOAD = 130,
|
|
SVM_VMEXIT_VMSAVE = 131,
|
|
SVM_VMEXIT_STGI = 132,
|
|
SVM_VMEXIT_CLGI = 133,
|
|
SVM_VMEXIT_SKINIT = 134,
|
|
SVM_VMEXIT_RDTSCP = 135,
|
|
SVM_VMEXIT_ICEBP = 136,
|
|
SVM_VMEXIT_WBINVD = 137,
|
|
SVM_VMEXIT_MONITOR = 138,
|
|
SVM_VMEXIT_MWAIT = 139,
|
|
SVM_VMEXIT_MWAIT_CONDITIONAL = 140,
|
|
SVM_VMEXIT_XSETBV = 141,
|
|
SVM_VMEXIT_NPF = 1024,
|
|
};
|
|
|
|
#define SVM_VMEXIT_INVALID (-1)
|
|
|
|
// =====================
|
|
// VMCB control fields
|
|
// =====================
|
|
|
|
#define SVM_CONTROL_INTERCEPT_CR_READ (0x000)
|
|
#define SVM_CONTROL_INTERCEPT_CR_WRITE (0x002)
|
|
#define SVM_CONTROL_INTERCEPT_DR_READ (0x004)
|
|
#define SVM_CONTROL_INTERCEPT_DR_WRITE (0x006)
|
|
#define SVM_CONTROL_INTERCEPT_EXCEPTIONS (0x008)
|
|
#define SVM_CONTROL_INTERCEPT1 (0x00c)
|
|
#define SVM_CONTROL_INTERCEPT2 (0x010)
|
|
|
|
#define SVM_CONTROL_IOPM_BASE_PHY_ADDR (0x040)
|
|
#define SVM_CONTROL_MSRPM_BASE_PHY_ADDR (0x048)
|
|
#define SVM_CONTROL_TSC_OFFSET (0x050)
|
|
#define SVM_CONTROL_GUEST_ASID (0x058)
|
|
#define SVM_CONTROL_TLB_CONTROL (0x05c)
|
|
#define SVM_CONTROL_VTPR (0x060)
|
|
#define SVM_CONTROL_VIRQ (0x061)
|
|
#define SVM_CONTROL_VINTR_PRIO_IGN_TPR (0x062)
|
|
#define SVM_CONTROL_VINTR_MASKING (0x063)
|
|
#define SVM_CONTROL_VINTR_VECTOR (0x064)
|
|
#define SVM_CONTROL_INTERRUPT_SHADOW (0x068)
|
|
#define SVM_CONTROL_EXITCODE (0x070)
|
|
#define SVM_CONTROL_EXITINFO1 (0x078)
|
|
#define SVM_CONTROL_EXITINFO2 (0x080)
|
|
#define SVM_CONTROL_EXITINTINFO (0x088)
|
|
#define SVM_CONTROL_EXITINTINFO_ERROR_CODE (0x08c)
|
|
#define SVM_CONTROL_NESTED_PAGING_ENABLE (0x090)
|
|
|
|
#define SVM_CONTROL_EVENT_INJECTION (0x0a8)
|
|
#define SVM_CONTROL_EVENT_INJECTION_ERRORCODE (0x0ac)
|
|
#define SVM_CONTROL_NESTED_PAGING_HOST_CR3 (0x0b0)
|
|
|
|
// ======================
|
|
// VMCB save state area
|
|
// ======================
|
|
|
|
// ES
|
|
#define SVM_GUEST_ES_SELECTOR (0x400)
|
|
#define SVM_GUEST_ES_ATTR (0x402)
|
|
#define SVM_GUEST_ES_LIMIT (0x404)
|
|
#define SVM_GUEST_ES_BASE (0x408)
|
|
|
|
// CS
|
|
#define SVM_GUEST_CS_SELECTOR (0x410)
|
|
#define SVM_GUEST_CS_ATTR (0x412)
|
|
#define SVM_GUEST_CS_LIMIT (0x414)
|
|
#define SVM_GUEST_CS_BASE (0x418)
|
|
|
|
// SS
|
|
#define SVM_GUEST_SS_SELECTOR (0x420)
|
|
#define SVM_GUEST_SS_ATTR (0x422)
|
|
#define SVM_GUEST_SS_LIMIT (0x424)
|
|
#define SVM_GUEST_SS_BASE (0x428)
|
|
|
|
// DS
|
|
#define SVM_GUEST_DS_SELECTOR (0x430)
|
|
#define SVM_GUEST_DS_ATTR (0x432)
|
|
#define SVM_GUEST_DS_LIMIT (0x434)
|
|
#define SVM_GUEST_DS_BASE (0x438)
|
|
|
|
// FS
|
|
#define SVM_GUEST_FS_SELECTOR (0x440)
|
|
#define SVM_GUEST_FS_ATTR (0x442)
|
|
#define SVM_GUEST_FS_LIMIT (0x444)
|
|
#define SVM_GUEST_FS_BASE (0x448)
|
|
|
|
// GS
|
|
#define SVM_GUEST_GS_SELECTOR (0x450)
|
|
#define SVM_GUEST_GS_ATTR (0x452)
|
|
#define SVM_GUEST_GS_LIMIT (0x454)
|
|
#define SVM_GUEST_GS_BASE (0x458)
|
|
|
|
// GDTR
|
|
#define SVM_GUEST_GDTR_LIMIT (0x464)
|
|
#define SVM_GUEST_GDTR_BASE (0x468)
|
|
|
|
// LDTR
|
|
#define SVM_GUEST_LDTR_SELECTOR (0x470)
|
|
#define SVM_GUEST_LDTR_ATTR (0x472)
|
|
#define SVM_GUEST_LDTR_LIMIT (0x474)
|
|
#define SVM_GUEST_LDTR_BASE (0x478)
|
|
|
|
// IDTR
|
|
#define SVM_GUEST_IDTR_LIMIT (0x484)
|
|
#define SVM_GUEST_IDTR_BASE (0x488)
|
|
|
|
// TR
|
|
#define SVM_GUEST_TR_SELECTOR (0x490)
|
|
#define SVM_GUEST_TR_ATTR (0x492)
|
|
#define SVM_GUEST_TR_LIMIT (0x494)
|
|
#define SVM_GUEST_TR_BASE (0x498)
|
|
|
|
#define SVM_GUEST_CPL (0x4cb)
|
|
#define SVM_GUEST_EFER_MSR (0x4d0)
|
|
#define SVM_GUEST_EFER_MSR_HI (0x4d4)
|
|
|
|
#define SVM_GUEST_CR4 (0x548)
|
|
#define SVM_GUEST_CR4_HI (0x54c)
|
|
#define SVM_GUEST_CR3 (0x550)
|
|
#define SVM_GUEST_CR0 (0x558)
|
|
#define SVM_GUEST_CR0_HI (0x55c)
|
|
#define SVM_GUEST_DR7 (0x560)
|
|
#define SVM_GUEST_DR7_HI (0x564)
|
|
#define SVM_GUEST_DR6 (0x568)
|
|
#define SVM_GUEST_DR6_HI (0x56c)
|
|
#define SVM_GUEST_RFLAGS (0x570)
|
|
#define SVM_GUEST_RFLAGS_HI (0x574)
|
|
#define SVM_GUEST_RIP (0x578)
|
|
#define SVM_GUEST_RSP (0x5d8)
|
|
#define SVM_GUEST_RAX (0x5f8)
|
|
#define SVM_GUEST_STAR_MSR (0x600)
|
|
#define SVM_GUEST_LSTAR_MSR (0x608)
|
|
#define SVM_GUEST_CSTAR_MSR (0x610)
|
|
#define SVM_GUEST_SFMASK_MSR (0x618)
|
|
#define SVM_GUEST_KERNEL_GSBASE_MSR (0x620)
|
|
#define SVM_GUEST_SYSENTER_CS_MSR (0x628)
|
|
#define SVM_GUEST_SYSENTER_ESP_MSR (0x630)
|
|
#define SVM_GUEST_SYSENTER_EIP_MSR (0x638)
|
|
#define SVM_GUEST_CR2 (0x640)
|
|
#define SVM_GUEST_PAT (0x668) /* used only when nested paging is enabled */
|
|
|
|
typedef struct bx_SVM_HOST_STATE
|
|
{
|
|
bx_segment_reg_t sregs[4];
|
|
|
|
bx_global_segment_reg_t gdtr;
|
|
bx_global_segment_reg_t idtr;
|
|
|
|
Bit32u efer;
|
|
Bit32u cr0;
|
|
Bit32u cr4;
|
|
bx_phy_address cr3;
|
|
Bit32u eflags;
|
|
Bit64u rip;
|
|
Bit64u rsp;
|
|
Bit64u rax;
|
|
|
|
} SVM_HOST_STATE;
|
|
|
|
typedef struct bx_SVM_GUEST_STATE
|
|
{
|
|
bx_segment_reg_t sregs[4];
|
|
|
|
bx_global_segment_reg_t gdtr;
|
|
bx_global_segment_reg_t idtr;
|
|
|
|
bx_efer_t efer;
|
|
bx_cr0_t cr0;
|
|
bx_cr4_t cr4;
|
|
bx_address cr2;
|
|
Bit32u dr6;
|
|
Bit32u dr7;
|
|
bx_phy_address cr3;
|
|
Bit32u eflags;
|
|
Bit64u rip;
|
|
Bit64u rsp;
|
|
Bit64u rax;
|
|
|
|
unsigned cpl;
|
|
|
|
bx_bool inhibit_interrupts;
|
|
|
|
} SVM_GUEST_STATE;
|
|
|
|
typedef struct bx_SVM_CONTROLS
|
|
{
|
|
Bit16u cr_rd_ctrl;
|
|
Bit16u cr_wr_ctrl;
|
|
Bit16u dr_rd_ctrl;
|
|
Bit16u dr_wr_ctrl;
|
|
Bit32u exceptions_intercept;
|
|
|
|
Bit32u intercept_vector[2];
|
|
|
|
Bit32u exitintinfo;
|
|
Bit32u exitintinfo_error_code;
|
|
|
|
bx_phy_address iopm_base;
|
|
bx_phy_address msrpm_base;
|
|
|
|
Bit8u v_tpr;
|
|
bx_bool v_irq;
|
|
Bit8u v_intr_prio;
|
|
bx_bool v_ignore_tpr;
|
|
bx_bool v_intr_masking;
|
|
Bit8u v_intr_vector;
|
|
|
|
} SVM_CONTROLS;
|
|
|
|
#if defined(NEED_CPU_REG_SHORTCUTS)
|
|
|
|
#define SVM_V_TPR (BX_CPU_THIS_PTR vmcb.ctrls.v_tpr)
|
|
#define SVM_V_IRQ (BX_CPU_THIS_PTR vmcb.ctrls.v_irq)
|
|
#define SVM_V_INTR_PRIO (BX_CPU_THIS_PTR vmcb.ctrls.v_intr_prio)
|
|
#define SVM_V_IGNORE_TPR (BX_CPU_THIS_PTR vmcb.ctrls.v_ignore_tpr)
|
|
#define SVM_V_INTR_MASKING (BX_CPU_THIS_PTR vmcb.ctrls.v_intr_masking)
|
|
#define SVM_V_INTR_VECTOR (BX_CPU_THIS_PTR vmcb.ctrls.v_intr_vector)
|
|
|
|
#define SVM_HOST_IF (BX_CPU_THIS_PTR vmcb.host_state.eflags & EFlagsIFMask)
|
|
|
|
#endif
|
|
|
|
typedef struct bx_VMCB_CACHE
|
|
{
|
|
SVM_HOST_STATE host_state;
|
|
SVM_CONTROLS ctrls;
|
|
} VMCB_CACHE;
|
|
|
|
// ========================
|
|
// SVM intercept controls
|
|
// ========================
|
|
|
|
#define SVM_INTERCEPT0_INTR (0)
|
|
#define SVM_INTERCEPT0_NMI (1)
|
|
#define SVM_INTERCEPT0_SMI (2)
|
|
#define SVM_INTERCEPT0_INIT (3)
|
|
#define SVM_INTERCEPT0_VINTR (4)
|
|
#define SVM_INTERCEPT0_CR0_WRITE_NO_TS_MP (5)
|
|
#define SVM_INTERCEPT0_IDTR_READ (6)
|
|
#define SVM_INTERCEPT0_GDTR_READ (7)
|
|
#define SVM_INTERCEPT0_LDTR_READ (8)
|
|
#define SVM_INTERCEPT0_TR_READ (9)
|
|
#define SVM_INTERCEPT0_IDTR_WRITE (10)
|
|
#define SVM_INTERCEPT0_GDTR_WRITE (11)
|
|
#define SVM_INTERCEPT0_LDTR_WRITE (12)
|
|
#define SVM_INTERCEPT0_TR_WRITE (13)
|
|
#define SVM_INTERCEPT0_RDTSC (14)
|
|
#define SVM_INTERCEPT0_RDPMC (15)
|
|
#define SVM_INTERCEPT0_PUSHF (16)
|
|
#define SVM_INTERCEPT0_POPF (17)
|
|
#define SVM_INTERCEPT0_CPUID (18)
|
|
#define SVM_INTERCEPT0_RSM (19)
|
|
#define SVM_INTERCEPT0_IRET (20)
|
|
#define SVM_INTERCEPT0_SOFTINT (21)
|
|
#define SVM_INTERCEPT0_INVD (22)
|
|
#define SVM_INTERCEPT0_PAUSE (23)
|
|
#define SVM_INTERCEPT0_HLT (24)
|
|
#define SVM_INTERCEPT0_INVLPG (25)
|
|
#define SVM_INTERCEPT0_INVLPGA (26)
|
|
#define SVM_INTERCEPT0_IO (27)
|
|
#define SVM_INTERCEPT0_MSR (28)
|
|
#define SVM_INTERCEPT0_TASK_SWITCH (29)
|
|
#define SVM_INTERCEPT0_FERR_FREEZE (30)
|
|
#define SVM_INTERCEPT0_SHUTDOWN (31)
|
|
|
|
#define SVM_INTERCEPT1_VMRUN (32)
|
|
#define SVM_INTERCEPT1_VMMCALL (33)
|
|
#define SVM_INTERCEPT1_VMLOAD (34)
|
|
#define SVM_INTERCEPT1_VMSAVE (35)
|
|
#define SVM_INTERCEPT1_STGI (36)
|
|
#define SVM_INTERCEPT1_CLGI (37)
|
|
#define SVM_INTERCEPT1_SKINIT (38)
|
|
#define SVM_INTERCEPT1_RDTSCP (39)
|
|
#define SVM_INTERCEPT1_ICEBP (40)
|
|
#define SVM_INTERCEPT1_WBINVD (41)
|
|
#define SVM_INTERCEPT1_MONITOR (42)
|
|
#define SVM_INTERCEPT1_MWAIT (43)
|
|
#define SVM_INTERCEPT1_MWAIT_ARMED (44)
|
|
#define SVM_INTERCEPT1_XSETBV (45)
|
|
|
|
#define SVM_INTERCEPT(intercept_bitnum) \
|
|
(BX_CPU_THIS_PTR vmcb.ctrls.intercept_vector[intercept_bitnum / 32] & (1 << (intercept_bitnum & 31)))
|
|
|
|
#define SVM_EXCEPTION_INTERCEPTED(vector) \
|
|
(BX_CPU_THIS_PTR vmcb.ctrls.exceptions_intercept & (1<<(vector)))
|
|
|
|
#define SVM_CR_READ_INTERCEPTED(reg_num) \
|
|
(BX_CPU_THIS_PTR vmcb.ctrls.cr_rd_ctrl & (1<<(reg_num)))
|
|
|
|
#define SVM_CR_WRITE_INTERCEPTED(reg_num) \
|
|
(BX_CPU_THIS_PTR vmcb.ctrls.cr_wr_ctrl & (1<<(reg_num)))
|
|
|
|
#define SVM_DR_READ_INTERCEPTED(reg_num) \
|
|
(BX_CPU_THIS_PTR vmcb.ctrls.dr_rd_ctrl & (1<<(reg_num)))
|
|
|
|
#define SVM_DR_WRITE_INTERCEPTED(reg_num) \
|
|
(BX_CPU_THIS_PTR vmcb.ctrls.dr_wr_ctrl & (1<<(reg_num)))
|
|
|
|
#endif // BX_SUPPORT_SVM
|
|
|
|
#endif // _BX_SVM_AMD_H_
|