Fix SMT bug in AMD. I would like to improve it, since Intel can use APIC with 0x1 and 0xB (extended) while AMD does with 0x1 and extended seems to be 0x1E. Add support to detect more than one L3 cache. This is not a very elegant solution, since we still assume that we have the same number of caches as caches in a given level. To fix it, cpufetch should know how many caches are in a given level (hint, Linux knows using shared_cpu_map)

This commit is contained in:
Dr-Noob
2020-08-29 15:42:56 +02:00
parent e08b60b1c8
commit d8dad29a57
4 changed files with 44 additions and 18 deletions

View File

@@ -252,7 +252,7 @@ uint32_t is_smt_enabled(struct topology* topo) {
printErr("Failed binding to CPU %d", i);
return false;
}
id = get_apic_id(true) & 1; // get the last bit
id = get_apic_id(false) & 1; // get the last bit
if(id == 1) return 2; // We assume there isn't any AMD CPU with more than 2th per core
}

View File

@@ -67,6 +67,7 @@ struct cache {
int32_t L1d;
int32_t L2;
int32_t L3;
int8_t nL3;
};
struct frequency {
@@ -346,7 +347,21 @@ struct topology* get_topology_info(struct cpuInfo* cpu) {
return topo;
}
struct cache* get_cache_info(struct cpuInfo* cpu) {
uint8_t get_number_llc_amd(struct topology* topo) {
uint32_t eax = 0x8000001D;
uint32_t ebx = 0;
uint32_t ecx = 3; // LLC Level
uint32_t edx = 0;
uint32_t num_sharing_cache = 0;
cpuid(&eax, &ebx, &ecx, &edx);
num_sharing_cache = ((eax >> 14) & 0xfff) + 1;
return topo->logical_cores / num_sharing_cache;
}
struct cache* get_cache_info(struct cpuInfo* cpu, struct topology* topo) {
struct cache* cach = malloc(sizeof(struct cache));
uint32_t eax = 0;
uint32_t ebx = 0;
@@ -460,6 +475,13 @@ struct cache* get_cache_info(struct cpuInfo* cpu) {
return NULL;
}
if(cpu->cpu_vendor == VENDOR_INTEL) {
if(cach->L3 != UNKNOWN) cach->nL3 = 1;
}
else {
if(cach->L3 != UNKNOWN) cach->nL3 = get_number_llc_amd(topo);
}
return cach;
}
@@ -805,41 +827,45 @@ char* get_str_cache_one(int32_t cache_size) {
return string;
}
char* get_str_cache(int32_t cache_size, struct topology* topo, bool llc) {
char* get_str_cache(int32_t cache_size, struct topology* topo, bool llc, int nllc) {
if(topo->sockets == 1) {
if(llc)
return get_str_cache_one(cache_size);
if(llc) {
if(nllc > 1)
return get_str_cache_two(cache_size, nllc);
else
return get_str_cache_one(cache_size);
}
else
return get_str_cache_two(cache_size, topo->physical_cores);
}
else {
else {
if(llc)
return get_str_cache_two(cache_size, topo->sockets);
return get_str_cache_two(cache_size, nllc * topo->sockets);
else
return get_str_cache_two(cache_size, topo->physical_cores * topo->sockets);
}
}
char* get_str_l1i(struct cache* cach, struct topology* topo) {
return get_str_cache(cach->L1i, topo, false);
return get_str_cache(cach->L1i, topo, false, 1);
}
char* get_str_l1d(struct cache* cach, struct topology* topo) {
return get_str_cache(cach->L1d, topo, false);
return get_str_cache(cach->L1d, topo, false, 1);
}
char* get_str_l2(struct cache* cach, struct topology* topo) {
assert(cach->L2 != UNKNOWN);
if(cach->L3 == UNKNOWN)
return get_str_cache(cach->L2, topo, true);
return get_str_cache(cach->L2, topo, true, 1);
else
return get_str_cache(cach->L2, topo, false);
return get_str_cache(cach->L2, topo, false, 1);
}
char* get_str_l3(struct cache* cach, struct topology* topo) {
if(cach->L3 == UNKNOWN)
return NULL;
return get_str_cache(cach->L3, topo, true);
return get_str_cache(cach->L3, topo, true, cach->nL3);
}
char* get_str_freq(struct frequency* freq) {

View File

@@ -30,7 +30,7 @@ struct cpuInfo* get_cpu_info();
VENDOR get_cpu_vendor(struct cpuInfo* cpu);
uint32_t get_nsockets(struct topology* topo);
int64_t get_freq(struct frequency* freq);
struct cache* get_cache_info(struct cpuInfo* cpu);
struct cache* get_cache_info(struct cpuInfo* cpu, struct topology* topo);
struct frequency* get_frequency_info(struct cpuInfo* cpu);
struct topology* get_topology_info(struct cpuInfo* cpu);

View File

@@ -53,11 +53,7 @@ int main(int argc, char* argv[]) {
print_version();
print_levels(cpu, get_str_cpu_name(cpu));
return EXIT_SUCCESS;
}
struct cache* cach = get_cache_info(cpu);
if(cach == NULL)
return EXIT_FAILURE;
}
struct frequency* freq = get_frequency_info(cpu);
if(freq == NULL)
@@ -67,6 +63,10 @@ int main(int argc, char* argv[]) {
if(topo == NULL)
return EXIT_FAILURE;
struct cache* cach = get_cache_info(cpu, topo);
if(cach == NULL)
return EXIT_FAILURE;
if(print_cpufetch(cpu, cach, freq, topo, get_style(), get_colors()))
return EXIT_SUCCESS;
else