summaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
authorSven Schnelle <svens@stackframe.org>2012-01-10 12:01:43 +0100
committerSven Schnelle <svens@stackframe.org>2012-01-10 21:51:40 +0100
commitadfbcb79ab719af4435e3fdbb8321cda825e076c (patch)
treeb1a6b834c0c7b50c69a01bd4b969fadc132df472 /src/arch
parent75fb40e15dbffe4148ab108e11d10fe3a9ed6cbe (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')
-rw-r--r--src/arch/x86/include/arch/cpu.h2
-rw-r--r--src/arch/x86/lib/cpu.c20
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];