aboutsummaryrefslogtreecommitdiff
path: root/src/x86/cache/init.c
blob: b2af08d4db74770cabe4d777862f5cfb117c44e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <stdint.h>

#include <cpuinfo.h>
#include <utils.h>
#include <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 && 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));
	}
}