dep: Add cpuinfo

This commit is contained in:
Connor McLaughlin
2022-09-09 20:43:06 +10:00
parent bf76780f11
commit c27026aed5
71 changed files with 23257 additions and 0 deletions

1726
dep/cpuinfo/src/x86/cache/descriptor.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,257 @@
#include <stdint.h>
#include <cpuinfo.h>
#include <x86/cpuid.h>
#include <cpuinfo/utils.h>
#include <cpuinfo/log.h>
enum cache_type {
cache_type_none = 0,
cache_type_data = 1,
cache_type_instruction = 2,
cache_type_unified = 3,
};
bool cpuinfo_x86_decode_deterministic_cache_parameters(
struct cpuid_regs regs,
struct cpuinfo_x86_caches* cache,
uint32_t* package_cores_max)
{
const uint32_t type = regs.eax & UINT32_C(0x1F);
if (type == cache_type_none) {
return false;
}
/* Level starts at 1 */
const uint32_t level = (regs.eax >> 5) & UINT32_C(0x7);
const uint32_t sets = 1 + regs.ecx;
const uint32_t line_size = 1 + (regs.ebx & UINT32_C(0x00000FFF));
const uint32_t partitions = 1 + ((regs.ebx >> 12) & UINT32_C(0x000003FF));
const uint32_t associativity = 1 + (regs.ebx >> 22);
*package_cores_max = 1 + (regs.eax >> 26);
const uint32_t processors = 1 + ((regs.eax >> 14) & UINT32_C(0x00000FFF));
const uint32_t apic_bits = bit_length(processors);
uint32_t flags = 0;
if (regs.edx & UINT32_C(0x00000002)) {
flags |= CPUINFO_CACHE_INCLUSIVE;
}
if (regs.edx & UINT32_C(0x00000004)) {
flags |= CPUINFO_CACHE_COMPLEX_INDEXING;
}
switch (level) {
case 1:
switch (type) {
case cache_type_unified:
cache->l1d = cache->l1i = (struct cpuinfo_x86_cache) {
.size = associativity * partitions * line_size * sets,
.associativity = associativity,
.sets = sets,
.partitions = partitions,
.line_size = line_size,
.flags = flags | CPUINFO_CACHE_UNIFIED,
.apic_bits = apic_bits
};
break;
case cache_type_data:
cache->l1d = (struct cpuinfo_x86_cache) {
.size = associativity * partitions * line_size * sets,
.associativity = associativity,
.sets = sets,
.partitions = partitions,
.line_size = line_size,
.flags = flags,
.apic_bits = apic_bits
};
break;
case cache_type_instruction:
cache->l1i = (struct cpuinfo_x86_cache) {
.size = associativity * partitions * line_size * sets,
.associativity = associativity,
.sets = sets,
.partitions = partitions,
.line_size = line_size,
.flags = flags,
.apic_bits = apic_bits
};
break;
}
break;
case 2:
switch (type) {
case cache_type_instruction:
cpuinfo_log_warning("unexpected L2 instruction cache reported in leaf 0x00000004 is ignored");
break;
case cache_type_unified:
flags |= CPUINFO_CACHE_UNIFIED;
case cache_type_data:
cache->l2 = (struct cpuinfo_x86_cache) {
.size = associativity * partitions * line_size * sets,
.associativity = associativity,
.sets = sets,
.partitions = partitions,
.line_size = line_size,
.flags = flags,
.apic_bits = apic_bits
};
break;
}
break;
case 3:
switch (type) {
case cache_type_instruction:
cpuinfo_log_warning("unexpected L3 instruction cache reported in leaf 0x00000004 is ignored");
break;
case cache_type_unified:
flags |= CPUINFO_CACHE_UNIFIED;
case cache_type_data:
cache->l3 = (struct cpuinfo_x86_cache) {
.size = associativity * partitions * line_size * sets,
.associativity = associativity,
.sets = sets,
.partitions = partitions,
.line_size = line_size,
.flags = flags,
.apic_bits = apic_bits
};
break;
}
break;
case 4:
switch (type) {
case cache_type_instruction:
cpuinfo_log_warning("unexpected L4 instruction cache reported in leaf 0x00000004 is ignored");
break;
case cache_type_unified:
flags |= CPUINFO_CACHE_UNIFIED;
case cache_type_data:
cache->l4 = (struct cpuinfo_x86_cache) {
.size = associativity * partitions * line_size * sets,
.associativity = associativity,
.sets = sets,
.partitions = partitions,
.line_size = line_size,
.flags = flags,
.apic_bits = apic_bits
};
break;
}
break;
default:
cpuinfo_log_warning("unexpected L%"PRIu32" cache reported in leaf 0x00000004 is ignored", level);
break;
}
return true;
}
bool cpuinfo_x86_decode_cache_properties(
struct cpuid_regs regs,
struct cpuinfo_x86_caches* cache)
{
const uint32_t type = regs.eax & UINT32_C(0x1F);
if (type == cache_type_none) {
return false;
}
const uint32_t level = (regs.eax >> 5) & UINT32_C(0x7);
const uint32_t cores = 1 + ((regs.eax >> 14) & UINT32_C(0x00000FFF));
const uint32_t apic_bits = bit_length(cores);
const uint32_t sets = 1 + regs.ecx;
const uint32_t line_size = 1 + (regs.ebx & UINT32_C(0x00000FFF));
const uint32_t partitions = 1 + ((regs.ebx >> 12) & UINT32_C(0x000003FF));
const uint32_t associativity = 1 + (regs.ebx >> 22);
uint32_t flags = 0;
if (regs.edx & UINT32_C(0x00000002)) {
flags |= CPUINFO_CACHE_INCLUSIVE;
}
switch (level) {
case 1:
switch (type) {
case cache_type_unified:
cache->l1d = cache->l1i = (struct cpuinfo_x86_cache) {
.size = associativity * partitions * line_size * sets,
.associativity = associativity,
.sets = sets,
.partitions = partitions,
.line_size = line_size,
.flags = flags | CPUINFO_CACHE_UNIFIED,
.apic_bits = apic_bits
};
break;
case cache_type_data:
cache->l1d = (struct cpuinfo_x86_cache) {
.size = associativity * partitions * line_size * sets,
.associativity = associativity,
.sets = sets,
.partitions = partitions,
.line_size = line_size,
.flags = flags,
.apic_bits = apic_bits
};
break;
case cache_type_instruction:
cache->l1i = (struct cpuinfo_x86_cache) {
.size = associativity * partitions * line_size * sets,
.associativity = associativity,
.sets = sets,
.partitions = partitions,
.line_size = line_size,
.flags = flags,
.apic_bits = apic_bits
};
break;
}
break;
case 2:
switch (type) {
case cache_type_instruction:
cpuinfo_log_warning("unexpected L2 instruction cache reported in leaf 0x8000001D is ignored");
break;
case cache_type_unified:
flags |= CPUINFO_CACHE_UNIFIED;
case cache_type_data:
cache->l2 = (struct cpuinfo_x86_cache) {
.size = associativity * partitions * line_size * sets,
.associativity = associativity,
.sets = sets,
.partitions = partitions,
.line_size = line_size,
.flags = flags,
.apic_bits = apic_bits
};
break;
}
break;
case 3:
switch (type) {
case cache_type_instruction:
cpuinfo_log_warning("unexpected L3 instruction cache reported in leaf 0x8000001D is ignored");
break;
case cache_type_unified:
flags |= CPUINFO_CACHE_UNIFIED;
case cache_type_data:
cache->l3 = (struct cpuinfo_x86_cache) {
.size = associativity * partitions * line_size * sets,
.associativity = associativity,
.sets = sets,
.partitions = partitions,
.line_size = line_size,
.flags = flags,
.apic_bits = apic_bits
};
break;
}
break;
default:
cpuinfo_log_warning("unexpected L%"PRIu32" cache reported in leaf 0x8000001D is ignored", level);
break;
}
return true;
}

