support for NX outside of x86-64.

required for Intel Yonah processor which is another interesting CPUID to be added
also found Via C7 CPUID, looking for the way to add it too
This commit is contained in:
Stanislav Shwartsman 2011-08-10 22:04:33 +00:00
parent 1b27438146
commit f15bc6cf75
16 changed files with 74 additions and 36 deletions

View File

@ -378,8 +378,9 @@ enum {
#define BX_MSR_IA32_SMM_MONITOR_CTL 0x09B
#endif
#if BX_SUPPORT_X86_64
#define BX_MSR_EFER 0xc0000080
#if BX_SUPPORT_X86_64
#define BX_MSR_STAR 0xc0000081
#define BX_MSR_LSTAR 0xc0000082
#define BX_MSR_CSTAR 0xc0000083
@ -899,12 +900,10 @@ public: // for now...
Bit32u cr4_suppmask;
#endif
#if BX_SUPPORT_X86_64
#if BX_CPU_LEVEL >= 6
bx_efer_t efer;
Bit32u efer_suppmask;
#endif
#if BX_CPU_LEVEL >= 6
xcr0_t xcr0;
Bit32u xcr0_suppmask;
#endif
@ -3346,7 +3345,7 @@ public: // for now...
#if BX_SUPPORT_VMX >= 2
BX_SMF bx_bool CheckPDPTR(Bit64u *pdptr) BX_CPP_AttrRegparmN(1);
#endif
#if BX_SUPPORT_X86_64
#if BX_CPU_LEVEL >= 6
BX_SMF bx_bool SetEFER(bx_address val) BX_CPP_AttrRegparmN(1);
#endif

View File

@ -105,7 +105,8 @@ Bit32u athlon64_clawhammer_t::get_cpu_extensions_bitmask(void) const
BX_CPU_PGE |
BX_CPU_PSE36 |
BX_CPU_PAT_MTRR |
BX_CPU_XAPIC;
BX_CPU_XAPIC |
BX_CPU_NX;
}
// leaf 0x00000000 //

View File

@ -142,7 +142,8 @@ Bit32u core2_extreme_x9770_t::get_cpu_extensions_bitmask(void) const
BX_CPU_PGE |
BX_CPU_PSE36 |
BX_CPU_PAT_MTRR |
BX_CPU_XAPIC;
BX_CPU_XAPIC |
BX_CPU_NX;
}
// leaf 0x00000000 //

View File

@ -150,7 +150,8 @@ Bit32u core2_penryn_t9600_t::get_cpu_extensions_bitmask(void) const
BX_CPU_PGE |
BX_CPU_PSE36 |
BX_CPU_PAT_MTRR |
BX_CPU_XAPIC;
BX_CPU_XAPIC |
BX_CPU_NX;
}
// leaf 0x00000000 //

View File

@ -164,6 +164,7 @@ Bit32u corei7_sandy_bridge_2600k_t::get_cpu_extensions_bitmask(void) const
BX_CPU_PAT_MTRR |
BX_CPU_XAPIC |
/* BX_CPU_X2APIC | */
BX_CPU_NX |
BX_CPU_PCID;
}

View File

@ -113,7 +113,8 @@ Bit32u p4_prescott_celeron_336_t::get_cpu_extensions_bitmask(void) const
BX_CPU_PGE |
BX_CPU_PSE36 |
BX_CPU_PAT_MTRR |
BX_CPU_XAPIC;
BX_CPU_XAPIC |
BX_CPU_NX;
}
// leaf 0x00000000 //

View File

@ -108,10 +108,11 @@ typedef bx_cpuid_t* (*bx_create_cpuid_method)(BX_CPU_C *cpu);
#define BX_CPU_PAT_MTRR (1 << 6) /* PAT and MTRR support */
#define BX_CPU_XAPIC (1 << 7) /* XAPIC support */
#define BX_CPU_X2APIC (1 << 8) /* X2APIC support */
#define BX_CPU_1G_PAGES (1 << 9) /* 1Gb pages support */
#define BX_CPU_PCID (1 << 10) /* PCID pages support */
#define BX_CPU_SMEP (1 << 11) /* SMEP support */
#define BX_CPU_FFXSR (1 << 12) /* EFER.FFXSR support */
#define BX_CPU_NX (1 << 9) /* Non-Execute support */
#define BX_CPU_1G_PAGES (1 << 10) /* 1Gb pages support */
#define BX_CPU_PCID (1 << 11) /* PCID pages support */
#define BX_CPU_SMEP (1 << 12) /* SMEP support */
#define BX_CPU_FFXSR (1 << 13) /* EFER.FFXSR support */
// CPUID defines - STD features CPUID[0x00000001].EDX
// ----------------------------

