1fcf5ef2aSThomas Huth /*
2fcf5ef2aSThomas Huth * QEMU AArch64 CPU
3fcf5ef2aSThomas Huth *
4fcf5ef2aSThomas Huth * Copyright (c) 2013 Linaro Ltd
5fcf5ef2aSThomas Huth *
6fcf5ef2aSThomas Huth * This program is free software; you can redistribute it and/or
7fcf5ef2aSThomas Huth * modify it under the terms of the GNU General Public License
8fcf5ef2aSThomas Huth * as published by the Free Software Foundation; either version 2
9fcf5ef2aSThomas Huth * of the License, or (at your option) any later version.
10fcf5ef2aSThomas Huth *
11fcf5ef2aSThomas Huth * This program is distributed in the hope that it will be useful,
12fcf5ef2aSThomas Huth * but WITHOUT ANY WARRANTY; without even the implied warranty of
13fcf5ef2aSThomas Huth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14fcf5ef2aSThomas Huth * GNU General Public License for more details.
15fcf5ef2aSThomas Huth *
16fcf5ef2aSThomas Huth * You should have received a copy of the GNU General Public License
17fcf5ef2aSThomas Huth * along with this program; if not, see
18fcf5ef2aSThomas Huth * <http://www.gnu.org/licenses/gpl-2.0.html>
19fcf5ef2aSThomas Huth */
20fcf5ef2aSThomas Huth
21fcf5ef2aSThomas Huth #include "qemu/osdep.h"
22fcf5ef2aSThomas Huth #include "qapi/error.h"
23fcf5ef2aSThomas Huth #include "cpu.h"
240b903369SChen Baozi #include "cpregs.h"
250b8fa32fSMarkus Armbruster #include "qemu/module.h"
26*676624d7SAlireza Sanaee #include "qemu/units.h"
27fcf5ef2aSThomas Huth #include "sysemu/kvm.h"
286ee609b7SPeter Maydell #include "sysemu/hvf.h"
29fcab465eSFabiano Rosas #include "sysemu/qtest.h"
30fcab465eSFabiano Rosas #include "sysemu/tcg.h"
31bab52d4bSPeter Maydell #include "kvm_arm.h"
32dcfb1d04SPeter Maydell #include "hvf_arm.h"
33adf92eabSRichard Henderson #include "qapi/visitor.h"
34eb94284dSRichard Henderson #include "hw/qdev-properties.h"
357c1aaf98SRichard Henderson #include "internals.h"
365a534314SPeter Maydell #include "cpu-features.h"
3734bfe467SFabiano Rosas #include "cpregs.h"
38eb94284dSRichard Henderson
arm_cpu_sve_finalize(ARMCPU * cpu,Error ** errp)390df9142dSAndrew Jones void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
400df9142dSAndrew Jones {
410df9142dSAndrew Jones /*
420df9142dSAndrew Jones * If any vector lengths are explicitly enabled with sve<N> properties,
430df9142dSAndrew Jones * then all other lengths are implicitly disabled. If sve-max-vq is
440df9142dSAndrew Jones * specified then it is the same as explicitly enabling all lengths
450df9142dSAndrew Jones * up to and including the specified maximum, which means all larger
460df9142dSAndrew Jones * lengths will be implicitly disabled. If no sve<N> properties
470df9142dSAndrew Jones * are enabled and sve-max-vq is not specified, then all lengths not
480df9142dSAndrew Jones * explicitly disabled will be enabled. Additionally, all power-of-two
490df9142dSAndrew Jones * vector lengths less than the maximum enabled length will be
500df9142dSAndrew Jones * automatically enabled and all vector lengths larger than the largest
510df9142dSAndrew Jones * disabled power-of-two vector length will be automatically disabled.
520df9142dSAndrew Jones * Errors are generated if the user provided input that interferes with
530df9142dSAndrew Jones * any of the above. Finally, if SVE is not disabled, then at least one
540df9142dSAndrew Jones * vector length must be enabled.
550df9142dSAndrew Jones */
567f9e25a6SRichard Henderson uint32_t vq_map = cpu->sve_vq.map;
577f9e25a6SRichard Henderson uint32_t vq_init = cpu->sve_vq.init;
58886902ecSRichard Henderson uint32_t vq_supported;
59886902ecSRichard Henderson uint32_t vq_mask = 0;
60886902ecSRichard Henderson uint32_t tmp, vq, max_vq = 0;
610df9142dSAndrew Jones
625b65e5abSAndrew Jones /*
635b65e5abSAndrew Jones * CPU models specify a set of supported vector lengths which are
645b65e5abSAndrew Jones * enabled by default. Attempting to enable any vector length not set
655b65e5abSAndrew Jones * in the supported bitmap results in an error. When KVM is enabled we
665b65e5abSAndrew Jones * fetch the supported bitmap from the host.
675b65e5abSAndrew Jones */
68886902ecSRichard Henderson if (kvm_enabled()) {
69886902ecSRichard Henderson if (kvm_arm_sve_supported()) {
70d6339282SPhilippe Mathieu-Daudé cpu->sve_vq.supported = kvm_arm_sve_get_vls(cpu);
717f9e25a6SRichard Henderson vq_supported = cpu->sve_vq.supported;
72886902ecSRichard Henderson } else {
736fa8a379SAndrew Jones assert(!cpu_isar_feature(aa64_sve, cpu));
74886902ecSRichard Henderson vq_supported = 0;
75886902ecSRichard Henderson }
76886902ecSRichard Henderson } else {
777f9e25a6SRichard Henderson vq_supported = cpu->sve_vq.supported;
786fa8a379SAndrew Jones }
796fa8a379SAndrew Jones
800df9142dSAndrew Jones /*
810df9142dSAndrew Jones * Process explicit sve<N> properties.
820df9142dSAndrew Jones * From the properties, sve_vq_map<N> implies sve_vq_init<N>.
830df9142dSAndrew Jones * Check first for any sve<N> enabled.
840df9142dSAndrew Jones */
85886902ecSRichard Henderson if (vq_map != 0) {
86886902ecSRichard Henderson max_vq = 32 - clz32(vq_map);
87886902ecSRichard Henderson vq_mask = MAKE_64BIT_MASK(0, max_vq);
880df9142dSAndrew Jones
890df9142dSAndrew Jones if (cpu->sve_max_vq && max_vq > cpu->sve_max_vq) {
900df9142dSAndrew Jones error_setg(errp, "cannot enable sve%d", max_vq * 128);
910df9142dSAndrew Jones error_append_hint(errp, "sve%d is larger than the maximum vector "
920df9142dSAndrew Jones "length, sve-max-vq=%d (%d bits)\n",
930df9142dSAndrew Jones max_vq * 128, cpu->sve_max_vq,
940df9142dSAndrew Jones cpu->sve_max_vq * 128);
950df9142dSAndrew Jones return;
960df9142dSAndrew Jones }
970df9142dSAndrew Jones
986fa8a379SAndrew Jones if (kvm_enabled()) {
996fa8a379SAndrew Jones /*
100673d8215SMichael Tokarev * For KVM we have to automatically enable all supported uninitialized
1016fa8a379SAndrew Jones * lengths, even when the smaller lengths are not all powers-of-two.
1026fa8a379SAndrew Jones */
103886902ecSRichard Henderson vq_map |= vq_supported & ~vq_init & vq_mask;
1046fa8a379SAndrew Jones } else {
1050df9142dSAndrew Jones /* Propagate enabled bits down through required powers-of-two. */
106886902ecSRichard Henderson vq_map |= SVE_VQ_POW2_MAP & ~vq_init & vq_mask;
1076fa8a379SAndrew Jones }
1080df9142dSAndrew Jones } else if (cpu->sve_max_vq == 0) {
1090df9142dSAndrew Jones /*
1100df9142dSAndrew Jones * No explicit bits enabled, and no implicit bits from sve-max-vq.
1110df9142dSAndrew Jones */
1120df9142dSAndrew Jones if (!cpu_isar_feature(aa64_sve, cpu)) {
113daf9748aSMarcin Juszkiewicz /*
114daf9748aSMarcin Juszkiewicz * SVE is disabled and so are all vector lengths. Good.
115daf9748aSMarcin Juszkiewicz * Disable all SVE extensions as well.
116daf9748aSMarcin Juszkiewicz */
117daf9748aSMarcin Juszkiewicz cpu->isar.id_aa64zfr0 = 0;
1180df9142dSAndrew Jones return;
1190df9142dSAndrew Jones }
1200df9142dSAndrew Jones
1216fa8a379SAndrew Jones if (kvm_enabled()) {
1226fa8a379SAndrew Jones /* Disabling a supported length disables all larger lengths. */
123886902ecSRichard Henderson tmp = vq_init & vq_supported;
124022707e5SAndrew Jones } else {
125022707e5SAndrew Jones /* Disabling a power-of-two disables all larger lengths. */
126886902ecSRichard Henderson tmp = vq_init & SVE_VQ_POW2_MAP;
127022707e5SAndrew Jones }
128886902ecSRichard Henderson vq = ctz32(tmp) + 1;
129022707e5SAndrew Jones
1306fa8a379SAndrew Jones max_vq = vq <= ARM_MAX_VQ ? vq - 1 : ARM_MAX_VQ;
131c4107723SPeter Maydell vq_mask = max_vq > 0 ? MAKE_64BIT_MASK(0, max_vq) : 0;
132886902ecSRichard Henderson vq_map = vq_supported & ~vq_init & vq_mask;
133886902ecSRichard Henderson
134c4107723SPeter Maydell if (vq_map == 0) {
1356fa8a379SAndrew Jones error_setg(errp, "cannot disable sve%d", vq * 128);
1366fa8a379SAndrew Jones error_append_hint(errp, "Disabling sve%d results in all "
1376fa8a379SAndrew Jones "vector lengths being disabled.\n",
1386fa8a379SAndrew Jones vq * 128);
1396fa8a379SAndrew Jones error_append_hint(errp, "With SVE enabled, at least one "
1406fa8a379SAndrew Jones "vector length must be enabled.\n");
1416fa8a379SAndrew Jones return;
1426fa8a379SAndrew Jones }
1436fa8a379SAndrew Jones
144886902ecSRichard Henderson max_vq = 32 - clz32(vq_map);
145886902ecSRichard Henderson vq_mask = MAKE_64BIT_MASK(0, max_vq);
1460df9142dSAndrew Jones }
1470df9142dSAndrew Jones
1480df9142dSAndrew Jones /*
1490df9142dSAndrew Jones * Process the sve-max-vq property.
1500df9142dSAndrew Jones * Note that we know from the above that no bit above
1510df9142dSAndrew Jones * sve-max-vq is currently set.
1520df9142dSAndrew Jones */
1530df9142dSAndrew Jones if (cpu->sve_max_vq != 0) {
1540df9142dSAndrew Jones max_vq = cpu->sve_max_vq;
155886902ecSRichard Henderson vq_mask = MAKE_64BIT_MASK(0, max_vq);
1560df9142dSAndrew Jones
157886902ecSRichard Henderson if (vq_init & ~vq_map & (1 << (max_vq - 1))) {
1580df9142dSAndrew Jones error_setg(errp, "cannot disable sve%d", max_vq * 128);
1590df9142dSAndrew Jones error_append_hint(errp, "The maximum vector length must be "
1600df9142dSAndrew Jones "enabled, sve-max-vq=%d (%d bits)\n",
1610df9142dSAndrew Jones max_vq, max_vq * 128);
1620df9142dSAndrew Jones return;
1630df9142dSAndrew Jones }
1640df9142dSAndrew Jones
1650df9142dSAndrew Jones /* Set all bits not explicitly set within sve-max-vq. */
166886902ecSRichard Henderson vq_map |= ~vq_init & vq_mask;
1670df9142dSAndrew Jones }
1680df9142dSAndrew Jones
1690df9142dSAndrew Jones /*
1700df9142dSAndrew Jones * We should know what max-vq is now. Also, as we're done
1710df9142dSAndrew Jones * manipulating sve-vq-map, we ensure any bits above max-vq
1720df9142dSAndrew Jones * are clear, just in case anybody looks.
1730df9142dSAndrew Jones */
1740df9142dSAndrew Jones assert(max_vq != 0);
175886902ecSRichard Henderson assert(vq_mask != 0);
176886902ecSRichard Henderson vq_map &= vq_mask;
1770df9142dSAndrew Jones
178022707e5SAndrew Jones /* Ensure the set of lengths matches what is supported. */
179886902ecSRichard Henderson tmp = vq_map ^ (vq_supported & vq_mask);
180886902ecSRichard Henderson if (tmp) {
181886902ecSRichard Henderson vq = 32 - clz32(tmp);
182886902ecSRichard Henderson if (vq_map & (1 << (vq - 1))) {
1836fa8a379SAndrew Jones if (cpu->sve_max_vq) {
184022707e5SAndrew Jones error_setg(errp, "cannot set sve-max-vq=%d", cpu->sve_max_vq);
185022707e5SAndrew Jones error_append_hint(errp, "This CPU does not support "
186022707e5SAndrew Jones "the vector length %d-bits.\n", vq * 128);
1876fa8a379SAndrew Jones error_append_hint(errp, "It may not be possible to use "
188022707e5SAndrew Jones "sve-max-vq with this CPU. Try "
1896fa8a379SAndrew Jones "using only sve<N> properties.\n");
1906fa8a379SAndrew Jones } else {
1916fa8a379SAndrew Jones error_setg(errp, "cannot enable sve%d", vq * 128);
192531cc510SRichard Henderson if (vq_supported) {
193022707e5SAndrew Jones error_append_hint(errp, "This CPU does not support "
194022707e5SAndrew Jones "the vector length %d-bits.\n", vq * 128);
195531cc510SRichard Henderson } else {
196531cc510SRichard Henderson error_append_hint(errp, "SVE not supported by KVM "
197531cc510SRichard Henderson "on this host\n");
198531cc510SRichard Henderson }
1996fa8a379SAndrew Jones }
200022707e5SAndrew Jones return;
2016fa8a379SAndrew Jones } else {
202022707e5SAndrew Jones if (kvm_enabled()) {
2036fa8a379SAndrew Jones error_setg(errp, "cannot disable sve%d", vq * 128);
2046fa8a379SAndrew Jones error_append_hint(errp, "The KVM host requires all "
2056fa8a379SAndrew Jones "supported vector lengths smaller "
2066fa8a379SAndrew Jones "than %d bits to also be enabled.\n",
2076fa8a379SAndrew Jones max_vq * 128);
2086fa8a379SAndrew Jones return;
2096fa8a379SAndrew Jones } else {
2100df9142dSAndrew Jones /* Ensure all required powers-of-two are enabled. */
211886902ecSRichard Henderson tmp = SVE_VQ_POW2_MAP & vq_mask & ~vq_map;
212886902ecSRichard Henderson if (tmp) {
213886902ecSRichard Henderson vq = 32 - clz32(tmp);
2140df9142dSAndrew Jones error_setg(errp, "cannot disable sve%d", vq * 128);
2150df9142dSAndrew Jones error_append_hint(errp, "sve%d is required as it "
216022707e5SAndrew Jones "is a power-of-two length smaller "
217022707e5SAndrew Jones "than the maximum, sve%d\n",
2180df9142dSAndrew Jones vq * 128, max_vq * 128);
2190df9142dSAndrew Jones return;
2200df9142dSAndrew Jones }
2210df9142dSAndrew Jones }
2226fa8a379SAndrew Jones }
223022707e5SAndrew Jones }
2240df9142dSAndrew Jones
2250df9142dSAndrew Jones /*
2260df9142dSAndrew Jones * Now that we validated all our vector lengths, the only question
2270df9142dSAndrew Jones * left to answer is if we even want SVE at all.
2280df9142dSAndrew Jones */
2290df9142dSAndrew Jones if (!cpu_isar_feature(aa64_sve, cpu)) {
2300df9142dSAndrew Jones error_setg(errp, "cannot enable sve%d", max_vq * 128);
2310df9142dSAndrew Jones error_append_hint(errp, "SVE must be enabled to enable vector "
2320df9142dSAndrew Jones "lengths.\n");
2330df9142dSAndrew Jones error_append_hint(errp, "Add sve=on to the CPU property list.\n");
2340df9142dSAndrew Jones return;
2350df9142dSAndrew Jones }
2360df9142dSAndrew Jones
2370df9142dSAndrew Jones /* From now on sve_max_vq is the actual maximum supported length. */
2380df9142dSAndrew Jones cpu->sve_max_vq = max_vq;
2397f9e25a6SRichard Henderson cpu->sve_vq.map = vq_map;
2400df9142dSAndrew Jones }
2410df9142dSAndrew Jones
2428073b871SRichard Henderson /*
2430f40784eSRichard Henderson * Note that cpu_arm_{get,set}_vq cannot use the simpler
2440f40784eSRichard Henderson * object_property_add_bool interface because they make use of the
2450f40784eSRichard Henderson * contents of "name" to determine which bit on which to operate.
2468073b871SRichard Henderson */
cpu_arm_get_vq(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2470f40784eSRichard Henderson static void cpu_arm_get_vq(Object *obj, Visitor *v, const char *name,
2480df9142dSAndrew Jones void *opaque, Error **errp)
2490df9142dSAndrew Jones {
2500df9142dSAndrew Jones ARMCPU *cpu = ARM_CPU(obj);
2510f40784eSRichard Henderson ARMVQMap *vq_map = opaque;
2520df9142dSAndrew Jones uint32_t vq = atoi(&name[3]) / 128;
253e74c0976SRichard Henderson bool sve = vq_map == &cpu->sve_vq;
2540df9142dSAndrew Jones bool value;
2550df9142dSAndrew Jones
256e74c0976SRichard Henderson /* All vector lengths are disabled when feature is off. */
257e74c0976SRichard Henderson if (sve
258e74c0976SRichard Henderson ? !cpu_isar_feature(aa64_sve, cpu)
259e74c0976SRichard Henderson : !cpu_isar_feature(aa64_sme, cpu)) {
2600df9142dSAndrew Jones value = false;
2610df9142dSAndrew Jones } else {
2620f40784eSRichard Henderson value = extract32(vq_map->map, vq - 1, 1);
2630df9142dSAndrew Jones }
2640df9142dSAndrew Jones visit_type_bool(v, name, &value, errp);
2650df9142dSAndrew Jones }
2660df9142dSAndrew Jones
cpu_arm_set_vq(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)2670f40784eSRichard Henderson static void cpu_arm_set_vq(Object *obj, Visitor *v, const char *name,
2680df9142dSAndrew Jones void *opaque, Error **errp)
2690df9142dSAndrew Jones {
2700f40784eSRichard Henderson ARMVQMap *vq_map = opaque;
2710df9142dSAndrew Jones uint32_t vq = atoi(&name[3]) / 128;
2720df9142dSAndrew Jones bool value;
2730df9142dSAndrew Jones
274668f62ecSMarkus Armbruster if (!visit_type_bool(v, name, &value, errp)) {
2750df9142dSAndrew Jones return;
2760df9142dSAndrew Jones }
2770df9142dSAndrew Jones
2780f40784eSRichard Henderson vq_map->map = deposit32(vq_map->map, vq - 1, 1, value);
2790f40784eSRichard Henderson vq_map->init |= 1 << (vq - 1);
2800df9142dSAndrew Jones }
2810df9142dSAndrew Jones
cpu_arm_get_sve(Object * obj,Error ** errp)2828073b871SRichard Henderson static bool cpu_arm_get_sve(Object *obj, Error **errp)
28373234775SAndrew Jones {
28473234775SAndrew Jones ARMCPU *cpu = ARM_CPU(obj);
2858073b871SRichard Henderson return cpu_isar_feature(aa64_sve, cpu);
28673234775SAndrew Jones }
28773234775SAndrew Jones
cpu_arm_set_sve(Object * obj,bool value,Error ** errp)2888073b871SRichard Henderson static void cpu_arm_set_sve(Object *obj, bool value, Error **errp)
28973234775SAndrew Jones {
29073234775SAndrew Jones ARMCPU *cpu = ARM_CPU(obj);
29173234775SAndrew Jones uint64_t t;
29273234775SAndrew Jones
2937d20e681SPhilippe Mathieu-Daudé if (value && kvm_enabled() && !kvm_arm_sve_supported()) {
29414e99e0fSAndrew Jones error_setg(errp, "'sve' feature not supported by KVM on this host");
29514e99e0fSAndrew Jones return;
29614e99e0fSAndrew Jones }
29714e99e0fSAndrew Jones
29873234775SAndrew Jones t = cpu->isar.id_aa64pfr0;
29973234775SAndrew Jones t = FIELD_DP64(t, ID_AA64PFR0, SVE, value);
30073234775SAndrew Jones cpu->isar.id_aa64pfr0 = t;
30173234775SAndrew Jones }
30273234775SAndrew Jones
arm_cpu_sme_finalize(ARMCPU * cpu,Error ** errp)303e74c0976SRichard Henderson void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp)
304e74c0976SRichard Henderson {
305e74c0976SRichard Henderson uint32_t vq_map = cpu->sme_vq.map;
306e74c0976SRichard Henderson uint32_t vq_init = cpu->sme_vq.init;
307e74c0976SRichard Henderson uint32_t vq_supported = cpu->sme_vq.supported;
308e74c0976SRichard Henderson uint32_t vq;
309e74c0976SRichard Henderson
310e74c0976SRichard Henderson if (vq_map == 0) {
311e74c0976SRichard Henderson if (!cpu_isar_feature(aa64_sme, cpu)) {
312e74c0976SRichard Henderson cpu->isar.id_aa64smfr0 = 0;
313e74c0976SRichard Henderson return;
314e74c0976SRichard Henderson }
315e74c0976SRichard Henderson
316e74c0976SRichard Henderson /* TODO: KVM will require limitations via SMCR_EL2. */
317e74c0976SRichard Henderson vq_map = vq_supported & ~vq_init;
318e74c0976SRichard Henderson
319e74c0976SRichard Henderson if (vq_map == 0) {
320e74c0976SRichard Henderson vq = ctz32(vq_supported) + 1;
321e74c0976SRichard Henderson error_setg(errp, "cannot disable sme%d", vq * 128);
322e74c0976SRichard Henderson error_append_hint(errp, "All SME vector lengths are disabled.\n");
323e74c0976SRichard Henderson error_append_hint(errp, "With SME enabled, at least one "
324e74c0976SRichard Henderson "vector length must be enabled.\n");
325e74c0976SRichard Henderson return;
326e74c0976SRichard Henderson }
327e74c0976SRichard Henderson } else {
328e74c0976SRichard Henderson if (!cpu_isar_feature(aa64_sme, cpu)) {
329e74c0976SRichard Henderson vq = 32 - clz32(vq_map);
330e74c0976SRichard Henderson error_setg(errp, "cannot enable sme%d", vq * 128);
331e74c0976SRichard Henderson error_append_hint(errp, "SME must be enabled to enable "
332e74c0976SRichard Henderson "vector lengths.\n");
333e74c0976SRichard Henderson error_append_hint(errp, "Add sme=on to the CPU property list.\n");
334e74c0976SRichard Henderson return;
335e74c0976SRichard Henderson }
336e74c0976SRichard Henderson /* TODO: KVM will require limitations via SMCR_EL2. */
337e74c0976SRichard Henderson }
338e74c0976SRichard Henderson
339e74c0976SRichard Henderson cpu->sme_vq.map = vq_map;
340e74c0976SRichard Henderson }
341e74c0976SRichard Henderson
cpu_arm_get_sme(Object * obj,Error ** errp)342e74c0976SRichard Henderson static bool cpu_arm_get_sme(Object *obj, Error **errp)
343e74c0976SRichard Henderson {
344e74c0976SRichard Henderson ARMCPU *cpu = ARM_CPU(obj);
345e74c0976SRichard Henderson return cpu_isar_feature(aa64_sme, cpu);
346e74c0976SRichard Henderson }
347e74c0976SRichard Henderson
cpu_arm_set_sme(Object * obj,bool value,Error ** errp)348e74c0976SRichard Henderson static void cpu_arm_set_sme(Object *obj, bool value, Error **errp)
349e74c0976SRichard Henderson {
350e74c0976SRichard Henderson ARMCPU *cpu = ARM_CPU(obj);
351e74c0976SRichard Henderson uint64_t t;
352e74c0976SRichard Henderson
353e74c0976SRichard Henderson t = cpu->isar.id_aa64pfr1;
354e74c0976SRichard Henderson t = FIELD_DP64(t, ID_AA64PFR1, SME, value);
355e74c0976SRichard Henderson cpu->isar.id_aa64pfr1 = t;
356e74c0976SRichard Henderson }
357e74c0976SRichard Henderson
cpu_arm_get_sme_fa64(Object * obj,Error ** errp)358e74c0976SRichard Henderson static bool cpu_arm_get_sme_fa64(Object *obj, Error **errp)
359e74c0976SRichard Henderson {
360e74c0976SRichard Henderson ARMCPU *cpu = ARM_CPU(obj);
361e74c0976SRichard Henderson return cpu_isar_feature(aa64_sme, cpu) &&
362e74c0976SRichard Henderson cpu_isar_feature(aa64_sme_fa64, cpu);
363e74c0976SRichard Henderson }
364e74c0976SRichard Henderson
cpu_arm_set_sme_fa64(Object * obj,bool value,Error ** errp)365e74c0976SRichard Henderson static void cpu_arm_set_sme_fa64(Object *obj, bool value, Error **errp)
366e74c0976SRichard Henderson {
367e74c0976SRichard Henderson ARMCPU *cpu = ARM_CPU(obj);
368e74c0976SRichard Henderson uint64_t t;
369e74c0976SRichard Henderson
370e74c0976SRichard Henderson t = cpu->isar.id_aa64smfr0;
371e74c0976SRichard Henderson t = FIELD_DP64(t, ID_AA64SMFR0, FA64, value);
372e74c0976SRichard Henderson cpu->isar.id_aa64smfr0 = t;
373e74c0976SRichard Henderson }
374e74c0976SRichard Henderson
375b3d52804SRichard Henderson #ifdef CONFIG_USER_ONLY
376e74c0976SRichard Henderson /* Mirror linux /proc/sys/abi/{sve,sme}_default_vector_length. */
cpu_arm_set_default_vec_len(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)377515816a8SRichard Henderson static void cpu_arm_set_default_vec_len(Object *obj, Visitor *v,
378b3d52804SRichard Henderson const char *name, void *opaque,
379b3d52804SRichard Henderson Error **errp)
380b3d52804SRichard Henderson {
381515816a8SRichard Henderson uint32_t *ptr_default_vq = opaque;
382b3d52804SRichard Henderson int32_t default_len, default_vq, remainder;
383b3d52804SRichard Henderson
384b3d52804SRichard Henderson if (!visit_type_int32(v, name, &default_len, errp)) {
385b3d52804SRichard Henderson return;
386b3d52804SRichard Henderson }
387b3d52804SRichard Henderson
388b3d52804SRichard Henderson /* Undocumented, but the kernel allows -1 to indicate "maximum". */
389b3d52804SRichard Henderson if (default_len == -1) {
390515816a8SRichard Henderson *ptr_default_vq = ARM_MAX_VQ;
391b3d52804SRichard Henderson return;
392b3d52804SRichard Henderson }
393b3d52804SRichard Henderson
394b3d52804SRichard Henderson default_vq = default_len / 16;
395b3d52804SRichard Henderson remainder = default_len % 16;
396b3d52804SRichard Henderson
397b3d52804SRichard Henderson /*
398b3d52804SRichard Henderson * Note that the 512 max comes from include/uapi/asm/sve_context.h
399b3d52804SRichard Henderson * and is the maximum architectural width of ZCR_ELx.LEN.
400b3d52804SRichard Henderson */
401b3d52804SRichard Henderson if (remainder || default_vq < 1 || default_vq > 512) {
402e74c0976SRichard Henderson ARMCPU *cpu = ARM_CPU(obj);
403e74c0976SRichard Henderson const char *which =
404e74c0976SRichard Henderson (ptr_default_vq == &cpu->sve_default_vq ? "sve" : "sme");
405e74c0976SRichard Henderson
406e74c0976SRichard Henderson error_setg(errp, "cannot set %s-default-vector-length", which);
407b3d52804SRichard Henderson if (remainder) {
408b3d52804SRichard Henderson error_append_hint(errp, "Vector length not a multiple of 16\n");
409b3d52804SRichard Henderson } else if (default_vq < 1) {
410b3d52804SRichard Henderson error_append_hint(errp, "Vector length smaller than 16\n");
411b3d52804SRichard Henderson } else {
412b3d52804SRichard Henderson error_append_hint(errp, "Vector length larger than %d\n",
413b3d52804SRichard Henderson 512 * 16);
414b3d52804SRichard Henderson }
415b3d52804SRichard Henderson return;
416b3d52804SRichard Henderson }
417b3d52804SRichard Henderson
418515816a8SRichard Henderson *ptr_default_vq = default_vq;
419b3d52804SRichard Henderson }
420b3d52804SRichard Henderson
cpu_arm_get_default_vec_len(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)421515816a8SRichard Henderson static void cpu_arm_get_default_vec_len(Object *obj, Visitor *v,
422b3d52804SRichard Henderson const char *name, void *opaque,
423b3d52804SRichard Henderson Error **errp)
424b3d52804SRichard Henderson {
425515816a8SRichard Henderson uint32_t *ptr_default_vq = opaque;
426515816a8SRichard Henderson int32_t value = *ptr_default_vq * 16;
427b3d52804SRichard Henderson
428b3d52804SRichard Henderson visit_type_int32(v, name, &value, errp);
429b3d52804SRichard Henderson }
430b3d52804SRichard Henderson #endif
431b3d52804SRichard Henderson
aarch64_add_sve_properties(Object * obj)43239920a04SFabiano Rosas void aarch64_add_sve_properties(Object *obj)
43387014c6bSAndrew Jones {
4340f40784eSRichard Henderson ARMCPU *cpu = ARM_CPU(obj);
43587014c6bSAndrew Jones uint32_t vq;
43687014c6bSAndrew Jones
4378073b871SRichard Henderson object_property_add_bool(obj, "sve", cpu_arm_get_sve, cpu_arm_set_sve);
43887014c6bSAndrew Jones
43987014c6bSAndrew Jones for (vq = 1; vq <= ARM_MAX_VQ; ++vq) {
44087014c6bSAndrew Jones char name[8];
4412ad9d044SPhilippe Mathieu-Daudé snprintf(name, sizeof(name), "sve%d", vq * 128);
4420f40784eSRichard Henderson object_property_add(obj, name, "bool", cpu_arm_get_vq,
4430f40784eSRichard Henderson cpu_arm_set_vq, NULL, &cpu->sve_vq);
44487014c6bSAndrew Jones }
445b3d52804SRichard Henderson
446b3d52804SRichard Henderson #ifdef CONFIG_USER_ONLY
447b3d52804SRichard Henderson /* Mirror linux /proc/sys/abi/sve_default_vector_length. */
448b3d52804SRichard Henderson object_property_add(obj, "sve-default-vector-length", "int32",
449515816a8SRichard Henderson cpu_arm_get_default_vec_len,
450515816a8SRichard Henderson cpu_arm_set_default_vec_len, NULL,
451515816a8SRichard Henderson &cpu->sve_default_vq);
452b3d52804SRichard Henderson #endif
45387014c6bSAndrew Jones }
45487014c6bSAndrew Jones
aarch64_add_sme_properties(Object * obj)45539920a04SFabiano Rosas void aarch64_add_sme_properties(Object *obj)
456e74c0976SRichard Henderson {
457e74c0976SRichard Henderson ARMCPU *cpu = ARM_CPU(obj);
458e74c0976SRichard Henderson uint32_t vq;
459e74c0976SRichard Henderson
460e74c0976SRichard Henderson object_property_add_bool(obj, "sme", cpu_arm_get_sme, cpu_arm_set_sme);
461e74c0976SRichard Henderson object_property_add_bool(obj, "sme_fa64", cpu_arm_get_sme_fa64,
462e74c0976SRichard Henderson cpu_arm_set_sme_fa64);
463e74c0976SRichard Henderson
464e74c0976SRichard Henderson for (vq = 1; vq <= ARM_MAX_VQ; vq <<= 1) {
465e74c0976SRichard Henderson char name[8];
4662ad9d044SPhilippe Mathieu-Daudé snprintf(name, sizeof(name), "sme%d", vq * 128);
467e74c0976SRichard Henderson object_property_add(obj, name, "bool", cpu_arm_get_vq,
468e74c0976SRichard Henderson cpu_arm_set_vq, NULL, &cpu->sme_vq);
469e74c0976SRichard Henderson }
470e74c0976SRichard Henderson
471e74c0976SRichard Henderson #ifdef CONFIG_USER_ONLY
472e74c0976SRichard Henderson /* Mirror linux /proc/sys/abi/sme_default_vector_length. */
473e74c0976SRichard Henderson object_property_add(obj, "sme-default-vector-length", "int32",
474e74c0976SRichard Henderson cpu_arm_get_default_vec_len,
475e74c0976SRichard Henderson cpu_arm_set_default_vec_len, NULL,
476e74c0976SRichard Henderson &cpu->sme_default_vq);
477e74c0976SRichard Henderson #endif
478e74c0976SRichard Henderson }
479e74c0976SRichard Henderson
arm_cpu_pauth_finalize(ARMCPU * cpu,Error ** errp)480eb94284dSRichard Henderson void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
481eb94284dSRichard Henderson {
4826c3427eeSRichard Henderson ARMPauthFeature features = cpu_isar_feature(pauth_feature, cpu);
483399e5e71SRichard Henderson uint64_t isar1, isar2;
484eb94284dSRichard Henderson
4856c3427eeSRichard Henderson /*
4866c3427eeSRichard Henderson * These properties enable or disable Pauth as a whole, or change
4876c3427eeSRichard Henderson * the pauth algorithm, but do not change the set of features that
4886c3427eeSRichard Henderson * are present. We have saved a copy of those features above and
4896c3427eeSRichard Henderson * will now place it into the field that chooses the algorithm.
4906c3427eeSRichard Henderson *
4916c3427eeSRichard Henderson * Begin by disabling all fields.
4926c3427eeSRichard Henderson */
4936c3427eeSRichard Henderson isar1 = cpu->isar.id_aa64isar1;
4946c3427eeSRichard Henderson isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, APA, 0);
4956c3427eeSRichard Henderson isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPA, 0);
4966c3427eeSRichard Henderson isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, API, 0);
4976c3427eeSRichard Henderson isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPI, 0);
4986c3427eeSRichard Henderson
499399e5e71SRichard Henderson isar2 = cpu->isar.id_aa64isar2;
500399e5e71SRichard Henderson isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, APA3, 0);
501399e5e71SRichard Henderson isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, GPA3, 0);
502399e5e71SRichard Henderson
5036c3427eeSRichard Henderson if (kvm_enabled() || hvf_enabled()) {
5046c3427eeSRichard Henderson /*
5056c3427eeSRichard Henderson * Exit early if PAuth is enabled and fall through to disable it.
5066c3427eeSRichard Henderson * The algorithm selection properties are not present.
5076c3427eeSRichard Henderson */
5086c3427eeSRichard Henderson if (cpu->prop_pauth) {
5096c3427eeSRichard Henderson if (features == 0) {
5106c3427eeSRichard Henderson error_setg(errp, "'pauth' feature not supported by "
5116c3427eeSRichard Henderson "%s on this host", current_accel_name());
51295ea96e8SMarc Zyngier }
5136c3427eeSRichard Henderson return;
5146c3427eeSRichard Henderson }
5156c3427eeSRichard Henderson } else {
5166c3427eeSRichard Henderson /* Pauth properties are only present when the model supports it. */
5176c3427eeSRichard Henderson if (features == 0) {
5186c3427eeSRichard Henderson assert(!cpu->prop_pauth);
51995ea96e8SMarc Zyngier return;
52095ea96e8SMarc Zyngier }
52195ea96e8SMarc Zyngier
522eb94284dSRichard Henderson if (cpu->prop_pauth) {
523399e5e71SRichard Henderson if (cpu->prop_pauth_impdef && cpu->prop_pauth_qarma3) {
524399e5e71SRichard Henderson error_setg(errp,
525399e5e71SRichard Henderson "cannot enable both pauth-impdef and pauth-qarma3");
526399e5e71SRichard Henderson return;
527399e5e71SRichard Henderson }
528399e5e71SRichard Henderson
529eb94284dSRichard Henderson if (cpu->prop_pauth_impdef) {
5306c3427eeSRichard Henderson isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, API, features);
5316c3427eeSRichard Henderson isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPI, 1);
532399e5e71SRichard Henderson } else if (cpu->prop_pauth_qarma3) {
533399e5e71SRichard Henderson isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, APA3, features);
534399e5e71SRichard Henderson isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, GPA3, 1);
535eb94284dSRichard Henderson } else {
5366c3427eeSRichard Henderson isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, APA, features);
5376c3427eeSRichard Henderson isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPA, 1);
538eb94284dSRichard Henderson }
539399e5e71SRichard Henderson } else if (cpu->prop_pauth_impdef || cpu->prop_pauth_qarma3) {
540399e5e71SRichard Henderson error_setg(errp, "cannot enable pauth-impdef or "
541399e5e71SRichard Henderson "pauth-qarma3 without pauth");
542eb94284dSRichard Henderson error_append_hint(errp, "Add pauth=on to the CPU property list.\n");
543eb94284dSRichard Henderson }
5446c3427eeSRichard Henderson }
545eb94284dSRichard Henderson
5466c3427eeSRichard Henderson cpu->isar.id_aa64isar1 = isar1;
547399e5e71SRichard Henderson cpu->isar.id_aa64isar2 = isar2;
548eb94284dSRichard Henderson }
549eb94284dSRichard Henderson
550eb94284dSRichard Henderson static Property arm_cpu_pauth_property =
551eb94284dSRichard Henderson DEFINE_PROP_BOOL("pauth", ARMCPU, prop_pauth, true);
552eb94284dSRichard Henderson static Property arm_cpu_pauth_impdef_property =
553eb94284dSRichard Henderson DEFINE_PROP_BOOL("pauth-impdef", ARMCPU, prop_pauth_impdef, false);
554399e5e71SRichard Henderson static Property arm_cpu_pauth_qarma3_property =
555399e5e71SRichard Henderson DEFINE_PROP_BOOL("pauth-qarma3", ARMCPU, prop_pauth_qarma3, false);
556eb94284dSRichard Henderson
aarch64_add_pauth_properties(Object * obj)55739920a04SFabiano Rosas void aarch64_add_pauth_properties(Object *obj)
55895ea96e8SMarc Zyngier {
55995ea96e8SMarc Zyngier ARMCPU *cpu = ARM_CPU(obj);
56095ea96e8SMarc Zyngier
56195ea96e8SMarc Zyngier /* Default to PAUTH on, with the architected algorithm on TCG. */
56295ea96e8SMarc Zyngier qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_property);
56392d6528dSPeter Maydell if (kvm_enabled() || hvf_enabled()) {
56495ea96e8SMarc Zyngier /*
56595ea96e8SMarc Zyngier * Mirror PAuth support from the probed sysregs back into the
56692d6528dSPeter Maydell * property for KVM or hvf. Is it just a bit backward? Yes it is!
56792d6528dSPeter Maydell * Note that prop_pauth is true whether the host CPU supports the
56892d6528dSPeter Maydell * architected QARMA5 algorithm or the IMPDEF one. We don't
56992d6528dSPeter Maydell * provide the separate pauth-impdef property for KVM or hvf,
57092d6528dSPeter Maydell * only for TCG.
57195ea96e8SMarc Zyngier */
57295ea96e8SMarc Zyngier cpu->prop_pauth = cpu_isar_feature(aa64_pauth, cpu);
57395ea96e8SMarc Zyngier } else {
57495ea96e8SMarc Zyngier qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_impdef_property);
575399e5e71SRichard Henderson qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_qarma3_property);
57695ea96e8SMarc Zyngier }
57795ea96e8SMarc Zyngier }
57895ea96e8SMarc Zyngier
arm_cpu_lpa2_finalize(ARMCPU * cpu,Error ** errp)57969b2265dSRichard Henderson void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp)
58069b2265dSRichard Henderson {
58169b2265dSRichard Henderson uint64_t t;
58269b2265dSRichard Henderson
58369b2265dSRichard Henderson /*
58469b2265dSRichard Henderson * We only install the property for tcg -cpu max; this is the
58569b2265dSRichard Henderson * only situation in which the cpu field can be true.
58669b2265dSRichard Henderson */
58769b2265dSRichard Henderson if (!cpu->prop_lpa2) {
58869b2265dSRichard Henderson return;
58969b2265dSRichard Henderson }
59069b2265dSRichard Henderson
59169b2265dSRichard Henderson t = cpu->isar.id_aa64mmfr0;
59269b2265dSRichard Henderson t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16, 2); /* 16k pages w/ LPA2 */
59369b2265dSRichard Henderson t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4, 1); /* 4k pages w/ LPA2 */
59469b2265dSRichard Henderson t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16_2, 3); /* 16k stage2 w/ LPA2 */
59569b2265dSRichard Henderson t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 3); /* 4k stage2 w/ LPA2 */
59669b2265dSRichard Henderson cpu->isar.id_aa64mmfr0 = t;
59769b2265dSRichard Henderson }
59869b2265dSRichard Henderson
aarch64_a57_initfn(Object * obj)599042e85d1SPeter Maydell static void aarch64_a57_initfn(Object *obj)
600042e85d1SPeter Maydell {
601042e85d1SPeter Maydell ARMCPU *cpu = ARM_CPU(obj);
602042e85d1SPeter Maydell
603042e85d1SPeter Maydell cpu->dtb_compatible = "arm,cortex-a57";
604042e85d1SPeter Maydell set_feature(&cpu->env, ARM_FEATURE_V8);
605042e85d1SPeter Maydell set_feature(&cpu->env, ARM_FEATURE_NEON);
606042e85d1SPeter Maydell set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
607f037f5b4SPeter Maydell set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
608042e85d1SPeter Maydell set_feature(&cpu->env, ARM_FEATURE_AARCH64);
609042e85d1SPeter Maydell set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
610042e85d1SPeter Maydell set_feature(&cpu->env, ARM_FEATURE_EL2);
611042e85d1SPeter Maydell set_feature(&cpu->env, ARM_FEATURE_EL3);
612042e85d1SPeter Maydell set_feature(&cpu->env, ARM_FEATURE_PMU);
613042e85d1SPeter Maydell cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A57;
614042e85d1SPeter Maydell cpu->midr = 0x411fd070;
615042e85d1SPeter Maydell cpu->revidr = 0x00000000;
616042e85d1SPeter Maydell cpu->reset_fpsid = 0x41034070;
617042e85d1SPeter Maydell cpu->isar.mvfr0 = 0x10110222;
618042e85d1SPeter Maydell cpu->isar.mvfr1 = 0x12111111;
619042e85d1SPeter Maydell cpu->isar.mvfr2 = 0x00000043;
620042e85d1SPeter Maydell cpu->ctr = 0x8444c004;
621042e85d1SPeter Maydell cpu->reset_sctlr = 0x00c50838;
622042e85d1SPeter Maydell cpu->isar.id_pfr0 = 0x00000131;
623042e85d1SPeter Maydell cpu->isar.id_pfr1 = 0x00011011;
624042e85d1SPeter Maydell cpu->isar.id_dfr0 = 0x03010066;
625042e85d1SPeter Maydell cpu->id_afr0 = 0x00000000;
626042e85d1SPeter Maydell cpu->isar.id_mmfr0 = 0x10101105;
627042e85d1SPeter Maydell cpu->isar.id_mmfr1 = 0x40000000;
628042e85d1SPeter Maydell cpu->isar.id_mmfr2 = 0x01260000;
629042e85d1SPeter Maydell cpu->isar.id_mmfr3 = 0x02102211;
630042e85d1SPeter Maydell cpu->isar.id_isar0 = 0x02101110;
631042e85d1SPeter Maydell cpu->isar.id_isar1 = 0x13112111;
632042e85d1SPeter Maydell cpu->isar.id_isar2 = 0x21232042;
633042e85d1SPeter Maydell cpu->isar.id_isar3 = 0x01112131;
634042e85d1SPeter Maydell cpu->isar.id_isar4 = 0x00011142;
635042e85d1SPeter Maydell cpu->isar.id_isar5 = 0x00011121;
636042e85d1SPeter Maydell cpu->isar.id_isar6 = 0;
637042e85d1SPeter Maydell cpu->isar.id_aa64pfr0 = 0x00002222;
638042e85d1SPeter Maydell cpu->isar.id_aa64dfr0 = 0x10305106;
639042e85d1SPeter Maydell cpu->isar.id_aa64isar0 = 0x00011120;
640042e85d1SPeter Maydell cpu->isar.id_aa64mmfr0 = 0x00001124;
641042e85d1SPeter Maydell cpu->isar.dbgdidr = 0x3516d000;
642042e85d1SPeter Maydell cpu->isar.dbgdevid = 0x01110f13;
643042e85d1SPeter Maydell cpu->isar.dbgdevid1 = 0x2;
644042e85d1SPeter Maydell cpu->isar.reset_pmcr_el0 = 0x41013000;
645042e85d1SPeter Maydell cpu->clidr = 0x0a200023;
646*676624d7SAlireza Sanaee /* 32KB L1 dcache */
647*676624d7SAlireza Sanaee cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7);
648*676624d7SAlireza Sanaee /* 48KB L1 icache */
649*676624d7SAlireza Sanaee cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 3, 64, 48 * KiB, 2);
650*676624d7SAlireza Sanaee /* 2048KB L2 cache */
651*676624d7SAlireza Sanaee cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 2 * MiB, 7);
652042e85d1SPeter Maydell cpu->dcz_blocksize = 4; /* 64 bytes */
653042e85d1SPeter Maydell cpu->gic_num_lrs = 4;
654042e85d1SPeter Maydell cpu->gic_vpribits = 5;
655042e85d1SPeter Maydell cpu->gic_vprebits = 5;
656042e85d1SPeter Maydell cpu->gic_pribits = 5;
657042e85d1SPeter Maydell define_cortex_a72_a57_a53_cp_reginfo(cpu);
658042e85d1SPeter Maydell }
659042e85d1SPeter Maydell
aarch64_a53_initfn(Object * obj)660042e85d1SPeter Maydell static void aarch64_a53_initfn(Object *obj)
661042e85d1SPeter Maydell {
662042e85d1SPeter Maydell ARMCPU *cpu = ARM_CPU(obj);
663042e85d1SPeter Maydell
664042e85d1SPeter Maydell cpu->dtb_compatible = "arm,cortex-a53";
665042e85d1SPeter Maydell set_feature(&cpu->env, ARM_FEATURE_V8);
666042e85d1SPeter Maydell set_feature(&cpu->env, ARM_FEATURE_NEON);
667042e85d1SPeter Maydell set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
668f037f5b4SPeter Maydell set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
669042e85d1SPeter Maydell set_feature(&cpu->env, ARM_FEATURE_AARCH64);
670042e85d1SPeter Maydell set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
671042e85d1SPeter Maydell set_feature(&cpu->env, ARM_FEATURE_EL2);
672042e85d1SPeter Maydell set_feature(&cpu->env, ARM_FEATURE_EL3);
673042e85d1SPeter Maydell set_feature(&cpu->env, ARM_FEATURE_PMU);
674042e85d1SPeter Maydell cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A53;
675042e85d1SPeter Maydell cpu->midr = 0x410fd034;
676aa29cdd6SArd Biesheuvel cpu->revidr = 0x00000100;
677042e85d1SPeter Maydell cpu->reset_fpsid = 0x41034070;
678042e85d1SPeter Maydell cpu->isar.mvfr0 = 0x10110222;
679042e85d1SPeter Maydell cpu->isar.mvfr1 = 0x12111111;
680042e85d1SPeter Maydell cpu->isar.mvfr2 = 0x00000043;
681042e85d1SPeter Maydell cpu->ctr = 0x84448004; /* L1Ip = VIPT */
682042e85d1SPeter Maydell cpu->reset_sctlr = 0x00c50838;
683042e85d1SPeter Maydell cpu->isar.id_pfr0 = 0x00000131;
684042e85d1SPeter Maydell cpu->isar.id_pfr1 = 0x00011011;
685042e85d1SPeter Maydell cpu->isar.id_dfr0 = 0x03010066;
686042e85d1SPeter Maydell cpu->id_afr0 = 0x00000000;
687042e85d1SPeter Maydell cpu->isar.id_mmfr0 = 0x10101105;
688042e85d1SPeter Maydell cpu->isar.id_mmfr1 = 0x40000000;
689042e85d1SPeter Maydell cpu->isar.id_mmfr2 = 0x01260000;
690042e85d1SPeter Maydell cpu->isar.id_mmfr3 = 0x02102211;
691042e85d1SPeter Maydell cpu->isar.id_isar0 = 0x02101110;
692042e85d1SPeter Maydell cpu->isar.id_isar1 = 0x13112111;
693042e85d1SPeter Maydell cpu->isar.id_isar2 = 0x21232042;
694042e85d1SPeter Maydell cpu->isar.id_isar3 = 0x01112131;
695042e85d1SPeter Maydell cpu->isar.id_isar4 = 0x00011142;
696042e85d1SPeter Maydell cpu->isar.id_isar5 = 0x00011121;
697042e85d1SPeter Maydell cpu->isar.id_isar6 = 0;
698042e85d1SPeter Maydell cpu->isar.id_aa64pfr0 = 0x00002222;
699042e85d1SPeter Maydell cpu->isar.id_aa64dfr0 = 0x10305106;
700042e85d1SPeter Maydell cpu->isar.id_aa64isar0 = 0x00011120;
701042e85d1SPeter Maydell cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */
702042e85d1SPeter Maydell cpu->isar.dbgdidr = 0x3516d000;
703042e85d1SPeter Maydell cpu->isar.dbgdevid = 0x00110f13;
704042e85d1SPeter Maydell cpu->isar.dbgdevid1 = 0x1;
705042e85d1SPeter Maydell cpu->isar.reset_pmcr_el0 = 0x41033000;
706042e85d1SPeter Maydell cpu->clidr = 0x0a200023;
707*676624d7SAlireza Sanaee /* 32KB L1 dcache */
708*676624d7SAlireza Sanaee cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7);
709*676624d7SAlireza Sanaee /* 32KB L1 icache */
710*676624d7SAlireza Sanaee cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 1, 64, 32 * KiB, 2);
711*676624d7SAlireza Sanaee /* 1024KB L2 cache */
712*676624d7SAlireza Sanaee cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 1 * MiB, 7);
713042e85d1SPeter Maydell cpu->dcz_blocksize = 4; /* 64 bytes */
714042e85d1SPeter Maydell cpu->gic_num_lrs = 4;
715042e85d1SPeter Maydell cpu->gic_vpribits = 5;
716042e85d1SPeter Maydell cpu->gic_vprebits = 5;
717042e85d1SPeter Maydell cpu->gic_pribits = 5;
718042e85d1SPeter Maydell define_cortex_a72_a57_a53_cp_reginfo(cpu);
719042e85d1SPeter Maydell }
720042e85d1SPeter Maydell
aarch64_host_initfn(Object * obj)72173cc9ee6SPeter Maydell static void aarch64_host_initfn(Object *obj)
722dcfb1d04SPeter Maydell {
7230baa21beSPeter Maydell #if defined(CONFIG_KVM)
724dcfb1d04SPeter Maydell ARMCPU *cpu = ARM_CPU(obj);
725dcfb1d04SPeter Maydell kvm_arm_set_cpu_features_from_host(cpu);
726dcfb1d04SPeter Maydell if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
727dcfb1d04SPeter Maydell aarch64_add_sve_properties(obj);
728dcfb1d04SPeter Maydell aarch64_add_pauth_properties(obj);
729dcfb1d04SPeter Maydell }
7300baa21beSPeter Maydell #elif defined(CONFIG_HVF)
7310baa21beSPeter Maydell ARMCPU *cpu = ARM_CPU(obj);
732dcfb1d04SPeter Maydell hvf_arm_set_cpu_features_from_host(cpu);
73392d6528dSPeter Maydell aarch64_add_pauth_properties(obj);
7340baa21beSPeter Maydell #else
7350baa21beSPeter Maydell g_assert_not_reached();
736dcfb1d04SPeter Maydell #endif
737dcfb1d04SPeter Maydell }
738dcfb1d04SPeter Maydell
aarch64_max_initfn(Object * obj)73925be2105SFabiano Rosas static void aarch64_max_initfn(Object *obj)
74025be2105SFabiano Rosas {
74125be2105SFabiano Rosas if (kvm_enabled() || hvf_enabled()) {
74225be2105SFabiano Rosas /* With KVM or HVF, '-cpu max' is identical to '-cpu host' */
74325be2105SFabiano Rosas aarch64_host_initfn(obj);
74425be2105SFabiano Rosas return;
74525be2105SFabiano Rosas }
74625be2105SFabiano Rosas
747fcab465eSFabiano Rosas if (tcg_enabled() || qtest_enabled()) {
74825be2105SFabiano Rosas aarch64_a57_initfn(obj);
749fcab465eSFabiano Rosas }
750fcab465eSFabiano Rosas
751fcab465eSFabiano Rosas /* '-cpu max' for TCG: we currently do this as "A57 with extra things" */
752fcab465eSFabiano Rosas if (tcg_enabled()) {
75325be2105SFabiano Rosas aarch64_max_tcg_initfn(obj);
75425be2105SFabiano Rosas }
755fcab465eSFabiano Rosas }
75625be2105SFabiano Rosas
757fcf5ef2aSThomas Huth static const ARMCPUInfo aarch64_cpus[] = {
758fcf5ef2aSThomas Huth { .name = "cortex-a57", .initfn = aarch64_a57_initfn },
759fcf5ef2aSThomas Huth { .name = "cortex-a53", .initfn = aarch64_a53_initfn },
760bab52d4bSPeter Maydell { .name = "max", .initfn = aarch64_max_initfn },
76173cc9ee6SPeter Maydell #if defined(CONFIG_KVM) || defined(CONFIG_HVF)
76273cc9ee6SPeter Maydell { .name = "host", .initfn = aarch64_host_initfn },
76373cc9ee6SPeter Maydell #endif
764fcf5ef2aSThomas Huth };
765fcf5ef2aSThomas Huth
aarch64_cpu_get_aarch64(Object * obj,Error ** errp)766fcf5ef2aSThomas Huth static bool aarch64_cpu_get_aarch64(Object *obj, Error **errp)
767fcf5ef2aSThomas Huth {
768fcf5ef2aSThomas Huth ARMCPU *cpu = ARM_CPU(obj);
769fcf5ef2aSThomas Huth
770fcf5ef2aSThomas Huth return arm_feature(&cpu->env, ARM_FEATURE_AARCH64);
771fcf5ef2aSThomas Huth }
772fcf5ef2aSThomas Huth
aarch64_cpu_set_aarch64(Object * obj,bool value,Error ** errp)773fcf5ef2aSThomas Huth static void aarch64_cpu_set_aarch64(Object *obj, bool value, Error **errp)
774fcf5ef2aSThomas Huth {
775fcf5ef2aSThomas Huth ARMCPU *cpu = ARM_CPU(obj);
776fcf5ef2aSThomas Huth
777fcf5ef2aSThomas Huth /* At this time, this property is only allowed if KVM is enabled. This
778fcf5ef2aSThomas Huth * restriction allows us to avoid fixing up functionality that assumes a
779fcf5ef2aSThomas Huth * uniform execution state like do_interrupt.
780fcf5ef2aSThomas Huth */
781b9e758f0SAndrew Jones if (value == false) {
7827d20e681SPhilippe Mathieu-Daudé if (!kvm_enabled() || !kvm_arm_aarch32_supported()) {
783fcf5ef2aSThomas Huth error_setg(errp, "'aarch64' feature cannot be disabled "
784b9e758f0SAndrew Jones "unless KVM is enabled and 32-bit EL1 "
785b9e758f0SAndrew Jones "is supported");
786fcf5ef2aSThomas Huth return;
787fcf5ef2aSThomas Huth }
788fcf5ef2aSThomas Huth unset_feature(&cpu->env, ARM_FEATURE_AARCH64);
789fcf5ef2aSThomas Huth } else {
790fcf5ef2aSThomas Huth set_feature(&cpu->env, ARM_FEATURE_AARCH64);
791fcf5ef2aSThomas Huth }
792fcf5ef2aSThomas Huth }
793fcf5ef2aSThomas Huth
aarch64_cpu_finalizefn(Object * obj)794fcf5ef2aSThomas Huth static void aarch64_cpu_finalizefn(Object *obj)
795fcf5ef2aSThomas Huth {
796fcf5ef2aSThomas Huth }
797fcf5ef2aSThomas Huth
aarch64_gdb_arch_name(CPUState * cs)798a6506838SAkihiko Odaki static const gchar *aarch64_gdb_arch_name(CPUState *cs)
799fcf5ef2aSThomas Huth {
800a6506838SAkihiko Odaki return "aarch64";
801fcf5ef2aSThomas Huth }
802fcf5ef2aSThomas Huth
aarch64_cpu_class_init(ObjectClass * oc,void * data)803fcf5ef2aSThomas Huth static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
804fcf5ef2aSThomas Huth {
805fcf5ef2aSThomas Huth CPUClass *cc = CPU_CLASS(oc);
806fcf5ef2aSThomas Huth
807fcf5ef2aSThomas Huth cc->gdb_read_register = aarch64_cpu_gdb_read_register;
808fcf5ef2aSThomas Huth cc->gdb_write_register = aarch64_cpu_gdb_write_register;
809fcf5ef2aSThomas Huth cc->gdb_core_xml_file = "aarch64-core.xml";
810fcf5ef2aSThomas Huth cc->gdb_arch_name = aarch64_gdb_arch_name;
81185cc807cSEduardo Habkost
81285cc807cSEduardo Habkost object_class_property_add_bool(oc, "aarch64", aarch64_cpu_get_aarch64,
81385cc807cSEduardo Habkost aarch64_cpu_set_aarch64);
81485cc807cSEduardo Habkost object_class_property_set_description(oc, "aarch64",
81585cc807cSEduardo Habkost "Set on/off to enable/disable aarch64 "
81685cc807cSEduardo Habkost "execution state ");
817fcf5ef2aSThomas Huth }
818fcf5ef2aSThomas Huth
aarch64_cpu_instance_init(Object * obj)81951e5ef45SMarc-André Lureau static void aarch64_cpu_instance_init(Object *obj)
82051e5ef45SMarc-André Lureau {
82151e5ef45SMarc-André Lureau ARMCPUClass *acc = ARM_CPU_GET_CLASS(obj);
82251e5ef45SMarc-André Lureau
82351e5ef45SMarc-André Lureau acc->info->initfn(obj);
82451e5ef45SMarc-André Lureau arm_cpu_post_init(obj);
82551e5ef45SMarc-André Lureau }
82651e5ef45SMarc-André Lureau
cpu_register_class_init(ObjectClass * oc,void * data)82751e5ef45SMarc-André Lureau static void cpu_register_class_init(ObjectClass *oc, void *data)
82851e5ef45SMarc-André Lureau {
82951e5ef45SMarc-André Lureau ARMCPUClass *acc = ARM_CPU_CLASS(oc);
83051e5ef45SMarc-André Lureau
83151e5ef45SMarc-André Lureau acc->info = data;
83251e5ef45SMarc-André Lureau }
83351e5ef45SMarc-André Lureau
aarch64_cpu_register(const ARMCPUInfo * info)83437bcf244SThomas Huth void aarch64_cpu_register(const ARMCPUInfo *info)
835fcf5ef2aSThomas Huth {
836fcf5ef2aSThomas Huth TypeInfo type_info = {
837fcf5ef2aSThomas Huth .parent = TYPE_AARCH64_CPU,
83851e5ef45SMarc-André Lureau .instance_init = aarch64_cpu_instance_init,
83951e5ef45SMarc-André Lureau .class_init = info->class_init ?: cpu_register_class_init,
84051e5ef45SMarc-André Lureau .class_data = (void *)info,
841fcf5ef2aSThomas Huth };
842fcf5ef2aSThomas Huth
843fcf5ef2aSThomas Huth type_info.name = g_strdup_printf("%s-" TYPE_ARM_CPU, info->name);
844fcf5ef2aSThomas Huth type_register(&type_info);
845fcf5ef2aSThomas Huth g_free((void *)type_info.name);
846fcf5ef2aSThomas Huth }
847fcf5ef2aSThomas Huth
848fcf5ef2aSThomas Huth static const TypeInfo aarch64_cpu_type_info = {
849fcf5ef2aSThomas Huth .name = TYPE_AARCH64_CPU,
850fcf5ef2aSThomas Huth .parent = TYPE_ARM_CPU,
851fcf5ef2aSThomas Huth .instance_finalize = aarch64_cpu_finalizefn,
852fcf5ef2aSThomas Huth .abstract = true,
853fcf5ef2aSThomas Huth .class_init = aarch64_cpu_class_init,
854fcf5ef2aSThomas Huth };
855fcf5ef2aSThomas Huth
aarch64_cpu_register_types(void)856fcf5ef2aSThomas Huth static void aarch64_cpu_register_types(void)
857fcf5ef2aSThomas Huth {
85892b6a659SPhilippe Mathieu-Daudé size_t i;
859fcf5ef2aSThomas Huth
860fcf5ef2aSThomas Huth type_register_static(&aarch64_cpu_type_info);
861fcf5ef2aSThomas Huth
86292b6a659SPhilippe Mathieu-Daudé for (i = 0; i < ARRAY_SIZE(aarch64_cpus); ++i) {
86392b6a659SPhilippe Mathieu-Daudé aarch64_cpu_register(&aarch64_cpus[i]);
864fcf5ef2aSThomas Huth }
865fcf5ef2aSThomas Huth }
866fcf5ef2aSThomas Huth
867fcf5ef2aSThomas Huth type_init(aarch64_cpu_register_types)
868