• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdint.h>
2 
3 #include <cpuinfo.h>
4 #include <x86/cpuid.h>
5 #include <cpuinfo/utils.h>
6 #include <cpuinfo/log.h>
7 
8 
9 enum cache_type {
10 	cache_type_none = 0,
11 	cache_type_data = 1,
12 	cache_type_instruction = 2,
13 	cache_type_unified = 3,
14 };
15 
cpuinfo_x86_decode_deterministic_cache_parameters(struct cpuid_regs regs,struct cpuinfo_x86_caches * cache,uint32_t * package_cores_max)16 bool cpuinfo_x86_decode_deterministic_cache_parameters(
17 	struct cpuid_regs regs,
18 	struct cpuinfo_x86_caches* cache,
19 	uint32_t* package_cores_max)
20 {
21 	const uint32_t type = regs.eax & UINT32_C(0x1F);
22 	if (type == cache_type_none) {
23 		return false;
24 	}
25 
26 	/* Level starts at 1 */
27 	const uint32_t level = (regs.eax >> 5) & UINT32_C(0x7);
28 
29 	const uint32_t sets = 1 + regs.ecx;
30 	const uint32_t line_size = 1 + (regs.ebx & UINT32_C(0x00000FFF));
31 	const uint32_t partitions = 1 + ((regs.ebx >> 12) & UINT32_C(0x000003FF));
32 	const uint32_t associativity = 1 + (regs.ebx >> 22);
33 
34 	*package_cores_max = 1 + (regs.eax >> 26);
35 	const uint32_t processors = 1 + ((regs.eax >> 14) & UINT32_C(0x00000FFF));
36 	const uint32_t apic_bits = bit_length(processors);
37 
38 	uint32_t flags = 0;
39 	if (regs.edx & UINT32_C(0x00000002)) {
40 		flags |= CPUINFO_CACHE_INCLUSIVE;
41 	}
42 	if (regs.edx & UINT32_C(0x00000004)) {
43 		flags |= CPUINFO_CACHE_COMPLEX_INDEXING;
44 	}
45 	switch (level) {
46 		case 1:
47 			switch (type) {
48 				case cache_type_unified:
49 					cache->l1d = cache->l1i = (struct cpuinfo_x86_cache) {
50 						.size = associativity * partitions * line_size * sets,
51 						.associativity = associativity,
52 						.sets = sets,
53 						.partitions = partitions,
54 						.line_size = line_size,
55 						.flags = flags | CPUINFO_CACHE_UNIFIED,
56 						.apic_bits = apic_bits
57 					};
58 					break;
59 				case cache_type_data:
60 					cache->l1d = (struct cpuinfo_x86_cache) {
61 						.size = associativity * partitions * line_size * sets,
62 						.associativity = associativity,
63 						.sets = sets,
64 						.partitions = partitions,
65 						.line_size = line_size,
66 						.flags = flags,
67 						.apic_bits = apic_bits
68 					};
69 					break;
70 				case cache_type_instruction:
71 					cache->l1i = (struct cpuinfo_x86_cache) {
72 						.size = associativity * partitions * line_size * sets,
73 						.associativity = associativity,
74 						.sets = sets,
75 						.partitions = partitions,
76 						.line_size = line_size,
77 						.flags = flags,
78 						.apic_bits = apic_bits
79 					};
80 					break;
81 			}
82 			break;
83 		case 2:
84 			switch (type) {
85 				case cache_type_instruction:
86 					cpuinfo_log_warning("unexpected L2 instruction cache reported in leaf 0x00000004 is ignored");
87 					break;
88 				case cache_type_unified:
89 					flags |= CPUINFO_CACHE_UNIFIED;
90 				case cache_type_data:
91 					cache->l2 = (struct cpuinfo_x86_cache) {
92 						.size = associativity * partitions * line_size * sets,
93 						.associativity = associativity,
94 						.sets = sets,
95 						.partitions = partitions,
96 						.line_size = line_size,
97 						.flags = flags,
98 						.apic_bits = apic_bits
99 					};
100 					break;
101 			}
102 			break;
103 		case 3:
104 			switch (type) {
105 				case cache_type_instruction:
106 					cpuinfo_log_warning("unexpected L3 instruction cache reported in leaf 0x00000004 is ignored");
107 					break;
108 				case cache_type_unified:
109 					flags |= CPUINFO_CACHE_UNIFIED;
110 				case cache_type_data:
111 					cache->l3 = (struct cpuinfo_x86_cache) {
112 						.size = associativity * partitions * line_size * sets,
113 						.associativity = associativity,
114 						.sets = sets,
115 						.partitions = partitions,
116 						.line_size = line_size,
117 						.flags = flags,
118 						.apic_bits = apic_bits
119 					};
120 					break;
121 			}
122 			break;
123 		case 4:
124 			switch (type) {
125 				case cache_type_instruction:
126 					cpuinfo_log_warning("unexpected L4 instruction cache reported in leaf 0x00000004 is ignored");
127 					break;
128 				case cache_type_unified:
129 					flags |= CPUINFO_CACHE_UNIFIED;
130 				case cache_type_data:
131 					cache->l4 = (struct cpuinfo_x86_cache) {
132 						.size = associativity * partitions * line_size * sets,
133 						.associativity = associativity,
134 						.sets = sets,
135 						.partitions = partitions,
136 						.line_size = line_size,
137 						.flags = flags,
138 						.apic_bits = apic_bits
139 					};
140 					break;
141 			}
142 			break;
143 		default:
144 			cpuinfo_log_warning("unexpected L%"PRIu32" cache reported in leaf 0x00000004 is ignored", level);
145 			break;
146 	}
147 	return true;
148 }
149 
150 
cpuinfo_x86_decode_cache_properties(struct cpuid_regs regs,struct cpuinfo_x86_caches * cache)151 bool cpuinfo_x86_decode_cache_properties(
152 	struct cpuid_regs regs,
153 	struct cpuinfo_x86_caches* cache)
154 {
155 	const uint32_t type = regs.eax & UINT32_C(0x1F);
156 	if (type == cache_type_none) {
157 		return false;
158 	}
159 
160 	const uint32_t level = (regs.eax >> 5) & UINT32_C(0x7);
161 	const uint32_t cores = 1 + ((regs.eax >> 14) & UINT32_C(0x00000FFF));
162 	const uint32_t apic_bits = bit_length(cores);
163 
164 	const uint32_t sets = 1 + regs.ecx;
165 	const uint32_t line_size = 1 + (regs.ebx & UINT32_C(0x00000FFF));
166 	const uint32_t partitions = 1 + ((regs.ebx >> 12) & UINT32_C(0x000003FF));
167 	const uint32_t associativity = 1 + (regs.ebx >> 22);
168 
169 	uint32_t flags = 0;
170 	if (regs.edx & UINT32_C(0x00000002)) {
171 		flags |= CPUINFO_CACHE_INCLUSIVE;
172 	}
173 
174 	switch (level) {
175 		case 1:
176 			switch (type) {
177 				case cache_type_unified:
178 					cache->l1d = cache->l1i = (struct cpuinfo_x86_cache) {
179 						.size = associativity * partitions * line_size * sets,
180 						.associativity = associativity,
181 						.sets = sets,
182 						.partitions = partitions,
183 						.line_size = line_size,
184 						.flags = flags | CPUINFO_CACHE_UNIFIED,
185 						.apic_bits = apic_bits
186 					};
187 					break;
188 				case cache_type_data:
189 					cache->l1d = (struct cpuinfo_x86_cache) {
190 						.size = associativity * partitions * line_size * sets,
191 						.associativity = associativity,
192 						.sets = sets,
193 						.partitions = partitions,
194 						.line_size = line_size,
195 						.flags = flags,
196 						.apic_bits = apic_bits
197 					};
198 					break;
199 				case cache_type_instruction:
200 					cache->l1i = (struct cpuinfo_x86_cache) {
201 						.size = associativity * partitions * line_size * sets,
202 						.associativity = associativity,
203 						.sets = sets,
204 						.partitions = partitions,
205 						.line_size = line_size,
206 						.flags = flags,
207 						.apic_bits = apic_bits
208 					};
209 					break;
210 			}
211 			break;
212 		case 2:
213 			switch (type) {
214 				case cache_type_instruction:
215 					cpuinfo_log_warning("unexpected L2 instruction cache reported in leaf 0x8000001D is ignored");
216 					break;
217 				case cache_type_unified:
218 					flags |= CPUINFO_CACHE_UNIFIED;
219 				case cache_type_data:
220 					cache->l2 = (struct cpuinfo_x86_cache) {
221 						.size = associativity * partitions * line_size * sets,
222 						.associativity = associativity,
223 						.sets = sets,
224 						.partitions = partitions,
225 						.line_size = line_size,
226 						.flags = flags,
227 						.apic_bits = apic_bits
228 					};
229 					break;
230 			}
231 			break;
232 		case 3:
233 			switch (type) {
234 				case cache_type_instruction:
235 					cpuinfo_log_warning("unexpected L3 instruction cache reported in leaf 0x8000001D is ignored");
236 					break;
237 				case cache_type_unified:
238 					flags |= CPUINFO_CACHE_UNIFIED;
239 				case cache_type_data:
240 					cache->l3 = (struct cpuinfo_x86_cache) {
241 						.size = associativity * partitions * line_size * sets,
242 						.associativity = associativity,
243 						.sets = sets,
244 						.partitions = partitions,
245 						.line_size = line_size,
246 						.flags = flags,
247 						.apic_bits = apic_bits
248 					};
249 					break;
250 			}
251 			break;
252 		default:
253 			cpuinfo_log_warning("unexpected L%"PRIu32" cache reported in leaf 0x8000001D is ignored", level);
254 			break;
255 	}
256 	return true;
257 }
258