summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErwan Velu <erwan.velu@free.fr>2009-11-27 19:47:46 +0100
committerErwan Velu <erwan.velu@free.fr>2009-12-04 10:11:14 +0100
commit86f0a14f7c045776b14c5ad8f7c4974f9e0cfc01 (patch)
tree9daa2c38442b13793e0fc9c7c83a9cc2a18ee19d
parent91df71284aecce943b7d4e46220cf277b4098304 (diff)
downloadsyslinux-86f0a14f7c045776b14c5ad8f7c4974f9e0cfc01.tar.gz
cpuid: Adding L1 & L2 cache detection
Impact: Adding L1 & L2 cache detection Adding L1 & L2 cache detection
-rw-r--r--com32/gplinclude/cpuid.h7
-rw-r--r--com32/gpllib/cpuid.c52
2 files changed, 57 insertions, 2 deletions
diff --git a/com32/gplinclude/cpuid.h b/com32/gplinclude/cpuid.h
index 677f3f9f..bc9df171 100644
--- a/com32/gplinclude/cpuid.h
+++ b/com32/gplinclude/cpuid.h
@@ -128,6 +128,9 @@ typedef struct {
uint8_t model_id;
uint8_t stepping;
uint8_t num_cores;
+ uint16_t l1_data_cache_size;
+ uint16_t l1_instruction_cache_size;
+ uint16_t l2_cache_size;
s_cpu_flags flags;
} s_cpu;
@@ -196,7 +199,9 @@ struct cpuinfo_x86 {
uint32_t x86_capability[NCAPINTS];
char x86_vendor_id[16];
char x86_model_id[64];
- int x86_cache_size; /* in KB, if available */
+ uint16_t x86_l1_data_cache_size; /* in KB, if available */
+ uint16_t x86_l1_instruction_cache_size; /* in KB, if available */
+ uint16_t x86_l2_cache_size; /* in KB, if available */
int x86_cache_alignment; /* in bytes */
char fdiv_bug;
char f00f_bug;
diff --git a/com32/gpllib/cpuid.c b/com32/gpllib/cpuid.c
index b2451403..fa212045 100644
--- a/com32/gpllib/cpuid.c
+++ b/com32/gpllib/cpuid.c
@@ -133,6 +133,50 @@ int get_model_name(struct cpuinfo_x86 *c)
return 1;
}
+void detect_cache(uint32_t xlvl, struct cpuinfo_x86 *c)
+{
+ uint32_t eax, ebx, ecx, edx, l2size;
+ /* Detecting L1 cache */
+ if (xlvl >= 0x80000005) {
+ cpuid(0x80000005, &eax, &ebx, &ecx, &edx);
+ c->x86_l1_data_cache_size = ecx >> 24;
+ c->x86_l1_instruction_cache_size = edx >> 24;
+ }
+
+ /* Detecting L2 cache */
+ c->x86_l2_cache_size = 0;
+
+ if (xlvl < 0x80000006) /* Some chips just has a large L1. */
+ return;
+
+ cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
+ l2size = ecx >> 16;
+
+ /* Vendor based fixes */
+ switch (c->x86_vendor) {
+ case X86_VENDOR_INTEL:
+ /*
+ * Intel PIII Tualatin. This comes in two flavours.
+ * One has 256kb of cache, the other 512. We have no way
+ * to determine which, so we use a boottime override
+ * for the 512kb model, and assume 256 otherwise.
+ */
+ if ((c->x86 == 6) && (c->x86_model == 11) && (l2size == 0))
+ l2size = 256;
+ break;
+ case X86_VENDOR_AMD:
+ /* AMD errata T13 (order #21922) */
+ if ((c->x86 == 6)) {
+ if (c->x86_model == 3 && c->x86_mask == 0) /* Duron Rev A0 */
+ l2size = 64;
+ if (c->x86_model == 4 && (c->x86_mask == 0 || c->x86_mask == 1)) /* Tbird rev A1/A2 */
+ l2size = 256;
+ }
+ break;
+ }
+ c->x86_l2_cache_size = l2size;
+}
+
void generic_identify(struct cpuinfo_x86 *c)
{
uint32_t tfms, xlvl;
@@ -196,6 +240,7 @@ void generic_identify(struct cpuinfo_x86 *c)
break;
}
+ detect_cache(xlvl, c);
}
/*
@@ -380,13 +425,18 @@ void set_generic_info(struct cpuinfo_x86 *c, s_cpu * cpu)
sizeof(cpu->vendor));
strncpy(cpu->model, c->x86_model_id, sizeof(cpu->model));
cpu->num_cores = c->x86_num_cores;
+ cpu->l1_data_cache_size = c->x86_l1_data_cache_size;
+ cpu->l1_instruction_cache_size = c->x86_l1_instruction_cache_size;
+ cpu->l2_cache_size = c->x86_l2_cache_size;
}
void detect_cpu(s_cpu * cpu)
{
struct cpuinfo_x86 c;
c.x86_clflush_size = 32;
- c.x86_cache_size = -1;
+ c.x86_l1_data_cache_size = 0;
+ c.x86_l1_instruction_cache_size = 0;
+ c.x86_l2_cache_size = 0;
c.x86_vendor = X86_VENDOR_UNKNOWN;
c.cpuid_level = -1; /* CPUID not detected */
c.x86_model = c.x86_mask = 0; /* So far unknown... */