88
dep/cpuinfo/src/x86/cache/init.c vendored Normal file
View File

@ -0,0 +1,88 @@
#include <stdint.h>
#include <cpuinfo.h>
#include <cpuinfo/utils.h>
#include <cpuinfo/log.h>
#include <x86/cpuid.h>
#include <x86/api.h>
union cpuinfo_x86_cache_descriptors {
struct cpuid_regs regs;
uint8_t as_bytes[16];
};
enum cache_type {
cache_type_none = 0,
cache_type_data = 1,
cache_type_instruction = 2,
cache_type_unified = 3,
};
void cpuinfo_x86_detect_cache(
uint32_t max_base_index, uint32_t max_extended_index,
bool amd_topology_extensions,
enum cpuinfo_vendor vendor,
const struct cpuinfo_x86_model_info* model_info,
struct cpuinfo_x86_caches* cache,
struct cpuinfo_tlb* itlb_4KB,
struct cpuinfo_tlb* itlb_2MB,
struct cpuinfo_tlb* itlb_4MB,
struct cpuinfo_tlb* dtlb0_4KB,
struct cpuinfo_tlb* dtlb0_2MB,
struct cpuinfo_tlb* dtlb0_4MB,
struct cpuinfo_tlb* dtlb_4KB,
struct cpuinfo_tlb* dtlb_2MB,
struct cpuinfo_tlb* dtlb_4MB,
struct cpuinfo_tlb* dtlb_1GB,
struct cpuinfo_tlb* stlb2_4KB,
struct cpuinfo_tlb* stlb2_2MB,
struct cpuinfo_tlb* stlb2_1GB,
uint32_t* log2_package_cores_max)
{
if (max_base_index >= 2) {
union cpuinfo_x86_cache_descriptors descriptors;
descriptors.regs = cpuid(2);
uint32_t iterations = (uint8_t) descriptors.as_bytes[0];
if (iterations != 0) {
iterate_descriptors:
for (uint32_t i = 1 /* note: not 0 */; i < 16; i++) {
const uint8_t descriptor = descriptors.as_bytes[i];
if (descriptor != 0) {
cpuinfo_x86_decode_cache_descriptor(
descriptor, vendor, model_info,
cache,
itlb_4KB, itlb_2MB, itlb_4MB,
dtlb0_4KB, dtlb0_2MB, dtlb0_4MB,
dtlb_4KB, dtlb_2MB, dtlb_4MB, dtlb_1GB,
stlb2_4KB, stlb2_2MB, stlb2_1GB,
&cache->prefetch_size);
}
}
if (--iterations != 0) {
descriptors.regs = cpuid(2);
goto iterate_descriptors;
}
}
if (vendor != cpuinfo_vendor_amd && vendor != cpuinfo_vendor_hygon && max_base_index >= 4) {
struct cpuid_regs leaf4;
uint32_t input_ecx = 0;
uint32_t package_cores_max = 0;
do {
leaf4 = cpuidex(4, input_ecx++);
} while (cpuinfo_x86_decode_deterministic_cache_parameters(
leaf4, cache, &package_cores_max));
if (package_cores_max != 0) {
*log2_package_cores_max = bit_length(package_cores_max);
}
}
}
if (amd_topology_extensions && max_extended_index >= UINT32_C(0x8000001D)) {
struct cpuid_regs leaf0x8000001D;
uint32_t input_ecx = 0;
do {
leaf0x8000001D = cpuidex(UINT32_C(0x8000001D), input_ecx++);
} while (cpuinfo_x86_decode_cache_properties(leaf0x8000001D, cache));
}
}