make functions from rdmsr and wrmsr - they will be reused in VMX
This commit is contained in:
parent
cc60240dc1
commit
ef5df7c4a8
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: cpu.h,v 1.554 2009-01-17 22:35:44 sshwarts Exp $
|
||||
// $Id: cpu.h,v 1.555 2009-01-19 18:08:38 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -3103,6 +3103,11 @@ public: // for now...
|
||||
BX_SMF void handleAlignmentCheck(void);
|
||||
#endif
|
||||
|
||||
#if BX_CPU_LEVEL >= 5
|
||||
BX_SMF bx_bool rdmsr(Bit32u index, Bit64u *val_64) BX_CPP_AttrRegparmN(2);
|
||||
BX_SMF bx_bool wrmsr(Bit32u index, Bit64u val_64) BX_CPP_AttrRegparmN(2);
|
||||
#endif
|
||||
|
||||
BX_SMF void jump_protected(bxInstruction_c *, Bit16u cs, bx_address disp) BX_CPP_AttrRegparmN(3);
|
||||
BX_SMF void jmp_task_gate(bx_descriptor_t *gate_descriptor) BX_CPP_AttrRegparmN(1);
|
||||
BX_SMF void jmp_call_gate(bx_descriptor_t *gate_descriptor) BX_CPP_AttrRegparmN(1);
|
||||
|
200
bochs/cpu/msr.cc
200
bochs/cpu/msr.cc
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: msr.cc,v 1.10 2009-01-19 17:43:54 sshwarts Exp $
|
||||
// $Id: msr.cc,v 1.11 2009-01-19 18:08:38 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2008 Stanislav Shwartsman
|
||||
@ -32,18 +32,11 @@
|
||||
#define RDX EDX
|
||||
#endif
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::RDMSR(bxInstruction_c *i)
|
||||
{
|
||||
#if BX_CPU_LEVEL >= 5
|
||||
if (!real_mode() && CPL!=0) {
|
||||
BX_ERROR(("RDMSR: CPL!=0 not in real mode"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
Bit32u index = ECX;
|
||||
bx_bool BX_CPP_AttrRegparmN(2) BX_CPU_C::rdmsr(Bit32u index, Bit64u *msr)
|
||||
{
|
||||
Bit64u val64 = 0;
|
||||
|
||||
/* We have the requested MSR register in ECX */
|
||||
switch(index) {
|
||||
|
||||
#if BX_SUPPORT_SEP
|
||||
@ -180,14 +173,33 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::RDMSR(bxInstruction_c *i)
|
||||
#endif
|
||||
// failed to find the MSR, could #GP or ignore it silently
|
||||
BX_ERROR(("RDMSR: Unknown register %#x", index));
|
||||
|
||||
#if BX_IGNORE_BAD_MSR == 0
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0; // will result in #GP fault due to unknown MSR
|
||||
#endif
|
||||
}
|
||||
|
||||
*msr = val64;
|
||||
return 1;
|
||||
}
|
||||
#endif // BX_CPU_LEVEL >= 5
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::RDMSR(bxInstruction_c *i)
|
||||
{
|
||||
#if BX_CPU_LEVEL >= 5
|
||||
if (!real_mode() && CPL != 0) {
|
||||
BX_ERROR(("RDMSR: CPL != 0 not in real mode"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
Bit32u index = ECX;
|
||||
Bit64u val64 = 0;
|
||||
|
||||
if (!rdmsr(index, &val64))
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
|
||||
RAX = GET32L(val64);
|
||||
RDX = GET32H(val64);
|
||||
|
||||
#else
|
||||
BX_INFO(("RDMSR: Pentium CPU required, use --enable-cpu-level=5"));
|
||||
exception(BX_UD_EXCEPTION, 0, 0);
|
||||
@ -215,52 +227,46 @@ BX_CPP_INLINE bx_bool isMemTypeValidPAT(Bit8u memtype)
|
||||
}
|
||||
#endif
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::WRMSR(bxInstruction_c *i)
|
||||
{
|
||||
#if BX_CPU_LEVEL >= 5
|
||||
if (!real_mode() && CPL!=0) {
|
||||
BX_ERROR(("WRMSR: CPL!=0 not in real mode"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
bx_bool BX_CPP_AttrRegparmN(2) BX_CPU_C::wrmsr(Bit32u index, Bit64u val_64)
|
||||
{
|
||||
Bit32u val32_lo = GET32L(val_64);
|
||||
Bit32u val32_hi = GET32H(val_64);
|
||||
|
||||
Bit64u val64 = ((Bit64u) EDX << 32) | EAX;
|
||||
Bit32u index = ECX;
|
||||
BX_INSTR_WRMSR(BX_CPU_ID, index, val_64);
|
||||
|
||||
BX_INSTR_WRMSR(BX_CPU_ID, index, val64);
|
||||
|
||||
/* ECX has the MSR to write to */
|
||||
switch(index) {
|
||||
|
||||
#if BX_SUPPORT_SEP
|
||||
case BX_MSR_SYSENTER_CS:
|
||||
BX_CPU_THIS_PTR msr.sysenter_cs_msr = EAX;
|
||||
BX_CPU_THIS_PTR msr.sysenter_cs_msr = val32_lo;
|
||||
break;
|
||||
|
||||
case BX_MSR_SYSENTER_ESP:
|
||||
#if BX_SUPPORT_X86_64
|
||||
if (! IsCanonical(val64)) {
|
||||
if (! IsCanonical(val_64)) {
|
||||
BX_ERROR(("WRMSR: attempt to write non-canonical value to MSR_SYSENTER_ESP !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
BX_CPU_THIS_PTR msr.sysenter_esp_msr = val64;
|
||||
BX_CPU_THIS_PTR msr.sysenter_esp_msr = val_64;
|
||||
break;
|
||||
|
||||
case BX_MSR_SYSENTER_EIP:
|
||||
#if BX_SUPPORT_X86_64
|
||||
if (! IsCanonical(val64)) {
|
||||
if (! IsCanonical(val_64)) {
|
||||
BX_ERROR(("WRMSR: attempt to write non-canonical value to MSR_SYSENTER_EIP !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
BX_CPU_THIS_PTR msr.sysenter_eip_msr = val64;
|
||||
BX_CPU_THIS_PTR msr.sysenter_eip_msr = val_64;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_MTRR
|
||||
case BX_MSR_MTRRCAP:
|
||||
BX_ERROR(("WRMSR: MTRRCAP is read only MSR"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0;
|
||||
|
||||
case BX_MSR_MTRRPHYSBASE0:
|
||||
case BX_MSR_MTRRPHYSBASE1:
|
||||
@ -270,9 +276,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::WRMSR(bxInstruction_c *i)
|
||||
case BX_MSR_MTRRPHYSBASE5:
|
||||
case BX_MSR_MTRRPHYSBASE6:
|
||||
case BX_MSR_MTRRPHYSBASE7:
|
||||
if (! isMemTypeValidMTRR(AL)) {
|
||||
if (! isMemTypeValidMTRR(val32_lo & 0xFF)) {
|
||||
BX_ERROR(("WRMSR: attempt to write invalid Memory Type to BX_MSR_MTRRPHYSBASE"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
case BX_MSR_MTRRPHYSMASK0:
|
||||
case BX_MSR_MTRRPHYSMASK1:
|
||||
@ -282,29 +288,29 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::WRMSR(bxInstruction_c *i)
|
||||
case BX_MSR_MTRRPHYSMASK5:
|
||||
case BX_MSR_MTRRPHYSMASK6:
|
||||
case BX_MSR_MTRRPHYSMASK7:
|
||||
BX_CPU_THIS_PTR msr.mtrrphys[index - BX_MSR_MTRRPHYSBASE0] = val64;
|
||||
BX_CPU_THIS_PTR msr.mtrrphys[index - BX_MSR_MTRRPHYSBASE0] = val_64;
|
||||
break;
|
||||
|
||||
case BX_MSR_MTRRFIX64K_00000:
|
||||
if (! isMemTypeValidMTRR(AL)) {
|
||||
if (! isMemTypeValidMTRR(val32_lo & 0xFF)) {
|
||||
BX_ERROR(("WRMSR: attempt to write invalid Memory Type to MSR_MTRRFIX64K_00000"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
BX_CPU_THIS_PTR msr.mtrrfix64k_00000 = val64;
|
||||
BX_CPU_THIS_PTR msr.mtrrfix64k_00000 = val_64;
|
||||
break;
|
||||
case BX_MSR_MTRRFIX16K_80000:
|
||||
if (! isMemTypeValidMTRR(AL)) {
|
||||
if (! isMemTypeValidMTRR(val32_lo & 0xFF)) {
|
||||
BX_ERROR(("WRMSR: attempt to write invalid Memory Type to MSR_MTRRFIX16K_80000"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
BX_CPU_THIS_PTR msr.mtrrfix16k_80000 = val64;
|
||||
BX_CPU_THIS_PTR msr.mtrrfix16k_80000 = val_64;
|
||||
break;
|
||||
case BX_MSR_MTRRFIX16K_A0000:
|
||||
if (! isMemTypeValidMTRR(AL)) {
|
||||
if (! isMemTypeValidMTRR(val32_lo & 0xFF)) {
|
||||
BX_ERROR(("WRMSR: attempt to write invalid Memory Type to MSR_MTRRFIX16K_A0000"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
BX_CPU_THIS_PTR msr.mtrrfix16k_a0000 = val64;
|
||||
BX_CPU_THIS_PTR msr.mtrrfix16k_a0000 = val_64;
|
||||
break;
|
||||
|
||||
case BX_MSR_MTRRFIX4K_C0000:
|
||||
@ -315,36 +321,38 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::WRMSR(bxInstruction_c *i)
|
||||
case BX_MSR_MTRRFIX4K_E8000:
|
||||
case BX_MSR_MTRRFIX4K_F0000:
|
||||
case BX_MSR_MTRRFIX4K_F8000:
|
||||
BX_CPU_THIS_PTR msr.mtrrfix4k[index - BX_MSR_MTRRFIX4K_C0000] = val64;
|
||||
BX_CPU_THIS_PTR msr.mtrrfix4k[index - BX_MSR_MTRRFIX4K_C0000] = val_64;
|
||||
break;
|
||||
|
||||
case BX_MSR_PAT:
|
||||
if (! isMemTypeValidPAT(AL) || ! isMemTypeValidPAT(AH) ||
|
||||
! isMemTypeValidPAT((EAX >> 16) & 0xFF) ||
|
||||
! isMemTypeValidPAT(EAX >> 24) ||
|
||||
! isMemTypeValidPAT(DL) || ! isMemTypeValidPAT(DH) ||
|
||||
! isMemTypeValidPAT((EDX >> 16) & 0xFF) ||
|
||||
! isMemTypeValidPAT(EDX >> 24))
|
||||
if (! isMemTypeValidPAT(val32_lo & 0xFF) ||
|
||||
! isMemTypeValidPAT((val32_lo >> 8) & 0xFF) ||
|
||||
! isMemTypeValidPAT((val32_lo >> 16) & 0xFF) ||
|
||||
! isMemTypeValidPAT(val32_lo >> 24) ||
|
||||
! isMemTypeValidPAT(val32_hi & 0xFF) ||
|
||||
! isMemTypeValidPAT((val32_hi >> 8) & 0xFF) ||
|
||||
! isMemTypeValidPAT((val32_hi >> 16) & 0xFF) ||
|
||||
! isMemTypeValidPAT(val32_hi >> 24))
|
||||
{
|
||||
BX_ERROR(("WRMSR: attempt to write invalid Memory Type to MSR_PAT"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BX_CPU_THIS_PTR msr.pat = val64;
|
||||
BX_CPU_THIS_PTR msr.pat = val_64;
|
||||
break;
|
||||
|
||||
case BX_MSR_MTRR_DEFTYPE:
|
||||
if (! isMemTypeValidMTRR(AL)) {
|
||||
if (! isMemTypeValidMTRR(val32_lo & 0xFF)) {
|
||||
BX_ERROR(("WRMSR: attempt to write invalid Memory Type to MSR_MTRR_DEFTYPE"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
BX_CPU_THIS_PTR msr.mtrr_deftype = EAX;
|
||||
BX_CPU_THIS_PTR msr.mtrr_deftype = val32_lo;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case BX_MSR_TSC:
|
||||
BX_CPU_THIS_PTR set_TSC(val64);
|
||||
BX_INFO(("WRMSR: wrote 0x%08x%08x to MSR_TSC", EDX, EAX));
|
||||
BX_INFO(("WRMSR: write 0x%08x%08x to MSR_TSC", val32_hi, val32_lo));
|
||||
BX_CPU_THIS_PTR set_TSC(val_64);
|
||||
break;
|
||||
|
||||
/* MSR_APICBASE
|
||||
@ -358,13 +366,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::WRMSR(bxInstruction_c *i)
|
||||
#if BX_SUPPORT_APIC
|
||||
case BX_MSR_APICBASE:
|
||||
if (BX_CPU_THIS_PTR msr.apicbase & 0x800) {
|
||||
BX_INFO(("WRMSR: wrote %08x:%08x to MSR_APICBASE", EDX, EAX));
|
||||
BX_CPU_THIS_PTR msr.apicbase = EAX; /* ignore the high 32bits */
|
||||
BX_INFO(("WRMSR: wrote %08x:%08x to MSR_APICBASE", val32_hi, val32_lo));
|
||||
#if BX_PHY_ADDRESS_WIDTH == 32
|
||||
if (EDX != 0) {
|
||||
if (val32_hi != 0) {
|
||||
BX_PANIC(("MSR_APICBASE: Only 32 bit physical address space is emulated !"));
|
||||
}
|
||||
#endif
|
||||
BX_CPU_THIS_PTR msr.apicbase = val_64;
|
||||
BX_CPU_THIS_PTR local_apic.set_base(BX_CPU_THIS_PTR msr.apicbase);
|
||||
// TLB flush is required for emulation correctness
|
||||
TLB_flush(); // don't care about performance of apic relocation
|
||||
@ -377,82 +385,82 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::WRMSR(bxInstruction_c *i)
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
case BX_MSR_EFER:
|
||||
if (val64 & ~BX_EFER_SUPPORTED_BITS) {
|
||||
if (val_64 & ~BX_EFER_SUPPORTED_BITS) {
|
||||
BX_ERROR(("WRMSR: attempt to set reserved bits of EFER MSR !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* #GP(0) if changing EFER.LME when cr0.pg = 1 */
|
||||
if ((BX_CPU_THIS_PTR efer.get_LME() != ((EAX >> 8) & 1)) &&
|
||||
if ((BX_CPU_THIS_PTR efer.get_LME() != ((val32_lo >> 8) & 1)) &&
|
||||
BX_CPU_THIS_PTR cr0.get_PG())
|
||||
{
|
||||
BX_ERROR(("WRMSR: attempt to change LME when CR0.PG=1"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BX_CPU_THIS_PTR efer.set32((EAX & BX_EFER_SUPPORTED_BITS & ~BX_EFER_LMA_MASK)
|
||||
| (BX_CPU_THIS_PTR efer.val32 & BX_EFER_LMA_MASK)); // keep LMA untouched
|
||||
BX_CPU_THIS_PTR efer.set32((val32_lo & BX_EFER_SUPPORTED_BITS & ~BX_EFER_LMA_MASK)
|
||||
| (BX_CPU_THIS_PTR efer.get32() & BX_EFER_LMA_MASK)); // keep LMA untouched
|
||||
break;
|
||||
|
||||
case BX_MSR_STAR:
|
||||
MSR_STAR = val64;
|
||||
MSR_STAR = val_64;
|
||||
break;
|
||||
|
||||
case BX_MSR_LSTAR:
|
||||
if (! IsCanonical(val64)) {
|
||||
if (! IsCanonical(val_64)) {
|
||||
BX_ERROR(("WRMSR: attempt to write non-canonical value to MSR_LSTAR !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
MSR_LSTAR = val64;
|
||||
MSR_LSTAR = val_64;
|
||||
break;
|
||||
|
||||
case BX_MSR_CSTAR:
|
||||
if (! IsCanonical(val64)) {
|
||||
if (! IsCanonical(val_64)) {
|
||||
BX_ERROR(("WRMSR: attempt to write non-canonical value to MSR_CSTAR !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
MSR_CSTAR = val64;
|
||||
MSR_CSTAR = val_64;
|
||||
break;
|
||||
|
||||
case BX_MSR_FMASK:
|
||||
MSR_FMASK = (Bit32u) val64;
|
||||
MSR_FMASK = (Bit32u) val_64;
|
||||
break;
|
||||
|
||||
case BX_MSR_FSBASE:
|
||||
if (! IsCanonical(val64)) {
|
||||
if (! IsCanonical(val_64)) {
|
||||
BX_ERROR(("WRMSR: attempt to write non-canonical value to MSR_FSBASE !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
MSR_FSBASE = val64;
|
||||
MSR_FSBASE = val_64;
|
||||
break;
|
||||
|
||||
case BX_MSR_GSBASE:
|
||||
if (! IsCanonical(val64)) {
|
||||
if (! IsCanonical(val_64)) {
|
||||
BX_ERROR(("WRMSR: attempt to write non-canonical value to MSR_GSBASE !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
MSR_GSBASE = val64;
|
||||
MSR_GSBASE = val_64;
|
||||
break;
|
||||
|
||||
case BX_MSR_KERNELGSBASE:
|
||||
if (! IsCanonical(val64)) {
|
||||
if (! IsCanonical(val_64)) {
|
||||
BX_ERROR(("WRMSR: attempt to write non-canonical value to MSR_KERNELGSBASE !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
MSR_KERNELGSBASE = val64;
|
||||
MSR_KERNELGSBASE = val_64;
|
||||
break;
|
||||
|
||||
case BX_MSR_TSC_AUX:
|
||||
MSR_TSC_AUX = EAX;
|
||||
MSR_TSC_AUX = val32_lo;
|
||||
break;
|
||||
#endif // #if BX_SUPPORT_X86_64
|
||||
|
||||
default:
|
||||
#if BX_CONFIGURE_MSRS
|
||||
if (index < BX_MSR_MAX_INDEX && BX_CPU_THIS_PTR msrs[index]) {
|
||||
if (! BX_CPU_THIS_PTR msrs[index]->set64(val64)) {
|
||||
if (! BX_CPU_THIS_PTR msrs[index]->set64(val_64)) {
|
||||
BX_ERROR(("WRMSR: Write failed to MSR %#x - #GP fault", index));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -460,9 +468,27 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::WRMSR(bxInstruction_c *i)
|
||||
// failed to find the MSR, could #GP or ignore it silently
|
||||
BX_ERROR(("WRMSR: Unknown register %#x", index));
|
||||
#if BX_IGNORE_BAD_MSR == 0
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif // BX_CPU_LEVEL >= 5
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::WRMSR(bxInstruction_c *i)
|
||||
{
|
||||
#if BX_CPU_LEVEL >= 5
|
||||
if (!real_mode() && CPL != 0) {
|
||||
BX_ERROR(("WRMSR: CPL != 0 not in real mode"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
Bit64u val_64 = ((Bit64u) EDX << 32) | EAX;
|
||||
Bit32u index = ECX;
|
||||
|
||||
if (! wrmsr(index, val_64))
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
#else
|
||||
BX_INFO(("WRMSR: Pentium CPU required, use --enable-cpu-level=5"));
|
||||
exception(BX_UD_EXCEPTION, 0, 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user