diff --git a/bochs/cpu/cpu.h b/bochs/cpu/cpu.h index 7e4f58852..fc0426929 100644 --- a/bochs/cpu/cpu.h +++ b/bochs/cpu/cpu.h @@ -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); diff --git a/bochs/cpu/msr.cc b/bochs/cpu/msr.cc index c0bd96812..c9fbe138b 100755 --- a/bochs/cpu/msr.cc +++ b/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);