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