mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-18 06:15:47 -04:00
dep: Add cpuinfo
This commit is contained in:
1726
dep/cpuinfo/src/x86/cache/descriptor.c
vendored
Normal file
1726
dep/cpuinfo/src/x86/cache/descriptor.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
257
dep/cpuinfo/src/x86/cache/deterministic.c
vendored
Normal file
257
dep/cpuinfo/src/x86/cache/deterministic.c
vendored
Normal 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
88
dep/cpuinfo/src/x86/cache/init.c
vendored
Normal 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));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user