View File

@ -1196,7 +1196,7 @@ bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::SetCR3(bx_address val)
return 1;
}
#if BX_SUPPORT_X86_64
#if BX_CPU_LEVEL >= 6
bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::SetEFER(bx_address val_64)
{
if (val_64 & ~((Bit64u) BX_CPU_THIS_PTR efer_suppmask)) {
@ -1206,6 +1206,7 @@ bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::SetEFER(bx_address val_64)
Bit32u val32 = (Bit32u) val_64;
#if BX_SUPPORT_X86_64
/* #GP(0) if changing EFER.LME when cr0.pg = 1 */
if ((BX_CPU_THIS_PTR efer.get_LME() != ((val32 >> 8) & 1)) &&
BX_CPU_THIS_PTR cr0.get_PG())
@ -1213,6 +1214,7 @@ bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::SetEFER(bx_address val_64)
BX_ERROR(("SetEFER: attempt to change LME when CR0.PG=1"));
return 0;
}
#endif
BX_CPU_THIS_PTR efer.set32((val32 & BX_CPU_THIS_PTR efer_suppmask & ~BX_EFER_LMA_MASK)
| (BX_CPU_THIS_PTR efer.get32() & BX_EFER_LMA_MASK)); // keep LMA untouched

View File

@ -183,7 +183,7 @@ struct bx_dr7_t {
BX_CPP_INLINE void set32(Bit32u val) { val32 = val; }
};
#if BX_SUPPORT_X86_64
#if BX_CPU_LEVEL >= 6
#define BX_EFER_SCE_MASK (1 << 0)
#define BX_EFER_LME_MASK (1 << 8)
@ -196,21 +196,22 @@ struct bx_dr7_t {
struct bx_efer_t {
Bit32u val32; // 32bit value of register
#if BX_SUPPORT_X86_64
IMPLEMENT_CRREG_ACCESSORS(SCE, 0);
IMPLEMENT_CRREG_ACCESSORS(LME, 8);
IMPLEMENT_CRREG_ACCESSORS(LMA, 10);
#endif
IMPLEMENT_CRREG_ACCESSORS(NXE, 11);
IMPLEMENT_CRREG_ACCESSORS(SVME, 12); /* AMD Secure Virtual Machine */
IMPLEMENT_CRREG_ACCESSORS(LMSLE, 13); /* AMD Long Mode Segment Limit */
#if BX_SUPPORT_X86_64
IMPLEMENT_CRREG_ACCESSORS(FFXSR, 14);
#endif
BX_CPP_INLINE Bit32u get32() const { return val32; }
BX_CPP_INLINE void set32(Bit32u val) { val32 = val; }
};
#endif
#if BX_CPU_LEVEL >= 6
struct xcr0_t {
Bit32u val32; // 32bit value of register

View File

@ -832,7 +832,7 @@ void bx_generic_cpuid_t::init_cpu_extensions_bitmask(void)
features_bitmask |= BX_CPU_SMEP;
#if BX_SUPPORT_X86_64
features_bitmask |= BX_CPU_FFXSR;
features_bitmask |= BX_CPU_FFXSR | BX_CPU_NX;
static bx_bool pcid_enabled = SIM->get_param_bool(BXPN_CPUID_PCID)->get();
if (pcid_enabled)

View File

@ -480,8 +480,10 @@ void BX_CPU_C::register_state(void)
#if BX_SUPPORT_APIC
BXRS_HEX_PARAM_FIELD(MSR, apicbase, msr.apicbase);
#endif
#if BX_SUPPORT_X86_64
#if BX_CPU_LEVEL >= 6
BXRS_HEX_PARAM_FIELD(MSR, EFER, efer.val32);
#endif
#if BX_SUPPORT_X86_64
BXRS_HEX_PARAM_FIELD(MSR, star, msr.star);
BXRS_HEX_PARAM_FIELD(MSR, lstar, msr.lstar);
BXRS_HEX_PARAM_FIELD(MSR, cstar, msr.cstar);
@ -949,13 +951,21 @@ void BX_CPU_C::reset(unsigned source)
BX_CPU_THIS_PTR msr.apicbase |= 0x900;
BX_CPU_THIS_PTR lapic.set_base(BX_CPU_THIS_PTR msr.apicbase);
#endif
#if BX_SUPPORT_X86_64
#if BX_CPU_LEVEL >= 6
BX_CPU_THIS_PTR efer.set32(0);
BX_CPU_THIS_PTR efer_suppmask = (BX_EFER_SCE_MASK | BX_EFER_LME_MASK |
BX_EFER_LMA_MASK | BX_EFER_NXE_MASK);
BX_CPU_THIS_PTR efer_suppmask = 0;
if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_NX))
BX_CPU_THIS_PTR efer_suppmask |= BX_EFER_NXE_MASK;
#if BX_SUPPORT_X86_64
if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_X86_64))
BX_CPU_THIS_PTR efer_suppmask |= (BX_EFER_SCE_MASK | BX_EFER_LME_MASK | BX_EFER_LMA_MASK);
if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_FFXSR))
BX_CPU_THIS_PTR efer_suppmask |= BX_EFER_FFXSR_MASK;
#endif
#endif
#if BX_SUPPORT_X86_64
BX_CPU_THIS_PTR msr.star = 0;
BX_CPU_THIS_PTR msr.lstar = 0;
BX_CPU_THIS_PTR msr.cstar = 0;
@ -1266,4 +1276,12 @@ void BX_CPU_C::assert_checks(void)
BX_PANIC(("assert_checks: TR is not TSS type !"));
}
}
#if BX_SUPPORT_X86_64 == 0
if (BX_CPU_THIS_PTR efer_suppmask & (BX_EFER_SCE_MASK |
BX_EFER_LME_MASK | BX_EFER_LMA_MASK | BX_EFER_FFXSR_MASK))
{
BX_PANIC(("assert_checks: EFER supports x86-64 specific bits !"));
}
#endif
}

