From 3f51d3ca25830981796135f463c7320db5c0e9c7 Mon Sep 17 00:00:00 2001 From: Veselin Georgiev Date: Thu, 9 Jun 2016 15:42:57 +0300 Subject: [PATCH] Add detection of L4 cache. --- cpuid_tool/cpuid_tool.c | 18 ++++++++++++++++++ libcpuid/cpuid_main.c | 14 +++++++------- libcpuid/libcpuid.h | 9 +++++++++ libcpuid/recog_intel.c | 11 ++++++++++- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/cpuid_tool/cpuid_tool.c b/cpuid_tool/cpuid_tool.c index 6835e33..1eb11a1 100644 --- a/cpuid_tool/cpuid_tool.c +++ b/cpuid_tool/cpuid_tool.c @@ -72,12 +72,15 @@ typedef enum { NEED_L1I_SIZE, NEED_L2_SIZE, NEED_L3_SIZE, + NEED_L4_SIZE, NEED_L1D_ASSOC, NEED_L2_ASSOC, NEED_L3_ASSOC, + NEED_L4_ASSOC, NEED_L1D_CACHELINE, NEED_L2_CACHELINE, NEED_L3_CACHELINE, + NEED_L4_CACHELINE, NEED_CODENAME, NEED_FEATURES, NEED_CLOCK, @@ -124,12 +127,15 @@ matchtable[] = { { NEED_L2_SIZE , "--cache" , 1}, { NEED_L2_SIZE , "--l2-cache" , 1}, { NEED_L3_SIZE , "--l3-cache" , 1}, + { NEED_L4_SIZE , "--l4-cache" , 1}, { NEED_L1D_ASSOC , "--l1d-assoc" , 1}, { NEED_L2_ASSOC , "--l2-assoc" , 1}, { NEED_L3_ASSOC , "--l3-assoc" , 1}, + { NEED_L4_ASSOC , "--l4-assoc" , 1}, { NEED_L1D_CACHELINE, "--l1d-cacheline", 1}, { NEED_L2_CACHELINE , "--l2-cacheline" , 1}, { NEED_L3_CACHELINE , "--l3-cacheline" , 1}, + { NEED_L4_CACHELINE , "--l4-cacheline" , 1}, { NEED_CODENAME , "--codename" , 1}, { NEED_FEATURES , "--flags" , 1}, { NEED_CLOCK , "--clock" , 0}, @@ -370,6 +376,9 @@ static void print_info(output_data_switch query, struct cpu_raw_data_t* raw, case NEED_L3_SIZE: fprintf(fout, "%d\n", data->l3_cache); break; + case NEED_L4_SIZE: + fprintf(fout, "%d\n", data->l4_cache); + break; case NEED_L1D_ASSOC: fprintf(fout, "%d\n", data->l1_assoc); break; @@ -379,6 +388,9 @@ static void print_info(output_data_switch query, struct cpu_raw_data_t* raw, case NEED_L3_ASSOC: fprintf(fout, "%d\n", data->l3_assoc); break; + case NEED_L4_ASSOC: + fprintf(fout, "%d\n", data->l4_assoc); + break; case NEED_L1D_CACHELINE: fprintf(fout, "%d\n", data->l1_cacheline); break; @@ -388,6 +400,9 @@ static void print_info(output_data_switch query, struct cpu_raw_data_t* raw, case NEED_L3_CACHELINE: fprintf(fout, "%d\n", data->l3_cacheline); break; + case NEED_L4_CACHELINE: + fprintf(fout, "%d\n", data->l4_cacheline); + break; case NEED_CODENAME: fprintf(fout, "%s\n", data->cpu_codename); break; @@ -594,12 +609,15 @@ int main(int argc, char** argv) fprintf(fout, " L1 I cache : %d KB\n", data.l1_instruction_cache); fprintf(fout, " L2 cache : %d KB\n", data.l2_cache); fprintf(fout, " L3 cache : %d KB\n", data.l3_cache); + fprintf(fout, " L4 cache : %d KB\n", data.l4_cache); fprintf(fout, " L1D assoc. : %d-way\n", data.l1_assoc); fprintf(fout, " L2 assoc. : %d-way\n", data.l2_assoc); fprintf(fout, " L3 assoc. : %d-way\n", data.l3_assoc); + fprintf(fout, " L4 assoc. : %d-way\n", data.l4_assoc); fprintf(fout, " L1D line sz: %d bytes\n", data.l1_cacheline); fprintf(fout, " L2 line sz : %d bytes\n", data.l2_cacheline); fprintf(fout, " L3 line sz : %d bytes\n", data.l3_cacheline); + fprintf(fout, " L4 line sz : %d bytes\n", data.l4_cacheline); fprintf(fout, " SSE units : %d bits (%s)\n", data.sse_size, data.detection_hints[CPU_HINT_SSE_SIZE_AUTH] ? "authoritative" : "non-authoritative"); fprintf(fout, " code name : `%s'\n", data.cpu_codename); fprintf(fout, " features :"); diff --git a/libcpuid/cpuid_main.c b/libcpuid/cpuid_main.c index c73946a..d0113f9 100644 --- a/libcpuid/cpuid_main.c +++ b/libcpuid/cpuid_main.c @@ -54,9 +54,9 @@ static void raw_data_t_constructor(struct cpu_raw_data_t* raw) static void cpu_id_t_constructor(struct cpu_id_t* id) { memset(id, 0, sizeof(struct cpu_id_t)); - id->l1_data_cache = id->l1_instruction_cache = id->l2_cache = id->l3_cache = -1; - id->l1_assoc = id->l2_assoc = id->l3_assoc = -1; - id->l1_cacheline = id->l2_cacheline = id->l3_cacheline = -1; + id->l1_data_cache = id->l1_instruction_cache = id->l2_cache = id->l3_cache = id->l4_cache = -1; + id->l1_assoc = id->l2_assoc = id->l3_assoc = id->l4_assoc = -1; + id->l1_cacheline = id->l2_cacheline = id->l3_cacheline = id->l4_cacheline = -1; id->sse_size = -1; } @@ -460,10 +460,10 @@ int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename recognized = 1; } syntax = 1; - syntax = syntax && parse_token("basic_cpuid", token, value, data->basic_cpuid, 32, &recognized); - syntax = syntax && parse_token("ext_cpuid", token, value, data->ext_cpuid, 32, &recognized); - syntax = syntax && parse_token("intel_fn4", token, value, data->intel_fn4, 4, &recognized); - syntax = syntax && parse_token("intel_fn11", token, value, data->intel_fn11, 4, &recognized); + syntax = syntax && parse_token("basic_cpuid", token, value, data->basic_cpuid, MAX_CPUID_LEVEL, &recognized); + syntax = syntax && parse_token("ext_cpuid", token, value, data->ext_cpuid, MAX_EXT_CPUID_LEVEL, &recognized); + syntax = syntax && parse_token("intel_fn4", token, value, data->intel_fn4, MAX_INTELFN4_LEVEL, &recognized); + syntax = syntax && parse_token("intel_fn11", token, value, data->intel_fn11, MAX_INTELFN11_LEVEL, &recognized); if (!syntax) { warnf("Error: %s:%d: Syntax error\n", filename, cur_line); fclose(f); diff --git a/libcpuid/libcpuid.h b/libcpuid/libcpuid.h index 6cd9fd4..f0c99e6 100644 --- a/libcpuid/libcpuid.h +++ b/libcpuid/libcpuid.h @@ -212,6 +212,9 @@ struct cpu_id_t { /** L3 cache size in KB. Zero on most systems */ int32_t l3_cache; + + /** L4 cache size in KB. Zero on most systems */ + int32_t l4_cache; /** Cache associativity for the L1 data cache. -1 if undetermined */ int32_t l1_assoc; @@ -221,6 +224,9 @@ struct cpu_id_t { /** Cache associativity for the L3 cache. -1 if undetermined */ int32_t l3_assoc; + + /** Cache associativity for the L4 cache. -1 if undetermined */ + int32_t l4_assoc; /** Cache-line size for L1 data cache. -1 if undetermined */ int32_t l1_cacheline; @@ -231,6 +237,9 @@ struct cpu_id_t { /** Cache-line size for L3 cache. -1 if undetermined */ int32_t l3_cacheline; + /** Cache-line size for L4 cache. -1 if undetermined */ + int32_t l4_cacheline; + /** * The brief and human-friendly CPU codename, which was recognized.
* Examples: diff --git a/libcpuid/recog_intel.c b/libcpuid/recog_intel.c index 0d56d18..10f1172 100644 --- a/libcpuid/recog_intel.c +++ b/libcpuid/recog_intel.c @@ -372,7 +372,8 @@ enum _cache_type_t { L1I, L1D, L2, - L3 + L3, + L4 }; typedef enum _cache_type_t cache_type_t; @@ -397,6 +398,12 @@ static void check_case(uint8_t on, cache_type_t cache, int size, int assoc, int data->l3_cache = size; data->l3_assoc = assoc; data->l3_cacheline = linesize; + break; + case L4: + data->l4_cache = size; + data->l4_assoc = assoc; + data->l4_cacheline = linesize; + break; default: break; } @@ -517,6 +524,8 @@ static void decode_intel_deterministic_cache_info(struct cpu_raw_data_t* raw, type = L2; else if (level == 3 && typenumber == 3) type = L3; + else if (level == 4 && typenumber == 3) + type = L4; else { warnf("deterministic_cache: unknown level/typenumber combo (%d/%d), cannot\n", level, typenumber); warnf("deterministic_cache: recognize cache type\n");