diff options
author | Sven Schnelle <svens@stackframe.org> | 2012-01-10 12:01:43 +0100 |
---|---|---|
committer | Sven Schnelle <svens@stackframe.org> | 2012-01-10 21:51:40 +0100 |
commit | adfbcb79ab719af4435e3fdbb8321cda825e076c (patch) | |
tree | b1a6b834c0c7b50c69a01bd4b969fadc132df472 /src/arch/x86 | |
parent | 75fb40e15dbffe4148ab108e11d10fe3a9ed6cbe (diff) |
MTRR: get physical address size from CPUID
The current code uses static values for the physical address size
supported by a CPU. This isn't always the right value: I.e. on
model_6[ef]x Core (2) Duo CPUs physical address size is 36, while
Xeons from the same family have 38 bits, which results in invalid
MTRR setup. Fix this by getting the right number from CPUID.
Change-Id: If019c3d9147c3b86357f0ef0d9fda94d49d811ca
Signed-off-by: Sven Schnelle <svens@stackframe.org>
Reviewed-on: http://review.coreboot.org/529
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/arch/x86')
-rw-r--r-- | src/arch/x86/include/arch/cpu.h | 2 | ||||
-rw-r--r-- | src/arch/x86/lib/cpu.c | 20 |
2 files changed, 22 insertions, 0 deletions
diff --git a/src/arch/x86/include/arch/cpu.h b/src/arch/x86/include/arch/cpu.h index 4d7be86223..85357d744e 100644 --- a/src/arch/x86/include/arch/cpu.h +++ b/src/arch/x86/include/arch/cpu.h @@ -108,6 +108,8 @@ static inline unsigned int cpuid_edx(unsigned int op) #if !defined(__PRE_RAM__) #include <device/device.h> +int cpu_phys_address_size(void); + struct cpu_device_id { unsigned vendor; unsigned device; diff --git a/src/arch/x86/lib/cpu.c b/src/arch/x86/lib/cpu.c index 3732ae296e..aaa0a16185 100644 --- a/src/arch/x86/lib/cpu.c +++ b/src/arch/x86/lib/cpu.c @@ -131,6 +131,26 @@ static const char *cpu_vendor_name(int vendor) return name; } +static int cpu_cpuid_extended_level(void) +{ + return cpuid_eax(0x80000000); +} + +#define CPUID_FEATURE_PAE (1 << 6) +#define CPUID_FEATURE_PSE36 (1 << 17) + +int cpu_phys_address_size(void) +{ + if (!(have_cpuid_p())) + return 32; + + if (cpu_cpuid_extended_level() > 0x80000008) + return cpuid_eax(0x80000008) & 0xff; + + if (cpuid_eax(1) & (CPUID_FEATURE_PAE | CPUID_FEATURE_PSE36)) + return 36; + return 32; +} static void identify_cpu(struct device *cpu) { char vendor_name[16]; |