1
0
Fork 0
mirror of https://github.com/anrieff/libcpuid synced 2024-12-16 16:35:45 +00:00

Re-fix L3 cache associativity detection on AMD Zen 2 CPUs

Previous commit: 848394ee46
This commit is contained in:
Xorg 2020-05-09 19:43:02 +02:00
parent b23145144f
commit e562798cec
No known key found for this signature in database
GPG key ID: 1E55EE2EFF18BC1A
5 changed files with 37 additions and 3 deletions

View file

@ -410,6 +410,12 @@ int cpuid_get_raw_data(struct cpu_raw_data_t* data)
data->intel_fn14h[i][ECX] = i;
cpu_exec_cpuid_ext(data->intel_fn14h[i]);
}
for (i = 0; i < MAX_AMDFN8000001DH_LEVEL; i++) {
memset(data->amd_fn8000001dh[i], 0, sizeof(data->amd_fn8000001dh[i]));
data->amd_fn8000001dh[i][EAX] = 0x8000001d;
data->amd_fn8000001dh[i][ECX] = i;
cpu_exec_cpuid_ext(data->amd_fn8000001dh[i]);
}
return set_error(ERR_OK);
}
@ -449,6 +455,10 @@ int cpuid_serialize_raw_data(struct cpu_raw_data_t* data, const char* filename)
fprintf(f, "intel_fn14h[%d]=%08x %08x %08x %08x\n", i,
data->intel_fn14h[i][EAX], data->intel_fn14h[i][EBX],
data->intel_fn14h[i][ECX], data->intel_fn14h[i][EDX]);
for (i = 0; i < MAX_AMDFN8000001DH_LEVEL; i++)
fprintf(f, "amd_fn8000001dh[%d]=%08x %08x %08x %08x\n", i,
data->amd_fn8000001dh[i][EAX], data->amd_fn8000001dh[i][EBX],
data->amd_fn8000001dh[i][ECX], data->amd_fn8000001dh[i][EDX]);
if (strcmp(filename, ""))
fclose(f);
@ -499,6 +509,7 @@ int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename
syntax = syntax && parse_token("intel_fn11", token, value, data->intel_fn11, MAX_INTELFN11_LEVEL, &recognized);
syntax = syntax && parse_token("intel_fn12h", token, value, data->intel_fn12h, MAX_INTELFN12H_LEVEL, &recognized);
syntax = syntax && parse_token("intel_fn14h", token, value, data->intel_fn14h, MAX_INTELFN14H_LEVEL, &recognized);
syntax = syntax && parse_token("amd_fn8000001dh", token, value, data->amd_fn8000001dh, MAX_AMDFN8000001DH_LEVEL, &recognized);
if (!syntax) {
warnf("Error: %s:%d: Syntax error\n", filename, cur_line);
fclose(f);

View file

@ -151,6 +151,12 @@ struct cpu_raw_data_t {
* this stores the result of CPUID with eax = 0x12 and
* ecx = 0, 1, 2... */
uint32_t intel_fn14h[MAX_INTELFN14H_LEVEL][NUM_REGS];
/** when the CPU is AMD and supports leaf 8000001Dh
* (topology information for the DC)
* this stores the result of CPUID with eax = 8000001Dh and
* ecx = 0, 1, 2... */
uint32_t amd_fn8000001dh[MAX_AMDFN8000001DH_LEVEL][NUM_REGS];
};
/**

View file

@ -41,6 +41,7 @@
#define MAX_INTELFN11_LEVEL 4
#define MAX_INTELFN12H_LEVEL 4
#define MAX_INTELFN14H_LEVEL 4
#define MAX_AMDFN8000001DH_LEVEL 4
#define CPU_HINTS_MAX 16
#define SGX_FLAGS_MAX 14

View file

@ -30,6 +30,9 @@
* for the workings of the internal library infrastructure.
*/
#define EXTRACTS_BIT(reg, bit) ((reg >> bit) & 0x1)
#define EXTRACTS_BITS(reg, highbit, lowbit) ((reg >> lowbit) & ((1ULL << (highbit - lowbit + 1)) - 1))
enum _common_codes_t {
NA = 0,
NC, /* No code */

View file

@ -368,7 +368,7 @@ static void load_amd_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
static void decode_amd_cache_info(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
{
int l3_result;
int l3_result, l3_assoc;
const int assoc_table[16] = {
0, 1, 2, 0, 4, 0, 8, 0, 16, 16, 32, 48, 64, 96, 128, 255
};
@ -389,9 +389,22 @@ static void decode_amd_cache_info(struct cpu_raw_data_t* raw, struct cpu_id_t* d
if (l3_result > 0) {
l3_result = 512 * l3_result; /* AMD spec says it's a range,
but we take the lower bound */
l3_assoc = (raw->ext_cpuid[6][EDX] >> 12) & 0xf;
data->l3_cache = l3_result;
data->l3_assoc = assoc_table[(raw->ext_cpuid[6][EDX] >> 12) & 0xf];
if(l3_assoc == 0x9) {
/* Since Zen 2, CPUID_Fn80000006_EDX[15:12] is invalid (0x9)
According to page 74 on
Processor Programming Reference (PPR) for AMD Family 17h Model 71h, Revision B0 Processors:
"There are insufficient available encodings to represent all possible L3
associativities. Please refer to Core::X86::Cpuid::CachePropEbx3[CacheNumWays]."
Note: we do not read CPUID_Fn80000001_ECX[22] (AKA TopologyExtensions) to allow retrocompatibility with existing tests */
data->l3_assoc = EXTRACTS_BITS(raw->amd_fn8000001dh[0x3][EBX], 31, 22) + 1; // Cache number of ways is CacheNumWays + 1
data->l3_cacheline = EXTRACTS_BITS(raw->amd_fn8000001dh[0x3][EBX], 11, 0) + 1; // Cache line size in bytes is CacheLineSize + 1
} else {
data->l3_assoc = assoc_table[l3_assoc];
data->l3_cacheline = (raw->ext_cpuid[6][EDX]) & 0xff;
}
} else {
data->l3_cache = 0;
}