Bochs/bochs/cpu/svm.h
2011-12-28 21:54:51 +00:00

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_