]>
Commit | Line | Data |
---|---|---|
d14d42f1 PM |
1 | /* |
2 | * QEMU AArch64 CPU | |
3 | * | |
4 | * Copyright (c) 2013 Linaro Ltd | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License | |
8 | * as published by the Free Software Foundation; either version 2 | |
9 | * of the License, or (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program; if not, see | |
18 | * <http://www.gnu.org/licenses/gpl-2.0.html> | |
19 | */ | |
20 | ||
74c21bd0 | 21 | #include "qemu/osdep.h" |
da34e65c | 22 | #include "qapi/error.h" |
d14d42f1 | 23 | #include "cpu.h" |
0b8fa32f | 24 | #include "qemu/module.h" |
d14d42f1 | 25 | #include "sysemu/kvm.h" |
6ee609b7 | 26 | #include "sysemu/hvf.h" |
bab52d4b | 27 | #include "kvm_arm.h" |
dcfb1d04 | 28 | #include "hvf_arm.h" |
adf92eab | 29 | #include "qapi/visitor.h" |
eb94284d | 30 | #include "hw/qdev-properties.h" |
7c1aaf98 | 31 | #include "internals.h" |
eb94284d | 32 | |
3b16766b HW |
33 | static void aarch64_a35_initfn(Object *obj) |
34 | { | |
35 | ARMCPU *cpu = ARM_CPU(obj); | |
36 | ||
37 | cpu->dtb_compatible = "arm,cortex-a35"; | |
38 | set_feature(&cpu->env, ARM_FEATURE_V8); | |
39 | set_feature(&cpu->env, ARM_FEATURE_NEON); | |
40 | set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); | |
41 | set_feature(&cpu->env, ARM_FEATURE_AARCH64); | |
42 | set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); | |
43 | set_feature(&cpu->env, ARM_FEATURE_EL2); | |
44 | set_feature(&cpu->env, ARM_FEATURE_EL3); | |
45 | set_feature(&cpu->env, ARM_FEATURE_PMU); | |
46 | ||
47 | /* From B2.2 AArch64 identification registers. */ | |
48 | cpu->midr = 0x411fd040; | |
49 | cpu->revidr = 0; | |
50 | cpu->ctr = 0x84448004; | |
51 | cpu->isar.id_pfr0 = 0x00000131; | |
52 | cpu->isar.id_pfr1 = 0x00011011; | |
53 | cpu->isar.id_dfr0 = 0x03010066; | |
54 | cpu->id_afr0 = 0; | |
55 | cpu->isar.id_mmfr0 = 0x10201105; | |
56 | cpu->isar.id_mmfr1 = 0x40000000; | |
57 | cpu->isar.id_mmfr2 = 0x01260000; | |
58 | cpu->isar.id_mmfr3 = 0x02102211; | |
59 | cpu->isar.id_isar0 = 0x02101110; | |
60 | cpu->isar.id_isar1 = 0x13112111; | |
61 | cpu->isar.id_isar2 = 0x21232042; | |
62 | cpu->isar.id_isar3 = 0x01112131; | |
63 | cpu->isar.id_isar4 = 0x00011142; | |
64 | cpu->isar.id_isar5 = 0x00011121; | |
65 | cpu->isar.id_aa64pfr0 = 0x00002222; | |
66 | cpu->isar.id_aa64pfr1 = 0; | |
67 | cpu->isar.id_aa64dfr0 = 0x10305106; | |
68 | cpu->isar.id_aa64dfr1 = 0; | |
69 | cpu->isar.id_aa64isar0 = 0x00011120; | |
70 | cpu->isar.id_aa64isar1 = 0; | |
71 | cpu->isar.id_aa64mmfr0 = 0x00101122; | |
72 | cpu->isar.id_aa64mmfr1 = 0; | |
73 | cpu->clidr = 0x0a200023; | |
74 | cpu->dcz_blocksize = 4; | |
75 | ||
76 | /* From B2.4 AArch64 Virtual Memory control registers */ | |
77 | cpu->reset_sctlr = 0x00c50838; | |
78 | ||
79 | /* From B2.10 AArch64 performance monitor registers */ | |
80 | cpu->isar.reset_pmcr_el0 = 0x410a3000; | |
81 | ||
82 | /* From B2.29 Cache ID registers */ | |
83 | cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */ | |
84 | cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */ | |
85 | cpu->ccsidr[2] = 0x703fe03a; /* 512KB L2 cache */ | |
86 | ||
87 | /* From B3.5 VGIC Type register */ | |
88 | cpu->gic_num_lrs = 4; | |
89 | cpu->gic_vpribits = 5; | |
90 | cpu->gic_vprebits = 5; | |
91 | cpu->gic_pribits = 5; | |
92 | ||
93 | /* From C6.4 Debug ID Register */ | |
94 | cpu->isar.dbgdidr = 0x3516d000; | |
95 | /* From C6.5 Debug Device ID Register */ | |
96 | cpu->isar.dbgdevid = 0x00110f13; | |
97 | /* From C6.6 Debug Device ID Register 1 */ | |
98 | cpu->isar.dbgdevid1 = 0x2; | |
99 | ||
100 | /* From Cortex-A35 SIMD and Floating-point Support r1p0 */ | |
101 | /* From 3.2 AArch32 register summary */ | |
102 | cpu->reset_fpsid = 0x41034043; | |
103 | ||
104 | /* From 2.2 AArch64 register summary */ | |
105 | cpu->isar.mvfr0 = 0x10110222; | |
106 | cpu->isar.mvfr1 = 0x12111111; | |
107 | cpu->isar.mvfr2 = 0x00000043; | |
108 | ||
109 | /* These values are the same with A53/A57/A72. */ | |
110 | define_cortex_a72_a57_a53_cp_reginfo(cpu); | |
111 | } | |
d14d42f1 | 112 | |
0df9142d AJ |
113 | void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) |
114 | { | |
115 | /* | |
116 | * If any vector lengths are explicitly enabled with sve<N> properties, | |
117 | * then all other lengths are implicitly disabled. If sve-max-vq is | |
118 | * specified then it is the same as explicitly enabling all lengths | |
119 | * up to and including the specified maximum, which means all larger | |
120 | * lengths will be implicitly disabled. If no sve<N> properties | |
121 | * are enabled and sve-max-vq is not specified, then all lengths not | |
122 | * explicitly disabled will be enabled. Additionally, all power-of-two | |
123 | * vector lengths less than the maximum enabled length will be | |
124 | * automatically enabled and all vector lengths larger than the largest | |
125 | * disabled power-of-two vector length will be automatically disabled. | |
126 | * Errors are generated if the user provided input that interferes with | |
127 | * any of the above. Finally, if SVE is not disabled, then at least one | |
128 | * vector length must be enabled. | |
129 | */ | |
7f9e25a6 RH |
130 | uint32_t vq_map = cpu->sve_vq.map; |
131 | uint32_t vq_init = cpu->sve_vq.init; | |
886902ec RH |
132 | uint32_t vq_supported; |
133 | uint32_t vq_mask = 0; | |
134 | uint32_t tmp, vq, max_vq = 0; | |
0df9142d | 135 | |
5b65e5ab AJ |
136 | /* |
137 | * CPU models specify a set of supported vector lengths which are | |
138 | * enabled by default. Attempting to enable any vector length not set | |
139 | * in the supported bitmap results in an error. When KVM is enabled we | |
140 | * fetch the supported bitmap from the host. | |
141 | */ | |
886902ec RH |
142 | if (kvm_enabled()) { |
143 | if (kvm_arm_sve_supported()) { | |
7f9e25a6 RH |
144 | cpu->sve_vq.supported = kvm_arm_sve_get_vls(CPU(cpu)); |
145 | vq_supported = cpu->sve_vq.supported; | |
886902ec RH |
146 | } else { |
147 | assert(!cpu_isar_feature(aa64_sve, cpu)); | |
148 | vq_supported = 0; | |
149 | } | |
150 | } else { | |
7f9e25a6 | 151 | vq_supported = cpu->sve_vq.supported; |
6fa8a379 AJ |
152 | } |
153 | ||
0df9142d AJ |
154 | /* |
155 | * Process explicit sve<N> properties. | |
156 | * From the properties, sve_vq_map<N> implies sve_vq_init<N>. | |
157 | * Check first for any sve<N> enabled. | |
158 | */ | |
886902ec RH |
159 | if (vq_map != 0) { |
160 | max_vq = 32 - clz32(vq_map); | |
161 | vq_mask = MAKE_64BIT_MASK(0, max_vq); | |
0df9142d AJ |
162 | |
163 | if (cpu->sve_max_vq && max_vq > cpu->sve_max_vq) { | |
164 | error_setg(errp, "cannot enable sve%d", max_vq * 128); | |
165 | error_append_hint(errp, "sve%d is larger than the maximum vector " | |
166 | "length, sve-max-vq=%d (%d bits)\n", | |
167 | max_vq * 128, cpu->sve_max_vq, | |
168 | cpu->sve_max_vq * 128); | |
169 | return; | |
170 | } | |
171 | ||
6fa8a379 AJ |
172 | if (kvm_enabled()) { |
173 | /* | |
174 | * For KVM we have to automatically enable all supported unitialized | |
175 | * lengths, even when the smaller lengths are not all powers-of-two. | |
176 | */ | |
886902ec | 177 | vq_map |= vq_supported & ~vq_init & vq_mask; |
6fa8a379 AJ |
178 | } else { |
179 | /* Propagate enabled bits down through required powers-of-two. */ | |
886902ec | 180 | vq_map |= SVE_VQ_POW2_MAP & ~vq_init & vq_mask; |
0df9142d AJ |
181 | } |
182 | } else if (cpu->sve_max_vq == 0) { | |
183 | /* | |
184 | * No explicit bits enabled, and no implicit bits from sve-max-vq. | |
185 | */ | |
186 | if (!cpu_isar_feature(aa64_sve, cpu)) { | |
187 | /* SVE is disabled and so are all vector lengths. Good. */ | |
188 | return; | |
189 | } | |
190 | ||
6fa8a379 AJ |
191 | if (kvm_enabled()) { |
192 | /* Disabling a supported length disables all larger lengths. */ | |
886902ec | 193 | tmp = vq_init & vq_supported; |
6fa8a379 AJ |
194 | } else { |
195 | /* Disabling a power-of-two disables all larger lengths. */ | |
886902ec | 196 | tmp = vq_init & SVE_VQ_POW2_MAP; |
022707e5 | 197 | } |
886902ec | 198 | vq = ctz32(tmp) + 1; |
022707e5 AJ |
199 | |
200 | max_vq = vq <= ARM_MAX_VQ ? vq - 1 : ARM_MAX_VQ; | |
886902ec RH |
201 | vq_mask = MAKE_64BIT_MASK(0, max_vq); |
202 | vq_map = vq_supported & ~vq_init & vq_mask; | |
203 | ||
204 | if (max_vq == 0 || vq_map == 0) { | |
022707e5 AJ |
205 | error_setg(errp, "cannot disable sve%d", vq * 128); |
206 | error_append_hint(errp, "Disabling sve%d results in all " | |
207 | "vector lengths being disabled.\n", | |
208 | vq * 128); | |
209 | error_append_hint(errp, "With SVE enabled, at least one " | |
210 | "vector length must be enabled.\n"); | |
211 | return; | |
0df9142d | 212 | } |
0df9142d | 213 | |
886902ec RH |
214 | max_vq = 32 - clz32(vq_map); |
215 | vq_mask = MAKE_64BIT_MASK(0, max_vq); | |
0df9142d AJ |
216 | } |
217 | ||
218 | /* | |
219 | * Process the sve-max-vq property. | |
220 | * Note that we know from the above that no bit above | |
221 | * sve-max-vq is currently set. | |
222 | */ | |
223 | if (cpu->sve_max_vq != 0) { | |
224 | max_vq = cpu->sve_max_vq; | |
886902ec | 225 | vq_mask = MAKE_64BIT_MASK(0, max_vq); |
0df9142d | 226 | |
886902ec | 227 | if (vq_init & ~vq_map & (1 << (max_vq - 1))) { |
0df9142d AJ |
228 | error_setg(errp, "cannot disable sve%d", max_vq * 128); |
229 | error_append_hint(errp, "The maximum vector length must be " | |
230 | "enabled, sve-max-vq=%d (%d bits)\n", | |
231 | max_vq, max_vq * 128); | |
232 | return; | |
233 | } | |
234 | ||
235 | /* Set all bits not explicitly set within sve-max-vq. */ | |
886902ec | 236 | vq_map |= ~vq_init & vq_mask; |
0df9142d AJ |
237 | } |
238 | ||
239 | /* | |
240 | * We should know what max-vq is now. Also, as we're done | |
241 | * manipulating sve-vq-map, we ensure any bits above max-vq | |
242 | * are clear, just in case anybody looks. | |
243 | */ | |
244 | assert(max_vq != 0); | |
886902ec RH |
245 | assert(vq_mask != 0); |
246 | vq_map &= vq_mask; | |
0df9142d | 247 | |
022707e5 | 248 | /* Ensure the set of lengths matches what is supported. */ |
886902ec RH |
249 | tmp = vq_map ^ (vq_supported & vq_mask); |
250 | if (tmp) { | |
251 | vq = 32 - clz32(tmp); | |
252 | if (vq_map & (1 << (vq - 1))) { | |
022707e5 AJ |
253 | if (cpu->sve_max_vq) { |
254 | error_setg(errp, "cannot set sve-max-vq=%d", cpu->sve_max_vq); | |
255 | error_append_hint(errp, "This CPU does not support " | |
256 | "the vector length %d-bits.\n", vq * 128); | |
257 | error_append_hint(errp, "It may not be possible to use " | |
258 | "sve-max-vq with this CPU. Try " | |
259 | "using only sve<N> properties.\n"); | |
6fa8a379 | 260 | } else { |
022707e5 | 261 | error_setg(errp, "cannot enable sve%d", vq * 128); |
531cc510 RH |
262 | if (vq_supported) { |
263 | error_append_hint(errp, "This CPU does not support " | |
264 | "the vector length %d-bits.\n", vq * 128); | |
265 | } else { | |
266 | error_append_hint(errp, "SVE not supported by KVM " | |
267 | "on this host\n"); | |
268 | } | |
022707e5 AJ |
269 | } |
270 | return; | |
271 | } else { | |
272 | if (kvm_enabled()) { | |
6fa8a379 AJ |
273 | error_setg(errp, "cannot disable sve%d", vq * 128); |
274 | error_append_hint(errp, "The KVM host requires all " | |
275 | "supported vector lengths smaller " | |
276 | "than %d bits to also be enabled.\n", | |
277 | max_vq * 128); | |
6fa8a379 | 278 | return; |
022707e5 AJ |
279 | } else { |
280 | /* Ensure all required powers-of-two are enabled. */ | |
886902ec RH |
281 | tmp = SVE_VQ_POW2_MAP & vq_mask & ~vq_map; |
282 | if (tmp) { | |
283 | vq = 32 - clz32(tmp); | |
284 | error_setg(errp, "cannot disable sve%d", vq * 128); | |
285 | error_append_hint(errp, "sve%d is required as it " | |
286 | "is a power-of-two length smaller " | |
287 | "than the maximum, sve%d\n", | |
288 | vq * 128, max_vq * 128); | |
289 | return; | |
022707e5 | 290 | } |
6fa8a379 AJ |
291 | } |
292 | } | |
0df9142d AJ |
293 | } |
294 | ||
295 | /* | |
296 | * Now that we validated all our vector lengths, the only question | |
297 | * left to answer is if we even want SVE at all. | |
298 | */ | |
299 | if (!cpu_isar_feature(aa64_sve, cpu)) { | |
300 | error_setg(errp, "cannot enable sve%d", max_vq * 128); | |
301 | error_append_hint(errp, "SVE must be enabled to enable vector " | |
302 | "lengths.\n"); | |
303 | error_append_hint(errp, "Add sve=on to the CPU property list.\n"); | |
304 | return; | |
305 | } | |
306 | ||
307 | /* From now on sve_max_vq is the actual maximum supported length. */ | |
308 | cpu->sve_max_vq = max_vq; | |
7f9e25a6 | 309 | cpu->sve_vq.map = vq_map; |
0df9142d AJ |
310 | } |
311 | ||
73234775 AJ |
312 | static void cpu_max_get_sve_max_vq(Object *obj, Visitor *v, const char *name, |
313 | void *opaque, Error **errp) | |
adf92eab RH |
314 | { |
315 | ARMCPU *cpu = ARM_CPU(obj); | |
73234775 AJ |
316 | uint32_t value; |
317 | ||
318 | /* All vector lengths are disabled when SVE is off. */ | |
319 | if (!cpu_isar_feature(aa64_sve, cpu)) { | |
320 | value = 0; | |
321 | } else { | |
322 | value = cpu->sve_max_vq; | |
323 | } | |
324 | visit_type_uint32(v, name, &value, errp); | |
adf92eab RH |
325 | } |
326 | ||
73234775 AJ |
327 | static void cpu_max_set_sve_max_vq(Object *obj, Visitor *v, const char *name, |
328 | void *opaque, Error **errp) | |
adf92eab RH |
329 | { |
330 | ARMCPU *cpu = ARM_CPU(obj); | |
6fa8a379 AJ |
331 | uint32_t max_vq; |
332 | ||
668f62ec | 333 | if (!visit_type_uint32(v, name, &max_vq, errp)) { |
6fa8a379 AJ |
334 | return; |
335 | } | |
adf92eab | 336 | |
7d20e681 | 337 | if (kvm_enabled() && !kvm_arm_sve_supported()) { |
6fa8a379 AJ |
338 | error_setg(errp, "cannot set sve-max-vq"); |
339 | error_append_hint(errp, "SVE not supported by KVM on this host\n"); | |
340 | return; | |
341 | } | |
adf92eab | 342 | |
6fa8a379 AJ |
343 | if (max_vq == 0 || max_vq > ARM_MAX_VQ) { |
344 | error_setg(errp, "unsupported SVE vector length"); | |
345 | error_append_hint(errp, "Valid sve-max-vq in range [1-%d]\n", | |
adf92eab | 346 | ARM_MAX_VQ); |
6fa8a379 | 347 | return; |
adf92eab | 348 | } |
6fa8a379 AJ |
349 | |
350 | cpu->sve_max_vq = max_vq; | |
adf92eab RH |
351 | } |
352 | ||
8073b871 | 353 | /* |
0f40784e RH |
354 | * Note that cpu_arm_{get,set}_vq cannot use the simpler |
355 | * object_property_add_bool interface because they make use of the | |
356 | * contents of "name" to determine which bit on which to operate. | |
8073b871 | 357 | */ |
0f40784e RH |
358 | static void cpu_arm_get_vq(Object *obj, Visitor *v, const char *name, |
359 | void *opaque, Error **errp) | |
0df9142d AJ |
360 | { |
361 | ARMCPU *cpu = ARM_CPU(obj); | |
0f40784e | 362 | ARMVQMap *vq_map = opaque; |
0df9142d | 363 | uint32_t vq = atoi(&name[3]) / 128; |
e74c0976 | 364 | bool sve = vq_map == &cpu->sve_vq; |
0df9142d AJ |
365 | bool value; |
366 | ||
e74c0976 RH |
367 | /* All vector lengths are disabled when feature is off. */ |
368 | if (sve | |
369 | ? !cpu_isar_feature(aa64_sve, cpu) | |
370 | : !cpu_isar_feature(aa64_sme, cpu)) { | |
0df9142d AJ |
371 | value = false; |
372 | } else { | |
0f40784e | 373 | value = extract32(vq_map->map, vq - 1, 1); |
0df9142d AJ |
374 | } |
375 | visit_type_bool(v, name, &value, errp); | |
376 | } | |
377 | ||
0f40784e RH |
378 | static void cpu_arm_set_vq(Object *obj, Visitor *v, const char *name, |
379 | void *opaque, Error **errp) | |
0df9142d | 380 | { |
0f40784e | 381 | ARMVQMap *vq_map = opaque; |
0df9142d | 382 | uint32_t vq = atoi(&name[3]) / 128; |
0df9142d AJ |
383 | bool value; |
384 | ||
668f62ec | 385 | if (!visit_type_bool(v, name, &value, errp)) { |
0df9142d AJ |
386 | return; |
387 | } | |
388 | ||
0f40784e RH |
389 | vq_map->map = deposit32(vq_map->map, vq - 1, 1, value); |
390 | vq_map->init |= 1 << (vq - 1); | |
0df9142d AJ |
391 | } |
392 | ||
8073b871 | 393 | static bool cpu_arm_get_sve(Object *obj, Error **errp) |
73234775 AJ |
394 | { |
395 | ARMCPU *cpu = ARM_CPU(obj); | |
8073b871 | 396 | return cpu_isar_feature(aa64_sve, cpu); |
73234775 AJ |
397 | } |
398 | ||
8073b871 | 399 | static void cpu_arm_set_sve(Object *obj, bool value, Error **errp) |
73234775 AJ |
400 | { |
401 | ARMCPU *cpu = ARM_CPU(obj); | |
73234775 AJ |
402 | uint64_t t; |
403 | ||
7d20e681 | 404 | if (value && kvm_enabled() && !kvm_arm_sve_supported()) { |
14e99e0f AJ |
405 | error_setg(errp, "'sve' feature not supported by KVM on this host"); |
406 | return; | |
407 | } | |
408 | ||
73234775 AJ |
409 | t = cpu->isar.id_aa64pfr0; |
410 | t = FIELD_DP64(t, ID_AA64PFR0, SVE, value); | |
411 | cpu->isar.id_aa64pfr0 = t; | |
412 | } | |
413 | ||
e74c0976 RH |
414 | void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp) |
415 | { | |
416 | uint32_t vq_map = cpu->sme_vq.map; | |
417 | uint32_t vq_init = cpu->sme_vq.init; | |
418 | uint32_t vq_supported = cpu->sme_vq.supported; | |
419 | uint32_t vq; | |
420 | ||
421 | if (vq_map == 0) { | |
422 | if (!cpu_isar_feature(aa64_sme, cpu)) { | |
423 | cpu->isar.id_aa64smfr0 = 0; | |
424 | return; | |
425 | } | |
426 | ||
427 | /* TODO: KVM will require limitations via SMCR_EL2. */ | |
428 | vq_map = vq_supported & ~vq_init; | |
429 | ||
430 | if (vq_map == 0) { | |
431 | vq = ctz32(vq_supported) + 1; | |
432 | error_setg(errp, "cannot disable sme%d", vq * 128); | |
433 | error_append_hint(errp, "All SME vector lengths are disabled.\n"); | |
434 | error_append_hint(errp, "With SME enabled, at least one " | |
435 | "vector length must be enabled.\n"); | |
436 | return; | |
437 | } | |
438 | } else { | |
439 | if (!cpu_isar_feature(aa64_sme, cpu)) { | |
440 | vq = 32 - clz32(vq_map); | |
441 | error_setg(errp, "cannot enable sme%d", vq * 128); | |
442 | error_append_hint(errp, "SME must be enabled to enable " | |
443 | "vector lengths.\n"); | |
444 | error_append_hint(errp, "Add sme=on to the CPU property list.\n"); | |
445 | return; | |
446 | } | |
447 | /* TODO: KVM will require limitations via SMCR_EL2. */ | |
448 | } | |
449 | ||
450 | cpu->sme_vq.map = vq_map; | |
451 | } | |
452 | ||
453 | static bool cpu_arm_get_sme(Object *obj, Error **errp) | |
454 | { | |
455 | ARMCPU *cpu = ARM_CPU(obj); | |
456 | return cpu_isar_feature(aa64_sme, cpu); | |
457 | } | |
458 | ||
459 | static void cpu_arm_set_sme(Object *obj, bool value, Error **errp) | |
460 | { | |
461 | ARMCPU *cpu = ARM_CPU(obj); | |
462 | uint64_t t; | |
463 | ||
464 | t = cpu->isar.id_aa64pfr1; | |
465 | t = FIELD_DP64(t, ID_AA64PFR1, SME, value); | |
466 | cpu->isar.id_aa64pfr1 = t; | |
467 | } | |
468 | ||
469 | static bool cpu_arm_get_sme_fa64(Object *obj, Error **errp) | |
470 | { | |
471 | ARMCPU *cpu = ARM_CPU(obj); | |
472 | return cpu_isar_feature(aa64_sme, cpu) && | |
473 | cpu_isar_feature(aa64_sme_fa64, cpu); | |
474 | } | |
475 | ||
476 | static void cpu_arm_set_sme_fa64(Object *obj, bool value, Error **errp) | |
477 | { | |
478 | ARMCPU *cpu = ARM_CPU(obj); | |
479 | uint64_t t; | |
480 | ||
481 | t = cpu->isar.id_aa64smfr0; | |
482 | t = FIELD_DP64(t, ID_AA64SMFR0, FA64, value); | |
483 | cpu->isar.id_aa64smfr0 = t; | |
484 | } | |
485 | ||
b3d52804 | 486 | #ifdef CONFIG_USER_ONLY |
e74c0976 | 487 | /* Mirror linux /proc/sys/abi/{sve,sme}_default_vector_length. */ |
515816a8 RH |
488 | static void cpu_arm_set_default_vec_len(Object *obj, Visitor *v, |
489 | const char *name, void *opaque, | |
490 | Error **errp) | |
b3d52804 | 491 | { |
515816a8 | 492 | uint32_t *ptr_default_vq = opaque; |
b3d52804 RH |
493 | int32_t default_len, default_vq, remainder; |
494 | ||
495 | if (!visit_type_int32(v, name, &default_len, errp)) { | |
496 | return; | |
497 | } | |
498 | ||
499 | /* Undocumented, but the kernel allows -1 to indicate "maximum". */ | |
500 | if (default_len == -1) { | |
515816a8 | 501 | *ptr_default_vq = ARM_MAX_VQ; |
b3d52804 RH |
502 | return; |
503 | } | |
504 | ||
505 | default_vq = default_len / 16; | |
506 | remainder = default_len % 16; | |
507 | ||
508 | /* | |
042e85d1 PM |
509 | * Note that the 512 max comes from include/uapi/asm/sve_context.h |
510 | * and is the maximum architectural width of ZCR_ELx.LEN. | |
511 | */ | |
512 | if (remainder || default_vq < 1 || default_vq > 512) { | |
513 | ARMCPU *cpu = ARM_CPU(obj); | |
514 | const char *which = | |
515 | (ptr_default_vq == &cpu->sve_default_vq ? "sve" : "sme"); | |
516 | ||
517 | error_setg(errp, "cannot set %s-default-vector-length", which); | |
518 | if (remainder) { | |
519 | error_append_hint(errp, "Vector length not a multiple of 16\n"); | |
520 | } else if (default_vq < 1) { | |
521 | error_append_hint(errp, "Vector length smaller than 16\n"); | |
522 | } else { | |
523 | error_append_hint(errp, "Vector length larger than %d\n", | |
524 | 512 * 16); | |
525 | } | |
526 | return; | |
527 | } | |
528 | ||
529 | *ptr_default_vq = default_vq; | |
530 | } | |
531 | ||
532 | static void cpu_arm_get_default_vec_len(Object *obj, Visitor *v, | |
533 | const char *name, void *opaque, | |
534 | Error **errp) | |
535 | { | |
536 | uint32_t *ptr_default_vq = opaque; | |
537 | int32_t value = *ptr_default_vq * 16; | |
538 | ||
539 | visit_type_int32(v, name, &value, errp); | |
540 | } | |
541 | #endif | |
542 | ||
543 | static void aarch64_add_sve_properties(Object *obj) | |
544 | { | |
545 | ARMCPU *cpu = ARM_CPU(obj); | |
546 | uint32_t vq; | |
547 | ||
548 | object_property_add_bool(obj, "sve", cpu_arm_get_sve, cpu_arm_set_sve); | |
549 | ||
550 | for (vq = 1; vq <= ARM_MAX_VQ; ++vq) { | |
551 | char name[8]; | |
552 | sprintf(name, "sve%d", vq * 128); | |
553 | object_property_add(obj, name, "bool", cpu_arm_get_vq, | |
554 | cpu_arm_set_vq, NULL, &cpu->sve_vq); | |
555 | } | |
556 | ||
557 | #ifdef CONFIG_USER_ONLY | |
558 | /* Mirror linux /proc/sys/abi/sve_default_vector_length. */ | |
559 | object_property_add(obj, "sve-default-vector-length", "int32", | |
560 | cpu_arm_get_default_vec_len, | |
561 | cpu_arm_set_default_vec_len, NULL, | |
562 | &cpu->sve_default_vq); | |
563 | #endif | |
564 | } | |
565 | ||
566 | static void aarch64_add_sme_properties(Object *obj) | |
567 | { | |
568 | ARMCPU *cpu = ARM_CPU(obj); | |
569 | uint32_t vq; | |
570 | ||
571 | object_property_add_bool(obj, "sme", cpu_arm_get_sme, cpu_arm_set_sme); | |
572 | object_property_add_bool(obj, "sme_fa64", cpu_arm_get_sme_fa64, | |
573 | cpu_arm_set_sme_fa64); | |
574 | ||
575 | for (vq = 1; vq <= ARM_MAX_VQ; vq <<= 1) { | |
576 | char name[8]; | |
577 | sprintf(name, "sme%d", vq * 128); | |
578 | object_property_add(obj, name, "bool", cpu_arm_get_vq, | |
579 | cpu_arm_set_vq, NULL, &cpu->sme_vq); | |
580 | } | |
581 | ||
582 | #ifdef CONFIG_USER_ONLY | |
583 | /* Mirror linux /proc/sys/abi/sme_default_vector_length. */ | |
584 | object_property_add(obj, "sme-default-vector-length", "int32", | |
585 | cpu_arm_get_default_vec_len, | |
586 | cpu_arm_set_default_vec_len, NULL, | |
587 | &cpu->sme_default_vq); | |
588 | #endif | |
589 | } | |
590 | ||
591 | void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) | |
592 | { | |
593 | int arch_val = 0, impdef_val = 0; | |
594 | uint64_t t; | |
595 | ||
596 | /* Exit early if PAuth is enabled, and fall through to disable it */ | |
597 | if ((kvm_enabled() || hvf_enabled()) && cpu->prop_pauth) { | |
598 | if (!cpu_isar_feature(aa64_pauth, cpu)) { | |
599 | error_setg(errp, "'pauth' feature not supported by %s on this host", | |
600 | kvm_enabled() ? "KVM" : "hvf"); | |
601 | } | |
602 | ||
603 | return; | |
604 | } | |
605 | ||
606 | /* TODO: Handle HaveEnhancedPAC, HaveEnhancedPAC2, HaveFPAC. */ | |
607 | if (cpu->prop_pauth) { | |
608 | if (cpu->prop_pauth_impdef) { | |
609 | impdef_val = 1; | |
610 | } else { | |
611 | arch_val = 1; | |
612 | } | |
613 | } else if (cpu->prop_pauth_impdef) { | |
614 | error_setg(errp, "cannot enable pauth-impdef without pauth"); | |
615 | error_append_hint(errp, "Add pauth=on to the CPU property list.\n"); | |
616 | } | |
617 | ||
618 | t = cpu->isar.id_aa64isar1; | |
619 | t = FIELD_DP64(t, ID_AA64ISAR1, APA, arch_val); | |
620 | t = FIELD_DP64(t, ID_AA64ISAR1, GPA, arch_val); | |
621 | t = FIELD_DP64(t, ID_AA64ISAR1, API, impdef_val); | |
622 | t = FIELD_DP64(t, ID_AA64ISAR1, GPI, impdef_val); | |
623 | cpu->isar.id_aa64isar1 = t; | |
624 | } | |
625 | ||
626 | static Property arm_cpu_pauth_property = | |
627 | DEFINE_PROP_BOOL("pauth", ARMCPU, prop_pauth, true); | |
628 | static Property arm_cpu_pauth_impdef_property = | |
629 | DEFINE_PROP_BOOL("pauth-impdef", ARMCPU, prop_pauth_impdef, false); | |
630 | ||
631 | static void aarch64_add_pauth_properties(Object *obj) | |
632 | { | |
633 | ARMCPU *cpu = ARM_CPU(obj); | |
634 | ||
635 | /* Default to PAUTH on, with the architected algorithm on TCG. */ | |
636 | qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_property); | |
637 | if (kvm_enabled() || hvf_enabled()) { | |
638 | /* | |
639 | * Mirror PAuth support from the probed sysregs back into the | |
640 | * property for KVM or hvf. Is it just a bit backward? Yes it is! | |
641 | * Note that prop_pauth is true whether the host CPU supports the | |
642 | * architected QARMA5 algorithm or the IMPDEF one. We don't | |
643 | * provide the separate pauth-impdef property for KVM or hvf, | |
644 | * only for TCG. | |
645 | */ | |
646 | cpu->prop_pauth = cpu_isar_feature(aa64_pauth, cpu); | |
647 | } else { | |
648 | qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_impdef_property); | |
649 | } | |
650 | } | |
651 | ||
652 | static Property arm_cpu_lpa2_property = | |
653 | DEFINE_PROP_BOOL("lpa2", ARMCPU, prop_lpa2, true); | |
654 | ||
655 | void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp) | |
656 | { | |
657 | uint64_t t; | |
658 | ||
659 | /* | |
660 | * We only install the property for tcg -cpu max; this is the | |
661 | * only situation in which the cpu field can be true. | |
b3d52804 | 662 | */ |
042e85d1 | 663 | if (!cpu->prop_lpa2) { |
b3d52804 RH |
664 | return; |
665 | } | |
666 | ||
042e85d1 PM |
667 | t = cpu->isar.id_aa64mmfr0; |
668 | t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16, 2); /* 16k pages w/ LPA2 */ | |
669 | t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4, 1); /* 4k pages w/ LPA2 */ | |
670 | t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16_2, 3); /* 16k stage2 w/ LPA2 */ | |
671 | t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 3); /* 4k stage2 w/ LPA2 */ | |
672 | cpu->isar.id_aa64mmfr0 = t; | |
b3d52804 RH |
673 | } |
674 | ||
042e85d1 | 675 | static void aarch64_a57_initfn(Object *obj) |
b3d52804 | 676 | { |
042e85d1 | 677 | ARMCPU *cpu = ARM_CPU(obj); |
b3d52804 | 678 | |
042e85d1 PM |
679 | cpu->dtb_compatible = "arm,cortex-a57"; |
680 | set_feature(&cpu->env, ARM_FEATURE_V8); | |
681 | set_feature(&cpu->env, ARM_FEATURE_NEON); | |
682 | set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); | |
683 | set_feature(&cpu->env, ARM_FEATURE_AARCH64); | |
684 | set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); | |
685 | set_feature(&cpu->env, ARM_FEATURE_EL2); | |
686 | set_feature(&cpu->env, ARM_FEATURE_EL3); | |
687 | set_feature(&cpu->env, ARM_FEATURE_PMU); | |
688 | cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A57; | |
689 | cpu->midr = 0x411fd070; | |
690 | cpu->revidr = 0x00000000; | |
691 | cpu->reset_fpsid = 0x41034070; | |
692 | cpu->isar.mvfr0 = 0x10110222; | |
693 | cpu->isar.mvfr1 = 0x12111111; | |
694 | cpu->isar.mvfr2 = 0x00000043; | |
695 | cpu->ctr = 0x8444c004; | |
696 | cpu->reset_sctlr = 0x00c50838; | |
697 | cpu->isar.id_pfr0 = 0x00000131; | |
698 | cpu->isar.id_pfr1 = 0x00011011; | |
699 | cpu->isar.id_dfr0 = 0x03010066; | |
700 | cpu->id_afr0 = 0x00000000; | |
701 | cpu->isar.id_mmfr0 = 0x10101105; | |
702 | cpu->isar.id_mmfr1 = 0x40000000; | |
703 | cpu->isar.id_mmfr2 = 0x01260000; | |
704 | cpu->isar.id_mmfr3 = 0x02102211; | |
705 | cpu->isar.id_isar0 = 0x02101110; | |
706 | cpu->isar.id_isar1 = 0x13112111; | |
707 | cpu->isar.id_isar2 = 0x21232042; | |
708 | cpu->isar.id_isar3 = 0x01112131; | |
709 | cpu->isar.id_isar4 = 0x00011142; | |
710 | cpu->isar.id_isar5 = 0x00011121; | |
711 | cpu->isar.id_isar6 = 0; | |
712 | cpu->isar.id_aa64pfr0 = 0x00002222; | |
713 | cpu->isar.id_aa64dfr0 = 0x10305106; | |
714 | cpu->isar.id_aa64isar0 = 0x00011120; | |
715 | cpu->isar.id_aa64mmfr0 = 0x00001124; | |
716 | cpu->isar.dbgdidr = 0x3516d000; | |
717 | cpu->isar.dbgdevid = 0x01110f13; | |
718 | cpu->isar.dbgdevid1 = 0x2; | |
719 | cpu->isar.reset_pmcr_el0 = 0x41013000; | |
720 | cpu->clidr = 0x0a200023; | |
721 | cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ | |
722 | cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */ | |
723 | cpu->ccsidr[2] = 0x70ffe07a; /* 2048KB L2 cache */ | |
724 | cpu->dcz_blocksize = 4; /* 64 bytes */ | |
725 | cpu->gic_num_lrs = 4; | |
726 | cpu->gic_vpribits = 5; | |
727 | cpu->gic_vprebits = 5; | |
728 | cpu->gic_pribits = 5; | |
729 | define_cortex_a72_a57_a53_cp_reginfo(cpu); | |
b3d52804 | 730 | } |
b3d52804 | 731 | |
042e85d1 | 732 | static void aarch64_a53_initfn(Object *obj) |
87014c6b | 733 | { |
0f40784e | 734 | ARMCPU *cpu = ARM_CPU(obj); |
87014c6b | 735 | |
042e85d1 PM |
736 | cpu->dtb_compatible = "arm,cortex-a53"; |
737 | set_feature(&cpu->env, ARM_FEATURE_V8); | |
738 | set_feature(&cpu->env, ARM_FEATURE_NEON); | |
739 | set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); | |
740 | set_feature(&cpu->env, ARM_FEATURE_AARCH64); | |
741 | set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); | |
742 | set_feature(&cpu->env, ARM_FEATURE_EL2); | |
743 | set_feature(&cpu->env, ARM_FEATURE_EL3); | |
744 | set_feature(&cpu->env, ARM_FEATURE_PMU); | |
745 | cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A53; | |
746 | cpu->midr = 0x410fd034; | |
747 | cpu->revidr = 0x00000000; | |
748 | cpu->reset_fpsid = 0x41034070; | |
749 | cpu->isar.mvfr0 = 0x10110222; | |
750 | cpu->isar.mvfr1 = 0x12111111; | |
751 | cpu->isar.mvfr2 = 0x00000043; | |
752 | cpu->ctr = 0x84448004; /* L1Ip = VIPT */ | |
753 | cpu->reset_sctlr = 0x00c50838; | |
754 | cpu->isar.id_pfr0 = 0x00000131; | |
755 | cpu->isar.id_pfr1 = 0x00011011; | |
756 | cpu->isar.id_dfr0 = 0x03010066; | |
757 | cpu->id_afr0 = 0x00000000; | |
758 | cpu->isar.id_mmfr0 = 0x10101105; | |
759 | cpu->isar.id_mmfr1 = 0x40000000; | |
760 | cpu->isar.id_mmfr2 = 0x01260000; | |
761 | cpu->isar.id_mmfr3 = 0x02102211; | |
762 | cpu->isar.id_isar0 = 0x02101110; | |
763 | cpu->isar.id_isar1 = 0x13112111; | |
764 | cpu->isar.id_isar2 = 0x21232042; | |
765 | cpu->isar.id_isar3 = 0x01112131; | |
766 | cpu->isar.id_isar4 = 0x00011142; | |
767 | cpu->isar.id_isar5 = 0x00011121; | |
768 | cpu->isar.id_isar6 = 0; | |
769 | cpu->isar.id_aa64pfr0 = 0x00002222; | |
770 | cpu->isar.id_aa64dfr0 = 0x10305106; | |
771 | cpu->isar.id_aa64isar0 = 0x00011120; | |
772 | cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */ | |
773 | cpu->isar.dbgdidr = 0x3516d000; | |
774 | cpu->isar.dbgdevid = 0x00110f13; | |
775 | cpu->isar.dbgdevid1 = 0x1; | |
776 | cpu->isar.reset_pmcr_el0 = 0x41033000; | |
777 | cpu->clidr = 0x0a200023; | |
778 | cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */ | |
779 | cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */ | |
780 | cpu->ccsidr[2] = 0x707fe07a; /* 1024KB L2 cache */ | |
781 | cpu->dcz_blocksize = 4; /* 64 bytes */ | |
782 | cpu->gic_num_lrs = 4; | |
783 | cpu->gic_vpribits = 5; | |
784 | cpu->gic_vprebits = 5; | |
785 | cpu->gic_pribits = 5; | |
786 | define_cortex_a72_a57_a53_cp_reginfo(cpu); | |
787 | } | |
87014c6b | 788 | |
94bc3b06 TK |
789 | static void aarch64_a55_initfn(Object *obj) |
790 | { | |
791 | ARMCPU *cpu = ARM_CPU(obj); | |
792 | ||
793 | cpu->dtb_compatible = "arm,cortex-a55"; | |
794 | set_feature(&cpu->env, ARM_FEATURE_V8); | |
795 | set_feature(&cpu->env, ARM_FEATURE_NEON); | |
796 | set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); | |
797 | set_feature(&cpu->env, ARM_FEATURE_AARCH64); | |
798 | set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); | |
799 | set_feature(&cpu->env, ARM_FEATURE_EL2); | |
800 | set_feature(&cpu->env, ARM_FEATURE_EL3); | |
801 | set_feature(&cpu->env, ARM_FEATURE_PMU); | |
802 | ||
803 | /* Ordered by B2.4 AArch64 registers by functional group */ | |
804 | cpu->clidr = 0x82000023; | |
805 | cpu->ctr = 0x84448004; /* L1Ip = VIPT */ | |
806 | cpu->dcz_blocksize = 4; /* 64 bytes */ | |
807 | cpu->isar.id_aa64dfr0 = 0x0000000010305408ull; | |
808 | cpu->isar.id_aa64isar0 = 0x0000100010211120ull; | |
809 | cpu->isar.id_aa64isar1 = 0x0000000000100001ull; | |
810 | cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull; | |
811 | cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; | |
812 | cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; | |
813 | cpu->isar.id_aa64pfr0 = 0x0000000010112222ull; | |
814 | cpu->isar.id_aa64pfr1 = 0x0000000000000010ull; | |
815 | cpu->id_afr0 = 0x00000000; | |
816 | cpu->isar.id_dfr0 = 0x04010088; | |
817 | cpu->isar.id_isar0 = 0x02101110; | |
818 | cpu->isar.id_isar1 = 0x13112111; | |
819 | cpu->isar.id_isar2 = 0x21232042; | |
820 | cpu->isar.id_isar3 = 0x01112131; | |
821 | cpu->isar.id_isar4 = 0x00011142; | |
822 | cpu->isar.id_isar5 = 0x01011121; | |
823 | cpu->isar.id_isar6 = 0x00000010; | |
824 | cpu->isar.id_mmfr0 = 0x10201105; | |
825 | cpu->isar.id_mmfr1 = 0x40000000; | |
826 | cpu->isar.id_mmfr2 = 0x01260000; | |
827 | cpu->isar.id_mmfr3 = 0x02122211; | |
828 | cpu->isar.id_mmfr4 = 0x00021110; | |
829 | cpu->isar.id_pfr0 = 0x10010131; | |
830 | cpu->isar.id_pfr1 = 0x00011011; | |
831 | cpu->isar.id_pfr2 = 0x00000011; | |
832 | cpu->midr = 0x412FD050; /* r2p0 */ | |
833 | cpu->revidr = 0; | |
834 | ||
835 | /* From B2.23 CCSIDR_EL1 */ | |
836 | cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */ | |
837 | cpu->ccsidr[1] = 0x200fe01a; /* 32KB L1 icache */ | |
838 | cpu->ccsidr[2] = 0x703fe07a; /* 512KB L2 cache */ | |
839 | ||
840 | /* From B2.96 SCTLR_EL3 */ | |
841 | cpu->reset_sctlr = 0x30c50838; | |
842 | ||
843 | /* From B4.45 ICH_VTR_EL2 */ | |
844 | cpu->gic_num_lrs = 4; | |
845 | cpu->gic_vpribits = 5; | |
846 | cpu->gic_vprebits = 5; | |
847 | cpu->gic_pribits = 5; | |
848 | ||
849 | cpu->isar.mvfr0 = 0x10110222; | |
850 | cpu->isar.mvfr1 = 0x13211111; | |
851 | cpu->isar.mvfr2 = 0x00000043; | |
852 | ||
853 | /* From D5.4 AArch64 PMU register summary */ | |
854 | cpu->isar.reset_pmcr_el0 = 0x410b3000; | |
855 | } | |
856 | ||
042e85d1 PM |
857 | static void aarch64_a72_initfn(Object *obj) |
858 | { | |
859 | ARMCPU *cpu = ARM_CPU(obj); | |
b3d52804 | 860 | |
042e85d1 PM |
861 | cpu->dtb_compatible = "arm,cortex-a72"; |
862 | set_feature(&cpu->env, ARM_FEATURE_V8); | |
863 | set_feature(&cpu->env, ARM_FEATURE_NEON); | |
864 | set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); | |
865 | set_feature(&cpu->env, ARM_FEATURE_AARCH64); | |
866 | set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); | |
867 | set_feature(&cpu->env, ARM_FEATURE_EL2); | |
868 | set_feature(&cpu->env, ARM_FEATURE_EL3); | |
869 | set_feature(&cpu->env, ARM_FEATURE_PMU); | |
870 | cpu->midr = 0x410fd083; | |
871 | cpu->revidr = 0x00000000; | |
872 | cpu->reset_fpsid = 0x41034080; | |
873 | cpu->isar.mvfr0 = 0x10110222; | |
874 | cpu->isar.mvfr1 = 0x12111111; | |
875 | cpu->isar.mvfr2 = 0x00000043; | |
876 | cpu->ctr = 0x8444c004; | |
877 | cpu->reset_sctlr = 0x00c50838; | |
878 | cpu->isar.id_pfr0 = 0x00000131; | |
879 | cpu->isar.id_pfr1 = 0x00011011; | |
880 | cpu->isar.id_dfr0 = 0x03010066; | |
881 | cpu->id_afr0 = 0x00000000; | |
882 | cpu->isar.id_mmfr0 = 0x10201105; | |
883 | cpu->isar.id_mmfr1 = 0x40000000; | |
884 | cpu->isar.id_mmfr2 = 0x01260000; | |
885 | cpu->isar.id_mmfr3 = 0x02102211; | |
886 | cpu->isar.id_isar0 = 0x02101110; | |
887 | cpu->isar.id_isar1 = 0x13112111; | |
888 | cpu->isar.id_isar2 = 0x21232042; | |
889 | cpu->isar.id_isar3 = 0x01112131; | |
890 | cpu->isar.id_isar4 = 0x00011142; | |
891 | cpu->isar.id_isar5 = 0x00011121; | |
892 | cpu->isar.id_aa64pfr0 = 0x00002222; | |
893 | cpu->isar.id_aa64dfr0 = 0x10305106; | |
894 | cpu->isar.id_aa64isar0 = 0x00011120; | |
895 | cpu->isar.id_aa64mmfr0 = 0x00001124; | |
896 | cpu->isar.dbgdidr = 0x3516d000; | |
897 | cpu->isar.dbgdevid = 0x01110f13; | |
898 | cpu->isar.dbgdevid1 = 0x2; | |
899 | cpu->isar.reset_pmcr_el0 = 0x41023000; | |
900 | cpu->clidr = 0x0a200023; | |
901 | cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ | |
902 | cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */ | |
903 | cpu->ccsidr[2] = 0x707fe07a; /* 1MB L2 cache */ | |
904 | cpu->dcz_blocksize = 4; /* 64 bytes */ | |
905 | cpu->gic_num_lrs = 4; | |
906 | cpu->gic_vpribits = 5; | |
907 | cpu->gic_vprebits = 5; | |
908 | cpu->gic_pribits = 5; | |
909 | define_cortex_a72_a57_a53_cp_reginfo(cpu); | |
87014c6b AJ |
910 | } |
911 | ||
042e85d1 PM |
912 | static void aarch64_a76_initfn(Object *obj) |
913 | { | |
914 | ARMCPU *cpu = ARM_CPU(obj); | |
915 | ||
916 | cpu->dtb_compatible = "arm,cortex-a76"; | |
917 | set_feature(&cpu->env, ARM_FEATURE_V8); | |
918 | set_feature(&cpu->env, ARM_FEATURE_NEON); | |
919 | set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); | |
920 | set_feature(&cpu->env, ARM_FEATURE_AARCH64); | |
921 | set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); | |
922 | set_feature(&cpu->env, ARM_FEATURE_EL2); | |
923 | set_feature(&cpu->env, ARM_FEATURE_EL3); | |
924 | set_feature(&cpu->env, ARM_FEATURE_PMU); | |
925 | ||
926 | /* Ordered by B2.4 AArch64 registers by functional group */ | |
927 | cpu->clidr = 0x82000023; | |
928 | cpu->ctr = 0x8444C004; | |
929 | cpu->dcz_blocksize = 4; | |
930 | cpu->isar.id_aa64dfr0 = 0x0000000010305408ull; | |
931 | cpu->isar.id_aa64isar0 = 0x0000100010211120ull; | |
932 | cpu->isar.id_aa64isar1 = 0x0000000000100001ull; | |
933 | cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull; | |
934 | cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; | |
935 | cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; | |
936 | cpu->isar.id_aa64pfr0 = 0x1100000010111112ull; /* GIC filled in later */ | |
937 | cpu->isar.id_aa64pfr1 = 0x0000000000000010ull; | |
938 | cpu->id_afr0 = 0x00000000; | |
939 | cpu->isar.id_dfr0 = 0x04010088; | |
940 | cpu->isar.id_isar0 = 0x02101110; | |
941 | cpu->isar.id_isar1 = 0x13112111; | |
942 | cpu->isar.id_isar2 = 0x21232042; | |
943 | cpu->isar.id_isar3 = 0x01112131; | |
944 | cpu->isar.id_isar4 = 0x00010142; | |
945 | cpu->isar.id_isar5 = 0x01011121; | |
946 | cpu->isar.id_isar6 = 0x00000010; | |
947 | cpu->isar.id_mmfr0 = 0x10201105; | |
948 | cpu->isar.id_mmfr1 = 0x40000000; | |
949 | cpu->isar.id_mmfr2 = 0x01260000; | |
950 | cpu->isar.id_mmfr3 = 0x02122211; | |
951 | cpu->isar.id_mmfr4 = 0x00021110; | |
952 | cpu->isar.id_pfr0 = 0x10010131; | |
953 | cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */ | |
954 | cpu->isar.id_pfr2 = 0x00000011; | |
955 | cpu->midr = 0x414fd0b1; /* r4p1 */ | |
956 | cpu->revidr = 0; | |
957 | ||
958 | /* From B2.18 CCSIDR_EL1 */ | |
959 | cpu->ccsidr[0] = 0x701fe01a; /* 64KB L1 dcache */ | |
960 | cpu->ccsidr[1] = 0x201fe01a; /* 64KB L1 icache */ | |
961 | cpu->ccsidr[2] = 0x707fe03a; /* 512KB L2 cache */ | |
962 | ||
963 | /* From B2.93 SCTLR_EL3 */ | |
964 | cpu->reset_sctlr = 0x30c50838; | |
e74c0976 | 965 | |
042e85d1 PM |
966 | /* From B4.23 ICH_VTR_EL2 */ |
967 | cpu->gic_num_lrs = 4; | |
968 | cpu->gic_vpribits = 5; | |
969 | cpu->gic_vprebits = 5; | |
970 | cpu->gic_pribits = 5; | |
e74c0976 | 971 | |
042e85d1 PM |
972 | /* From B5.1 AdvSIMD AArch64 register summary */ |
973 | cpu->isar.mvfr0 = 0x10110222; | |
974 | cpu->isar.mvfr1 = 0x13211111; | |
975 | cpu->isar.mvfr2 = 0x00000043; | |
e74c0976 | 976 | |
042e85d1 PM |
977 | /* From D5.1 AArch64 PMU register summary */ |
978 | cpu->isar.reset_pmcr_el0 = 0x410b3000; | |
e74c0976 RH |
979 | } |
980 | ||
042e85d1 | 981 | static void aarch64_a64fx_initfn(Object *obj) |
eb94284d | 982 | { |
042e85d1 | 983 | ARMCPU *cpu = ARM_CPU(obj); |
eb94284d | 984 | |
042e85d1 PM |
985 | cpu->dtb_compatible = "arm,a64fx"; |
986 | set_feature(&cpu->env, ARM_FEATURE_V8); | |
987 | set_feature(&cpu->env, ARM_FEATURE_NEON); | |
988 | set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); | |
989 | set_feature(&cpu->env, ARM_FEATURE_AARCH64); | |
990 | set_feature(&cpu->env, ARM_FEATURE_EL2); | |
991 | set_feature(&cpu->env, ARM_FEATURE_EL3); | |
992 | set_feature(&cpu->env, ARM_FEATURE_PMU); | |
993 | cpu->midr = 0x461f0010; | |
994 | cpu->revidr = 0x00000000; | |
995 | cpu->ctr = 0x86668006; | |
996 | cpu->reset_sctlr = 0x30000180; | |
997 | cpu->isar.id_aa64pfr0 = 0x0000000101111111; /* No RAS Extensions */ | |
998 | cpu->isar.id_aa64pfr1 = 0x0000000000000000; | |
999 | cpu->isar.id_aa64dfr0 = 0x0000000010305408; | |
1000 | cpu->isar.id_aa64dfr1 = 0x0000000000000000; | |
1001 | cpu->id_aa64afr0 = 0x0000000000000000; | |
1002 | cpu->id_aa64afr1 = 0x0000000000000000; | |
1003 | cpu->isar.id_aa64mmfr0 = 0x0000000000001122; | |
1004 | cpu->isar.id_aa64mmfr1 = 0x0000000011212100; | |
1005 | cpu->isar.id_aa64mmfr2 = 0x0000000000001011; | |
1006 | cpu->isar.id_aa64isar0 = 0x0000000010211120; | |
1007 | cpu->isar.id_aa64isar1 = 0x0000000000010001; | |
1008 | cpu->isar.id_aa64zfr0 = 0x0000000000000000; | |
1009 | cpu->clidr = 0x0000000080000023; | |
1010 | cpu->ccsidr[0] = 0x7007e01c; /* 64KB L1 dcache */ | |
1011 | cpu->ccsidr[1] = 0x2007e01c; /* 64KB L1 icache */ | |
1012 | cpu->ccsidr[2] = 0x70ffe07c; /* 8MB L2 cache */ | |
1013 | cpu->dcz_blocksize = 6; /* 256 bytes */ | |
1014 | cpu->gic_num_lrs = 4; | |
1015 | cpu->gic_vpribits = 5; | |
1016 | cpu->gic_vprebits = 5; | |
1017 | cpu->gic_pribits = 5; | |
95ea96e8 | 1018 | |
042e85d1 PM |
1019 | /* The A64FX supports only 128, 256 and 512 bit vector lengths */ |
1020 | aarch64_add_sve_properties(obj); | |
1021 | cpu->sve_vq.supported = (1 << 0) /* 128bit */ | |
1022 | | (1 << 1) /* 256bit */ | |
1023 | | (1 << 3); /* 512bit */ | |
95ea96e8 | 1024 | |
042e85d1 | 1025 | cpu->isar.reset_pmcr_el0 = 0x46014040; |
eb94284d | 1026 | |
042e85d1 | 1027 | /* TODO: Add A64FX specific HPC extension registers */ |
eb94284d RH |
1028 | } |
1029 | ||
042e85d1 | 1030 | static void aarch64_neoverse_n1_initfn(Object *obj) |
95ea96e8 MZ |
1031 | { |
1032 | ARMCPU *cpu = ARM_CPU(obj); | |
1033 | ||
042e85d1 PM |
1034 | cpu->dtb_compatible = "arm,neoverse-n1"; |
1035 | set_feature(&cpu->env, ARM_FEATURE_V8); | |
1036 | set_feature(&cpu->env, ARM_FEATURE_NEON); | |
1037 | set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); | |
1038 | set_feature(&cpu->env, ARM_FEATURE_AARCH64); | |
1039 | set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); | |
1040 | set_feature(&cpu->env, ARM_FEATURE_EL2); | |
1041 | set_feature(&cpu->env, ARM_FEATURE_EL3); | |
1042 | set_feature(&cpu->env, ARM_FEATURE_PMU); | |
95ea96e8 | 1043 | |
042e85d1 PM |
1044 | /* Ordered by B2.4 AArch64 registers by functional group */ |
1045 | cpu->clidr = 0x82000023; | |
1046 | cpu->ctr = 0x8444c004; | |
1047 | cpu->dcz_blocksize = 4; | |
1048 | cpu->isar.id_aa64dfr0 = 0x0000000110305408ull; | |
1049 | cpu->isar.id_aa64isar0 = 0x0000100010211120ull; | |
1050 | cpu->isar.id_aa64isar1 = 0x0000000000100001ull; | |
1051 | cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull; | |
1052 | cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; | |
1053 | cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; | |
1054 | cpu->isar.id_aa64pfr0 = 0x1100000010111112ull; /* GIC filled in later */ | |
1055 | cpu->isar.id_aa64pfr1 = 0x0000000000000020ull; | |
1056 | cpu->id_afr0 = 0x00000000; | |
1057 | cpu->isar.id_dfr0 = 0x04010088; | |
1058 | cpu->isar.id_isar0 = 0x02101110; | |
1059 | cpu->isar.id_isar1 = 0x13112111; | |
1060 | cpu->isar.id_isar2 = 0x21232042; | |
1061 | cpu->isar.id_isar3 = 0x01112131; | |
1062 | cpu->isar.id_isar4 = 0x00010142; | |
1063 | cpu->isar.id_isar5 = 0x01011121; | |
1064 | cpu->isar.id_isar6 = 0x00000010; | |
1065 | cpu->isar.id_mmfr0 = 0x10201105; | |
1066 | cpu->isar.id_mmfr1 = 0x40000000; | |
1067 | cpu->isar.id_mmfr2 = 0x01260000; | |
1068 | cpu->isar.id_mmfr3 = 0x02122211; | |
1069 | cpu->isar.id_mmfr4 = 0x00021110; | |
1070 | cpu->isar.id_pfr0 = 0x10010131; | |
1071 | cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */ | |
1072 | cpu->isar.id_pfr2 = 0x00000011; | |
1073 | cpu->midr = 0x414fd0c1; /* r4p1 */ | |
1074 | cpu->revidr = 0; | |
69b2265d | 1075 | |
042e85d1 PM |
1076 | /* From B2.23 CCSIDR_EL1 */ |
1077 | cpu->ccsidr[0] = 0x701fe01a; /* 64KB L1 dcache */ | |
1078 | cpu->ccsidr[1] = 0x201fe01a; /* 64KB L1 icache */ | |
1079 | cpu->ccsidr[2] = 0x70ffe03a; /* 1MB L2 cache */ | |
69b2265d | 1080 | |
042e85d1 PM |
1081 | /* From B2.98 SCTLR_EL3 */ |
1082 | cpu->reset_sctlr = 0x30c50838; | |
69b2265d | 1083 | |
042e85d1 PM |
1084 | /* From B4.23 ICH_VTR_EL2 */ |
1085 | cpu->gic_num_lrs = 4; | |
1086 | cpu->gic_vpribits = 5; | |
1087 | cpu->gic_vprebits = 5; | |
1088 | cpu->gic_pribits = 5; | |
1089 | ||
1090 | /* From B5.1 AdvSIMD AArch64 register summary */ | |
1091 | cpu->isar.mvfr0 = 0x10110222; | |
1092 | cpu->isar.mvfr1 = 0x13211111; | |
1093 | cpu->isar.mvfr2 = 0x00000043; | |
1094 | ||
1095 | /* From D5.1 AArch64 PMU register summary */ | |
1096 | cpu->isar.reset_pmcr_el0 = 0x410c3000; | |
69b2265d RH |
1097 | } |
1098 | ||
73cc9ee6 | 1099 | static void aarch64_host_initfn(Object *obj) |
dcfb1d04 | 1100 | { |
0baa21be | 1101 | #if defined(CONFIG_KVM) |
dcfb1d04 | 1102 | ARMCPU *cpu = ARM_CPU(obj); |
dcfb1d04 PM |
1103 | kvm_arm_set_cpu_features_from_host(cpu); |
1104 | if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { | |
1105 | aarch64_add_sve_properties(obj); | |
1106 | aarch64_add_pauth_properties(obj); | |
1107 | } | |
0baa21be PM |
1108 | #elif defined(CONFIG_HVF) |
1109 | ARMCPU *cpu = ARM_CPU(obj); | |
dcfb1d04 | 1110 | hvf_arm_set_cpu_features_from_host(cpu); |
92d6528d | 1111 | aarch64_add_pauth_properties(obj); |
0baa21be PM |
1112 | #else |
1113 | g_assert_not_reached(); | |
dcfb1d04 | 1114 | #endif |
dcfb1d04 | 1115 | } |
dcfb1d04 | 1116 | |
bab52d4b PM |
1117 | /* -cpu max: if KVM is enabled, like -cpu host (best possible with this host); |
1118 | * otherwise, a CPU with as many features enabled as our emulation supports. | |
1119 | * The version of '-cpu max' for qemu-system-arm is defined in cpu.c; | |
1120 | * this only needs to handle 64 bits. | |
1121 | */ | |
1122 | static void aarch64_max_initfn(Object *obj) | |
1123 | { | |
1124 | ARMCPU *cpu = ARM_CPU(obj); | |
ddaebdda | 1125 | uint64_t t; |
e04bf5a7 | 1126 | uint32_t u; |
bab52d4b | 1127 | |
6ee609b7 PM |
1128 | if (kvm_enabled() || hvf_enabled()) { |
1129 | /* With KVM or HVF, '-cpu max' is identical to '-cpu host' */ | |
0baa21be PM |
1130 | aarch64_host_initfn(obj); |
1131 | return; | |
ddaebdda | 1132 | } |
962fcbf2 | 1133 | |
ddaebdda PM |
1134 | /* '-cpu max' for TCG: we currently do this as "A57 with extra things" */ |
1135 | ||
1136 | aarch64_a57_initfn(obj); | |
1137 | ||
1138 | /* | |
1139 | * Reset MIDR so the guest doesn't mistake our 'max' CPU type for a real | |
1140 | * one and try to apply errata workarounds or use impdef features we | |
1141 | * don't provide. | |
1142 | * An IMPLEMENTER field of 0 means "reserved for software use"; | |
1143 | * ARCHITECTURE must be 0xf indicating "v7 or later, check ID registers | |
1144 | * to see which features are present"; | |
1145 | * the VARIANT, PARTNUM and REVISION fields are all implementation | |
1146 | * defined and we choose to define PARTNUM just in case guest | |
1147 | * code needs to distinguish this QEMU CPU from other software | |
1148 | * implementations, though this shouldn't be needed. | |
1149 | */ | |
1150 | t = FIELD_DP64(0, MIDR_EL1, IMPLEMENTER, 0); | |
1151 | t = FIELD_DP64(t, MIDR_EL1, ARCHITECTURE, 0xf); | |
1152 | t = FIELD_DP64(t, MIDR_EL1, PARTNUM, 'Q'); | |
1153 | t = FIELD_DP64(t, MIDR_EL1, VARIANT, 0); | |
1154 | t = FIELD_DP64(t, MIDR_EL1, REVISION, 0); | |
1155 | cpu->midr = t; | |
1156 | ||
e04bf5a7 PM |
1157 | /* |
1158 | * We're going to set FEAT_S2FWB, which mandates that CLIDR_EL1.{LoUU,LoUIS} | |
1159 | * are zero. | |
1160 | */ | |
1161 | u = cpu->clidr; | |
1162 | u = FIELD_DP32(u, CLIDR_EL1, LOUIS, 0); | |
1163 | u = FIELD_DP32(u, CLIDR_EL1, LOUU, 0); | |
1164 | cpu->clidr = u; | |
1165 | ||
ddaebdda | 1166 | t = cpu->isar.id_aa64isar0; |
ef696cfb RH |
1167 | t = FIELD_DP64(t, ID_AA64ISAR0, AES, 2); /* FEAT_PMULL */ |
1168 | t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 1); /* FEAT_SHA1 */ | |
1169 | t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 2); /* FEAT_SHA512 */ | |
ddaebdda | 1170 | t = FIELD_DP64(t, ID_AA64ISAR0, CRC32, 1); |
ef696cfb RH |
1171 | t = FIELD_DP64(t, ID_AA64ISAR0, ATOMIC, 2); /* FEAT_LSE */ |
1172 | t = FIELD_DP64(t, ID_AA64ISAR0, RDM, 1); /* FEAT_RDM */ | |
1173 | t = FIELD_DP64(t, ID_AA64ISAR0, SHA3, 1); /* FEAT_SHA3 */ | |
1174 | t = FIELD_DP64(t, ID_AA64ISAR0, SM3, 1); /* FEAT_SM3 */ | |
1175 | t = FIELD_DP64(t, ID_AA64ISAR0, SM4, 1); /* FEAT_SM4 */ | |
1176 | t = FIELD_DP64(t, ID_AA64ISAR0, DP, 1); /* FEAT_DotProd */ | |
1177 | t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 1); /* FEAT_FHM */ | |
1178 | t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* FEAT_FlagM2 */ | |
1179 | t = FIELD_DP64(t, ID_AA64ISAR0, TLB, 2); /* FEAT_TLBIRANGE */ | |
1180 | t = FIELD_DP64(t, ID_AA64ISAR0, RNDR, 1); /* FEAT_RNG */ | |
ddaebdda PM |
1181 | cpu->isar.id_aa64isar0 = t; |
1182 | ||
1183 | t = cpu->isar.id_aa64isar1; | |
ef696cfb RH |
1184 | t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2); /* FEAT_DPB2 */ |
1185 | t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1); /* FEAT_JSCVT */ | |
1186 | t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1); /* FEAT_FCMA */ | |
1187 | t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 2); /* FEAT_LRCPC2 */ | |
1188 | t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1); /* FEAT_FRINTTS */ | |
1189 | t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1); /* FEAT_SB */ | |
1190 | t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1); /* FEAT_SPECRES */ | |
1191 | t = FIELD_DP64(t, ID_AA64ISAR1, BF16, 1); /* FEAT_BF16 */ | |
6d965019 | 1192 | t = FIELD_DP64(t, ID_AA64ISAR1, DGH, 1); /* FEAT_DGH */ |
ef696cfb | 1193 | t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 1); /* FEAT_I8MM */ |
ddaebdda PM |
1194 | cpu->isar.id_aa64isar1 = t; |
1195 | ||
1196 | t = cpu->isar.id_aa64pfr0; | |
ef696cfb RH |
1197 | t = FIELD_DP64(t, ID_AA64PFR0, FP, 1); /* FEAT_FP16 */ |
1198 | t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1); /* FEAT_FP16 */ | |
7ac61020 | 1199 | t = FIELD_DP64(t, ID_AA64PFR0, RAS, 2); /* FEAT_RASv1p1 + FEAT_DoubleFault */ |
ddaebdda | 1200 | t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1); |
ef696cfb RH |
1201 | t = FIELD_DP64(t, ID_AA64PFR0, SEL2, 1); /* FEAT_SEL2 */ |
1202 | t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1); /* FEAT_DIT */ | |
7cb1e618 | 1203 | t = FIELD_DP64(t, ID_AA64PFR0, CSV2, 2); /* FEAT_CSV2_2 */ |
3082b86b | 1204 | t = FIELD_DP64(t, ID_AA64PFR0, CSV3, 1); /* FEAT_CSV3 */ |
ddaebdda PM |
1205 | cpu->isar.id_aa64pfr0 = t; |
1206 | ||
1207 | t = cpu->isar.id_aa64pfr1; | |
ef696cfb RH |
1208 | t = FIELD_DP64(t, ID_AA64PFR1, BT, 1); /* FEAT_BTI */ |
1209 | t = FIELD_DP64(t, ID_AA64PFR1, SSBS, 2); /* FEAT_SSBS2 */ | |
ddaebdda PM |
1210 | /* |
1211 | * Begin with full support for MTE. This will be downgraded to MTE=0 | |
1212 | * during realize if the board provides no tag memory, much like | |
1213 | * we do for EL2 with the virtualization=on property. | |
1214 | */ | |
ef696cfb | 1215 | t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3); /* FEAT_MTE3 */ |
7ac61020 | 1216 | t = FIELD_DP64(t, ID_AA64PFR1, RAS_FRAC, 0); /* FEAT_RASv1p1 + FEAT_DoubleFault */ |
78cb9776 | 1217 | t = FIELD_DP64(t, ID_AA64PFR1, SME, 1); /* FEAT_SME */ |
7cb1e618 | 1218 | t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_2 */ |
ddaebdda PM |
1219 | cpu->isar.id_aa64pfr1 = t; |
1220 | ||
1221 | t = cpu->isar.id_aa64mmfr0; | |
7a928f43 | 1222 | t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 6); /* FEAT_LPA: 52 bits */ |
c20281b2 RH |
1223 | t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16, 1); /* 16k pages supported */ |
1224 | t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16_2, 2); /* 16k stage2 supported */ | |
1225 | t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN64_2, 2); /* 64k stage2 supported */ | |
1226 | t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 2); /* 4k stage2 supported */ | |
bb18151d | 1227 | t = FIELD_DP64(t, ID_AA64MMFR0, FGT, 1); /* FEAT_FGT */ |
ddaebdda PM |
1228 | cpu->isar.id_aa64mmfr0 = t; |
1229 | ||
1230 | t = cpu->isar.id_aa64mmfr1; | |
65c123fd | 1231 | t = FIELD_DP64(t, ID_AA64MMFR1, HAFDBS, 2); /* FEAT_HAFDBS */ |
ef696cfb RH |
1232 | t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* FEAT_VMID16 */ |
1233 | t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1); /* FEAT_VHE */ | |
1234 | t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* FEAT_HPDS */ | |
1235 | t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1); /* FEAT_LOR */ | |
1236 | t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* FEAT_PAN2 */ | |
1237 | t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* FEAT_XNX */ | |
3fe72e21 | 1238 | t = FIELD_DP64(t, ID_AA64MMFR1, ETS, 1); /* FEAT_ETS */ |
5814d587 | 1239 | t = FIELD_DP64(t, ID_AA64MMFR1, HCX, 1); /* FEAT_HCX */ |
ddaebdda PM |
1240 | cpu->isar.id_aa64mmfr1 = t; |
1241 | ||
1242 | t = cpu->isar.id_aa64mmfr2; | |
ef696cfb RH |
1243 | t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* FEAT_TTCNP */ |
1244 | t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1); /* FEAT_UAO */ | |
880cd10e | 1245 | t = FIELD_DP64(t, ID_AA64MMFR2, IESB, 1); /* FEAT_IESB */ |
ef696cfb RH |
1246 | t = FIELD_DP64(t, ID_AA64MMFR2, VARANGE, 1); /* FEAT_LVA */ |
1247 | t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* FEAT_TTST */ | |
75662f36 | 1248 | t = FIELD_DP64(t, ID_AA64MMFR2, IDS, 1); /* FEAT_IDST */ |
e04bf5a7 | 1249 | t = FIELD_DP64(t, ID_AA64MMFR2, FWB, 1); /* FEAT_S2FWB */ |
ef696cfb RH |
1250 | t = FIELD_DP64(t, ID_AA64MMFR2, TTL, 1); /* FEAT_TTL */ |
1251 | t = FIELD_DP64(t, ID_AA64MMFR2, BBM, 2); /* FEAT_BBM at level 2 */ | |
41654f12 | 1252 | t = FIELD_DP64(t, ID_AA64MMFR2, EVT, 2); /* FEAT_EVT */ |
e4c93e44 | 1253 | t = FIELD_DP64(t, ID_AA64MMFR2, E0PD, 1); /* FEAT_E0PD */ |
ddaebdda PM |
1254 | cpu->isar.id_aa64mmfr2 = t; |
1255 | ||
1256 | t = cpu->isar.id_aa64zfr0; | |
1257 | t = FIELD_DP64(t, ID_AA64ZFR0, SVEVER, 1); | |
ef696cfb RH |
1258 | t = FIELD_DP64(t, ID_AA64ZFR0, AES, 2); /* FEAT_SVE_PMULL128 */ |
1259 | t = FIELD_DP64(t, ID_AA64ZFR0, BITPERM, 1); /* FEAT_SVE_BitPerm */ | |
1260 | t = FIELD_DP64(t, ID_AA64ZFR0, BFLOAT16, 1); /* FEAT_BF16 */ | |
1261 | t = FIELD_DP64(t, ID_AA64ZFR0, SHA3, 1); /* FEAT_SVE_SHA3 */ | |
1262 | t = FIELD_DP64(t, ID_AA64ZFR0, SM4, 1); /* FEAT_SVE_SM4 */ | |
1263 | t = FIELD_DP64(t, ID_AA64ZFR0, I8MM, 1); /* FEAT_I8MM */ | |
1264 | t = FIELD_DP64(t, ID_AA64ZFR0, F32MM, 1); /* FEAT_F32MM */ | |
1265 | t = FIELD_DP64(t, ID_AA64ZFR0, F64MM, 1); /* FEAT_F64MM */ | |
ddaebdda PM |
1266 | cpu->isar.id_aa64zfr0 = t; |
1267 | ||
ddaebdda | 1268 | t = cpu->isar.id_aa64dfr0; |
8fc756b6 | 1269 | t = FIELD_DP64(t, ID_AA64DFR0, DEBUGVER, 9); /* FEAT_Debugv8p4 */ |
e31e0f56 | 1270 | t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 6); /* FEAT_PMUv3p5 */ |
ddaebdda PM |
1271 | cpu->isar.id_aa64dfr0 = t; |
1272 | ||
78cb9776 RH |
1273 | t = cpu->isar.id_aa64smfr0; |
1274 | t = FIELD_DP64(t, ID_AA64SMFR0, F32F32, 1); /* FEAT_SME */ | |
1275 | t = FIELD_DP64(t, ID_AA64SMFR0, B16F32, 1); /* FEAT_SME */ | |
1276 | t = FIELD_DP64(t, ID_AA64SMFR0, F16F32, 1); /* FEAT_SME */ | |
1277 | t = FIELD_DP64(t, ID_AA64SMFR0, I8I32, 0xf); /* FEAT_SME */ | |
1278 | t = FIELD_DP64(t, ID_AA64SMFR0, F64F64, 1); /* FEAT_SME_F64F64 */ | |
1279 | t = FIELD_DP64(t, ID_AA64SMFR0, I16I64, 0xf); /* FEAT_SME_I16I64 */ | |
1280 | t = FIELD_DP64(t, ID_AA64SMFR0, FA64, 1); /* FEAT_SME_FA64 */ | |
1281 | cpu->isar.id_aa64smfr0 = t; | |
1282 | ||
b6f8b358 RH |
1283 | /* Replicate the same data to the 32-bit id registers. */ |
1284 | aa32_max_features(cpu); | |
5763190f RH |
1285 | |
1286 | #ifdef CONFIG_USER_ONLY | |
ddaebdda PM |
1287 | /* |
1288 | * For usermode -cpu max we can use a larger and more efficient DCZ | |
1289 | * blocksize since we don't have to follow what the hardware does. | |
1290 | */ | |
1291 | cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */ | |
1292 | cpu->dcz_blocksize = 7; /* 512 bytes */ | |
a0032cc5 | 1293 | #endif |
eb94284d | 1294 | |
7f9e25a6 | 1295 | cpu->sve_vq.supported = MAKE_64BIT_MASK(0, ARM_MAX_VQ); |
e74c0976 | 1296 | cpu->sme_vq.supported = SVE_VQ_POW2_MAP; |
14e99e0f | 1297 | |
95ea96e8 | 1298 | aarch64_add_pauth_properties(obj); |
87014c6b | 1299 | aarch64_add_sve_properties(obj); |
e74c0976 | 1300 | aarch64_add_sme_properties(obj); |
6fa8a379 | 1301 | object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq, |
d2623129 | 1302 | cpu_max_set_sve_max_vq, NULL, NULL); |
69b2265d | 1303 | qdev_property_add_static(DEVICE(obj), &arm_cpu_lpa2_property); |
bab52d4b PM |
1304 | } |
1305 | ||
d14d42f1 | 1306 | static const ARMCPUInfo aarch64_cpus[] = { |
3b16766b | 1307 | { .name = "cortex-a35", .initfn = aarch64_a35_initfn }, |
cb1fa941 | 1308 | { .name = "cortex-a57", .initfn = aarch64_a57_initfn }, |
e3531026 | 1309 | { .name = "cortex-a53", .initfn = aarch64_a53_initfn }, |
94bc3b06 | 1310 | { .name = "cortex-a55", .initfn = aarch64_a55_initfn }, |
f11b452b | 1311 | { .name = "cortex-a72", .initfn = aarch64_a72_initfn }, |
2f6283fc | 1312 | { .name = "cortex-a76", .initfn = aarch64_a76_initfn }, |
e31c70ac | 1313 | { .name = "a64fx", .initfn = aarch64_a64fx_initfn }, |
5db6de80 | 1314 | { .name = "neoverse-n1", .initfn = aarch64_neoverse_n1_initfn }, |
bab52d4b | 1315 | { .name = "max", .initfn = aarch64_max_initfn }, |
73cc9ee6 PM |
1316 | #if defined(CONFIG_KVM) || defined(CONFIG_HVF) |
1317 | { .name = "host", .initfn = aarch64_host_initfn }, | |
1318 | #endif | |
d14d42f1 PM |
1319 | }; |
1320 | ||
fb8d6c24 GB |
1321 | static bool aarch64_cpu_get_aarch64(Object *obj, Error **errp) |
1322 | { | |
1323 | ARMCPU *cpu = ARM_CPU(obj); | |
1324 | ||
1325 | return arm_feature(&cpu->env, ARM_FEATURE_AARCH64); | |
1326 | } | |
1327 | ||
1328 | static void aarch64_cpu_set_aarch64(Object *obj, bool value, Error **errp) | |
1329 | { | |
1330 | ARMCPU *cpu = ARM_CPU(obj); | |
1331 | ||
1332 | /* At this time, this property is only allowed if KVM is enabled. This | |
1333 | * restriction allows us to avoid fixing up functionality that assumes a | |
1334 | * uniform execution state like do_interrupt. | |
1335 | */ | |
fb8d6c24 | 1336 | if (value == false) { |
7d20e681 | 1337 | if (!kvm_enabled() || !kvm_arm_aarch32_supported()) { |
b9e758f0 AJ |
1338 | error_setg(errp, "'aarch64' feature cannot be disabled " |
1339 | "unless KVM is enabled and 32-bit EL1 " | |
1340 | "is supported"); | |
1341 | return; | |
1342 | } | |
fb8d6c24 GB |
1343 | unset_feature(&cpu->env, ARM_FEATURE_AARCH64); |
1344 | } else { | |
1345 | set_feature(&cpu->env, ARM_FEATURE_AARCH64); | |
1346 | } | |
1347 | } | |
1348 | ||
d14d42f1 PM |
1349 | static void aarch64_cpu_finalizefn(Object *obj) |
1350 | { | |
1351 | } | |
1352 | ||
b3820e6c DH |
1353 | static gchar *aarch64_gdb_arch_name(CPUState *cs) |
1354 | { | |
1355 | return g_strdup("aarch64"); | |
1356 | } | |
1357 | ||
d14d42f1 PM |
1358 | static void aarch64_cpu_class_init(ObjectClass *oc, void *data) |
1359 | { | |
14ade10f AG |
1360 | CPUClass *cc = CPU_CLASS(oc); |
1361 | ||
96c04212 AG |
1362 | cc->gdb_read_register = aarch64_cpu_gdb_read_register; |
1363 | cc->gdb_write_register = aarch64_cpu_gdb_write_register; | |
1364 | cc->gdb_num_core_regs = 34; | |
1365 | cc->gdb_core_xml_file = "aarch64-core.xml"; | |
b3820e6c | 1366 | cc->gdb_arch_name = aarch64_gdb_arch_name; |
85cc807c EH |
1367 | |
1368 | object_class_property_add_bool(oc, "aarch64", aarch64_cpu_get_aarch64, | |
1369 | aarch64_cpu_set_aarch64); | |
1370 | object_class_property_set_description(oc, "aarch64", | |
1371 | "Set on/off to enable/disable aarch64 " | |
1372 | "execution state "); | |
d14d42f1 PM |
1373 | } |
1374 | ||
51e5ef45 MAL |
1375 | static void aarch64_cpu_instance_init(Object *obj) |
1376 | { | |
1377 | ARMCPUClass *acc = ARM_CPU_GET_CLASS(obj); | |
1378 | ||
1379 | acc->info->initfn(obj); | |
1380 | arm_cpu_post_init(obj); | |
1381 | } | |
1382 | ||
1383 | static void cpu_register_class_init(ObjectClass *oc, void *data) | |
1384 | { | |
1385 | ARMCPUClass *acc = ARM_CPU_CLASS(oc); | |
1386 | ||
1387 | acc->info = data; | |
1388 | } | |
1389 | ||
37bcf244 | 1390 | void aarch64_cpu_register(const ARMCPUInfo *info) |
d14d42f1 PM |
1391 | { |
1392 | TypeInfo type_info = { | |
1393 | .parent = TYPE_AARCH64_CPU, | |
1394 | .instance_size = sizeof(ARMCPU), | |
51e5ef45 | 1395 | .instance_init = aarch64_cpu_instance_init, |
d14d42f1 | 1396 | .class_size = sizeof(ARMCPUClass), |
51e5ef45 MAL |
1397 | .class_init = info->class_init ?: cpu_register_class_init, |
1398 | .class_data = (void *)info, | |
d14d42f1 PM |
1399 | }; |
1400 | ||
1401 | type_info.name = g_strdup_printf("%s-" TYPE_ARM_CPU, info->name); | |
1402 | type_register(&type_info); | |
1403 | g_free((void *)type_info.name); | |
1404 | } | |
1405 | ||
1406 | static const TypeInfo aarch64_cpu_type_info = { | |
1407 | .name = TYPE_AARCH64_CPU, | |
1408 | .parent = TYPE_ARM_CPU, | |
1409 | .instance_size = sizeof(ARMCPU), | |
d14d42f1 PM |
1410 | .instance_finalize = aarch64_cpu_finalizefn, |
1411 | .abstract = true, | |
1412 | .class_size = sizeof(AArch64CPUClass), | |
1413 | .class_init = aarch64_cpu_class_init, | |
1414 | }; | |
1415 | ||
1416 | static void aarch64_cpu_register_types(void) | |
1417 | { | |
92b6a659 | 1418 | size_t i; |
d14d42f1 PM |
1419 | |
1420 | type_register_static(&aarch64_cpu_type_info); | |
83e6813a | 1421 | |
92b6a659 PMD |
1422 | for (i = 0; i < ARRAY_SIZE(aarch64_cpus); ++i) { |
1423 | aarch64_cpu_register(&aarch64_cpus[i]); | |
d14d42f1 PM |
1424 | } |
1425 | } | |
1426 | ||
1427 | type_init(aarch64_cpu_register_types) |