1
2
3
4
5
6
7
8
9#include "qemu/osdep.h"
10
11int qemu_icache_linesize = 0;
12int qemu_dcache_linesize = 0;
13
14
15
16
17
18#if defined(_AIX)
19# include <sys/systemcfg.h>
20
21static void sys_cache_info(int *isize, int *dsize)
22{
23 *isize = _system_configuration.icache_line;
24 *dsize = _system_configuration.dcache_line;
25}
26
27#elif defined(_WIN32)
28
29static void sys_cache_info(int *isize, int *dsize)
30{
31 SYSTEM_LOGICAL_PROCESSOR_INFORMATION *buf;
32 DWORD size = 0;
33 BOOL success;
34 size_t i, n;
35
36
37
38
39 success = GetLogicalProcessorInformation(0, &size);
40 if (success || GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
41 return;
42 }
43
44 n = size / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
45 size = n * sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
46 buf = g_new0(SYSTEM_LOGICAL_PROCESSOR_INFORMATION, n);
47 if (!GetLogicalProcessorInformation(buf, &size)) {
48 goto fail;
49 }
50
51 for (i = 0; i < n; i++) {
52 if (buf[i].Relationship == RelationCache
53 && buf[i].Cache.Level == 1) {
54 switch (buf[i].Cache.Type) {
55 case CacheUnified:
56 *isize = *dsize = buf[i].Cache.LineSize;
57 break;
58 case CacheInstruction:
59 *isize = buf[i].Cache.LineSize;
60 break;
61 case CacheData:
62 *dsize = buf[i].Cache.LineSize;
63 break;
64 default:
65 break;
66 }
67 }
68 }
69 fail:
70 g_free(buf);
71}
72
73#elif defined(__APPLE__) \
74 || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
75# include <sys/sysctl.h>
76# if defined(__APPLE__)
77# define SYSCTL_CACHELINE_NAME "hw.cachelinesize"
78# else
79# define SYSCTL_CACHELINE_NAME "machdep.cacheline_size"
80# endif
81
82static void sys_cache_info(int *isize, int *dsize)
83{
84
85 long size;
86 size_t len = sizeof(size);
87 if (!sysctlbyname(SYSCTL_CACHELINE_NAME, &size, &len, NULL, 0)) {
88 *isize = *dsize = size;
89 }
90}
91
92#else
93
94
95static void sys_cache_info(int *isize, int *dsize)
96{
97# ifdef _SC_LEVEL1_ICACHE_LINESIZE
98 *isize = sysconf(_SC_LEVEL1_ICACHE_LINESIZE);
99# endif
100# ifdef _SC_LEVEL1_DCACHE_LINESIZE
101 *dsize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
102# endif
103}
104#endif
105
106
107
108
109
110#if defined(__aarch64__)
111
112static void arch_cache_info(int *isize, int *dsize)
113{
114 if (*isize == 0 || *dsize == 0) {
115 unsigned long ctr;
116
117
118
119
120
121 asm volatile("mrs\t%0, ctr_el0" : "=r"(ctr));
122 if (*isize == 0) {
123 *isize = 4 << (ctr & 0xf);
124 }
125 if (*dsize == 0) {
126 *dsize = 4 << ((ctr >> 16) & 0xf);
127 }
128 }
129}
130
131#elif defined(_ARCH_PPC) && defined(__linux__)
132# include "elf.h"
133
134static void arch_cache_info(int *isize, int *dsize)
135{
136 if (*isize == 0) {
137 *isize = qemu_getauxval(AT_ICACHEBSIZE);
138 }
139 if (*dsize == 0) {
140 *dsize = qemu_getauxval(AT_DCACHEBSIZE);
141 }
142}
143
144#else
145static void arch_cache_info(int *isize, int *dsize) { }
146#endif
147
148
149
150
151
152static void fallback_cache_info(int *isize, int *dsize)
153{
154
155 if (*isize) {
156 if (*dsize) {
157
158 } else {
159 *dsize = *isize;
160 }
161 } else if (*dsize) {
162 *isize = *dsize;
163 } else {
164#if defined(_ARCH_PPC)
165
166
167
168 *isize = *dsize = 16;
169#else
170
171 *isize = *dsize = 64;
172#endif
173 }
174}
175
176static void __attribute__((constructor)) init_cache_info(void)
177{
178 int isize = 0, dsize = 0;
179
180 sys_cache_info(&isize, &dsize);
181 arch_cache_info(&isize, &dsize);
182 fallback_cache_info(&isize, &dsize);
183
184 qemu_icache_linesize = isize;
185 qemu_dcache_linesize = dsize;
186}
187