View File

@ -206,11 +206,13 @@ bx_bool BX_CPP_AttrRegparmN(2) BX_CPU_C::rdmsr(Bit32u index, Bit64u *msr)
break;
#endif
#if BX_SUPPORT_X86_64
#if BX_CPU_LEVEL >= 6
case BX_MSR_EFER:
val64 = BX_CPU_THIS_PTR efer.get32();
break;
#endif
#if BX_SUPPORT_X86_64
case BX_MSR_STAR:
val64 = MSR_STAR;
break;
@ -242,7 +244,7 @@ bx_bool BX_CPP_AttrRegparmN(2) BX_CPU_C::rdmsr(Bit32u index, Bit64u *msr)
case BX_MSR_TSC_AUX:
val64 = MSR_TSC_AUX; // 32 bit MSR
break;
#endif // #if BX_SUPPORT_X86_64
#endif
default: {
// Try to check cpuid_t first (can implement some MSRs)
@ -573,11 +575,13 @@ bx_bool BX_CPP_AttrRegparmN(2) BX_CPU_C::wrmsr(Bit32u index, Bit64u val_64)
return 0;
#endif
#if BX_SUPPORT_X86_64
#if BX_CPU_LEVEL >= 6
case BX_MSR_EFER:
if (! SetEFER(val_64)) return 0;
break;
#endif
#if BX_SUPPORT_X86_64
case BX_MSR_STAR:
MSR_STAR = val_64;
break;

View File

@ -505,10 +505,8 @@ void BX_CPU_C::page_fault(unsigned fault, bx_address laddr, unsigned user, unsig
if (rw == BX_EXECUTE) {
if (BX_CPU_THIS_PTR cr4.get_SMEP())
error_code |= ERROR_CODE_ACCESS; // I/D = 1
#if BX_SUPPORT_X86_64
if (BX_CPU_THIS_PTR cr4.get_PAE() && BX_CPU_THIS_PTR efer.get_NXE())
error_code |= ERROR_CODE_ACCESS;
#endif
}
#endif
@ -558,6 +556,7 @@ int BX_CPU_C::check_entry_PAE(const char *s, Bit64u entry, Bit64u reserved, unsi
return ERROR_RESERVED | ERROR_PROTECTION;
}
}
#endif
if (entry & PAGE_DIRECTORY_NX_BIT) {
if (! BX_CPU_THIS_PTR efer.get_NXE()) {
@ -569,7 +568,6 @@ int BX_CPU_C::check_entry_PAE(const char *s, Bit64u entry, Bit64u reserved, unsi
*nx_fault = 1;
}
}
#endif
return -1;
}
@ -1189,9 +1187,7 @@ bx_phy_address BX_CPU_C::translate_linear(bx_address laddr, unsigned user, unsig
#if BX_CPU_LEVEL >= 6
if (combined_access & 0x100) // Global bit
tlbEntry->accessBits |= TLB_GlobalPage;
#endif
#if BX_SUPPORT_X86_64
// EFER.NXE change won't flush TLB
if (BX_CPU_THIS_PTR cr4.get_PAE() && rw != BX_EXECUTE)
tlbEntry->accessBits |= TLB_NoExecute;

View File

@ -183,7 +183,7 @@ void BX_CPU_C::enter_system_management_mode(void)
// paging mode was changed - flush TLB
TLB_flush(); // Flush Global entries also
#if BX_SUPPORT_X86_64
#if BX_CPU_LEVEL >= 6
BX_CPU_THIS_PTR efer.set32(0);
#endif
@ -382,6 +382,7 @@ void BX_CPU_C::init_SMRAM(void)
smram_map[SMRAM_FIELD_CR0] = SMRAM_TRANSLATE(0x7ffc);
smram_map[SMRAM_FIELD_CR3] = SMRAM_TRANSLATE(0x7ff8);
smram_map[SMRAM_FIELD_CR4] = SMRAM_TRANSLATE(0x7f14);
smram_map[SMRAM_FIELD_EFER] = SMRAM_TRANSLATE(0x7f10);
smram_map[SMRAM_FIELD_IO_INSTRUCTION_RESTART] = SMRAM_TRANSLATE(0x7f00);
smram_map[SMRAM_FIELD_AUTOHALT_RESTART] = SMRAM_TRANSLATE(0x7f00);
smram_map[SMRAM_FIELD_NMI_MASK] = SMRAM_TRANSLATE(0x7f00);
@ -721,6 +722,9 @@ void BX_CPU_C::smram_save_state(Bit32u *saved_state)
SMRAM_FIELD(saved_state, SMRAM_FIELD_CR3) = BX_CPU_THIS_PTR cr3;
#if BX_CPU_LEVEL >= 4
SMRAM_FIELD(saved_state, SMRAM_FIELD_CR4) = BX_CPU_THIS_PTR cr4.get32();
#endif
#if BX_CPU_LEVEL >= 6
SMRAM_FIELD(saved_state, SMRAM_FIELD_EFER) = BX_CPU_THIS_PTR efer.get32();
#endif
SMRAM_FIELD(saved_state, SMRAM_FIELD_DR6) = BX_CPU_THIS_PTR dr6.get32();
SMRAM_FIELD(saved_state, SMRAM_FIELD_DR7) = BX_CPU_THIS_PTR dr7.get32();
@ -798,6 +802,13 @@ bx_bool BX_CPU_C::smram_restore_state(const Bit32u *saved_state)
return 0;
}
}
Bit32u temp_efer = SMRAM_FIELD(saved_state, SMRAM_FIELD_EFER);
if (temp_efer & ~BX_CPU_THIS_PTR efer_suppmask) {
BX_ERROR(("SMM restore: Attempt to set EFER reserved bits: 0x%08x !", temp_efer));
return 0;
}
BX_CPU_THIS_PTR efer.set32(temp_efer & BX_CPU_THIS_PTR efer_suppmask);
#endif
Bit32u temp_eflags = SMRAM_FIELD(saved_state, SMRAM_FIELD_EFLAGS);

