1 #include <stdint.h>
2
3 #include <cpuinfo.h>
4 #include <cpuinfo/utils.h>
5 #include <cpuinfo/log.h>
6 #include <x86/cpuid.h>
7 #include <x86/api.h>
8
9
10 union cpuinfo_x86_cache_descriptors {
11 struct cpuid_regs regs;
12 uint8_t as_bytes[16];
13 };
14
15 enum cache_type {
16 cache_type_none = 0,
17 cache_type_data = 1,
18 cache_type_instruction = 2,
19 cache_type_unified = 3,
20 };
21
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)22 void cpuinfo_x86_detect_cache(
23 uint32_t max_base_index, uint32_t max_extended_index,
24 bool amd_topology_extensions,
25 enum cpuinfo_vendor vendor,
26 const struct cpuinfo_x86_model_info* model_info,
27 struct cpuinfo_x86_caches* cache,
28 struct cpuinfo_tlb* itlb_4KB,
29 struct cpuinfo_tlb* itlb_2MB,
30 struct cpuinfo_tlb* itlb_4MB,
31 struct cpuinfo_tlb* dtlb0_4KB,
32 struct cpuinfo_tlb* dtlb0_2MB,
33 struct cpuinfo_tlb* dtlb0_4MB,
34 struct cpuinfo_tlb* dtlb_4KB,
35 struct cpuinfo_tlb* dtlb_2MB,
36 struct cpuinfo_tlb* dtlb_4MB,
37 struct cpuinfo_tlb* dtlb_1GB,
38 struct cpuinfo_tlb* stlb2_4KB,
39 struct cpuinfo_tlb* stlb2_2MB,
40 struct cpuinfo_tlb* stlb2_1GB,
41 uint32_t* log2_package_cores_max)
42 {
43 if (max_base_index >= 2) {
44 union cpuinfo_x86_cache_descriptors descriptors;
45 descriptors.regs = cpuid(2);
46 uint32_t iterations = (uint8_t) descriptors.as_bytes[0];
47 if (iterations != 0) {
48 iterate_descriptors:
49 for (uint32_t i = 1 /* note: not 0 */; i < 16; i++) {
50 const uint8_t descriptor = descriptors.as_bytes[i];
51 if (descriptor != 0) {
52 cpuinfo_x86_decode_cache_descriptor(
53 descriptor, vendor, model_info,
54 cache,
55 itlb_4KB, itlb_2MB, itlb_4MB,
56 dtlb0_4KB, dtlb0_2MB, dtlb0_4MB,
57 dtlb_4KB, dtlb_2MB, dtlb_4MB, dtlb_1GB,
58 stlb2_4KB, stlb2_2MB, stlb2_1GB,
59 &cache->prefetch_size);
60 }
61 }
62 if (--iterations != 0) {
63 descriptors.regs = cpuid(2);
64 goto iterate_descriptors;
65 }
66 }
67
68 if (vendor != cpuinfo_vendor_amd && vendor != cpuinfo_vendor_hygon && max_base_index >= 4) {
69 struct cpuid_regs leaf4;
70 uint32_t input_ecx = 0;
71 uint32_t package_cores_max = 0;
72 do {
73 leaf4 = cpuidex(4, input_ecx++);
74 } while (cpuinfo_x86_decode_deterministic_cache_parameters(
75 leaf4, cache, &package_cores_max));
76 if (package_cores_max != 0) {
77 *log2_package_cores_max = bit_length(package_cores_max);
78 }
79 }
80 }
81 if (amd_topology_extensions && max_extended_index >= UINT32_C(0x8000001D)) {
82 struct cpuid_regs leaf0x8000001D;
83 uint32_t input_ecx = 0;
84 do {
85 leaf0x8000001D = cpuidex(UINT32_C(0x8000001D), input_ecx++);
86 } while (cpuinfo_x86_decode_cache_properties(leaf0x8000001D, cache));
87 }
88 }
89