View File

@ -156,6 +156,7 @@ enum SMMRAM_Fields {
SMRAM_FIELD_CR0,
SMRAM_FIELD_CR3,
SMRAM_FIELD_CR4,
SMRAM_FIELD_EFER,
SMRAM_FIELD_IO_INSTRUCTION_RESTART,
SMRAM_FIELD_AUTOHALT_RESTART,
SMRAM_FIELD_NMI_MASK,

View File

@ -1482,9 +1482,9 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
{
// set EFER.LMA and EFER.LME before write to CR4
if (x86_64_guest)
BX_CPU_THIS_PTR efer.set32(BX_CPU_THIS_PTR efer.get32() | ((1 << 8) | (1 << 10)));
BX_CPU_THIS_PTR efer.set32(BX_CPU_THIS_PTR efer.get32() | (BX_EFER_LME_MASK | BX_EFER_LMA_MASK));
else
BX_CPU_THIS_PTR efer.set32(BX_CPU_THIS_PTR efer.get32() & ~((1 << 8) | (1 << 10)));
BX_CPU_THIS_PTR efer.set32(BX_CPU_THIS_PTR efer.get32() & ~(BX_EFER_LME_MASK | BX_EFER_LMA_MASK));
}
#endif
@ -1919,9 +1919,9 @@ void BX_CPU_C::VMexitLoadHostState(void)
{
// set EFER.LMA and EFER.LME before write to CR4
if (x86_64_host)
BX_CPU_THIS_PTR efer.set32(BX_CPU_THIS_PTR efer.get32() | ((1 << 8) | (1 << 10)));
BX_CPU_THIS_PTR efer.set32(BX_CPU_THIS_PTR efer.get32() | (BX_EFER_LME_MASK | BX_EFER_LMA_MASK));
else
BX_CPU_THIS_PTR efer.set32(BX_CPU_THIS_PTR efer.get32() & ~((1 << 8) | (1 << 10)));
BX_CPU_THIS_PTR efer.set32(BX_CPU_THIS_PTR efer.get32() & ~(BX_EFER_LME_MASK | BX_EFER_LMA_MASK));
}
#endif