diff --git a/MAINTAINERS b/MAINTAINERS index ada87bfa9e063798cf366992aacc09bfdcfd0230..73ae0ba448a7c6f43cdef70cd869f36200ef5c99 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -459,6 +459,7 @@ M: Peter Maydell L: qemu-arm@nongnu.org S: Maintained F: target/arm/kvm.c +F: scripts/*-sysreg* MIPS KVM CPUs M: Huacai Chen diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 6e3a3f14a17af5ef702a3dd6d37518d326e78a77..a321bf514cc3139c96a1799aecf7b60437271e94 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -2680,6 +2680,13 @@ static int kvm_init(MachineState *ms) query_stats_schemas_cb); } + if (kvm_check_extension(kvm_state, KVM_CAP_ARM_WRITABLE_IMP_ID_REGS)) { + ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_ARM_WRITABLE_IMP_ID_REGS, 0); + if (ret) { + fprintf(stderr, "Could not enable KVM_CAP_ARM_WRITABLE_IMP_ID_REGS: %d\n", ret); + } + } + return 0; err: diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst index a5fb929243c5339f519edaa5f5e615fb9668ad82..8b497134abd81c6c02580e0a15d0574afe178a7f 100644 --- a/docs/system/arm/cpu-features.rst +++ b/docs/system/arm/cpu-features.rst @@ -2,7 +2,10 @@ Arm CPU Features ================ CPU features are optional features that a CPU of supporting type may -choose to implement or not. In QEMU, optional CPU features have +choose to implement or not. QEMU provides two different mechanisms +to configure those features: + +1. For most CPU models, optional CPU features may have corresponding boolean CPU proprieties that, when enabled, indicate that the feature is implemented, and, conversely, when disabled, indicate that it is not implemented. An example of an Arm CPU feature @@ -29,6 +32,16 @@ supports the feature. While ``aarch64`` currently only works with KVM, it could work with TCG. CPU features that are specific to KVM are prefixed with "kvm-" and are described in "KVM VCPU Features". +2. Additionally, the ``host`` CPU model on KVM allows to configure optional +CPU features via the corresponding ID registers. The host kernel allows +to write a subset of ID register fields. The host model exposes +properties for each writable ID register field. Those options are named +SYSREG__. IDREG and FIELD names are those used in the +ARM ARM Reference Manual. They can also be found in the Linux +arch/arm64/tool/sysreg file which is used to automatically generate the +description for those registers and fields. This currently only has been +implemented for KVM. + CPU Feature Probing =================== @@ -124,13 +137,20 @@ A note about CPU models and KVM Named CPU models generally do not work with KVM. There are a few cases that do work, e.g. using the named CPU model ``cortex-a57`` with KVM on a -seattle host, but mostly if KVM is enabled the ``host`` CPU type must be -used. This means the guest is provided all the same CPU features as the -host CPU type has. And, for this reason, the ``host`` CPU type should -enable all CPU features that the host has by default. Indeed it's even -a bit strange to allow disabling CPU features that the host has when using -the ``host`` CPU type, but in the absence of CPU models it's the best we can -do if we want to launch guests without all the host's CPU features enabled. +seattle host, but mostly if KVM is enabled, the ``host`` CPU model must be +used. + +Using the ``host`` type means the guest is provided all the same CPU +features as the host CPU type has. And, for this reason, the ``host`` +CPU type should enable all CPU features that the host has by default. + +In case some features need to be hidden to the guest, and the host kernel +supports it, the ``host`` model can be instructed to disable individual +ID register values. This is especially useful for migration purposes. +However, this interface will not allow configuring an arbitrary set of +features; the ID registers must describe a subset of the host's features, +and all differences to the host's configuration must actually be supported +by the kernel to be deconfigured. Enabling KVM also affects the ``query-cpu-model-expansion`` QMP command. The affect is not only limited to specific features, as pointed out in example @@ -167,6 +187,13 @@ disabling many SVE vector lengths would be quite verbose, the ``sve`` CPU properties have special semantics (see "SVE CPU Property Parsing Semantics"). +Additionally, if supported by KVM on the host kernel, the ``host`` CPU model +may be configured via individual ID register field properties, for example:: + + $ qemu-system-aarch64 -M virt -cpu host,SYSREG_ID_AA64ISAR0_EL1_DP=0x0 + +This forces ID_AA64ISAR0_EL1 DP field to 0. + KVM VCPU Features ================= @@ -463,3 +490,64 @@ Legal values for ``S`` are 30, 34, 36, and 39; the default is 30. As with ``x-rme``, the ``x-l0gptsz`` property may be renamed or removed in some future QEMU release. + +Configuring CPU features via ID register fields +=============================================== + +Note that this is currently only supported under KVM, and with the +``host`` CPU model. + +Querying available ID register fields +------------------------------------- + +QEMU will create properties for all ID register fields that are +reported as being writable by the kernel, and that are known to the +QEMU instance. Therefore, the same QEMU binary may expose different +properties when run under a different kernel. + +To find out all available writable ID register fields, use the +``query-cpu-model-expansion`` QMP command:: + + (QEMU) query-cpu-model-expansion type=full model={"name":"host"} + {"return": { + "model": {"name": "host", "props": { + "SYSREG_ID_AA64PFR0_EL1_EL3": 1, "SYSREG_ID_AA64ISAR2_EL1_CLRBHB": 0, + "SYSREG_CTR_EL0_L1Ip": 3, "SYSREG_CTR_EL0_DminLine": 4, + "SYSREG_ID_AA64MMFR0_EL1_BIGEND": 1, "SYSREG_ID_AA64MMFR1_EL1_ECBHB": 0, + "SYSREG_ID_AA64MMFR2_EL1_CnP": 1, "SYSREG_ID_DFR0_EL1_PerfMon": 4, + "SYSREG_ID_AA64PFR0_EL1_DIT": 0, "SYSREG_ID_AA64MMFR1_EL1_HAFDBS": 2, + "SYSREG_ID_AA64ISAR0_EL1_FHM": 0, "SYSREG_ID_AA64ISAR2_EL1_CSSC": 0, + "SYSREG_ID_AA64ISAR0_EL1_DP": 1, (...) + }}}} + +If a certain field in an ID register does not show up in this list, it +is not writable with the specific host kernel. + +A note on compatibility +----------------------- + +A common use case for providing a defined set of ID register values is +to be able to present a fixed set of features to a guest, often referred +to as "stable guest ABI". This may take the form of ironing out differences +between two similar CPUs with the intention of being able to migrate +between machines with those CPUs, or providing the same CPU across Linux +kernel updates on the host. + +Over the course of time, the Linux kernel is changing the set of ID register +fields that are writable by userspace. Newly introduced writable ID +registers should be initialized to 0 to ensure compatibility. However, ID +registers that have already been introduced that undergo a change as to +which fields are writable may introduce incompatibities that need to be +addressed on a case-by-case basis for the systems that you wish to migrate +inbetween. + +A note on Arm CPU features (FEAT_xxx) +------------------------------------- + +Configuring CPUs is done on a feature level on other architectures, and this +would imply configuring FEAT_xxx values on Arm. However, differences between +CPUs may not map to FEAT_xxx, but to differences in other registers in the +ID register range; for example, differences in the cache architecture exposed +via ``CTR_EL0``. We therefore cannot rely on configuration via FEAT_xxx. A +feature-based interface more similar to other architectures may be implemented +on top of the ID register interface in the future. diff --git a/hw/arm/virt.c b/hw/arm/virt.c index cf4156ed49ca318375304926445c5343b093ae8b..d8890e319f608cb150b61fa6d7755f31b441a1af 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -29,6 +29,7 @@ */ #include "qemu/osdep.h" +#include "qemu/cutils.h" #include "qemu/datadir.h" #include "qemu/units.h" #include "qemu/option.h" @@ -3112,6 +3113,62 @@ static void virt_set_oem_table_id(Object *obj, const char *value, strncpy(vms->oem_table_id, value, 8); } +static TargetImplCpu target_impl_cpus[MAX_TARGET_IMPL_CPUS]; + +static void virt_set_target_impl_cpus(Object *obj, const char *value, + Error **errp) +{ + MachineState *ms = MACHINE(obj); + g_autofree char *target_dup = g_strdup(value); + char *target_impl = strtok(target_dup, "-"); + int cnt = 0; + + while (target_impl) { + char num[16]; + long val; + const char *num_start = target_impl; + const char *num_end = strchr(num_start, ':'); + + if (!num_end) { + error_setg(errp, + "Wrong format, Please use 0xmidr:0xrevid-0xmidr:0xrevid"); + return; + } + + strncpy(num, num_start, num_end - num_start); + num[num_end - num_start] = '\0'; + if (qemu_strtol(num, NULL, 16, &val)) { + error_setg(errp, + "Wrong format, Please use 0xmidr:0xrevid-0xmidr:0xrevid"); + return; + } + target_impl_cpus[cnt].midr = val; + num_start = num_end + 1; + if (!(*num_start)) { + error_setg(errp, + "Wrong format, Please use 0xmidr:0xrevid-0xmidr:0xrevid"); + return; + } + + strncpy(num, num_start, sizeof(num) - 1); + num[sizeof(num) - 1] = '\0'; + if (qemu_strtol(num, NULL, 16, &val)) { + error_setg(errp, + "Wrong format, Please use 0xmidr:0xrevid-0xmidr:0xrevid"); + return; + } + target_impl_cpus[cnt].revidr = val; + cnt++; + if (cnt >= MAX_TARGET_IMPL_CPUS) { + error_setg(errp, + "Wrong format, Max %d targets can be set for now!", MAX_TARGET_IMPL_CPUS); + return; + } + target_impl = strtok(NULL, "-"); + } + ms->target_ipml_cpu_num = cnt; + ms->target_ipml_cpu = target_impl_cpus; +} bool virt_is_acpi_enabled(VirtMachineState *vms) { @@ -4094,7 +4151,13 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) "Override the default value of field OEM Table ID " "in ACPI table header." "The string may be up to 8 bytes in size"); - + + object_class_property_add_str(oc, "x-target-impl-cpus", + NULL, + virt_set_target_impl_cpus); + object_class_property_set_description(oc, "x-target-impl-cpus", + "Describe target cpu impl in the format midr1:revidr1-midr2:revidr2" + "Maximum 4 midr:revidr pair is supported"); } static char *virt_get_kvm_type(Object *obj, Error **errp G_GNUC_UNUSED) diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 942be7bd112904abac8a1a1253694dd213aefd31..e34ca591f01c62bb96040163aba7c1c611786843 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -988,6 +988,7 @@ static void nvic_nmi_trigger(void *opaque, int n, int level) static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) { ARMCPU *cpu = s->cpu; + ARMISARegisters *isar = &cpu->isar; uint32_t val; switch (offset) { @@ -1263,17 +1264,17 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_pfr0; + return GET_IDREG(isar, ID_PFR0); case 0xd44: /* PFR1. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_pfr1; + return GET_IDREG(isar, ID_PFR1); case 0xd48: /* DFR0. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_dfr0; + return GET_IDREG(isar, ID_DFR0); case 0xd4c: /* AFR0. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; @@ -1283,52 +1284,52 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_mmfr0; + return GET_IDREG(isar, ID_MMFR0); case 0xd54: /* MMFR1. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_mmfr1; + return GET_IDREG(isar, ID_MMFR1); case 0xd58: /* MMFR2. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_mmfr2; + return GET_IDREG(isar, ID_MMFR2); case 0xd5c: /* MMFR3. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_mmfr3; + return GET_IDREG(isar, ID_MMFR3); case 0xd60: /* ISAR0. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_isar0; + return GET_IDREG(&cpu->isar, ID_ISAR0); case 0xd64: /* ISAR1. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_isar1; + return GET_IDREG(&cpu->isar, ID_ISAR1); case 0xd68: /* ISAR2. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_isar2; + return GET_IDREG(&cpu->isar, ID_ISAR2); case 0xd6c: /* ISAR3. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_isar3; + return GET_IDREG(&cpu->isar, ID_ISAR3); case 0xd70: /* ISAR4. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_isar4; + return GET_IDREG(&cpu->isar, ID_ISAR4); case 0xd74: /* ISAR5. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_isar5; + return GET_IDREG(&cpu->isar, ID_ISAR5); case 0xd78: /* CLIDR */ return cpu->clidr; case 0xd7c: /* CTR */ diff --git a/include/hw/boards.h b/include/hw/boards.h index 8ac8cad2a2225e97df1475c2f20118ccf2af394e..192dc7dc093574df304a5beffa5bbe3d5557d5d8 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -402,6 +402,9 @@ struct MachineState { CpuTopology smp; struct NVDIMMState *nvdimms_state; struct NumaState *numa_state; + + uint32_t target_ipml_cpu_num; + void *target_ipml_cpu; }; #define DEFINE_MACHINE(namestr, machine_initfn) \ diff --git a/scripts/arm-gen-cpu-sysregs-header.awk b/scripts/arm-gen-cpu-sysregs-header.awk new file mode 100755 index 0000000000000000000000000000000000000000..9f16e420f86d06424d3c08dcec94e48de0ed6f95 --- /dev/null +++ b/scripts/arm-gen-cpu-sysregs-header.awk @@ -0,0 +1,40 @@ +#!/bin/awk -f +# SPDX-License-Identifier: GPL-2.0-or-later +# arm-gen-cpu-sysregs-header.awk: arm64 sysreg header include generator +# +# Usage: awk -f arm-gen-cpu-sysregs-header.awk $LINUX_PATH/arch/arm64/tools/sysreg + +BEGIN { + print "/* SPDX-License-Identifier: GPL-2.0-or-later */" + print "/* GENERATED FILE, DO NOT EDIT */" + print "/* use arm-gen-cpu-sysregs-header.awk to regenerate */" +} END { + /* add MIDR, REVIDR, and AIDR */ + print "DEF(MIDR_EL1, 3, 0, 0, 0, 0)" + print "DEF(REVIDR_EL1, 3, 0, 0, 0, 6)" + print "DEF(AIDR_EL1, 3, 1, 0, 0, 7)" +} + +# skip blank lines and comment lines +/^$/ { next } +/^[\t ]*#/ { next } + +/^Sysreg\t/ || /^Sysreg /{ + + reg = $2 + op0 = $3 + op1 = $4 + crn = $5 + crm = $6 + op2 = $7 + + if (op0 == 3 && (op1==0 || op1==1 || op1==3) && crn==0 && (crm>=0 && crm<=7) && (op2>=0 && op2<=7)) { + print "DEF("reg", "op0", "op1", "crn", "crm", "op2")" + } + next +} + +{ + /* skip all other lines */ + next +} diff --git a/scripts/gen-cpu-sysreg-properties.awk b/scripts/gen-cpu-sysreg-properties.awk new file mode 100755 index 0000000000000000000000000000000000000000..56d9d8f002cf6e22828c3fb53c619131e8556f22 --- /dev/null +++ b/scripts/gen-cpu-sysreg-properties.awk @@ -0,0 +1,346 @@ +#!/bin/awk -f +# SPDX-License-Identifier: GPL-2.0 +# gen-cpu-sysreg-properties.awk: arm64 sysreg header generator +# +# Usage: awk -f gen-cpu-sysreg-properties.awk $LINUX_PATH/arch/arm64/tools/sysreg + +function block_current() { + return __current_block[__current_block_depth]; +} + +# Log an error and terminate +function fatal(msg) { + print "Error at " NR ": " msg > "/dev/stderr" + + printf "Current block nesting:" + + for (i = 0; i <= __current_block_depth; i++) { + printf " " __current_block[i] + } + printf "\n" + + exit 1 +} + +# Enter a new block, setting the active block to @block +function block_push(block) { + __current_block[++__current_block_depth] = block +} + +# Exit a block, setting the active block to the parent block +function block_pop() { + if (__current_block_depth == 0) + fatal("error: block_pop() in root block") + + __current_block_depth--; +} + +# Sanity check the number of records for a field makes sense. If not, produce +# an error and terminate. +function expect_fields(nf) { + if (NF != nf) + fatal(NF " fields found where " nf " expected") +} + +# Print a CPP macro definition, padded with spaces so that the macro bodies +# line up in a column +function define(name, val) { + printf "%-56s%s\n", "#define " name, val +} + +# Print standard BITMASK/SHIFT/WIDTH CPP definitions for a field +function define_field(reg, field, msb, lsb, idreg) { + if (idreg) + print " arm64_sysreg_add_field("reg", \""field"\", "lsb", "msb");" +} + +# Print a field _SIGNED definition for a field +function define_field_sign(reg, field, sign, idreg) { + if (idreg) + print " arm64_sysreg_add_field("reg", \""field"\", "lsb", "msb");" +} + +# Parse a "[:]" string into the global variables @msb and @lsb +function parse_bitdef(reg, field, bitdef, _bits) +{ + if (bitdef ~ /^[0-9]+$/) { + msb = bitdef + lsb = bitdef + } else if (split(bitdef, _bits, ":") == 2) { + msb = _bits[1] + lsb = _bits[2] + } else { + fatal("invalid bit-range definition '" bitdef "'") + } + + + if (msb != next_bit) + fatal(reg "." field " starts at " msb " not " next_bit) + if (63 < msb || msb < 0) + fatal(reg "." field " invalid high bit in '" bitdef "'") + if (63 < lsb || lsb < 0) + fatal(reg "." field " invalid low bit in '" bitdef "'") + if (msb < lsb) + fatal(reg "." field " invalid bit-range '" bitdef "'") + if (low > high) + fatal(reg "." field " has invalid range " high "-" low) + + next_bit = lsb - 1 +} + +BEGIN { + print "#include \"cpu-custom.h\"" + print "" + print "ARM64SysReg arm64_id_regs[NUM_ID_IDX];" + print "" + print "void initialize_cpu_sysreg_properties(void)" + print "{" + print " memset(arm64_id_regs, 0, sizeof(ARM64SysReg) * NUM_ID_IDX);" + print "" + + __current_block_depth = 0 + __current_block[__current_block_depth] = "Root" +} + +END { + if (__current_block_depth != 0) + fatal("Missing terminator for " block_current() " block") + + # Manually add MIDR/REVIDR/AIDR + print "" + print " /* MIDR_EL1 */" + print " ARM64SysReg *MIDR_EL1 = arm64_sysreg_get(MIDR_EL1_IDX);" + print " MIDR_EL1->name = \"MIDR_EL1\";" + print " arm64_sysreg_add_field(MIDR_EL1, \"Implementer\", 24, 31);" + print " arm64_sysreg_add_field(MIDR_EL1, \"Variant\", 20, 23);" + print " arm64_sysreg_add_field(MIDR_EL1, \"Architecture\", 16, 19);" + print " arm64_sysreg_add_field(MIDR_EL1, \"PartNum\", 4, 15);" + print " arm64_sysreg_add_field(MIDR_EL1, \"Revision\", 0, 3);" + print "" + print " /* REVIDR_EL1 */" + print " ARM64SysReg *REVIDR_EL1 = arm64_sysreg_get(REVIDR_EL1_IDX);" + print " REVIDR_EL1->name = \"REVIDR_EL1\";" + print " arm64_sysreg_add_field(REVIDR_EL1, \"IMPDEF\", 0, 63);" + print "" + print " /* AIDR_EL1 */" + print " ARM64SysReg *AIDR_EL1 = arm64_sysreg_get(AIDR_EL1_IDX);" + print " AIDR_EL1->name = \"AIDR_EL1\";" + print " arm64_sysreg_add_field(AIDR_EL1, \"IMPDEF\", 0, 63);" + print "" + print "}" +} + +# skip blank lines and comment lines +/^$/ { next } +/^[\t ]*#/ { next } + +/^SysregFields/ && block_current() == "Root" { + block_push("SysregFields") + + expect_fields(2) + + reg = $2 + + res0 = "UL(0)" + res1 = "UL(0)" + unkn = "UL(0)" + + next_bit = 63 + + next +} + +/^EndSysregFields/ && block_current() == "SysregFields" { + if (next_bit > 0) + fatal("Unspecified bits in " reg) + + reg = null + res0 = null + res1 = null + unkn = null + + block_pop() + next +} + +/^Sysreg/ && block_current() == "Root" { + block_push("Sysreg") + + expect_fields(7) + + reg = $2 + op0 = $3 + op1 = $4 + crn = $5 + crm = $6 + op2 = $7 + + res0 = "UL(0)" + res1 = "UL(0)" + unkn = "UL(0)" + + if (op0 == 3 && (op1<2 || op1==3) && crn==0 && (crm>=0 && crm<=7) && (op2>=0 && op2<=7)) { + idreg = 1 + } else { + idreg = 0 + } + + if (idreg == 1) { + print " /* "reg" */" + print " ARM64SysReg *"reg" = arm64_sysreg_get("reg"_IDX);" + print " "reg"->name = \""reg"\";" + } + + next_bit = 63 + + next +} + +/^EndSysreg/ && block_current() == "Sysreg" { + if (next_bit > 0) + fatal("Unspecified bits in " reg) + + reg = null + op0 = null + op1 = null + crn = null + crm = null + op2 = null + res0 = null + res1 = null + unkn = null + + if (idreg==1) + print "" + block_pop() + next +} + +# Currently this is effectivey a comment, in future we may want to emit +# defines for the fields. +(/^Fields/ || /^Mapping/) && block_current() == "Sysreg" { + expect_fields(2) + + if (next_bit != 63) + fatal("Some fields already defined for " reg) + + print "/* For " reg " fields see " $2 " */" + print "" + + next_bit = 0 + res0 = null + res1 = null + unkn = null + + next +} + + +/^Res0/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { + expect_fields(2) + parse_bitdef(reg, "RES0", $2) + field = "RES0_" msb "_" lsb + + res0 = res0 " | GENMASK_ULL(" msb ", " lsb ")" + + next +} + +/^Res1/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { + expect_fields(2) + parse_bitdef(reg, "RES1", $2) + field = "RES1_" msb "_" lsb + + res1 = res1 " | GENMASK_ULL(" msb ", " lsb ")" + + next +} + +/^Unkn/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { + expect_fields(2) + parse_bitdef(reg, "UNKN", $2) + field = "UNKN_" msb "_" lsb + + unkn = unkn " | GENMASK_ULL(" msb ", " lsb ")" + + next +} + +/^Field/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { + expect_fields(3) + field = $3 + parse_bitdef(reg, field, $2) + + + define_field(reg, field, msb, lsb, idreg) + + next +} + +/^Raz/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { + expect_fields(2) + parse_bitdef(reg, field, $2) + + next +} + +/^SignedEnum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { + block_push("Enum") + + expect_fields(3) + field = $3 + parse_bitdef(reg, field, $2) + + define_field(reg, field, msb, lsb, idreg) + define_field_sign(reg, field, "true", idreg) + + next +} + +/^UnsignedEnum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { + block_push("Enum") + + expect_fields(3) + field = $3 + parse_bitdef(reg, field, $2) + + define_field(reg, field, msb, lsb, idreg) + #define_field_sign(reg, field, "false", idreg) + + next +} + +/^Enum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { + block_push("Enum") + + expect_fields(3) + field = $3 + parse_bitdef(reg, field, $2) + + define_field(reg, field, msb, lsb, idreg) + + next +} + +/^EndEnum/ && block_current() == "Enum" { + + field = null + msb = null + lsb = null + + block_pop() + next +} + +/0b[01]+/ && block_current() == "Enum" { + expect_fields(2) + val = $1 + name = $2 + + next +} + +# Any lines not handled by previous rules are unexpected +{ + fatal("unhandled statement") +} diff --git a/scripts/update-aarch64-sysreg-code.sh b/scripts/update-aarch64-sysreg-code.sh new file mode 100755 index 0000000000000000000000000000000000000000..764c63a9cc5f1ad41d305fb7b5a7ce9aa42a40fa --- /dev/null +++ b/scripts/update-aarch64-sysreg-code.sh @@ -0,0 +1,35 @@ +#!/bin/sh -e +# +# SPDX-License-Identifier: GPL-2.0-or-later +# Update target/arm/cpu-sysreg-properties.c and target/arm/cpu-sysregs.h +# from a linux source tree (arch/arm64/tools/sysreg) +# +# Copyright Red Hat, Inc. 2024 +# +# Authors: +# Eric Auger +# + +scripts="$(dirname "$0")" +linux="$1" +output="$2" + +if [ -z "$linux" ] || ! [ -d "$linux" ]; then + cat << EOF +usage: update-aarch64-sysreg-code.sh LINUX_PATH [OUTPUT_PATH] + +LINUX_PATH Linux kernel directory to obtain the register definitions from +OUTPUT_PATH output directory, usually the qemu source tree (default: $PWD) +EOF + exit 1 +fi + +if [ -z "$output" ]; then + output="$PWD" +fi + +awk -f $scripts/arm-gen-cpu-sysregs-header.awk \ + $linux/arch/arm64/tools/sysreg > $output/target/arm/cpu-sysregs.h.inc + +awk -f $scripts/gen-cpu-sysreg-properties.awk \ + $linux/arch/arm64/tools/sysreg > $output/target/arm/cpu-sysreg-properties.c \ No newline at end of file diff --git a/target/arm/arm-qmp-cmds.c b/target/arm/arm-qmp-cmds.c index d201d319bdd3e39af4cca9f6e01c9b1be8e89daa..5109aeb873b50b334b42bf7f38fb8ba1a3e59aea 100644 --- a/target/arm/arm-qmp-cmds.c +++ b/target/arm/arm-qmp-cmds.c @@ -21,6 +21,7 @@ */ #include "qemu/osdep.h" +#include "qemu/error-report.h" #include "hw/boards.h" #include "kvm_arm.h" #include "qapi/error.h" @@ -218,6 +219,24 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, } } + /* If writable ID regs are supported, add them as well */ + if (ARM_CPU(obj)->writable_id_regs == WRITABLE_ID_REGS_AVAIL) { + ObjectProperty *prop; + ObjectPropertyIterator iter; + + object_property_iter_init(&iter, obj); + + while ((prop = object_property_iter_next(&iter))) { + QObject *value; + + if (!g_str_has_prefix(prop->name, "SYSREG_")) { + continue; + } + value = object_property_get_qobject(obj, prop->name, &error_abort); + qdict_put_obj(qdict_out, prop->name, value); + } + } + if (!qdict_size(qdict_out)) { qobject_unref(qdict_out); } else { diff --git a/target/arm/cpu-custom.h b/target/arm/cpu-custom.h new file mode 100644 index 0000000000000000000000000000000000000000..615347376e56b89db081806e053c47aaa0dc32a4 --- /dev/null +++ b/target/arm/cpu-custom.h @@ -0,0 +1,60 @@ +/* + * handle ID registers and their fields + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef ARM_CPU_CUSTOM_H +#define ARM_CPU_CUSTOM_H + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "cpu.h" +#include "cpu-sysregs.h" + +typedef struct ARM64SysRegField { + const char *name; /* name of the field, for instance CTR_EL0_IDC */ + int index; + int lower; + int upper; +} ARM64SysRegField; + +typedef struct ARM64SysReg { + const char *name; /* name of the sysreg, for instance CTR_EL0 */ + ARMSysRegs sysreg; + int index; + GList *fields; /* list of named fields, excluding RES* */ +} ARM64SysReg; + +void initialize_cpu_sysreg_properties(void); + +/* + * List of exposed ID regs (automatically populated from linux + * arch/arm64/tools/sysreg) + */ +extern ARM64SysReg arm64_id_regs[NUM_ID_IDX]; + +/* Allocate a new field and insert it at the head of the @reg list */ +static inline GList *arm64_sysreg_add_field(ARM64SysReg *reg, const char *name, + uint8_t min, uint8_t max) { + + ARM64SysRegField *field = g_new0(ARM64SysRegField, 1); + + field->name = name; + field->lower = min; + field->upper = max; + field->index = reg->index; + + reg->fields = g_list_append(reg->fields, field); + return reg->fields; +} + +static inline ARM64SysReg *arm64_sysreg_get(ARMIDRegisterIdx index) +{ + ARM64SysReg *reg = &arm64_id_regs[index]; + + reg->index = index; + reg->sysreg = id_register_sysreg[index]; + return reg; +} + +#endif diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index 165a497f7b9151562a143152f7f0dbd822e25a26..46a10163021462f972de3665aede282432f0ed7e 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -20,6 +20,7 @@ #ifndef TARGET_ARM_FEATURES_H #define TARGET_ARM_FEATURES_H +#include "cpu-sysregs.h" /* * Naming convention for isar_feature functions: * Functions which test 32-bit ID registers should have _aa32_ in @@ -41,103 +42,103 @@ */ static inline bool isar_feature_aa32_thumb_div(const ARMISARegisters *id) { - return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) != 0; + return FIELD_EX32_IDREG(id, ID_ISAR0, DIVIDE) != 0; } static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id) { - return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1; + return FIELD_EX32_IDREG(id, ID_ISAR0, DIVIDE) > 1; } static inline bool isar_feature_aa32_lob(const ARMISARegisters *id) { /* (M-profile) low-overhead loops and branch future */ - return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3; + return FIELD_EX32_IDREG(id, ID_ISAR0, CMPBRANCH) >= 3; } static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id) { - return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0; + return FIELD_EX32_IDREG(id, ID_ISAR1, JAZELLE) != 0; } static inline bool isar_feature_aa32_aes(const ARMISARegisters *id) { - return FIELD_EX32(id->id_isar5, ID_ISAR5, AES) != 0; + return FIELD_EX32_IDREG(id, ID_ISAR5, AES) != 0; } static inline bool isar_feature_aa32_pmull(const ARMISARegisters *id) { - return FIELD_EX32(id->id_isar5, ID_ISAR5, AES) > 1; + return FIELD_EX32_IDREG(id, ID_ISAR5, AES) > 1; } static inline bool isar_feature_aa32_sha1(const ARMISARegisters *id) { - return FIELD_EX32(id->id_isar5, ID_ISAR5, SHA1) != 0; + return FIELD_EX32_IDREG(id, ID_ISAR5, SHA1) != 0; } static inline bool isar_feature_aa32_sha2(const ARMISARegisters *id) { - return FIELD_EX32(id->id_isar5, ID_ISAR5, SHA2) != 0; + return FIELD_EX32_IDREG(id, ID_ISAR5, SHA2) != 0; } static inline bool isar_feature_aa32_crc32(const ARMISARegisters *id) { - return FIELD_EX32(id->id_isar5, ID_ISAR5, CRC32) != 0; + return FIELD_EX32_IDREG(id, ID_ISAR5, CRC32) != 0; } static inline bool isar_feature_aa32_rdm(const ARMISARegisters *id) { - return FIELD_EX32(id->id_isar5, ID_ISAR5, RDM) != 0; + return FIELD_EX32_IDREG(id, ID_ISAR5, RDM) != 0; } static inline bool isar_feature_aa32_vcma(const ARMISARegisters *id) { - return FIELD_EX32(id->id_isar5, ID_ISAR5, VCMA) != 0; + return FIELD_EX32_IDREG(id, ID_ISAR5, VCMA) != 0; } static inline bool isar_feature_aa32_jscvt(const ARMISARegisters *id) { - return FIELD_EX32(id->id_isar6, ID_ISAR6, JSCVT) != 0; + return FIELD_EX32_IDREG(id, ID_ISAR6, JSCVT) != 0; } static inline bool isar_feature_aa32_dp(const ARMISARegisters *id) { - return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0; + return FIELD_EX32_IDREG(id, ID_ISAR6, DP) != 0; } static inline bool isar_feature_aa32_fhm(const ARMISARegisters *id) { - return FIELD_EX32(id->id_isar6, ID_ISAR6, FHM) != 0; + return FIELD_EX32_IDREG(id, ID_ISAR6, FHM) != 0; } static inline bool isar_feature_aa32_sb(const ARMISARegisters *id) { - return FIELD_EX32(id->id_isar6, ID_ISAR6, SB) != 0; + return FIELD_EX32_IDREG(id, ID_ISAR6, SB) != 0; } static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id) { - return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0; + return FIELD_EX32_IDREG(id, ID_ISAR6, SPECRES) != 0; } static inline bool isar_feature_aa32_bf16(const ARMISARegisters *id) { - return FIELD_EX32(id->id_isar6, ID_ISAR6, BF16) != 0; + return FIELD_EX32_IDREG(id, ID_ISAR6, BF16) != 0; } static inline bool isar_feature_aa32_i8mm(const ARMISARegisters *id) { - return FIELD_EX32(id->id_isar6, ID_ISAR6, I8MM) != 0; + return FIELD_EX32_IDREG(id, ID_ISAR6, I8MM) != 0; } static inline bool isar_feature_aa32_ras(const ARMISARegisters *id) { - return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0; + return FIELD_EX32_IDREG(id, ID_PFR0, RAS) != 0; } static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id) { - return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0; + return FIELD_EX32_IDREG(id, ID_PFR1, MPROGMOD) != 0; } static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id) @@ -146,7 +147,7 @@ static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id) * Return true if M-profile state handling insns * (VSCCLRM, CLRM, FPCTX access insns) are implemented */ - return FIELD_EX32(id->id_pfr1, ID_PFR1, SECURITY) >= 3; + return FIELD_EX32_IDREG(id, ID_PFR1, SECURITY) >= 3; } static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id) @@ -279,88 +280,88 @@ static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id) static inline bool isar_feature_aa32_pxn(const ARMISARegisters *id) { - return FIELD_EX32(id->id_mmfr0, ID_MMFR0, VMSA) >= 4; + return FIELD_EX32_IDREG(id, ID_MMFR0, VMSA) >= 4; } static inline bool isar_feature_aa32_pan(const ARMISARegisters *id) { - return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) != 0; + return FIELD_EX32_IDREG(id, ID_MMFR3, PAN) != 0; } static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id) { - return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) >= 2; + return FIELD_EX32_IDREG(id, ID_MMFR3, PAN) >= 2; } static inline bool isar_feature_aa32_pmuv3p1(const ARMISARegisters *id) { /* 0xf means "non-standard IMPDEF PMU" */ - return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 4 && - FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; + return FIELD_EX32_IDREG(id, ID_DFR0, PERFMON) >= 4 && + FIELD_EX32_IDREG(id, ID_DFR0, PERFMON) != 0xf; } static inline bool isar_feature_aa32_pmuv3p4(const ARMISARegisters *id) { /* 0xf means "non-standard IMPDEF PMU" */ - return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 5 && - FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; + return FIELD_EX32_IDREG(id, ID_DFR0, PERFMON) >= 5 && + FIELD_EX32_IDREG(id, ID_DFR0, PERFMON) != 0xf; } static inline bool isar_feature_aa32_pmuv3p5(const ARMISARegisters *id) { /* 0xf means "non-standard IMPDEF PMU" */ - return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 6 && - FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; + return FIELD_EX32_IDREG(id, ID_DFR0, PERFMON) >= 6 && + FIELD_EX32_IDREG(id, ID_DFR0, PERFMON) != 0xf; } static inline bool isar_feature_aa32_hpd(const ARMISARegisters *id) { - return FIELD_EX32(id->id_mmfr4, ID_MMFR4, HPDS) != 0; + return FIELD_EX32_IDREG(id, ID_MMFR4, HPDS) != 0; } static inline bool isar_feature_aa32_ac2(const ARMISARegisters *id) { - return FIELD_EX32(id->id_mmfr4, ID_MMFR4, AC2) != 0; + return FIELD_EX32_IDREG(id, ID_MMFR4, AC2) != 0; } static inline bool isar_feature_aa32_ccidx(const ARMISARegisters *id) { - return FIELD_EX32(id->id_mmfr4, ID_MMFR4, CCIDX) != 0; + return FIELD_EX32_IDREG(id, ID_MMFR4, CCIDX) != 0; } static inline bool isar_feature_aa32_tts2uxn(const ARMISARegisters *id) { - return FIELD_EX32(id->id_mmfr4, ID_MMFR4, XNX) != 0; + return FIELD_EX32_IDREG(id, ID_MMFR4, XNX) != 0; } static inline bool isar_feature_aa32_half_evt(const ARMISARegisters *id) { - return FIELD_EX32(id->id_mmfr4, ID_MMFR4, EVT) >= 1; + return FIELD_EX32_IDREG(id, ID_MMFR4, EVT) >= 1; } static inline bool isar_feature_aa32_evt(const ARMISARegisters *id) { - return FIELD_EX32(id->id_mmfr4, ID_MMFR4, EVT) >= 2; + return FIELD_EX32_IDREG(id, ID_MMFR4, EVT) >= 2; } static inline bool isar_feature_aa32_dit(const ARMISARegisters *id) { - return FIELD_EX32(id->id_pfr0, ID_PFR0, DIT) != 0; + return FIELD_EX32_IDREG(id, ID_PFR0, DIT) != 0; } static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id) { - return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0; + return FIELD_EX32_IDREG(id, ID_PFR2, SSBS) != 0; } static inline bool isar_feature_aa32_debugv7p1(const ARMISARegisters *id) { - return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 5; + return FIELD_EX32_IDREG(id, ID_DFR0, COPDBG) >= 5; } static inline bool isar_feature_aa32_debugv8p2(const ARMISARegisters *id) { - return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 8; + return FIELD_EX32_IDREG(id, ID_DFR0, COPDBG) >= 8; } static inline bool isar_feature_aa32_doublelock(const ARMISARegisters *id) @@ -373,102 +374,102 @@ static inline bool isar_feature_aa32_doublelock(const ARMISARegisters *id) */ static inline bool isar_feature_aa64_aes(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, AES) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR0, AES) != 0; } static inline bool isar_feature_aa64_pmull(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, AES) > 1; + return FIELD_EX64_IDREG(id, ID_AA64ISAR0, AES) > 1; } static inline bool isar_feature_aa64_sha1(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA1) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SHA1) != 0; } static inline bool isar_feature_aa64_sha256(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA2) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SHA2) != 0; } static inline bool isar_feature_aa64_sha512(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA2) > 1; + return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SHA2) > 1; } static inline bool isar_feature_aa64_crc32(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, CRC32) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR0, CRC32) != 0; } static inline bool isar_feature_aa64_atomics(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, ATOMIC) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR0, ATOMIC) != 0; } static inline bool isar_feature_aa64_rdm(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, RDM) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR0, RDM) != 0; } static inline bool isar_feature_aa64_sha3(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA3) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SHA3) != 0; } static inline bool isar_feature_aa64_sm3(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SM3) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SM3) != 0; } static inline bool isar_feature_aa64_sm4(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SM4) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SM4) != 0; } static inline bool isar_feature_aa64_dp(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, DP) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR0, DP) != 0; } static inline bool isar_feature_aa64_fhm(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, FHM) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR0, FHM) != 0; } static inline bool isar_feature_aa64_condm_4(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR0, TS) != 0; } static inline bool isar_feature_aa64_condm_5(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) >= 2; + return FIELD_EX64_IDREG(id, ID_AA64ISAR0, TS) >= 2; } static inline bool isar_feature_aa64_rndr(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, RNDR) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR0, RNDR) != 0; } static inline bool isar_feature_aa64_tlbirange(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) == 2; + return FIELD_EX64_IDREG(id, ID_AA64ISAR0, TLB) == 2; } static inline bool isar_feature_aa64_tlbios(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR0, TLB) != 0; } static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR1, JSCVT) != 0; } static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR1, FCMA) != 0; } /* @@ -492,9 +493,9 @@ isar_feature_pauth_feature(const ARMISARegisters *id) * Architecturally, only one of {APA,API,APA3} may be active (non-zero) * and the other two must be zero. Thus we may avoid conditionals. */ - return (FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) | - FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, API) | - FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, APA3)); + return (FIELD_EX64_IDREG(id, ID_AA64ISAR1, APA) | + FIELD_EX64_IDREG(id, ID_AA64ISAR1, API) | + FIELD_EX64_IDREG(id, ID_AA64ISAR2, APA3)); } static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id) @@ -512,7 +513,7 @@ static inline bool isar_feature_aa64_pauth_qarma5(const ARMISARegisters *id) * Return true if pauth is enabled with the architected QARMA5 algorithm. * QEMU will always enable or disable both APA and GPA. */ - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR1, APA) != 0; } static inline bool isar_feature_aa64_pauth_qarma3(const ARMISARegisters *id) @@ -521,129 +522,129 @@ static inline bool isar_feature_aa64_pauth_qarma3(const ARMISARegisters *id) * Return true if pauth is enabled with the architected QARMA3 algorithm. * QEMU will always enable or disable both APA3 and GPA3. */ - return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, APA3) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR2, APA3) != 0; } static inline bool isar_feature_aa64_sb(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SB) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR1, SB) != 0; } static inline bool isar_feature_aa64_predinv(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SPECRES) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR1, SPECRES) != 0; } static inline bool isar_feature_aa64_frint(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR1, FRINTTS) != 0; } static inline bool isar_feature_aa64_dcpop(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR1, DPB) != 0; } static inline bool isar_feature_aa64_dcpodp(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) >= 2; + return FIELD_EX64_IDREG(id, ID_AA64ISAR1, DPB) >= 2; } static inline bool isar_feature_aa64_bf16(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, BF16) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR1, BF16) != 0; } static inline bool isar_feature_aa64_rcpc_8_3(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR1, LRCPC) != 0; } static inline bool isar_feature_aa64_rcpc_8_4(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) >= 2; + return FIELD_EX64_IDREG(id, ID_AA64ISAR1, LRCPC) >= 2; } static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, I8MM) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR1, I8MM) != 0; } static inline bool isar_feature_aa64_hbc(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, BC) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ISAR2, BC) != 0; } static inline bool isar_feature_aa64_mops(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, MOPS); + return FIELD_EX64_IDREG(id, ID_AA64ISAR2, MOPS); } static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id) { /* We always set the AdvSIMD and FP fields identically. */ - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) != 0xf; + return FIELD_EX64_IDREG(id, ID_AA64PFR0, FP) != 0xf; } static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id) { /* We always set the AdvSIMD and FP fields identically wrt FP16. */ - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1; + return FIELD_EX64_IDREG(id, ID_AA64PFR0, FP) == 1; } static inline bool isar_feature_aa64_aa32(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL0) >= 2; + return FIELD_EX64_IDREG(id, ID_AA64PFR0, EL0) >= 2; } static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2; + return FIELD_EX64_IDREG(id, ID_AA64PFR0, EL1) >= 2; } static inline bool isar_feature_aa64_aa32_el2(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL2) >= 2; + return FIELD_EX64_IDREG(id, ID_AA64PFR0, EL2) >= 2; } static inline bool isar_feature_aa64_ras(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) != 0; + return FIELD_EX64_IDREG(id, ID_AA64PFR0, RAS) != 0; } static inline bool isar_feature_aa64_doublefault(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) >= 2; + return FIELD_EX64_IDREG(id, ID_AA64PFR0, RAS) >= 2; } static inline bool isar_feature_aa64_sve(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0; + return FIELD_EX64_IDREG(id, ID_AA64PFR0, SVE) != 0; } static inline bool isar_feature_aa64_sel2(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SEL2) != 0; + return FIELD_EX64_IDREG(id, ID_AA64PFR0, SEL2) != 0; } static inline bool isar_feature_aa64_rme(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RME) != 0; + return FIELD_EX64_IDREG(id, ID_AA64PFR0, RME) != 0; } static inline bool isar_feature_aa64_dit(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0; + return FIELD_EX64_IDREG(id, ID_AA64PFR0, DIT) != 0; } static inline bool isar_feature_aa64_scxtnum(const ARMISARegisters *id) { - int key = FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, CSV2); + int key = FIELD_EX64_IDREG(id, ID_AA64PFR0, CSV2); if (key >= 2) { return true; /* FEAT_CSV2_2 */ } if (key == 1) { - key = FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, CSV2_FRAC); + key = FIELD_EX64_IDREG(id, ID_AA64PFR1, CSV2_FRAC); return key >= 2; /* FEAT_CSV2_1p2 */ } return false; @@ -651,285 +652,285 @@ static inline bool isar_feature_aa64_scxtnum(const ARMISARegisters *id) static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0; + return FIELD_EX64_IDREG(id, ID_AA64PFR1, SSBS) != 0; } static inline bool isar_feature_aa64_bti(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0; + return FIELD_EX64_IDREG(id, ID_AA64PFR1, BT) != 0; } static inline bool isar_feature_aa64_mte_insn_reg(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) != 0; + return FIELD_EX64_IDREG(id, ID_AA64PFR1, MTE) != 0; } static inline bool isar_feature_aa64_mte(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) >= 2; + return FIELD_EX64_IDREG(id, ID_AA64PFR1, MTE) >= 2; } static inline bool isar_feature_aa64_mte3(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) >= 3; + return FIELD_EX64_IDREG(id, ID_AA64PFR1, MTE) >= 3; } static inline bool isar_feature_aa64_sme(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SME) != 0; + return FIELD_EX64_IDREG(id, ID_AA64PFR1, SME) != 0; } static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id) { - return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 1; + return FIELD_SEX64_IDREG(id, ID_AA64MMFR0, TGRAN4) >= 1; } static inline bool isar_feature_aa64_tgran4_2_lpa2(const ARMISARegisters *id) { - unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2); + unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN4_2); return t >= 3 || (t == 0 && isar_feature_aa64_tgran4_lpa2(id)); } static inline bool isar_feature_aa64_tgran16_lpa2(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 2; + return FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN16) >= 2; } static inline bool isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters *id) { - unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2); + unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN16_2); return t >= 3 || (t == 0 && isar_feature_aa64_tgran16_lpa2(id)); } static inline bool isar_feature_aa64_tgran4(const ARMISARegisters *id) { - return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 0; + return FIELD_SEX64_IDREG(id, ID_AA64MMFR0, TGRAN4) >= 0; } static inline bool isar_feature_aa64_tgran16(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 1; + return FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN16) >= 1; } static inline bool isar_feature_aa64_tgran64(const ARMISARegisters *id) { - return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64) >= 0; + return FIELD_SEX64_IDREG(id, ID_AA64MMFR0, TGRAN64) >= 0; } static inline bool isar_feature_aa64_tgran4_2(const ARMISARegisters *id) { - unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2); + unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN4_2); return t >= 2 || (t == 0 && isar_feature_aa64_tgran4(id)); } static inline bool isar_feature_aa64_tgran16_2(const ARMISARegisters *id) { - unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2); + unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN16_2); return t >= 2 || (t == 0 && isar_feature_aa64_tgran16(id)); } static inline bool isar_feature_aa64_tgran64_2(const ARMISARegisters *id) { - unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64_2); + unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN64_2); return t >= 2 || (t == 0 && isar_feature_aa64_tgran64(id)); } static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0; + return FIELD_EX64_IDREG(id, ID_AA64MMFR0, FGT) != 0; } static inline bool isar_feature_aa64_vh(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0; + return FIELD_EX64_IDREG(id, ID_AA64MMFR1, VH) != 0; } static inline bool isar_feature_aa64_lor(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0; + return FIELD_EX64_IDREG(id, ID_AA64MMFR1, LO) != 0; } static inline bool isar_feature_aa64_pan(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) != 0; + return FIELD_EX64_IDREG(id, ID_AA64MMFR1, PAN) != 0; } static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2; + return FIELD_EX64_IDREG(id, ID_AA64MMFR1, PAN) >= 2; } static inline bool isar_feature_aa64_pan3(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 3; + return FIELD_EX64_IDREG(id, ID_AA64MMFR1, PAN) >= 3; } static inline bool isar_feature_aa64_hcx(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HCX) != 0; + return FIELD_EX64_IDREG(id, ID_AA64MMFR1, HCX) != 0; } static inline bool isar_feature_aa64_tidcp1(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, TIDCP1) != 0; + return FIELD_EX64_IDREG(id, ID_AA64MMFR1, TIDCP1) != 0; } static inline bool isar_feature_aa64_hafs(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) != 0; + return FIELD_EX64_IDREG(id, ID_AA64MMFR1, HAFDBS) != 0; } static inline bool isar_feature_aa64_hdbs(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) >= 2; + return FIELD_EX64_IDREG(id, ID_AA64MMFR1, HAFDBS) >= 2; } static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0; + return FIELD_EX64_IDREG(id, ID_AA64MMFR1, XNX) != 0; } static inline bool isar_feature_aa64_uao(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0; + return FIELD_EX64_IDREG(id, ID_AA64MMFR2, UAO) != 0; } static inline bool isar_feature_aa64_st(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0; + return FIELD_EX64_IDREG(id, ID_AA64MMFR2, ST) != 0; } static inline bool isar_feature_aa64_lse2(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, AT) != 0; + return FIELD_EX64_IDREG(id, ID_AA64MMFR2, AT) != 0; } static inline bool isar_feature_aa64_fwb(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, FWB) != 0; + return FIELD_EX64_IDREG(id, ID_AA64MMFR2, FWB) != 0; } static inline bool isar_feature_aa64_ids(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, IDS) != 0; + return FIELD_EX64_IDREG(id, ID_AA64MMFR2, IDS) != 0; } static inline bool isar_feature_aa64_half_evt(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, EVT) >= 1; + return FIELD_EX64_IDREG(id, ID_AA64MMFR2, EVT) >= 1; } static inline bool isar_feature_aa64_evt(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, EVT) >= 2; + return FIELD_EX64_IDREG(id, ID_AA64MMFR2, EVT) >= 2; } static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0; + return FIELD_EX64_IDREG(id, ID_AA64MMFR2, CCIDX) != 0; } static inline bool isar_feature_aa64_lva(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, VARANGE) != 0; + return FIELD_EX64_IDREG(id, ID_AA64MMFR2, VARANGE) != 0; } static inline bool isar_feature_aa64_e0pd(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, E0PD) != 0; + return FIELD_EX64_IDREG(id, ID_AA64MMFR2, E0PD) != 0; } static inline bool isar_feature_aa64_pmuv3p1(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 4 && - FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; + return FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) >= 4 && + FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) != 0xf; } static inline bool isar_feature_aa64_pmuv3p4(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 5 && - FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; + return FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) >= 5 && + FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) != 0xf; } static inline bool isar_feature_aa64_pmuv3p5(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 6 && - FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; + return FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) >= 6 && + FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) != 0xf; } static inline bool isar_feature_aa64_debugv8p2(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, DEBUGVER) >= 8; + return FIELD_EX64_IDREG(id, ID_AA64DFR0, DEBUGVER) >= 8; } static inline bool isar_feature_aa64_doublelock(const ARMISARegisters *id) { - return FIELD_SEX64(id->id_aa64dfr0, ID_AA64DFR0, DOUBLELOCK) >= 0; + return FIELD_SEX64_IDREG(id, ID_AA64DFR0, DOUBLELOCK) >= 0; } static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SVEVER) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ZFR0, SVEVER) != 0; } static inline bool isar_feature_aa64_sve2_aes(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ZFR0, AES) != 0; } static inline bool isar_feature_aa64_sve2_pmull128(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) >= 2; + return FIELD_EX64_IDREG(id, ID_AA64ZFR0, AES) >= 2; } static inline bool isar_feature_aa64_sve2_bitperm(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BITPERM) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ZFR0, BITPERM) != 0; } static inline bool isar_feature_aa64_sve_bf16(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BFLOAT16) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ZFR0, BFLOAT16) != 0; } static inline bool isar_feature_aa64_sve2_sha3(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SHA3) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ZFR0, SHA3) != 0; } static inline bool isar_feature_aa64_sve2_sm4(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SM4) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ZFR0, SM4) != 0; } static inline bool isar_feature_aa64_sve_i8mm(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, I8MM) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ZFR0, I8MM) != 0; } static inline bool isar_feature_aa64_sve_f32mm(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F32MM) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ZFR0, F32MM) != 0; } static inline bool isar_feature_aa64_sve_f64mm(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F64MM) != 0; + return FIELD_EX64_IDREG(id, ID_AA64ZFR0, F64MM) != 0; } static inline bool isar_feature_aa64_sme_f64f64(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, F64F64); + return FIELD_EX64_IDREG(id, ID_AA64SMFR0, F64F64); } static inline bool isar_feature_aa64_sme_i16i64(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, I16I64) == 0xf; + return FIELD_EX64_IDREG(id, ID_AA64SMFR0, I16I64) == 0xf; } static inline bool isar_feature_aa64_sme_fa64(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, FA64); + return FIELD_EX64_IDREG(id, ID_AA64SMFR0, FA64); } /* diff --git a/target/arm/cpu-sysreg-properties.c b/target/arm/cpu-sysreg-properties.c new file mode 100644 index 0000000000000000000000000000000000000000..c8a43c9eb418341e3842d75fe78ab7d0092f3cd3 --- /dev/null +++ b/target/arm/cpu-sysreg-properties.c @@ -0,0 +1,764 @@ +#include "cpu-custom.h" + +ARM64SysReg arm64_id_regs[NUM_ID_IDX]; + +void initialize_cpu_sysreg_properties(void) +{ + memset(arm64_id_regs, 0, sizeof(ARM64SysReg) * NUM_ID_IDX); + +/* For SPMACCESSR_EL12 fields see SPMACCESSR_EL1 */ + + /* ID_PFR0_EL1 */ + ARM64SysReg *ID_PFR0_EL1 = arm64_sysreg_get(ID_PFR0_EL1_IDX); + ID_PFR0_EL1->name = "ID_PFR0_EL1"; + arm64_sysreg_add_field(ID_PFR0_EL1, "RAS", 28, 31); + arm64_sysreg_add_field(ID_PFR0_EL1, "DIT", 24, 27); + arm64_sysreg_add_field(ID_PFR0_EL1, "AMU", 20, 23); + arm64_sysreg_add_field(ID_PFR0_EL1, "CSV2", 16, 19); + arm64_sysreg_add_field(ID_PFR0_EL1, "State3", 12, 15); + arm64_sysreg_add_field(ID_PFR0_EL1, "State2", 8, 11); + arm64_sysreg_add_field(ID_PFR0_EL1, "State1", 4, 7); + arm64_sysreg_add_field(ID_PFR0_EL1, "State0", 0, 3); + + /* ID_PFR1_EL1 */ + ARM64SysReg *ID_PFR1_EL1 = arm64_sysreg_get(ID_PFR1_EL1_IDX); + ID_PFR1_EL1->name = "ID_PFR1_EL1"; + arm64_sysreg_add_field(ID_PFR1_EL1, "GIC", 28, 31); + arm64_sysreg_add_field(ID_PFR1_EL1, "Virt_frac", 24, 27); + arm64_sysreg_add_field(ID_PFR1_EL1, "Sec_frac", 20, 23); + arm64_sysreg_add_field(ID_PFR1_EL1, "GenTimer", 16, 19); + arm64_sysreg_add_field(ID_PFR1_EL1, "Virtualization", 12, 15); + arm64_sysreg_add_field(ID_PFR1_EL1, "MProgMod", 8, 11); + arm64_sysreg_add_field(ID_PFR1_EL1, "Security", 4, 7); + arm64_sysreg_add_field(ID_PFR1_EL1, "ProgMod", 0, 3); + + /* ID_DFR0_EL1 */ + ARM64SysReg *ID_DFR0_EL1 = arm64_sysreg_get(ID_DFR0_EL1_IDX); + ID_DFR0_EL1->name = "ID_DFR0_EL1"; + arm64_sysreg_add_field(ID_DFR0_EL1, "TraceFilt", 28, 31); + arm64_sysreg_add_field(ID_DFR0_EL1, "PerfMon", 24, 27); + arm64_sysreg_add_field(ID_DFR0_EL1, "MProfDbg", 20, 23); + arm64_sysreg_add_field(ID_DFR0_EL1, "MMapTrc", 16, 19); + arm64_sysreg_add_field(ID_DFR0_EL1, "CopTrc", 12, 15); + arm64_sysreg_add_field(ID_DFR0_EL1, "MMapDbg", 8, 11); + arm64_sysreg_add_field(ID_DFR0_EL1, "CopSDbg", 4, 7); + arm64_sysreg_add_field(ID_DFR0_EL1, "CopDbg", 0, 3); + + /* ID_AFR0_EL1 */ + ARM64SysReg *ID_AFR0_EL1 = arm64_sysreg_get(ID_AFR0_EL1_IDX); + ID_AFR0_EL1->name = "ID_AFR0_EL1"; + arm64_sysreg_add_field(ID_AFR0_EL1, "IMPDEF3", 12, 15); + arm64_sysreg_add_field(ID_AFR0_EL1, "IMPDEF2", 8, 11); + arm64_sysreg_add_field(ID_AFR0_EL1, "IMPDEF1", 4, 7); + arm64_sysreg_add_field(ID_AFR0_EL1, "IMPDEF0", 0, 3); + + /* ID_MMFR0_EL1 */ + ARM64SysReg *ID_MMFR0_EL1 = arm64_sysreg_get(ID_MMFR0_EL1_IDX); + ID_MMFR0_EL1->name = "ID_MMFR0_EL1"; + arm64_sysreg_add_field(ID_MMFR0_EL1, "InnerShr", 28, 31); + arm64_sysreg_add_field(ID_MMFR0_EL1, "FCSE", 24, 27); + arm64_sysreg_add_field(ID_MMFR0_EL1, "AuxReg", 20, 23); + arm64_sysreg_add_field(ID_MMFR0_EL1, "TCM", 16, 19); + arm64_sysreg_add_field(ID_MMFR0_EL1, "ShareLvl", 12, 15); + arm64_sysreg_add_field(ID_MMFR0_EL1, "OuterShr", 8, 11); + arm64_sysreg_add_field(ID_MMFR0_EL1, "PMSA", 4, 7); + arm64_sysreg_add_field(ID_MMFR0_EL1, "VMSA", 0, 3); + + /* ID_MMFR1_EL1 */ + ARM64SysReg *ID_MMFR1_EL1 = arm64_sysreg_get(ID_MMFR1_EL1_IDX); + ID_MMFR1_EL1->name = "ID_MMFR1_EL1"; + arm64_sysreg_add_field(ID_MMFR1_EL1, "BPred", 28, 31); + arm64_sysreg_add_field(ID_MMFR1_EL1, "L1TstCln", 24, 27); + arm64_sysreg_add_field(ID_MMFR1_EL1, "L1Uni", 20, 23); + arm64_sysreg_add_field(ID_MMFR1_EL1, "L1Hvd", 16, 19); + arm64_sysreg_add_field(ID_MMFR1_EL1, "L1UniSW", 12, 15); + arm64_sysreg_add_field(ID_MMFR1_EL1, "L1HvdSW", 8, 11); + arm64_sysreg_add_field(ID_MMFR1_EL1, "L1UniVA", 4, 7); + arm64_sysreg_add_field(ID_MMFR1_EL1, "L1HvdVA", 0, 3); + + /* ID_MMFR2_EL1 */ + ARM64SysReg *ID_MMFR2_EL1 = arm64_sysreg_get(ID_MMFR2_EL1_IDX); + ID_MMFR2_EL1->name = "ID_MMFR2_EL1"; + arm64_sysreg_add_field(ID_MMFR2_EL1, "HWAccFlg", 28, 31); + arm64_sysreg_add_field(ID_MMFR2_EL1, "WFIStall", 24, 27); + arm64_sysreg_add_field(ID_MMFR2_EL1, "MemBarr", 20, 23); + arm64_sysreg_add_field(ID_MMFR2_EL1, "UniTLB", 16, 19); + arm64_sysreg_add_field(ID_MMFR2_EL1, "HvdTLB", 12, 15); + arm64_sysreg_add_field(ID_MMFR2_EL1, "L1HvdRng", 8, 11); + arm64_sysreg_add_field(ID_MMFR2_EL1, "L1HvdBG", 4, 7); + arm64_sysreg_add_field(ID_MMFR2_EL1, "L1HvdFG", 0, 3); + + /* ID_MMFR3_EL1 */ + ARM64SysReg *ID_MMFR3_EL1 = arm64_sysreg_get(ID_MMFR3_EL1_IDX); + ID_MMFR3_EL1->name = "ID_MMFR3_EL1"; + arm64_sysreg_add_field(ID_MMFR3_EL1, "Supersec", 28, 31); + arm64_sysreg_add_field(ID_MMFR3_EL1, "CMemSz", 24, 27); + arm64_sysreg_add_field(ID_MMFR3_EL1, "CohWalk", 20, 23); + arm64_sysreg_add_field(ID_MMFR3_EL1, "PAN", 16, 19); + arm64_sysreg_add_field(ID_MMFR3_EL1, "MaintBcst", 12, 15); + arm64_sysreg_add_field(ID_MMFR3_EL1, "BPMaint", 8, 11); + arm64_sysreg_add_field(ID_MMFR3_EL1, "CMaintSW", 4, 7); + arm64_sysreg_add_field(ID_MMFR3_EL1, "CMaintVA", 0, 3); + + /* ID_ISAR0_EL1 */ + ARM64SysReg *ID_ISAR0_EL1 = arm64_sysreg_get(ID_ISAR0_EL1_IDX); + ID_ISAR0_EL1->name = "ID_ISAR0_EL1"; + arm64_sysreg_add_field(ID_ISAR0_EL1, "Divide", 24, 27); + arm64_sysreg_add_field(ID_ISAR0_EL1, "Debug", 20, 23); + arm64_sysreg_add_field(ID_ISAR0_EL1, "Coproc", 16, 19); + arm64_sysreg_add_field(ID_ISAR0_EL1, "CmpBranch", 12, 15); + arm64_sysreg_add_field(ID_ISAR0_EL1, "BitField", 8, 11); + arm64_sysreg_add_field(ID_ISAR0_EL1, "BitCount", 4, 7); + arm64_sysreg_add_field(ID_ISAR0_EL1, "Swap", 0, 3); + + /* ID_ISAR1_EL1 */ + ARM64SysReg *ID_ISAR1_EL1 = arm64_sysreg_get(ID_ISAR1_EL1_IDX); + ID_ISAR1_EL1->name = "ID_ISAR1_EL1"; + arm64_sysreg_add_field(ID_ISAR1_EL1, "Jazelle", 28, 31); + arm64_sysreg_add_field(ID_ISAR1_EL1, "Interwork", 24, 27); + arm64_sysreg_add_field(ID_ISAR1_EL1, "Immediate", 20, 23); + arm64_sysreg_add_field(ID_ISAR1_EL1, "IfThen", 16, 19); + arm64_sysreg_add_field(ID_ISAR1_EL1, "Extend", 12, 15); + arm64_sysreg_add_field(ID_ISAR1_EL1, "Except_AR", 8, 11); + arm64_sysreg_add_field(ID_ISAR1_EL1, "Except", 4, 7); + arm64_sysreg_add_field(ID_ISAR1_EL1, "Endian", 0, 3); + + /* ID_ISAR2_EL1 */ + ARM64SysReg *ID_ISAR2_EL1 = arm64_sysreg_get(ID_ISAR2_EL1_IDX); + ID_ISAR2_EL1->name = "ID_ISAR2_EL1"; + arm64_sysreg_add_field(ID_ISAR2_EL1, "Reversal", 28, 31); + arm64_sysreg_add_field(ID_ISAR2_EL1, "PSR_AR", 24, 27); + arm64_sysreg_add_field(ID_ISAR2_EL1, "MultU", 20, 23); + arm64_sysreg_add_field(ID_ISAR2_EL1, "MultS", 16, 19); + arm64_sysreg_add_field(ID_ISAR2_EL1, "Mult", 12, 15); + arm64_sysreg_add_field(ID_ISAR2_EL1, "MultiAccessInt", 8, 11); + arm64_sysreg_add_field(ID_ISAR2_EL1, "MemHint", 4, 7); + arm64_sysreg_add_field(ID_ISAR2_EL1, "LoadStore", 0, 3); + + /* ID_ISAR3_EL1 */ + ARM64SysReg *ID_ISAR3_EL1 = arm64_sysreg_get(ID_ISAR3_EL1_IDX); + ID_ISAR3_EL1->name = "ID_ISAR3_EL1"; + arm64_sysreg_add_field(ID_ISAR3_EL1, "T32EE", 28, 31); + arm64_sysreg_add_field(ID_ISAR3_EL1, "TrueNOP", 24, 27); + arm64_sysreg_add_field(ID_ISAR3_EL1, "T32Copy", 20, 23); + arm64_sysreg_add_field(ID_ISAR3_EL1, "TabBranch", 16, 19); + arm64_sysreg_add_field(ID_ISAR3_EL1, "SynchPrim", 12, 15); + arm64_sysreg_add_field(ID_ISAR3_EL1, "SVC", 8, 11); + arm64_sysreg_add_field(ID_ISAR3_EL1, "SIMD", 4, 7); + arm64_sysreg_add_field(ID_ISAR3_EL1, "Saturate", 0, 3); + + /* ID_ISAR4_EL1 */ + ARM64SysReg *ID_ISAR4_EL1 = arm64_sysreg_get(ID_ISAR4_EL1_IDX); + ID_ISAR4_EL1->name = "ID_ISAR4_EL1"; + arm64_sysreg_add_field(ID_ISAR4_EL1, "SWP_frac", 28, 31); + arm64_sysreg_add_field(ID_ISAR4_EL1, "PSR_M", 24, 27); + arm64_sysreg_add_field(ID_ISAR4_EL1, "SynchPrim_frac", 20, 23); + arm64_sysreg_add_field(ID_ISAR4_EL1, "Barrier", 16, 19); + arm64_sysreg_add_field(ID_ISAR4_EL1, "SMC", 12, 15); + arm64_sysreg_add_field(ID_ISAR4_EL1, "Writeback", 8, 11); + arm64_sysreg_add_field(ID_ISAR4_EL1, "WithShifts", 4, 7); + arm64_sysreg_add_field(ID_ISAR4_EL1, "Unpriv", 0, 3); + + /* ID_ISAR5_EL1 */ + ARM64SysReg *ID_ISAR5_EL1 = arm64_sysreg_get(ID_ISAR5_EL1_IDX); + ID_ISAR5_EL1->name = "ID_ISAR5_EL1"; + arm64_sysreg_add_field(ID_ISAR5_EL1, "VCMA", 28, 31); + arm64_sysreg_add_field(ID_ISAR5_EL1, "RDM", 24, 27); + arm64_sysreg_add_field(ID_ISAR5_EL1, "CRC32", 16, 19); + arm64_sysreg_add_field(ID_ISAR5_EL1, "SHA2", 12, 15); + arm64_sysreg_add_field(ID_ISAR5_EL1, "SHA1", 8, 11); + arm64_sysreg_add_field(ID_ISAR5_EL1, "AES", 4, 7); + arm64_sysreg_add_field(ID_ISAR5_EL1, "SEVL", 0, 3); + + /* ID_ISAR6_EL1 */ + ARM64SysReg *ID_ISAR6_EL1 = arm64_sysreg_get(ID_ISAR6_EL1_IDX); + ID_ISAR6_EL1->name = "ID_ISAR6_EL1"; + arm64_sysreg_add_field(ID_ISAR6_EL1, "I8MM", 24, 27); + arm64_sysreg_add_field(ID_ISAR6_EL1, "BF16", 20, 23); + arm64_sysreg_add_field(ID_ISAR6_EL1, "SPECRES", 16, 19); + arm64_sysreg_add_field(ID_ISAR6_EL1, "SB", 12, 15); + arm64_sysreg_add_field(ID_ISAR6_EL1, "FHM", 8, 11); + arm64_sysreg_add_field(ID_ISAR6_EL1, "DP", 4, 7); + arm64_sysreg_add_field(ID_ISAR6_EL1, "JSCVT", 0, 3); + + /* ID_MMFR4_EL1 */ + ARM64SysReg *ID_MMFR4_EL1 = arm64_sysreg_get(ID_MMFR4_EL1_IDX); + ID_MMFR4_EL1->name = "ID_MMFR4_EL1"; + arm64_sysreg_add_field(ID_MMFR4_EL1, "EVT", 28, 31); + arm64_sysreg_add_field(ID_MMFR4_EL1, "CCIDX", 24, 27); + arm64_sysreg_add_field(ID_MMFR4_EL1, "LSM", 20, 23); + arm64_sysreg_add_field(ID_MMFR4_EL1, "HPDS", 16, 19); + arm64_sysreg_add_field(ID_MMFR4_EL1, "CnP", 12, 15); + arm64_sysreg_add_field(ID_MMFR4_EL1, "XNX", 8, 11); + arm64_sysreg_add_field(ID_MMFR4_EL1, "AC2", 4, 7); + arm64_sysreg_add_field(ID_MMFR4_EL1, "SpecSEI", 0, 3); + + /* MVFR0_EL1 */ + ARM64SysReg *MVFR0_EL1 = arm64_sysreg_get(MVFR0_EL1_IDX); + MVFR0_EL1->name = "MVFR0_EL1"; + arm64_sysreg_add_field(MVFR0_EL1, "FPRound", 28, 31); + arm64_sysreg_add_field(MVFR0_EL1, "FPShVec", 24, 27); + arm64_sysreg_add_field(MVFR0_EL1, "FPSqrt", 20, 23); + arm64_sysreg_add_field(MVFR0_EL1, "FPDivide", 16, 19); + arm64_sysreg_add_field(MVFR0_EL1, "FPTrap", 12, 15); + arm64_sysreg_add_field(MVFR0_EL1, "FPDP", 8, 11); + arm64_sysreg_add_field(MVFR0_EL1, "FPSP", 4, 7); + arm64_sysreg_add_field(MVFR0_EL1, "SIMDReg", 0, 3); + + /* MVFR1_EL1 */ + ARM64SysReg *MVFR1_EL1 = arm64_sysreg_get(MVFR1_EL1_IDX); + MVFR1_EL1->name = "MVFR1_EL1"; + arm64_sysreg_add_field(MVFR1_EL1, "SIMDFMAC", 28, 31); + arm64_sysreg_add_field(MVFR1_EL1, "FPHP", 24, 27); + arm64_sysreg_add_field(MVFR1_EL1, "SIMDHP", 20, 23); + arm64_sysreg_add_field(MVFR1_EL1, "SIMDSP", 16, 19); + arm64_sysreg_add_field(MVFR1_EL1, "SIMDInt", 12, 15); + arm64_sysreg_add_field(MVFR1_EL1, "SIMDLS", 8, 11); + arm64_sysreg_add_field(MVFR1_EL1, "FPDNaN", 4, 7); + arm64_sysreg_add_field(MVFR1_EL1, "FPFtZ", 0, 3); + + /* MVFR2_EL1 */ + ARM64SysReg *MVFR2_EL1 = arm64_sysreg_get(MVFR2_EL1_IDX); + MVFR2_EL1->name = "MVFR2_EL1"; + arm64_sysreg_add_field(MVFR2_EL1, "FPMisc", 4, 7); + arm64_sysreg_add_field(MVFR2_EL1, "SIMDMisc", 0, 3); + + /* ID_PFR2_EL1 */ + ARM64SysReg *ID_PFR2_EL1 = arm64_sysreg_get(ID_PFR2_EL1_IDX); + ID_PFR2_EL1->name = "ID_PFR2_EL1"; + arm64_sysreg_add_field(ID_PFR2_EL1, "RAS_frac", 8, 11); + arm64_sysreg_add_field(ID_PFR2_EL1, "SSBS", 4, 7); + arm64_sysreg_add_field(ID_PFR2_EL1, "CSV3", 0, 3); + + /* ID_DFR1_EL1 */ + ARM64SysReg *ID_DFR1_EL1 = arm64_sysreg_get(ID_DFR1_EL1_IDX); + ID_DFR1_EL1->name = "ID_DFR1_EL1"; + arm64_sysreg_add_field(ID_DFR1_EL1, "HPMN0", 4, 7); + arm64_sysreg_add_field(ID_DFR1_EL1, "MTPMU", 0, 3); + + /* ID_MMFR5_EL1 */ + ARM64SysReg *ID_MMFR5_EL1 = arm64_sysreg_get(ID_MMFR5_EL1_IDX); + ID_MMFR5_EL1->name = "ID_MMFR5_EL1"; + arm64_sysreg_add_field(ID_MMFR5_EL1, "nTLBPA", 4, 7); + arm64_sysreg_add_field(ID_MMFR5_EL1, "ETS", 0, 3); + + /* ID_AA64PFR0_EL1 */ + ARM64SysReg *ID_AA64PFR0_EL1 = arm64_sysreg_get(ID_AA64PFR0_EL1_IDX); + ID_AA64PFR0_EL1->name = "ID_AA64PFR0_EL1"; + arm64_sysreg_add_field(ID_AA64PFR0_EL1, "CSV3", 60, 63); + arm64_sysreg_add_field(ID_AA64PFR0_EL1, "CSV2", 56, 59); + arm64_sysreg_add_field(ID_AA64PFR0_EL1, "RME", 52, 55); + arm64_sysreg_add_field(ID_AA64PFR0_EL1, "DIT", 48, 51); + arm64_sysreg_add_field(ID_AA64PFR0_EL1, "AMU", 44, 47); + arm64_sysreg_add_field(ID_AA64PFR0_EL1, "MPAM", 40, 43); + arm64_sysreg_add_field(ID_AA64PFR0_EL1, "SEL2", 36, 39); + arm64_sysreg_add_field(ID_AA64PFR0_EL1, "SVE", 32, 35); + arm64_sysreg_add_field(ID_AA64PFR0_EL1, "RAS", 28, 31); + arm64_sysreg_add_field(ID_AA64PFR0_EL1, "GIC", 24, 27); + arm64_sysreg_add_field(ID_AA64PFR0_EL1, "AdvSIMD", 20, 23); + arm64_sysreg_add_field(ID_AA64PFR0_EL1, "AdvSIMD", 20, 23); + arm64_sysreg_add_field(ID_AA64PFR0_EL1, "FP", 16, 19); + arm64_sysreg_add_field(ID_AA64PFR0_EL1, "FP", 16, 19); + arm64_sysreg_add_field(ID_AA64PFR0_EL1, "EL3", 12, 15); + arm64_sysreg_add_field(ID_AA64PFR0_EL1, "EL2", 8, 11); + arm64_sysreg_add_field(ID_AA64PFR0_EL1, "EL1", 4, 7); + arm64_sysreg_add_field(ID_AA64PFR0_EL1, "EL0", 0, 3); + + /* ID_AA64PFR1_EL1 */ + ARM64SysReg *ID_AA64PFR1_EL1 = arm64_sysreg_get(ID_AA64PFR1_EL1_IDX); + ID_AA64PFR1_EL1->name = "ID_AA64PFR1_EL1"; + arm64_sysreg_add_field(ID_AA64PFR1_EL1, "PFAR", 60, 63); + arm64_sysreg_add_field(ID_AA64PFR1_EL1, "DF2", 56, 59); + arm64_sysreg_add_field(ID_AA64PFR1_EL1, "MTEX", 52, 55); + arm64_sysreg_add_field(ID_AA64PFR1_EL1, "THE", 48, 51); + arm64_sysreg_add_field(ID_AA64PFR1_EL1, "GCS", 44, 47); + arm64_sysreg_add_field(ID_AA64PFR1_EL1, "MTE_frac", 40, 43); + arm64_sysreg_add_field(ID_AA64PFR1_EL1, "NMI", 36, 39); + arm64_sysreg_add_field(ID_AA64PFR1_EL1, "CSV2_frac", 32, 35); + arm64_sysreg_add_field(ID_AA64PFR1_EL1, "RNDR_trap", 28, 31); + arm64_sysreg_add_field(ID_AA64PFR1_EL1, "SME", 24, 27); + arm64_sysreg_add_field(ID_AA64PFR1_EL1, "MPAM_frac", 16, 19); + arm64_sysreg_add_field(ID_AA64PFR1_EL1, "RAS_frac", 12, 15); + arm64_sysreg_add_field(ID_AA64PFR1_EL1, "MTE", 8, 11); + arm64_sysreg_add_field(ID_AA64PFR1_EL1, "SSBS", 4, 7); + arm64_sysreg_add_field(ID_AA64PFR1_EL1, "BT", 0, 3); + + /* ID_AA64PFR2_EL1 */ + ARM64SysReg *ID_AA64PFR2_EL1 = arm64_sysreg_get(ID_AA64PFR2_EL1_IDX); + ID_AA64PFR2_EL1->name = "ID_AA64PFR2_EL1"; + arm64_sysreg_add_field(ID_AA64PFR2_EL1, "FPMR", 32, 35); + arm64_sysreg_add_field(ID_AA64PFR2_EL1, "UINJ", 16, 19); + arm64_sysreg_add_field(ID_AA64PFR2_EL1, "MTEFAR", 8, 11); + arm64_sysreg_add_field(ID_AA64PFR2_EL1, "MTESTOREONLY", 4, 7); + arm64_sysreg_add_field(ID_AA64PFR2_EL1, "MTEPERM", 0, 3); + + /* ID_AA64ZFR0_EL1 */ + ARM64SysReg *ID_AA64ZFR0_EL1 = arm64_sysreg_get(ID_AA64ZFR0_EL1_IDX); + ID_AA64ZFR0_EL1->name = "ID_AA64ZFR0_EL1"; + arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "F64MM", 56, 59); + arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "F32MM", 52, 55); + arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "F16MM", 48, 51); + arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "I8MM", 44, 47); + arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "SM4", 40, 43); + arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "SHA3", 32, 35); + arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "B16B16", 24, 27); + arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "BF16", 20, 23); + arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "BitPerm", 16, 19); + arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "EltPerm", 12, 15); + arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "AES", 4, 7); + arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "SVEver", 0, 3); + + /* ID_AA64SMFR0_EL1 */ + ARM64SysReg *ID_AA64SMFR0_EL1 = arm64_sysreg_get(ID_AA64SMFR0_EL1_IDX); + ID_AA64SMFR0_EL1->name = "ID_AA64SMFR0_EL1"; + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "FA64", 63, 63); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "LUTv2", 60, 60); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "SMEver", 56, 59); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "I16I64", 52, 55); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "F64F64", 48, 48); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "I16I32", 44, 47); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "B16B16", 43, 43); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "F16F16", 42, 42); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "F8F16", 41, 41); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "F8F32", 40, 40); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "I8I32", 36, 39); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "F16F32", 35, 35); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "B16F32", 34, 34); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "BI32I32", 33, 33); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "F32F32", 32, 32); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "SF8FMA", 30, 30); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "SF8DP4", 29, 29); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "SF8DP2", 28, 28); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "SBitPerm", 25, 25); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "AES", 24, 24); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "SFEXPA", 23, 23); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "STMOP", 16, 16); + arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "SMOP4", 0, 0); + + /* ID_AA64FPFR0_EL1 */ + ARM64SysReg *ID_AA64FPFR0_EL1 = arm64_sysreg_get(ID_AA64FPFR0_EL1_IDX); + ID_AA64FPFR0_EL1->name = "ID_AA64FPFR0_EL1"; + arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8CVT", 31, 31); + arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8FMA", 30, 30); + arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8DP4", 29, 29); + arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8DP2", 28, 28); + arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8MM8", 27, 27); + arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8MM4", 26, 26); + arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8E4M3", 1, 1); + arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8E5M2", 0, 0); + + /* ID_AA64DFR0_EL1 */ + ARM64SysReg *ID_AA64DFR0_EL1 = arm64_sysreg_get(ID_AA64DFR0_EL1_IDX); + ID_AA64DFR0_EL1->name = "ID_AA64DFR0_EL1"; + arm64_sysreg_add_field(ID_AA64DFR0_EL1, "HPMN0", 60, 63); + arm64_sysreg_add_field(ID_AA64DFR0_EL1, "ExtTrcBuff", 56, 59); + arm64_sysreg_add_field(ID_AA64DFR0_EL1, "BRBE", 52, 55); + arm64_sysreg_add_field(ID_AA64DFR0_EL1, "MTPMU", 48, 51); + arm64_sysreg_add_field(ID_AA64DFR0_EL1, "MTPMU", 48, 51); + arm64_sysreg_add_field(ID_AA64DFR0_EL1, "TraceBuffer", 44, 47); + arm64_sysreg_add_field(ID_AA64DFR0_EL1, "TraceFilt", 40, 43); + arm64_sysreg_add_field(ID_AA64DFR0_EL1, "DoubleLock", 36, 39); + arm64_sysreg_add_field(ID_AA64DFR0_EL1, "PMSVer", 32, 35); + arm64_sysreg_add_field(ID_AA64DFR0_EL1, "CTX_CMPs", 28, 31); + arm64_sysreg_add_field(ID_AA64DFR0_EL1, "SEBEP", 24, 27); + arm64_sysreg_add_field(ID_AA64DFR0_EL1, "WRPs", 20, 23); + arm64_sysreg_add_field(ID_AA64DFR0_EL1, "PMSS", 16, 19); + arm64_sysreg_add_field(ID_AA64DFR0_EL1, "BRPs", 12, 15); + arm64_sysreg_add_field(ID_AA64DFR0_EL1, "PMUVer", 8, 11); + arm64_sysreg_add_field(ID_AA64DFR0_EL1, "TraceVer", 4, 7); + arm64_sysreg_add_field(ID_AA64DFR0_EL1, "DebugVer", 0, 3); + + /* ID_AA64DFR1_EL1 */ + ARM64SysReg *ID_AA64DFR1_EL1 = arm64_sysreg_get(ID_AA64DFR1_EL1_IDX); + ID_AA64DFR1_EL1->name = "ID_AA64DFR1_EL1"; + arm64_sysreg_add_field(ID_AA64DFR1_EL1, "ABL_CMPs", 56, 63); + arm64_sysreg_add_field(ID_AA64DFR1_EL1, "DPFZS", 52, 55); + arm64_sysreg_add_field(ID_AA64DFR1_EL1, "EBEP", 48, 51); + arm64_sysreg_add_field(ID_AA64DFR1_EL1, "ITE", 44, 47); + arm64_sysreg_add_field(ID_AA64DFR1_EL1, "ABLE", 40, 43); + arm64_sysreg_add_field(ID_AA64DFR1_EL1, "PMICNTR", 36, 39); + arm64_sysreg_add_field(ID_AA64DFR1_EL1, "SPMU", 32, 35); + arm64_sysreg_add_field(ID_AA64DFR1_EL1, "CTX_CMPs", 24, 31); + arm64_sysreg_add_field(ID_AA64DFR1_EL1, "WRPs", 16, 23); + arm64_sysreg_add_field(ID_AA64DFR1_EL1, "BRPs", 8, 15); + arm64_sysreg_add_field(ID_AA64DFR1_EL1, "SYSPMUID", 0, 7); + + /* ID_AA64DFR2_EL1 */ + ARM64SysReg *ID_AA64DFR2_EL1 = arm64_sysreg_get(ID_AA64DFR2_EL1_IDX); + ID_AA64DFR2_EL1->name = "ID_AA64DFR2_EL1"; + arm64_sysreg_add_field(ID_AA64DFR2_EL1, "TRBE_EXC", 24, 27); + arm64_sysreg_add_field(ID_AA64DFR2_EL1, "SPE_nVM", 20, 23); + arm64_sysreg_add_field(ID_AA64DFR2_EL1, "SPE_EXC", 16, 19); + arm64_sysreg_add_field(ID_AA64DFR2_EL1, "BWE", 4, 7); + arm64_sysreg_add_field(ID_AA64DFR2_EL1, "STEP", 0, 3); + + /* ID_AA64AFR0_EL1 */ + ARM64SysReg *ID_AA64AFR0_EL1 = arm64_sysreg_get(ID_AA64AFR0_EL1_IDX); + ID_AA64AFR0_EL1->name = "ID_AA64AFR0_EL1"; + arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF7", 28, 31); + arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF6", 24, 27); + arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF5", 20, 23); + arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF4", 16, 19); + arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF3", 12, 15); + arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF2", 8, 11); + arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF1", 4, 7); + arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF0", 0, 3); + + /* ID_AA64AFR1_EL1 */ + ARM64SysReg *ID_AA64AFR1_EL1 = arm64_sysreg_get(ID_AA64AFR1_EL1_IDX); + ID_AA64AFR1_EL1->name = "ID_AA64AFR1_EL1"; + + /* ID_AA64ISAR0_EL1 */ + ARM64SysReg *ID_AA64ISAR0_EL1 = arm64_sysreg_get(ID_AA64ISAR0_EL1_IDX); + ID_AA64ISAR0_EL1->name = "ID_AA64ISAR0_EL1"; + arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "RNDR", 60, 63); + arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "TLB", 56, 59); + arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "TS", 52, 55); + arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "FHM", 48, 51); + arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "DP", 44, 47); + arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "SM4", 40, 43); + arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "SM3", 36, 39); + arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "SHA3", 32, 35); + arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "RDM", 28, 31); + arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "TME", 24, 27); + arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "ATOMIC", 20, 23); + arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "CRC32", 16, 19); + arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "SHA2", 12, 15); + arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "SHA1", 8, 11); + arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "AES", 4, 7); + + /* ID_AA64ISAR1_EL1 */ + ARM64SysReg *ID_AA64ISAR1_EL1 = arm64_sysreg_get(ID_AA64ISAR1_EL1_IDX); + ID_AA64ISAR1_EL1->name = "ID_AA64ISAR1_EL1"; + arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "LS64", 60, 63); + arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "XS", 56, 59); + arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "I8MM", 52, 55); + arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "DGH", 48, 51); + arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "BF16", 44, 47); + arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "SPECRES", 40, 43); + arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "SB", 36, 39); + arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "FRINTTS", 32, 35); + arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "GPI", 28, 31); + arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "GPA", 24, 27); + arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "LRCPC", 20, 23); + arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "FCMA", 16, 19); + arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "JSCVT", 12, 15); + arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "API", 8, 11); + arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "APA", 4, 7); + arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "DPB", 0, 3); + + /* ID_AA64ISAR2_EL1 */ + ARM64SysReg *ID_AA64ISAR2_EL1 = arm64_sysreg_get(ID_AA64ISAR2_EL1_IDX); + ID_AA64ISAR2_EL1->name = "ID_AA64ISAR2_EL1"; + arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "ATS1A", 60, 63); + arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "LUT", 56, 59); + arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "CSSC", 52, 55); + arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "RPRFM", 48, 51); + arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "PCDPHINT", 44, 47); + arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "PRFMSLC", 40, 43); + arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "SYSINSTR_128", 36, 39); + arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "SYSREG_128", 32, 35); + arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "CLRBHB", 28, 31); + arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "PAC_frac", 24, 27); + arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "BC", 20, 23); + arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "MOPS", 16, 19); + arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "APA3", 12, 15); + arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "GPA3", 8, 11); + arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "RPRES", 4, 7); + arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "WFxT", 0, 3); + + /* ID_AA64ISAR3_EL1 */ + ARM64SysReg *ID_AA64ISAR3_EL1 = arm64_sysreg_get(ID_AA64ISAR3_EL1_IDX); + ID_AA64ISAR3_EL1->name = "ID_AA64ISAR3_EL1"; + arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "FPRCVT", 28, 31); + arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "LSUI", 24, 27); + arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "OCCMO", 20, 23); + arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "LSFE", 16, 19); + arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "PACM", 12, 15); + arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "TLBIW", 8, 11); + arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "FAMINMAX", 4, 7); + arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "CPA", 0, 3); + + /* ID_AA64MMFR0_EL1 */ + ARM64SysReg *ID_AA64MMFR0_EL1 = arm64_sysreg_get(ID_AA64MMFR0_EL1_IDX); + ID_AA64MMFR0_EL1->name = "ID_AA64MMFR0_EL1"; + arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "ECV", 60, 63); + arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "FGT", 56, 59); + arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "EXS", 44, 47); + arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN4_2", 40, 43); + arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN64_2", 36, 39); + arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN16_2", 32, 35); + arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN4", 28, 31); + arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN4", 28, 31); + arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN64", 24, 27); + arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN64", 24, 27); + arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN16", 20, 23); + arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "BIGENDEL0", 16, 19); + arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "SNSMEM", 12, 15); + arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "BIGEND", 8, 11); + arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "ASIDBITS", 4, 7); + arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "PARANGE", 0, 3); + + /* ID_AA64MMFR1_EL1 */ + ARM64SysReg *ID_AA64MMFR1_EL1 = arm64_sysreg_get(ID_AA64MMFR1_EL1_IDX); + ID_AA64MMFR1_EL1->name = "ID_AA64MMFR1_EL1"; + arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "ECBHB", 60, 63); + arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "CMOW", 56, 59); + arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "TIDCP1", 52, 55); + arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "nTLBPA", 48, 51); + arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "AFP", 44, 47); + arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "HCX", 40, 43); + arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "ETS", 36, 39); + arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "TWED", 32, 35); + arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "XNX", 28, 31); + arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "SpecSEI", 24, 27); + arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "PAN", 20, 23); + arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "LO", 16, 19); + arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "HPDS", 12, 15); + arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "VH", 8, 11); + arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "VMIDBits", 4, 7); + arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "HAFDBS", 0, 3); + + /* ID_AA64MMFR2_EL1 */ + ARM64SysReg *ID_AA64MMFR2_EL1 = arm64_sysreg_get(ID_AA64MMFR2_EL1_IDX); + ID_AA64MMFR2_EL1->name = "ID_AA64MMFR2_EL1"; + arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "E0PD", 60, 63); + arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "EVT", 56, 59); + arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "BBM", 52, 55); + arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "TTL", 48, 51); + arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "FWB", 40, 43); + arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "IDS", 36, 39); + arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "AT", 32, 35); + arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "ST", 28, 31); + arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "NV", 24, 27); + arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "CCIDX", 20, 23); + arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "VARange", 16, 19); + arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "IESB", 12, 15); + arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "LSM", 8, 11); + arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "UAO", 4, 7); + arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "CnP", 0, 3); + + /* ID_AA64MMFR3_EL1 */ + ARM64SysReg *ID_AA64MMFR3_EL1 = arm64_sysreg_get(ID_AA64MMFR3_EL1_IDX); + ID_AA64MMFR3_EL1->name = "ID_AA64MMFR3_EL1"; + arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "Spec_FPACC", 60, 63); + arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "ADERR", 56, 59); + arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "SDERR", 52, 55); + arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "ANERR", 44, 47); + arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "SNERR", 40, 43); + arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "D128_2", 36, 39); + arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "D128", 32, 35); + arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "MEC", 28, 31); + arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "AIE", 24, 27); + arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "S2POE", 20, 23); + arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "S1POE", 16, 19); + arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "S2PIE", 12, 15); + arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "S1PIE", 8, 11); + arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "SCTLRX", 4, 7); + arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "TCRX", 0, 3); + + /* ID_AA64MMFR4_EL1 */ + ARM64SysReg *ID_AA64MMFR4_EL1 = arm64_sysreg_get(ID_AA64MMFR4_EL1_IDX); + ID_AA64MMFR4_EL1->name = "ID_AA64MMFR4_EL1"; + arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "SRMASK", 44, 47); + arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "E3DSE", 36, 39); + arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "RMEGDI", 28, 31); + arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "E2H0", 24, 27); + arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "E2H0", 24, 27); + arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "NV_frac", 20, 23); + arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "FGWTE3", 16, 19); + arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "HACDBS", 12, 15); + arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "ASID2", 8, 11); + arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "EIESB", 4, 7); + arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "EIESB", 4, 7); + arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "PoPS", 0, 3); + +/* For SCTLR_EL12 fields see SCTLR_EL1 */ + +/* For SCTLRALIAS_EL1 fields see SCTLR_EL1 */ + +/* For ACTLR_EL12 fields see ACTLR_EL1 */ + +/* For ACTLRALIAS_EL1 fields see ACTLR_EL1 */ + +/* For CPACR_EL12 fields see CPACR_EL1 */ + +/* For CPACRALIAS_EL1 fields see CPACR_EL1 */ + +/* For ACTLRMASK_EL12 fields see ACTLRMASK_EL1 */ + +/* For CPACRMASK_EL12 fields see CPACRMASK_EL1 */ + +/* For PFAR_EL12 fields see PFAR_EL1 */ + +/* For SCTLR2_EL12 fields see SCTLR2_EL1 */ + +/* For SCTLR2ALIAS_EL1 fields see SCTLR2_EL1 */ + +/* For SCTLR2MASK_EL12 fields see SCTLR2MASK_EL1 */ + +/* For SCTLRMASK_EL12 fields see SCTLRMASK_EL1 */ + +/* For TCR2MASK_EL12 fields see TCR2MASK_EL1 */ + +/* For TCRMASK_EL12 fields see TCRMASK_EL1 */ + +/* For TRCITECR_EL12 fields see TRCITECR_EL1 */ + +/* For ZCR_EL1 fields see ZCR_ELx */ + +/* For SMCR_EL1 fields see SMCR_ELx */ + +/* For GCSCR_EL1 fields see GCSCR_ELx */ + +/* For GCSPR_EL1 fields see GCSPR_ELx */ + +/* For CONTEXTIDR_EL1 fields see CONTEXTIDR_ELx */ + + /* CCSIDR_EL1 */ + ARM64SysReg *CCSIDR_EL1 = arm64_sysreg_get(CCSIDR_EL1_IDX); + CCSIDR_EL1->name = "CCSIDR_EL1"; + arm64_sysreg_add_field(CCSIDR_EL1, "NumSets", 13, 27); + arm64_sysreg_add_field(CCSIDR_EL1, "Associativity", 3, 12); + arm64_sysreg_add_field(CCSIDR_EL1, "LineSize", 0, 2); + + /* CLIDR_EL1 */ + ARM64SysReg *CLIDR_EL1 = arm64_sysreg_get(CLIDR_EL1_IDX); + CLIDR_EL1->name = "CLIDR_EL1"; + arm64_sysreg_add_field(CLIDR_EL1, "Ttypen", 33, 46); + arm64_sysreg_add_field(CLIDR_EL1, "ICB", 30, 32); + arm64_sysreg_add_field(CLIDR_EL1, "LoUU", 27, 29); + arm64_sysreg_add_field(CLIDR_EL1, "LoC", 24, 26); + arm64_sysreg_add_field(CLIDR_EL1, "LoUIS", 21, 23); + arm64_sysreg_add_field(CLIDR_EL1, "Ctype7", 18, 20); + arm64_sysreg_add_field(CLIDR_EL1, "Ctype6", 15, 17); + arm64_sysreg_add_field(CLIDR_EL1, "Ctype5", 12, 14); + arm64_sysreg_add_field(CLIDR_EL1, "Ctype4", 9, 11); + arm64_sysreg_add_field(CLIDR_EL1, "Ctype3", 6, 8); + arm64_sysreg_add_field(CLIDR_EL1, "Ctype2", 3, 5); + arm64_sysreg_add_field(CLIDR_EL1, "Ctype1", 0, 2); + + /* CCSIDR2_EL1 */ + ARM64SysReg *CCSIDR2_EL1 = arm64_sysreg_get(CCSIDR2_EL1_IDX); + CCSIDR2_EL1->name = "CCSIDR2_EL1"; + arm64_sysreg_add_field(CCSIDR2_EL1, "NumSets", 0, 23); + + /* GMID_EL1 */ + ARM64SysReg *GMID_EL1 = arm64_sysreg_get(GMID_EL1_IDX); + GMID_EL1->name = "GMID_EL1"; + arm64_sysreg_add_field(GMID_EL1, "BS", 0, 3); + + /* SMIDR_EL1 */ + ARM64SysReg *SMIDR_EL1 = arm64_sysreg_get(SMIDR_EL1_IDX); + SMIDR_EL1->name = "SMIDR_EL1"; + arm64_sysreg_add_field(SMIDR_EL1, "IMPLEMENTER", 24, 31); + arm64_sysreg_add_field(SMIDR_EL1, "REVISION", 16, 23); + arm64_sysreg_add_field(SMIDR_EL1, "SMPS", 15, 15); + arm64_sysreg_add_field(SMIDR_EL1, "AFFINITY", 0, 11); + + /* CTR_EL0 */ + ARM64SysReg *CTR_EL0 = arm64_sysreg_get(CTR_EL0_IDX); + CTR_EL0->name = "CTR_EL0"; + arm64_sysreg_add_field(CTR_EL0, "TminLine", 32, 37); + arm64_sysreg_add_field(CTR_EL0, "DIC", 29, 29); + arm64_sysreg_add_field(CTR_EL0, "IDC", 28, 28); + arm64_sysreg_add_field(CTR_EL0, "CWG", 24, 27); + arm64_sysreg_add_field(CTR_EL0, "ERG", 20, 23); + arm64_sysreg_add_field(CTR_EL0, "DminLine", 16, 19); + arm64_sysreg_add_field(CTR_EL0, "L1Ip", 14, 15); + arm64_sysreg_add_field(CTR_EL0, "IminLine", 0, 3); + + /* DCZID_EL0 */ + ARM64SysReg *DCZID_EL0 = arm64_sysreg_get(DCZID_EL0_IDX); + DCZID_EL0->name = "DCZID_EL0"; + arm64_sysreg_add_field(DCZID_EL0, "DZP", 4, 4); + arm64_sysreg_add_field(DCZID_EL0, "BS", 0, 3); + +/* For GCSPR_EL0 fields see GCSPR_ELx */ + +/* For ZCR_EL2 fields see ZCR_ELx */ + +/* For SMCR_EL2 fields see SMCR_ELx */ + +/* For GCSCR_EL2 fields see GCSCR_ELx */ + +/* For GCSPR_EL2 fields see GCSPR_ELx */ + +/* For CONTEXTIDR_EL2 fields see CONTEXTIDR_ELx */ + +/* For CPACR_EL12 fields see CPACR_EL1 */ + +/* For ZCR_EL12 fields see ZCR_EL1 */ + +/* For TRFCR_EL12 fields see TRFCR_EL1 */ + +/* For SMCR_EL12 fields see SMCR_EL1 */ + +/* For GCSCR_EL12 fields see GCSCR_EL1 */ + +/* For GCSPR_EL12 fields see GCSPR_EL1 */ + +/* For MPAM1_EL12 fields see MPAM1_ELx */ + +/* For CONTEXTIDR_EL12 fields see CONTEXTIDR_EL1 */ + +/* For TTBR0_EL1 fields see TTBRx_EL1 */ + +/* For TTBR1_EL1 fields see TTBRx_EL1 */ + +/* For TCR_EL12 fields see TCR_EL1 */ + +/* For TCRALIAS_EL1 fields see TCR_EL1 */ + +/* For TCR2_EL12 fields see TCR2_EL1 */ + +/* For TCR2ALIAS_EL1 fields see TCR2_EL1 */ + +/* For MAIR2_EL1 fields see MAIR2_ELx */ + +/* For MAIR2_EL2 fields see MAIR2_ELx */ + +/* For PIRE0_EL1 fields see PIRx_ELx */ + +/* For PIRE0_EL12 fields see PIRE0_EL1 */ + +/* For PIRE0_EL2 fields see PIRx_ELx */ + +/* For PIR_EL1 fields see PIRx_ELx */ + +/* For PIR_EL12 fields see PIR_EL1 */ + +/* For PIR_EL2 fields see PIRx_ELx */ + +/* For POR_EL0 fields see PIRx_ELx */ + +/* For POR_EL1 fields see PIRx_ELx */ + +/* For POR_EL2 fields see PIRx_ELx */ + +/* For POR_EL12 fields see POR_EL1 */ + +/* For S2POR_EL1 fields see PIRx_ELx */ + +/* For S2PIR_EL2 fields see PIRx_ELx */ + + /* MIDR_EL1 */ + ARM64SysReg *MIDR_EL1 = arm64_sysreg_get(MIDR_EL1_IDX); + MIDR_EL1->name = "MIDR_EL1"; + arm64_sysreg_add_field(MIDR_EL1, "Implementer", 24, 31); + arm64_sysreg_add_field(MIDR_EL1, "Variant", 20, 23); + arm64_sysreg_add_field(MIDR_EL1, "Architecture", 16, 19); + arm64_sysreg_add_field(MIDR_EL1, "PartNum", 4, 15); + arm64_sysreg_add_field(MIDR_EL1, "Revision", 0, 3); + + /* REVIDR_EL1 */ + ARM64SysReg *REVIDR_EL1 = arm64_sysreg_get(REVIDR_EL1_IDX); + REVIDR_EL1->name = "REVIDR_EL1"; + arm64_sysreg_add_field(REVIDR_EL1, "IMPDEF", 0, 63); + + /* AIDR_EL1 */ + ARM64SysReg *AIDR_EL1 = arm64_sysreg_get(AIDR_EL1_IDX); + AIDR_EL1->name = "AIDR_EL1"; + arm64_sysreg_add_field(AIDR_EL1, "IMPDEF", 0, 63); + +} diff --git a/target/arm/cpu-sysregs.h b/target/arm/cpu-sysregs.h new file mode 100644 index 0000000000000000000000000000000000000000..367fab51f19eed36971facbdc1fe5351c7848cb2 --- /dev/null +++ b/target/arm/cpu-sysregs.h @@ -0,0 +1,48 @@ +/* + * Definitions for Arm ID system registers + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef ARM_CPU_SYSREGS_H +#define ARM_CPU_SYSREGS_H + +/* + * Following is similar to the coprocessor regs encodings, but with an argument + * ordering that matches the ARM ARM. We also reuse the various CP_REG_ defines + * that actually are the same as the equivalent KVM_REG_ values. + */ +#define ENCODE_ID_REG(op0, op1, crn, crm, op2) \ + (((op0) << CP_REG_ARM64_SYSREG_OP0_SHIFT) | \ + ((op1) << CP_REG_ARM64_SYSREG_OP1_SHIFT) | \ + ((crn) << CP_REG_ARM64_SYSREG_CRN_SHIFT) | \ + ((crm) << CP_REG_ARM64_SYSREG_CRM_SHIFT) | \ + ((op2) << CP_REG_ARM64_SYSREG_OP2_SHIFT)) + +#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) NAME##_IDX, + +typedef enum ARMIDRegisterIdx { +#include "cpu-sysregs.h.inc" + NUM_ID_IDX, +} ARMIDRegisterIdx; + +#undef DEF +#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) \ + SYS_##NAME = ENCODE_ID_REG(OP0, OP1, CRN, CRM, OP2), + +typedef enum ARMSysRegs { +#include "cpu-sysregs.h.inc" +} ARMSysRegs; + +#undef DEF + +extern const uint32_t id_register_sysreg[NUM_ID_IDX]; + +int get_sysreg_idx(ARMSysRegs sysreg); + +#ifdef CONFIG_KVM +uint64_t idregs_sysreg_to_kvm_reg(ARMSysRegs sysreg); +int kvm_idx_to_idregs_idx(int kidx); +int idregs_idx_to_kvm_idx(ARMIDRegisterIdx idx); +#endif + +#endif /* ARM_CPU_SYSREGS_H */ diff --git a/target/arm/cpu-sysregs.h.inc b/target/arm/cpu-sysregs.h.inc new file mode 100644 index 0000000000000000000000000000000000000000..e3e81e11eeb21f95df46f77446f9d75f68d670b5 --- /dev/null +++ b/target/arm/cpu-sysregs.h.inc @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* GENERATED FILE, DO NOT EDIT */ +/* use arm-gen-cpu-sysregs-header.awk to regenerate */ +DEF(ID_PFR0_EL1, 3, 0, 0, 1, 0) +DEF(ID_PFR1_EL1, 3, 0, 0, 1, 1) +DEF(ID_DFR0_EL1, 3, 0, 0, 1, 2) +DEF(ID_AFR0_EL1, 3, 0, 0, 1, 3) +DEF(ID_MMFR0_EL1, 3, 0, 0, 1, 4) +DEF(ID_MMFR1_EL1, 3, 0, 0, 1, 5) +DEF(ID_MMFR2_EL1, 3, 0, 0, 1, 6) +DEF(ID_MMFR3_EL1, 3, 0, 0, 1, 7) +DEF(ID_ISAR0_EL1, 3, 0, 0, 2, 0) +DEF(ID_ISAR1_EL1, 3, 0, 0, 2, 1) +DEF(ID_ISAR2_EL1, 3, 0, 0, 2, 2) +DEF(ID_ISAR3_EL1, 3, 0, 0, 2, 3) +DEF(ID_ISAR4_EL1, 3, 0, 0, 2, 4) +DEF(ID_ISAR5_EL1, 3, 0, 0, 2, 5) +DEF(ID_ISAR6_EL1, 3, 0, 0, 2, 7) +DEF(ID_MMFR4_EL1, 3, 0, 0, 2, 6) +DEF(MVFR0_EL1, 3, 0, 0, 3, 0) +DEF(MVFR1_EL1, 3, 0, 0, 3, 1) +DEF(MVFR2_EL1, 3, 0, 0, 3, 2) +DEF(ID_PFR2_EL1, 3, 0, 0, 3, 4) +DEF(ID_DFR1_EL1, 3, 0, 0, 3, 5) +DEF(ID_MMFR5_EL1, 3, 0, 0, 3, 6) +DEF(ID_AA64PFR0_EL1, 3, 0, 0, 4, 0) +DEF(ID_AA64PFR1_EL1, 3, 0, 0, 4, 1) +DEF(ID_AA64PFR2_EL1, 3, 0, 0, 4, 2) +DEF(ID_AA64ZFR0_EL1, 3, 0, 0, 4, 4) +DEF(ID_AA64SMFR0_EL1, 3, 0, 0, 4, 5) +DEF(ID_AA64FPFR0_EL1, 3, 0, 0, 4, 7) +DEF(ID_AA64DFR0_EL1, 3, 0, 0, 5, 0) +DEF(ID_AA64DFR1_EL1, 3, 0, 0, 5, 1) +DEF(ID_AA64DFR2_EL1, 3, 0, 0, 5, 2) +DEF(ID_AA64AFR0_EL1, 3, 0, 0, 5, 4) +DEF(ID_AA64AFR1_EL1, 3, 0, 0, 5, 5) +DEF(ID_AA64ISAR0_EL1, 3, 0, 0, 6, 0) +DEF(ID_AA64ISAR1_EL1, 3, 0, 0, 6, 1) +DEF(ID_AA64ISAR2_EL1, 3, 0, 0, 6, 2) +DEF(ID_AA64ISAR3_EL1, 3, 0, 0, 6, 3) +DEF(ID_AA64MMFR0_EL1, 3, 0, 0, 7, 0) +DEF(ID_AA64MMFR1_EL1, 3, 0, 0, 7, 1) +DEF(ID_AA64MMFR2_EL1, 3, 0, 0, 7, 2) +DEF(ID_AA64MMFR3_EL1, 3, 0, 0, 7, 3) +DEF(ID_AA64MMFR4_EL1, 3, 0, 0, 7, 4) +DEF(CCSIDR_EL1, 3, 1, 0, 0, 0) +DEF(CLIDR_EL1, 3, 1, 0, 0, 1) +DEF(CCSIDR2_EL1, 3, 1, 0, 0, 2) +DEF(GMID_EL1, 3, 1, 0, 0, 4) +DEF(SMIDR_EL1, 3, 1, 0, 0, 6) +DEF(CTR_EL0, 3, 3, 0, 0, 1) +DEF(DCZID_EL0, 3, 3, 0, 0, 7) +DEF(MIDR_EL1, 3, 0, 0, 0, 0) +DEF(REVIDR_EL1, 3, 0, 0, 0, 6) +DEF(AIDR_EL1, 3, 1, 0, 0, 7) \ No newline at end of file diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 3de2e1a3c30b037ed9109ab09d9488224a4f478c..0764f96879e0fd9d462e7b9e5008b174f4f64c84 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -1815,6 +1815,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); ARMCPU *cpu = ARM_CPU(dev); + ARMISARegisters *isar = &cpu->isar; ARMCPUClass *acc = ARM_CPU_GET_CLASS(dev); CPUARMState *env = &cpu->env; int pagebits; @@ -1838,6 +1839,18 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) return; } + /* + * If we failed to retrieve the set of writable ID registers for the "host" + * CPU model, report it here. No error if the interface for discovering + * writable ID registers is not available. + * In case we did get the set of writable ID registers, set the features to + * the configured values here and perform some sanity checks. + */ + if (cpu->writable_id_regs == WRITABLE_ID_REGS_FAILED) { + error_setg(errp, "Failed to discover writable id registers"); + return; + } + #ifndef CONFIG_USER_ONLY /* The NVIC and M-profile CPU are two halves of a single piece of * hardware; trying to use one without the other is a command line @@ -1960,21 +1973,16 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) } if (!cpu->has_vfp) { - uint64_t t; uint32_t u; - t = cpu->isar.id_aa64isar1; - t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 0); - cpu->isar.id_aa64isar1 = t; + FIELD_DP64_IDREG(isar, ID_AA64ISAR1, JSCVT, 0); - t = cpu->isar.id_aa64pfr0; - t = FIELD_DP64(t, ID_AA64PFR0, FP, 0xf); - cpu->isar.id_aa64pfr0 = t; + FIELD_DP64_IDREG(isar, ID_AA64PFR0, FP, 0xf); - u = cpu->isar.id_isar6; + u = GET_IDREG(isar, ID_ISAR6); u = FIELD_DP32(u, ID_ISAR6, JSCVT, 0); u = FIELD_DP32(u, ID_ISAR6, BF16, 0); - cpu->isar.id_isar6 = u; + SET_IDREG(isar, ID_ISAR6, u); u = cpu->isar.mvfr0; u = FIELD_DP32(u, MVFR0, FPSP, 0); @@ -2008,7 +2016,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) unset_feature(env, ARM_FEATURE_NEON); - t = cpu->isar.id_aa64isar0; + t = GET_IDREG(isar, ID_AA64ISAR0); t = FIELD_DP64(t, ID_AA64ISAR0, AES, 0); t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 0); t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 0); @@ -2016,32 +2024,30 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) t = FIELD_DP64(t, ID_AA64ISAR0, SM3, 0); t = FIELD_DP64(t, ID_AA64ISAR0, SM4, 0); t = FIELD_DP64(t, ID_AA64ISAR0, DP, 0); - cpu->isar.id_aa64isar0 = t; + SET_IDREG(isar, ID_AA64ISAR0, t); - t = cpu->isar.id_aa64isar1; + t = GET_IDREG(isar, ID_AA64ISAR1); t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 0); t = FIELD_DP64(t, ID_AA64ISAR1, BF16, 0); t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 0); - cpu->isar.id_aa64isar1 = t; + SET_IDREG(isar, ID_AA64ISAR1, t); - t = cpu->isar.id_aa64pfr0; - t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 0xf); - cpu->isar.id_aa64pfr0 = t; + FIELD_DP64_IDREG(isar, ID_AA64PFR0, ADVSIMD, 0xf); - u = cpu->isar.id_isar5; + u = GET_IDREG(isar, ID_ISAR5); u = FIELD_DP32(u, ID_ISAR5, AES, 0); u = FIELD_DP32(u, ID_ISAR5, SHA1, 0); u = FIELD_DP32(u, ID_ISAR5, SHA2, 0); u = FIELD_DP32(u, ID_ISAR5, RDM, 0); u = FIELD_DP32(u, ID_ISAR5, VCMA, 0); - cpu->isar.id_isar5 = u; + SET_IDREG(isar, ID_ISAR5, u); - u = cpu->isar.id_isar6; + u = GET_IDREG(isar, ID_ISAR6); u = FIELD_DP32(u, ID_ISAR6, DP, 0); u = FIELD_DP32(u, ID_ISAR6, FHM, 0); u = FIELD_DP32(u, ID_ISAR6, BF16, 0); u = FIELD_DP32(u, ID_ISAR6, I8MM, 0); - cpu->isar.id_isar6 = u; + SET_IDREG(isar, ID_ISAR6, u); if (!arm_feature(env, ARM_FEATURE_M)) { u = cpu->isar.mvfr1; @@ -2058,16 +2064,11 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) } if (!cpu->has_neon && !cpu->has_vfp) { - uint64_t t; uint32_t u; - t = cpu->isar.id_aa64isar0; - t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 0); - cpu->isar.id_aa64isar0 = t; + FIELD_DP64_IDREG(isar, ID_AA64ISAR0, FHM, 0); - t = cpu->isar.id_aa64isar1; - t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 0); - cpu->isar.id_aa64isar1 = t; + FIELD_DP64_IDREG(isar, ID_AA64ISAR1, FRINTTS, 0); u = cpu->isar.mvfr0; u = FIELD_DP32(u, MVFR0, SIMDREG, 0); @@ -2084,19 +2085,17 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) unset_feature(env, ARM_FEATURE_THUMB_DSP); - u = cpu->isar.id_isar1; - u = FIELD_DP32(u, ID_ISAR1, EXTEND, 1); - cpu->isar.id_isar1 = u; + FIELD_DP32_IDREG(isar, ID_ISAR1, EXTEND, 1); - u = cpu->isar.id_isar2; + u = GET_IDREG(isar, ID_ISAR2); u = FIELD_DP32(u, ID_ISAR2, MULTU, 1); u = FIELD_DP32(u, ID_ISAR2, MULTS, 1); - cpu->isar.id_isar2 = u; + SET_IDREG(isar, ID_ISAR2, u); - u = cpu->isar.id_isar3; + u = GET_IDREG(isar, ID_ISAR3); u = FIELD_DP32(u, ID_ISAR3, SIMD, 1); u = FIELD_DP32(u, ID_ISAR3, SATURATE, 0); - cpu->isar.id_isar3 = u; + SET_IDREG(isar, ID_ISAR3, u); } @@ -2163,14 +2162,12 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) * Disable the security extension feature bits in the processor * feature registers as well. */ - cpu->isar.id_pfr1 = FIELD_DP32(cpu->isar.id_pfr1, ID_PFR1, SECURITY, 0); - cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, COPSDBG, 0); - cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0, - ID_AA64PFR0, EL3, 0); + FIELD_DP32_IDREG(isar, ID_PFR1, SECURITY, 0); + FIELD_DP32_IDREG(isar, ID_DFR0, COPSDBG, 0); + FIELD_DP64_IDREG(isar, ID_AA64PFR0, EL3, 0); /* Disable the realm management extension, which requires EL3. */ - cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0, - ID_AA64PFR0, RME, 0); + FIELD_DP64_IDREG(isar, ID_AA64PFR0, RME, 0); } if (!cpu->has_el2) { @@ -2193,9 +2190,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) cpu); #endif } else { - cpu->isar.id_aa64dfr0 = - FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, PMUVER, 0); - cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, PERFMON, 0); + FIELD_DP64_IDREG(isar, ID_AA64DFR0, PMUVER, 0); + FIELD_DP32_IDREG(isar, ID_DFR0, PERFMON, 0); cpu->pmceid0 = 0; cpu->pmceid1 = 0; } @@ -2205,10 +2201,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) * Disable the hypervisor feature bits in the processor feature * registers if we don't have EL2. */ - cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0, - ID_AA64PFR0, EL2, 0); - cpu->isar.id_pfr1 = FIELD_DP32(cpu->isar.id_pfr1, - ID_PFR1, VIRTUALIZATION, 0); + FIELD_DP64_IDREG(isar, ID_AA64PFR0, EL2, 0); + FIELD_DP32_IDREG(isar, ID_PFR1, VIRTUALIZATION, 0); } if (cpu_isar_feature(aa64_mte, cpu)) { @@ -2227,8 +2221,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) * This matches Cortex-A710 BROADCASTMTE input being LOW. */ if (cpu->tag_memory == NULL) { - cpu->isar.id_aa64pfr1 = - FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 1); + FIELD_DP64_IDREG(isar, ID_AA64PFR1, MTE, 1); } #endif } @@ -2241,35 +2234,24 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) * try to access the non-existent system registers for them. */ /* FEAT_SPE (Statistical Profiling Extension) */ - cpu->isar.id_aa64dfr0 = - FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, PMSVER, 0); + FIELD_DP64_IDREG(isar, ID_AA64DFR0, PMSVER, 0); /* FEAT_TRBE (Trace Buffer Extension) */ - cpu->isar.id_aa64dfr0 = - FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, TRACEBUFFER, 0); + FIELD_DP64_IDREG(isar, ID_AA64DFR0, TRACEBUFFER, 0); /* FEAT_TRF (Self-hosted Trace Extension) */ - cpu->isar.id_aa64dfr0 = - FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, TRACEFILT, 0); - cpu->isar.id_dfr0 = - FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, TRACEFILT, 0); + FIELD_DP64_IDREG(isar, ID_AA64DFR0, TRACEFILT, 0); + FIELD_DP32_IDREG(isar, ID_DFR0, TRACEFILT, 0); /* Trace Macrocell system register access */ - cpu->isar.id_aa64dfr0 = - FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, TRACEVER, 0); - cpu->isar.id_dfr0 = - FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, COPTRC, 0); + FIELD_DP64_IDREG(isar, ID_AA64DFR0, TRACEVER, 0); + FIELD_DP32_IDREG(isar, ID_DFR0, COPTRC, 0); /* Memory mapped trace */ - cpu->isar.id_dfr0 = - FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, MMAPTRC, 0); + FIELD_DP32_IDREG(isar, ID_DFR0, MMAPTRC, 0); /* FEAT_AMU (Activity Monitors Extension) */ - cpu->isar.id_aa64pfr0 = - FIELD_DP64(cpu->isar.id_aa64pfr0, ID_AA64PFR0, AMU, 0); - cpu->isar.id_pfr0 = - FIELD_DP32(cpu->isar.id_pfr0, ID_PFR0, AMU, 0); + FIELD_DP64_IDREG(isar, ID_AA64PFR0, AMU, 0); + FIELD_DP32_IDREG(isar, ID_PFR0, AMU, 0); /* FEAT_MPAM (Memory Partitioning and Monitoring Extension) */ - cpu->isar.id_aa64pfr0 = - FIELD_DP64(cpu->isar.id_aa64pfr0, ID_AA64PFR0, MPAM, 0); + FIELD_DP64_IDREG(isar, ID_AA64PFR0, MPAM, 0); /* FEAT_NV (Nested Virtualization) */ - cpu->isar.id_aa64mmfr2 = - FIELD_DP64(cpu->isar.id_aa64mmfr2, ID_AA64MMFR2, NV, 0); + FIELD_DP64_IDREG(isar, ID_AA64MMFR2, NV, 0); } /* MPU can be configured out of a PMSA CPU either by setting has-mpu diff --git a/target/arm/cpu.h b/target/arm/cpu.h index cb546a93e2e2091854fff98666ae6f44578a4553..7f174ca319a47e4ef2e82962ce0766c8cc0d482c 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -26,6 +26,7 @@ #include "cpu-qom.h" #include "exec/cpu-defs.h" #include "qapi/qapi-types-common.h" +#include "target/arm/cpu-sysregs.h" /* ARM processors have a weak memory model */ #define TCG_GUEST_DEFAULT_MO (0) @@ -845,6 +846,91 @@ typedef struct { uint32_t map, init, supported; } ARMVQMap; +typedef enum ARMIdRegsState { + WRITABLE_ID_REGS_UNKNOWN, + WRITABLE_ID_REGS_NOT_DISCOVERABLE, + WRITABLE_ID_REGS_FAILED, + WRITABLE_ID_REGS_AVAIL, +} ARMIdRegsState; + +/* + * The following structures are for the purpose of mapping the output of + * KVM_ARM_GET_REG_WRITABLE_MASKS that also may cover id registers we do + * not support in QEMU + * ID registers in op0==3, op1=={0,1,3}, crn=0, crm=={0-7}, op2=={0-7}, + * as used by the KVM_ARM_GET_REG_WRITABLE_MASKS ioctl call. + */ +#define NR_ID_REGS (3 * 8 * 8) + +typedef struct IdRegMap { + uint64_t regs[NR_ID_REGS]; +} IdRegMap; + +#define ARM_FEATURE_ID_RANGE_IDX(op0, op1, crn, crm, op2) \ + ({ \ + __u64 __op1 = (op1) & 3; \ + __op1 -= (__op1 == 3); \ + (__op1 << 6 | ((crm) & 7) << 3 | (op2)); \ + }) + +/* REG is ID_XXX */ +#define FIELD_DP64_IDREG(ISAR, REG, FIELD, VALUE) \ + ({ \ + ARMISARegisters *i_ = (ISAR); \ + uint64_t regval = i_->idregs[REG ## _EL1_IDX]; \ + regval = FIELD_DP64(regval, REG, FIELD, VALUE); \ + i_->idregs[REG ## _EL1_IDX] = regval; \ + }) + +#define FIELD_DP32_IDREG(ISAR, REG, FIELD, VALUE) \ + ({ \ + ARMISARegisters *i_ = (ISAR); \ + uint64_t regval = i_->idregs[REG ## _EL1_IDX]; \ + regval = FIELD_DP32(regval, REG, FIELD, VALUE); \ + i_->idregs[REG ## _EL1_IDX] = regval; \ + }) + +#define FIELD_EX64_IDREG(ISAR, REG, FIELD) \ + ({ \ + const ARMISARegisters *i_ = (ISAR); \ + FIELD_EX64(i_->idregs[REG ## _EL1_IDX], REG, FIELD); \ + }) + +#define FIELD_EX32_IDREG(ISAR, REG, FIELD) \ + ({ \ + const ARMISARegisters *i_ = (ISAR); \ + FIELD_EX32(i_->idregs[REG ## _EL1_IDX], REG, FIELD); \ + }) + +#define FIELD_SEX64_IDREG(ISAR, REG, FIELD) \ + ({ \ + const ARMISARegisters *i_ = (ISAR); \ + FIELD_SEX64(i_->idregs[REG ## _EL1_IDX], REG, FIELD); \ + }) + +#define SET_IDREG(ISAR, REG, VALUE) \ + ({ \ + ARMISARegisters *i_ = (ISAR); \ + i_->idregs[REG ## _EL1_IDX] = VALUE; \ + }) + +#define GET_IDREG(ISAR, REG) \ + ({ \ + const ARMISARegisters *i_ = (ISAR); \ + i_->idregs[REG ## _EL1_IDX]; \ + }) + +#define GET_IDREG_WRITABLE(MAP, REG) \ + ({ \ + const IdRegMap *m_ = (MAP); \ + int index = ARM_FEATURE_ID_RANGE_IDX((sysreg >> 14) & 0x0000c000, \ + (sysreg >> 11) & 0x00003800, \ + (sysreg >> 7) & 0x00000780, \ + (sysreg >> 3) & 0x00000078, \ + sysreg & 0x00000007); \ + m_->regs[index]; \ + }) + /** * ARMCPU: * @env: #CPUARMState @@ -987,6 +1073,15 @@ struct ArchCPU { */ bool host_cpu_probe_failed; + /* + * state of writable id regs query used to report an error, if any, + * on KVM custom vcpu model realize + */ + ARMIdRegsState writable_id_regs; + + /* ID reg writable bitmask (KVM only) */ + IdRegMap *writable_map; + /* Specify the number of cores in this CPU cluster. Used for the L2CTLR * register. */ @@ -1010,43 +1105,14 @@ struct ArchCPU { * field by reading the value from the KVM vCPU. */ struct ARMISARegisters { - uint32_t id_isar0; - uint32_t id_isar1; - uint32_t id_isar2; - uint32_t id_isar3; - uint32_t id_isar4; - uint32_t id_isar5; - uint32_t id_isar6; - uint32_t id_mmfr0; - uint32_t id_mmfr1; - uint32_t id_mmfr2; - uint32_t id_mmfr3; - uint32_t id_mmfr4; - uint32_t id_mmfr5; - uint32_t id_pfr0; - uint32_t id_pfr1; - uint32_t id_pfr2; uint32_t mvfr0; uint32_t mvfr1; uint32_t mvfr2; - uint32_t id_dfr0; - uint32_t id_dfr1; uint32_t dbgdidr; uint32_t dbgdevid; uint32_t dbgdevid1; - uint64_t id_aa64isar0; - uint64_t id_aa64isar1; - uint64_t id_aa64isar2; - uint64_t id_aa64pfr0; - uint64_t id_aa64pfr1; - uint64_t id_aa64mmfr0; - uint64_t id_aa64mmfr1; - uint64_t id_aa64mmfr2; - uint64_t id_aa64dfr0; - uint64_t id_aa64dfr1; - uint64_t id_aa64zfr0; - uint64_t id_aa64smfr0; uint64_t reset_pmcr_el0; + uint64_t idregs[NUM_ID_IDX]; } isar; uint64_t midr; uint32_t revidr; diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 4cf8446b6e32fad93f971ab3ced54133502e8248..593bfea2998da70431b86574ef09b0f3abb90baf 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -34,6 +34,29 @@ #include "internals.h" #include "cpu-features.h" #include "cpregs.h" +#include "cpu-custom.h" + +/* convert between _IDX and SYS_ */ +#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) \ + [NAME##_IDX] = SYS_##NAME, + +const uint32_t id_register_sysreg[NUM_ID_IDX] = { +#include "cpu-sysregs.h.inc" +}; + +#undef DEF +#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) \ + case SYS_##NAME: return NAME##_IDX; + +int get_sysreg_idx(ARMSysRegs sysreg) +{ + switch (sysreg) { +#include "cpu-sysregs.h.inc" + } + return -1; +} + +#undef DEF void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) { @@ -114,7 +137,7 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) * SVE is disabled and so are all vector lengths. Good. * Disable all SVE extensions as well. */ - cpu->isar.id_aa64zfr0 = 0; + SET_IDREG(&cpu->isar, ID_AA64ZFR0, 0); return; } @@ -288,16 +311,13 @@ static bool cpu_arm_get_sve(Object *obj, Error **errp) static void cpu_arm_set_sve(Object *obj, bool value, Error **errp) { ARMCPU *cpu = ARM_CPU(obj); - uint64_t t; if (value && kvm_enabled() && !kvm_arm_sve_supported()) { error_setg(errp, "'sve' feature not supported by KVM on this host"); return; } - t = cpu->isar.id_aa64pfr0; - t = FIELD_DP64(t, ID_AA64PFR0, SVE, value); - cpu->isar.id_aa64pfr0 = t; + FIELD_DP64_IDREG(&cpu->isar, ID_AA64PFR0, SVE, value); } void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp) @@ -309,7 +329,7 @@ void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp) if (vq_map == 0) { if (!cpu_isar_feature(aa64_sme, cpu)) { - cpu->isar.id_aa64smfr0 = 0; + SET_IDREG(&cpu->isar, ID_AA64SMFR0, 0); return; } @@ -348,11 +368,8 @@ static bool cpu_arm_get_sme(Object *obj, Error **errp) static void cpu_arm_set_sme(Object *obj, bool value, Error **errp) { ARMCPU *cpu = ARM_CPU(obj); - uint64_t t; - t = cpu->isar.id_aa64pfr1; - t = FIELD_DP64(t, ID_AA64PFR1, SME, value); - cpu->isar.id_aa64pfr1 = t; + FIELD_DP64_IDREG(&cpu->isar, ID_AA64PFR1, SME, value); } static bool cpu_arm_get_sme_fa64(Object *obj, Error **errp) @@ -365,11 +382,8 @@ static bool cpu_arm_get_sme_fa64(Object *obj, Error **errp) static void cpu_arm_set_sme_fa64(Object *obj, bool value, Error **errp) { ARMCPU *cpu = ARM_CPU(obj); - uint64_t t; - t = cpu->isar.id_aa64smfr0; - t = FIELD_DP64(t, ID_AA64SMFR0, FA64, value); - cpu->isar.id_aa64smfr0 = t; + FIELD_DP64_IDREG(&cpu->isar, ID_AA64SMFR0, FA64, value); } #ifdef CONFIG_USER_ONLY @@ -480,6 +494,7 @@ void aarch64_add_sme_properties(Object *obj) void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) { ARMPauthFeature features = cpu_isar_feature(pauth_feature, cpu); + ARMISARegisters *isar = &cpu->isar; uint64_t isar1, isar2; /* @@ -490,13 +505,13 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) * * Begin by disabling all fields. */ - isar1 = cpu->isar.id_aa64isar1; + isar1 = GET_IDREG(isar, ID_AA64ISAR1); isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, APA, 0); isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPA, 0); isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, API, 0); isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPI, 0); - isar2 = cpu->isar.id_aa64isar2; + isar2 = GET_IDREG(isar, ID_AA64ISAR2); isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, APA3, 0); isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, GPA3, 0); @@ -543,8 +558,8 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) } } - cpu->isar.id_aa64isar1 = isar1; - cpu->isar.id_aa64isar2 = isar2; + SET_IDREG(isar, ID_AA64ISAR1, isar1); + SET_IDREG(isar, ID_AA64ISAR2, isar2); } static Property arm_cpu_pauth_property = @@ -585,7 +600,7 @@ static void arm_cpu_get_num_wps(Object *obj, Visitor *v, const char *name, val = cpu->num_wps; if (val == 0) { - val = FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) + 1; + val = FIELD_EX64_IDREG(&cpu->isar, ID_AA64DFR0, BRPS) + 1; } visit_type_uint8(v, name, &val, errp); @@ -596,7 +611,7 @@ static void arm_cpu_set_num_wps(Object *obj, Visitor *v, const char *name, { uint8_t val; ARMCPU *cpu = ARM_CPU(obj); - uint8_t max_wps = FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) + 1; + uint8_t max_wps = FIELD_EX64_IDREG(&cpu->isar, ID_AA64DFR0, WRPS) + 1; if (!visit_type_uint8(v, name, &val, errp)) { return; @@ -618,7 +633,7 @@ static void arm_cpu_get_num_bps(Object *obj, Visitor *v, const char *name, val = cpu->num_bps; if (val == 0) { - val = FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) + 1; + val = FIELD_EX64_IDREG(&cpu->isar, ID_AA64DFR0, BRPS) + 1; } visit_type_uint8(v, name, &val, errp); @@ -629,7 +644,7 @@ static void arm_cpu_set_num_bps(Object *obj, Visitor *v, const char *name, { uint8_t val; ARMCPU *cpu = ARM_CPU(obj); - uint8_t max_bps = FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) + 1; + uint8_t max_bps = FIELD_EX64_IDREG(&cpu->isar, ID_AA64DFR0, BRPS) + 1; if (!visit_type_uint8(v, name, &val, errp)) { return; @@ -705,17 +720,18 @@ void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp) return; } - t = cpu->isar.id_aa64mmfr0; + t = GET_IDREG(&cpu->isar, ID_AA64MMFR0); t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16, 2); /* 16k pages w/ LPA2 */ t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4, 1); /* 4k pages w/ LPA2 */ t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16_2, 3); /* 16k stage2 w/ LPA2 */ t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 3); /* 4k stage2 w/ LPA2 */ - cpu->isar.id_aa64mmfr0 = t; + SET_IDREG(&cpu->isar, ID_AA64MMFR0, t); } static void aarch64_a57_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; cpu->dtb_compatible = "arm,cortex-a57"; set_feature(&cpu->env, ARM_FEATURE_V8); @@ -735,25 +751,25 @@ static void aarch64_a57_initfn(Object *obj) cpu->isar.mvfr2 = 0x00000043; cpu->ctr = 0x8444c004; cpu->reset_sctlr = 0x00c50838; - cpu->isar.id_pfr0 = 0x00000131; - cpu->isar.id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x03010066; + SET_IDREG(isar, ID_PFR0, 0x00000131); + SET_IDREG(isar, ID_PFR1, 0x00011011); + SET_IDREG(isar, ID_DFR0, 0x03010066); cpu->id_afr0 = 0x00000000; - cpu->isar.id_mmfr0 = 0x10101105; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01260000; - cpu->isar.id_mmfr3 = 0x02102211; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x00011142; - cpu->isar.id_isar5 = 0x00011121; - cpu->isar.id_isar6 = 0; - cpu->isar.id_aa64pfr0 = 0x00002222; - cpu->isar.id_aa64dfr0 = 0x10305106; - cpu->isar.id_aa64isar0 = 0x00011120; - cpu->isar.id_aa64mmfr0 = 0x00001124; + SET_IDREG(isar, ID_MMFR0, 0x10101105); + SET_IDREG(isar, ID_MMFR1, 0x40000000); + SET_IDREG(isar, ID_MMFR2, 0x01260000); + SET_IDREG(isar, ID_MMFR3, 0x02102211); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); + SET_IDREG(isar, ID_ISAR3, 0x01112131); + SET_IDREG(isar, ID_ISAR4, 0x00011142); + SET_IDREG(isar, ID_ISAR5, 0x00011121); + SET_IDREG(isar, ID_ISAR6, 0); + SET_IDREG(isar, ID_AA64PFR0, 0x00002222); + SET_IDREG(isar, ID_AA64DFR0, 0x10305106); + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); + SET_IDREG(isar, ID_AA64MMFR0, 0x00001124); cpu->isar.dbgdidr = 0x3516d000; cpu->isar.dbgdevid = 0x01110f13; cpu->isar.dbgdevid1 = 0x2; @@ -773,6 +789,7 @@ static void aarch64_a57_initfn(Object *obj) static void aarch64_a53_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; cpu->dtb_compatible = "arm,cortex-a53"; set_feature(&cpu->env, ARM_FEATURE_V8); @@ -792,25 +809,25 @@ static void aarch64_a53_initfn(Object *obj) cpu->isar.mvfr2 = 0x00000043; cpu->ctr = 0x84448004; /* L1Ip = VIPT */ cpu->reset_sctlr = 0x00c50838; - cpu->isar.id_pfr0 = 0x00000131; - cpu->isar.id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x03010066; + SET_IDREG(isar, ID_PFR0, 0x00000131); + SET_IDREG(isar, ID_PFR1, 0x00011011); + SET_IDREG(isar, ID_DFR0, 0x03010066); cpu->id_afr0 = 0x00000000; - cpu->isar.id_mmfr0 = 0x10101105; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01260000; - cpu->isar.id_mmfr3 = 0x02102211; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x00011142; - cpu->isar.id_isar5 = 0x00011121; - cpu->isar.id_isar6 = 0; - cpu->isar.id_aa64pfr0 = 0x00002222; - cpu->isar.id_aa64dfr0 = 0x10305106; - cpu->isar.id_aa64isar0 = 0x00011120; - cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */ + SET_IDREG(isar, ID_MMFR0, 0x10101105); + SET_IDREG(isar, ID_MMFR1, 0x40000000); + SET_IDREG(isar, ID_MMFR2, 0x01260000); + SET_IDREG(isar, ID_MMFR3, 0x02102211); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); + SET_IDREG(isar, ID_ISAR3, 0x01112131); + SET_IDREG(isar, ID_ISAR4, 0x00011142); + SET_IDREG(isar, ID_ISAR5, 0x00011121); + SET_IDREG(isar, ID_ISAR6, 0); + SET_IDREG(isar, ID_AA64PFR0, 0x00002222); + SET_IDREG(isar, ID_AA64DFR0, 0x10305106); + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); + SET_IDREG(isar, ID_AA64MMFR0, 0x00001122); /* 40 bit physical addr */ cpu->isar.dbgdidr = 0x3516d000; cpu->isar.dbgdevid = 0x00110f13; cpu->isar.dbgdevid1 = 0x1; @@ -849,24 +866,24 @@ static void aarch64_a72_initfn(Object *obj) cpu->isar.mvfr2 = 0x00000043; cpu->ctr = 0x8444c004; cpu->reset_sctlr = 0x00c50838; - cpu->isar.id_pfr0 = 0x00000131; - cpu->isar.id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x03010066; + SET_IDREG(&cpu->isar, ID_PFR0, 0x00000131); + SET_IDREG(&cpu->isar, ID_PFR1, 0x00011011); + SET_IDREG(&cpu->isar, ID_DFR0, 0x03010066); cpu->id_afr0 = 0x00000000; - cpu->isar.id_mmfr0 = 0x10201105; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01260000; - cpu->isar.id_mmfr3 = 0x02102211; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x00011142; - cpu->isar.id_isar5 = 0x00011121; - cpu->isar.id_aa64pfr0 = 0x00002222; - cpu->isar.id_aa64dfr0 = 0x10305106; - cpu->isar.id_aa64isar0 = 0x00011120; - cpu->isar.id_aa64mmfr0 = 0x00001124; + SET_IDREG(&cpu->isar, ID_MMFR0, 0x10201105); + SET_IDREG(&cpu->isar, ID_MMFR1, 0x40000000); + SET_IDREG(&cpu->isar, ID_MMFR2, 0x01260000); + SET_IDREG(&cpu->isar, ID_MMFR3, 0x02102211); + SET_IDREG(&cpu->isar, ID_ISAR0, 0x02101110); + SET_IDREG(&cpu->isar, ID_ISAR1, 0x13112111); + SET_IDREG(&cpu->isar, ID_ISAR2, 0x21232042); + SET_IDREG(&cpu->isar, ID_ISAR3, 0x01112131); + SET_IDREG(&cpu->isar, ID_ISAR4, 0x00011142); + SET_IDREG(&cpu->isar, ID_ISAR5, 0x00011121); + SET_IDREG(&cpu->isar, ID_AA64PFR0, 0x00002222); + SET_IDREG(&cpu->isar, ID_AA64DFR0, 0x10305106); + SET_IDREG(&cpu->isar, ID_AA64ISAR0, 0x00011120); + SET_IDREG(&cpu->isar, ID_AA64MMFR0, 0x00001124); cpu->isar.dbgdidr = 0x3516d000; cpu->clidr = 0x0a200023; cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ @@ -892,22 +909,42 @@ static void aarch64_kunpeng_920_initfn(Object *obj) cpu->midr = 0x480fd010; cpu->ctr = 0x84448004; - cpu->isar.id_aa64pfr0 = 0x11001111; - cpu->isar.id_aa64dfr0 = 0x110305408; - cpu->isar.id_aa64isar0 = 0x10211120; - cpu->isar.id_aa64mmfr0 = 0x101125; + SET_IDREG(&cpu->isar, ID_AA64PFR0, 0x11001111); + SET_IDREG(&cpu->isar, ID_AA64DFR0, 0x110305408); + SET_IDREG(&cpu->isar, ID_AA64ISAR0, 0x10211120); + SET_IDREG(&cpu->isar, ID_AA64MMFR0, 0x101125); } static void aarch64_host_initfn(Object *obj) { #if defined(CONFIG_KVM) ARMCPU *cpu = ARM_CPU(obj); - kvm_arm_set_cpu_features_from_host(cpu); + bool expose_id_regs = true; + int ret; + + cpu->writable_map = g_malloc(sizeof(IdRegMap)); + + /* discover via KVM_ARM_GET_REG_WRITABLE_MASKS */ + ret = kvm_arm_get_writable_id_regs(cpu, cpu->writable_map); + if (ret == -ENOSYS) { + /* legacy: continue without writable id regs */ + expose_id_regs = false; + } else if (ret) { + /* function will have marked an error */ + return; + } + + kvm_arm_set_cpu_features_from_host(cpu, expose_id_regs); if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { aarch64_add_sve_properties(obj); aarch64_add_pauth_properties(obj); aarch64_add_kvm_writable_properties(obj); } + if (expose_id_regs) { + /* generate SYSREG properties according to writable masks */ + kvm_arm_expose_idreg_properties(cpu, arm64_id_regs); + } + #elif defined(CONFIG_HVF) ARMCPU *cpu = ARM_CPU(obj); hvf_arm_set_cpu_features_from_host(cpu); @@ -1055,6 +1092,7 @@ static void aarch64_cpu_register_types(void) { size_t i; + initialize_cpu_sysreg_properties(); type_register_static(&aarch64_cpu_type_info); for (i = 0; i < ARRAY_SIZE(aarch64_cpus); ++i) { diff --git a/target/arm/helper.c b/target/arm/helper.c index 0370a739e3bbfcf3b04c548190764dd5ac3c4637..f50baa0f7b9c812617aeebce52afd34e465a0475 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -7268,7 +7268,7 @@ static void define_pmu_regs(ARMCPU *cpu) static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri) { ARMCPU *cpu = env_archcpu(env); - uint64_t pfr1 = cpu->isar.id_pfr1; + uint64_t pfr1 = GET_IDREG(&cpu->isar, ID_PFR1); if (env->gicv3state) { pfr1 |= 1 << 28; @@ -7279,7 +7279,7 @@ static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri) static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri) { ARMCPU *cpu = env_archcpu(env); - uint64_t pfr0 = cpu->isar.id_aa64pfr0; + uint64_t pfr0 = GET_IDREG(&cpu->isar, ID_AA64PFR0); if (env->gicv3state) { pfr0 |= 1 << 24; @@ -8202,6 +8202,8 @@ void register_cp_regs_for_features(ARMCPU *cpu) { /* Register all the coprocessor registers based on feature bits */ CPUARMState *env = &cpu->env; + ARMISARegisters *isar = &cpu->isar; + if (arm_feature(env, ARM_FEATURE_M)) { /* M profile has no coprocessor registers */ return; @@ -8223,7 +8225,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_pfr0 }, + .resetvalue = GET_IDREG(isar, ID_PFR0)}, /* * ID_PFR1 is not a plain ARM_CP_CONST because we don't know * the value of the GIC field until after we define these regs. @@ -8234,7 +8236,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) .accessfn = access_aa32_tid3, #ifdef CONFIG_USER_ONLY .type = ARM_CP_CONST, - .resetvalue = cpu->isar.id_pfr1, + .resetvalue = GET_IDREG(isar, ID_PFR1), #else .type = ARM_CP_NO_RAW, .accessfn = access_aa32_tid3, @@ -8246,7 +8248,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_dfr0 }, + .resetvalue = GET_IDREG(isar, ID_DFR0)}, { .name = "ID_AFR0", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 3, .access = PL1_R, .type = ARM_CP_CONST, @@ -8256,62 +8258,62 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 4, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_mmfr0 }, + .resetvalue = GET_IDREG(isar, ID_MMFR0)}, { .name = "ID_MMFR1", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 5, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_mmfr1 }, + .resetvalue = GET_IDREG(isar, ID_MMFR1)}, { .name = "ID_MMFR2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 6, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_mmfr2 }, + .resetvalue = GET_IDREG(isar, ID_MMFR2)}, { .name = "ID_MMFR3", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 7, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_mmfr3 }, + .resetvalue = GET_IDREG(isar, ID_MMFR3)}, { .name = "ID_ISAR0", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_isar0 }, + .resetvalue = GET_IDREG(isar, ID_ISAR0)}, { .name = "ID_ISAR1", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 1, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_isar1 }, + .resetvalue = GET_IDREG(isar, ID_ISAR1)}, { .name = "ID_ISAR2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_isar2 }, + .resetvalue = GET_IDREG(isar, ID_ISAR2)}, { .name = "ID_ISAR3", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 3, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_isar3 }, + .resetvalue = GET_IDREG(isar, ID_ISAR3) }, { .name = "ID_ISAR4", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 4, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_isar4 }, + .resetvalue = GET_IDREG(isar, ID_ISAR4) }, { .name = "ID_ISAR5", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 5, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_isar5 }, + .resetvalue = GET_IDREG(isar, ID_ISAR5) }, { .name = "ID_MMFR4", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 6, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_mmfr4 }, + .resetvalue = GET_IDREG(isar, ID_MMFR4)}, { .name = "ID_ISAR6", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 7, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_isar6 }, + .resetvalue = GET_IDREG(isar, ID_ISAR6) }, }; define_arm_cp_regs(cpu, v6_idregs); define_arm_cp_regs(cpu, v6_cp_reginfo); @@ -8366,7 +8368,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) .access = PL1_R, #ifdef CONFIG_USER_ONLY .type = ARM_CP_CONST, - .resetvalue = cpu->isar.id_aa64pfr0 + .resetvalue = GET_IDREG(isar, ID_AA64PFR0) #else .type = ARM_CP_NO_RAW, .accessfn = access_aa64_tid3, @@ -8378,7 +8380,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 1, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64pfr1}, + .resetvalue = GET_IDREG(isar, ID_AA64PFR1)}, { .name = "ID_AA64PFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST, @@ -8393,12 +8395,12 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 4, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64zfr0 }, + .resetvalue = GET_IDREG(isar, ID_AA64ZFR0)}, { .name = "ID_AA64SMFR0_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 5, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64smfr0 }, + .resetvalue = GET_IDREG(isar, ID_AA64SMFR0)}, { .name = "ID_AA64PFR6_EL1_RESERVED", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 6, .access = PL1_R, .type = ARM_CP_CONST, @@ -8413,12 +8415,12 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 0, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64dfr0 }, + .resetvalue = GET_IDREG(isar, ID_AA64DFR0) }, { .name = "ID_AA64DFR1_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 1, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64dfr1 }, + .resetvalue = GET_IDREG(isar, ID_AA64DFR1) }, { .name = "ID_AA64DFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST, @@ -8453,17 +8455,17 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 0, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64isar0 }, + .resetvalue = GET_IDREG(isar, ID_AA64ISAR0)}, { .name = "ID_AA64ISAR1_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 1, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64isar1 }, + .resetvalue = GET_IDREG(isar, ID_AA64ISAR1)}, { .name = "ID_AA64ISAR2_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64isar2 }, + .resetvalue = GET_IDREG(isar, ID_AA64ISAR2)}, { .name = "ID_AA64ISAR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 3, .access = PL1_R, .type = ARM_CP_CONST, @@ -8493,17 +8495,17 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64mmfr0 }, + .resetvalue = GET_IDREG(isar, ID_AA64MMFR0)}, { .name = "ID_AA64MMFR1_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 1, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64mmfr1 }, + .resetvalue = GET_IDREG(isar, ID_AA64MMFR1) }, { .name = "ID_AA64MMFR2_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64mmfr2 }, + .resetvalue = GET_IDREG(isar, ID_AA64MMFR2) }, { .name = "ID_AA64MMFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 3, .access = PL1_R, .type = ARM_CP_CONST, @@ -8580,17 +8582,17 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 4, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_pfr2 }, + .resetvalue = GET_IDREG(isar, ID_PFR2)}, { .name = "ID_DFR1", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 5, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_dfr1 }, + .resetvalue = GET_IDREG(isar, ID_DFR1)}, { .name = "ID_MMFR5", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 6, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_mmfr5 }, + .resetvalue = GET_IDREG(isar, ID_MMFR5)}, { .name = "RES_0_C0_C3_7", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 7, .access = PL1_R, .type = ARM_CP_CONST, diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index d7cc00a084b413fc6df6c7322b37a542b3780be1..13d72b0bd6c933940b8dd4b5b34d872e3426b2d3 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -18,6 +18,7 @@ #include "sysemu/hw_accel.h" #include "hvf_arm.h" #include "cpregs.h" +#include "cpu-sysregs.h" #include @@ -841,16 +842,16 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) int reg; uint64_t *val; } regs[] = { - { HV_SYS_REG_ID_AA64PFR0_EL1, &host_isar.id_aa64pfr0 }, - { HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.id_aa64pfr1 }, - { HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.id_aa64dfr0 }, - { HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.id_aa64dfr1 }, - { HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.id_aa64isar0 }, - { HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.id_aa64isar1 }, + { HV_SYS_REG_ID_AA64PFR0_EL1, &host_isar.idregs[ID_AA64PFR0_EL1_IDX] }, + { HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.idregs[ID_AA64PFR1_EL1_IDX] }, + { HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.idregs[ID_AA64DFR0_EL1_IDX] }, + { HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.idregs[ID_AA64DFR1_EL1_IDX] }, + { HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.idregs[ID_AA64ISAR0_EL1_IDX] }, + { HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.idregs[ID_AA64ISAR1_EL1_IDX] }, /* Add ID_AA64ISAR2_EL1 here when HVF supports it */ - { HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.id_aa64mmfr0 }, - { HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.id_aa64mmfr1 }, - { HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.id_aa64mmfr2 }, + { HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.idregs[ID_AA64MMFR0_EL1_IDX] }, + { HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.idregs[ID_AA64MMFR1_EL1_IDX] }, + { HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.idregs[ID_AA64MMFR2_EL1_IDX] }, }; hv_vcpu_t fd; hv_return_t r = HV_SUCCESS; @@ -891,7 +892,7 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) ahcf->reset_sctlr |= 0x00800000; /* Make sure we don't advertise AArch32 support for EL0/EL1 */ - if ((host_isar.id_aa64pfr0 & 0xff) != 0x11) { + if ((GET_IDREG(&host_isar, ID_AA64PFR0) & 0xff) != 0x11) { return false; } @@ -986,7 +987,7 @@ int hvf_arch_init_vcpu(CPUState *cpu) /* We're limited to underlying hardware caps, override internal versions */ ret = hv_vcpu_get_sys_reg(cpu->accel->fd, HV_SYS_REG_ID_AA64MMFR0_EL1, - &arm_cpu->isar.id_aa64mmfr0); + &arm_cpu->isar.idregs[ID_AA64MMFR0_EL1_IDX]); assert_hvf_ok(ret); return 0; diff --git a/target/arm/internals.h b/target/arm/internals.h index efc58c714652abaa34501f431bc14d8798f2fea7..dc0c5d905140d42eaaee472dcb6525ffcd75c7d2 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -831,7 +831,7 @@ static inline bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx) static inline int arm_num_brps(ARMCPU *cpu) { if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { - return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) + 1; + return FIELD_EX64_IDREG(&cpu->isar, ID_AA64DFR0, BRPS) + 1; } else { return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, BRPS) + 1; } @@ -845,7 +845,7 @@ static inline int arm_num_brps(ARMCPU *cpu) static inline int arm_num_wrps(ARMCPU *cpu) { if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { - return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) + 1; + return FIELD_EX64_IDREG(&cpu->isar, ID_AA64DFR0, WRPS) + 1; } else { return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, WRPS) + 1; } @@ -859,7 +859,7 @@ static inline int arm_num_wrps(ARMCPU *cpu) static inline int arm_num_ctx_cmps(ARMCPU *cpu) { if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { - return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) + 1; + return FIELD_EX64_IDREG(&cpu->isar, ID_AA64DFR0, CTX_CMPS) + 1; } else { return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, CTX_CMPS) + 1; } diff --git a/target/arm/kvm-rme.c b/target/arm/kvm-rme.c index 26dda39df65f82f7dd74f8a1b0dadd54c9073352..43ff82542539057773f406ca3f31677d074ae219 100644 --- a/target/arm/kvm-rme.c +++ b/target/arm/kvm-rme.c @@ -267,8 +267,9 @@ static int rme_log_realm_create(Error **errp) params.flags |= REALM_PARAMS_FLAG_SVE; params.sve_vl = cpu->sve_max_vq - 1; } - params.num_bps = FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS); - params.num_wps = FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS); + + params.num_bps = FIELD_EX64_IDREG(&cpu->isar, ID_AA64DFR0, BRPS); + params.num_wps = FIELD_EX64_IDREG(&cpu->isar, ID_AA64DFR0, WRPS); switch (rme_guest->measurement_algo) { case RME_GUEST_MEASUREMENT_ALGORITHM_SHA256: diff --git a/target/arm/kvm.c b/target/arm/kvm.c index f45783a9dafe76c81e3411fcf35d7b455db3d1e4..96b0784b90fcc92008138d7b118b91647d0d8940 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -23,6 +23,8 @@ #include "sysemu/kvm_int.h" #include "kvm_arm.h" #include "cpu.h" +#include "cpu-custom.h" +#include "cpu-sysregs.h" #include "trace.h" #include "internals.h" #include "hw/pci/pci.h" @@ -35,6 +37,51 @@ #include "qapi/visitor.h" #include "qemu/log.h" +/* + * SMMCC KVM Vendor hypercall definitions. + * ToDo: Include using update-linux-headers.sh + */ +#define ARM_SMCCC_FAST_CALL _AC(1,U) +#define ARM_SMCCC_TYPE_SHIFT 31 + +#define ARM_SMCCC_SMC_32 0 +#define ARM_SMCCC_SMC_64 1 +#define ARM_SMCCC_CALL_CONV_SHIFT 30 + +#define ARM_SMCCC_OWNER_MASK 0x3F +#define ARM_SMCCC_OWNER_SHIFT 24 + +#define ARM_SMCCC_FUNC_MASK 0xFFFF + +#define ARM_SMCCC_OWNER_VENDOR_HYP 6 + + +#define ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_VER 64 +#define ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_CPUS 65 + +#define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \ + (((type) << ARM_SMCCC_TYPE_SHIFT) | \ + ((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \ + (((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \ + ((func_num) & ARM_SMCCC_FUNC_MASK)) + +#define ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_64, \ + ARM_SMCCC_OWNER_VENDOR_HYP, \ + ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_VER) + +#define ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_64, \ + ARM_SMCCC_OWNER_VENDOR_HYP, \ + ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_CPUS) + +#define SMCCC_RET_SUCCESS 0 +#define SMCCC_RET_NOT_SUPPORTED -1 +#define SMCCC_RET_NOT_REQUIRED -2 +#define SMCCC_RET_INVALID_PARAMETER -3 + const KVMCapabilityInfo kvm_arch_required_capabilities[] = { KVM_CAP_LAST_INFO }; @@ -42,6 +89,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = { static bool cap_has_mp_state; static bool cap_has_inject_serror_esr; static bool cap_has_inject_ext_dabt; +static int cap_writable_id_regs; static ARMHostCPUFeatures arm_host_cpu_features; @@ -171,13 +219,13 @@ void kvm_arm_destroy_scratch_host_vcpu(int *fdarray) } } -void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) +void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu, bool exhaustive) { CPUARMState *env = &cpu->env; if (!arm_host_cpu_features.dtb_compatible) { if (!kvm_enabled() || - !kvm_arm_get_host_cpu_features(&arm_host_cpu_features)) { + !kvm_arm_get_host_cpu_features(cpu, &arm_host_cpu_features, exhaustive)) { /* We can't report this error yet, so flag that we need to * in arm_cpu_realizefn(). */ @@ -193,6 +241,37 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) env->features = arm_host_cpu_features.features; } +int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap) +{ + struct reg_mask_range range = { + .range = 0, /* up to now only a single range is supported */ + .addr = (uint64_t)idregmap, + }; + int ret; + + if (!kvm_enabled()) { + cpu->writable_id_regs = WRITABLE_ID_REGS_NOT_DISCOVERABLE; + return -ENOSYS; + } + + cap_writable_id_regs = + kvm_check_extension(kvm_state, KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES); + + if (!cap_writable_id_regs || + !(cap_writable_id_regs & (1 << KVM_ARM_FEATURE_ID_RANGE))) { + cpu->writable_id_regs = WRITABLE_ID_REGS_NOT_DISCOVERABLE; + return -ENOSYS; + } + + ret = kvm_vm_ioctl(kvm_state, KVM_ARM_GET_REG_WRITABLE_MASKS, &range); + if (ret) { + cpu->writable_id_regs = WRITABLE_ID_REGS_FAILED; + return ret; + } + cpu->writable_id_regs = WRITABLE_ID_REGS_AVAIL; + return ret; +} + static bool kvm_no_adjvtime_get(Object *obj, Error **errp) { return !ARM_CPU(obj)->kvm_adjvtime; @@ -355,6 +434,16 @@ int kvm_arch_init(MachineState *ms, KVMState *s) if (ret) { error_report("Failed to enable RME: %s", strerror(-ret)); } + + if (kvm_arm_set_smccc_filter(ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID, + KVM_SMCCC_FILTER_FWD_TO_USER)) { + error_report("ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_VER fwd filter install failed"); + } + + if (kvm_arm_set_smccc_filter(ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID, + KVM_SMCCC_FILTER_FWD_TO_USER)) { + error_report("ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_CPUS fwd filter install failed"); + } return ret; } @@ -691,7 +780,7 @@ static void kvm_arm_configure_aa64dfr0(ARMCPU *cpu) return; } - newval = cpu->isar.id_aa64dfr0; + newval = GET_IDREG(&cpu->isar, ID_AA64DFR0); if (cpu->num_bps) { uint64_t ctx_cmps = FIELD_EX64(newval, ID_AA64DFR0, CTX_CMPS); @@ -761,6 +850,39 @@ static void kvm_arm_configure_vcpu_regs(ARMCPU *cpu) kvm_arm_configure_pmcr(cpu); } +void kvm_arm_writable_idregs_to_cpreg_list(ARMCPU *cpu) +{ + if (!cpu->writable_map) { + return; + } + for (int i = 0; i < NR_ID_REGS; i++) { + uint64_t writable_mask = cpu->writable_map->regs[i]; + uint64_t *cpreg; + + if (writable_mask) { + uint64_t previous, new; + int idx = kvm_idx_to_idregs_idx(i); + ARM64SysReg *sysregdesc; + uint32_t sysreg; + + if (idx == -1) { + /* sysreg writable, but we don't know it */ + continue; + } + sysregdesc = &arm64_id_regs[idx]; + sysreg = sysregdesc->sysreg; + cpreg = kvm_arm_get_cpreg_ptr(cpu, idregs_sysreg_to_kvm_reg(sysreg)); + previous = *cpreg; + new = cpu->isar.idregs[idx]; + if (previous != new) { + *cpreg = new; + trace_kvm_arm_writable_idregs_to_cpreg_list(sysregdesc->name, + previous, new); + } + } + } +} + void kvm_arm_reset_vcpu(ARMCPU *cpu) { int ret; @@ -1060,6 +1182,55 @@ void kvm_arm_vm_state_change(void *opaque, bool running, RunState state) } } +static bool arm_handle_smcc_kvm_vendor_hypercall(ARMCPU *cpu) +{ + MachineState *ms = MACHINE(qdev_get_machine()); + CPUARMState *env = &cpu->env; + uint64_t param[4]; + int idx; + int i; + + for (i = 0; i < 4; i++) { + /* + * All PSCI functions take explicit 32-bit or native int sized + * arguments so we can simply zero-extend all arguments regardless + * of which exact function we are about to call. + */ + param[i] = is_a64(env) ? env->xregs[i] : env->regs[i]; + } + + if (is_a64(env)) { + TargetImplCpu *target = ms->target_ipml_cpu; + + switch (param[0]) { + case ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID: + if (!ms->target_ipml_cpu_num) { + env->xregs[0] = SMCCC_RET_NOT_SUPPORTED; + break; + } + env->xregs[0] = SMCCC_RET_SUCCESS; + env->xregs[1] = PSCI_VERSION(1, 0); + env->xregs[2] = ms->target_ipml_cpu_num; + break; + case ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID: + idx = param[1]; + if (idx >= ms->target_ipml_cpu_num) { + env->xregs[0] = SMCCC_RET_INVALID_PARAMETER; + break; + } + env->xregs[0] = SMCCC_RET_SUCCESS; + env->xregs[1] = target[idx].midr; + env->xregs[2] = target[idx].revidr; + break; + default: + return false; + } + } else { + return false; + } + return true; +} + /** * kvm_arm_handle_dabt_nisv: * @cs: CPUState @@ -1122,9 +1293,12 @@ static int kvm_arm_handle_hypercall(CPUState *cs, struct kvm_run *run) env->exception.syndrome = syn_aa64_hvc(0); } env->exception.target_el = 1; - qemu_mutex_lock_iothread(); - arm_cpu_do_interrupt(cs); - qemu_mutex_unlock_iothread(); + + if (!arm_handle_smcc_kvm_vendor_hypercall(cpu)) { + qemu_mutex_lock_iothread(); + arm_cpu_do_interrupt(cs); + qemu_mutex_unlock_iothread(); + } /* * For PSCI, exit the kvm_run loop and process the work. Especially @@ -1149,7 +1323,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) run->arm_nisv.fault_ipa); break; case KVM_EXIT_HYPERCALL: - ret = kvm_arm_handle_hypercall(cs, run); + ret = kvm_arm_handle_hypercall(cs, run); break; default: qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n", diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index 6a8aad0f066ae17a8b6b5e37ff15c69c3759ebcf..406c054ace632153010b5b7a85a345b80e99416e 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -17,6 +17,7 @@ #include #include "qapi/error.h" +#include "qapi/visitor.h" #include "cpu.h" #include "qemu/timer.h" #include "qemu/error-report.h" @@ -26,11 +27,13 @@ #include "sysemu/runstate.h" #include "sysemu/kvm.h" #include "sysemu/kvm_int.h" +#include "trace.h" #include "kvm_arm.h" #include "internals.h" #include "cpu-features.h" #include "hw/acpi/acpi.h" #include "hw/acpi/ghes.h" +#include "cpu-custom.h" static bool have_guest_debug; @@ -251,7 +254,229 @@ static bool kvm_arm_pauth_supported(void) kvm_check_extension(kvm_state, KVM_CAP_ARM_PTRAUTH_GENERIC)); } -bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) +uint64_t idregs_sysreg_to_kvm_reg(ARMSysRegs sysreg) +{ + return ARM64_SYS_REG((sysreg & CP_REG_ARM64_SYSREG_OP0_MASK) >> CP_REG_ARM64_SYSREG_OP0_SHIFT, + (sysreg & CP_REG_ARM64_SYSREG_OP1_MASK) >> CP_REG_ARM64_SYSREG_OP1_SHIFT, + (sysreg & CP_REG_ARM64_SYSREG_CRN_MASK) >> CP_REG_ARM64_SYSREG_CRN_SHIFT, + (sysreg & CP_REG_ARM64_SYSREG_CRM_MASK) >> CP_REG_ARM64_SYSREG_CRM_SHIFT, + (sysreg & CP_REG_ARM64_SYSREG_OP2_MASK) >> CP_REG_ARM64_SYSREG_OP2_SHIFT); +} + +/* read a sysreg value and store it in the idregs */ +static int get_host_cpu_reg(int fd, ARMHostCPUFeatures *ahcf, ARMIDRegisterIdx index) +{ + uint64_t *reg; + int ret; + + reg = &ahcf->isar.idregs[index]; + ret = read_sys_reg64(fd, reg, + idregs_sysreg_to_kvm_reg(id_register_sysreg[index])); + return ret; +} + +int kvm_idx_to_idregs_idx(int kidx) +{ + int op1, crm, op2; + ARMSysRegs sysreg; + + op1 = kidx / 64; + if (op1 == 2) { + op1 = 3; + } + crm = (kidx % 64) / 8; + op2 = kidx % 8; + sysreg = ENCODE_ID_REG(3, op1, 0, crm, op2); + return get_sysreg_idx(sysreg); +} + +int idregs_idx_to_kvm_idx(ARMIDRegisterIdx idx) +{ + ARMSysRegs sysreg = id_register_sysreg[idx]; + + return KVM_ARM_FEATURE_ID_RANGE_IDX((sysreg & CP_REG_ARM64_SYSREG_OP0_MASK) >> CP_REG_ARM64_SYSREG_OP0_SHIFT, + (sysreg & CP_REG_ARM64_SYSREG_OP1_MASK) >> CP_REG_ARM64_SYSREG_OP1_SHIFT, + (sysreg & CP_REG_ARM64_SYSREG_CRN_MASK) >> CP_REG_ARM64_SYSREG_CRN_SHIFT, + (sysreg & CP_REG_ARM64_SYSREG_CRM_MASK) >> CP_REG_ARM64_SYSREG_CRM_SHIFT, + (sysreg & CP_REG_ARM64_SYSREG_OP2_MASK) >> CP_REG_ARM64_SYSREG_OP2_SHIFT); +} + + +/* + * get_host_cpu_idregs: Read all the writable ID reg host values + * + * Need to be called once the writable mask has been populated + * Note we may want to read all the known id regs but some of them are not + * writable and return an error, hence the choice of reading only those which + * are writable. Those are also readable! + */ +static int get_host_cpu_idregs(ARMCPU *cpu, int fd, ARMHostCPUFeatures *ahcf) +{ + int err = 0; + int i; + + for (i = 0; i < NUM_ID_IDX; i++) { + ARM64SysReg *sysregdesc = &arm64_id_regs[i]; + ARMSysRegs sysreg = sysregdesc->sysreg; + uint64_t writable_mask = cpu->writable_map->regs[idregs_idx_to_kvm_idx(i)]; + uint64_t *reg; + int ret; + + if (!writable_mask) { + continue; + } + + reg = &ahcf->isar.idregs[i]; + ret = read_sys_reg64(fd, reg, idregs_sysreg_to_kvm_reg(sysreg)); + trace_get_host_cpu_idregs(sysregdesc->name, *reg); + if (ret) { + error_report("%s error reading value of host %s register (%m)", + __func__, sysregdesc->name); + + err = ret; + } + } + return err; +} + + +static ARM64SysRegField *get_field(int i, ARM64SysReg *reg) +{ + GList *l; + + for (l = reg->fields; l; l = l->next) { + ARM64SysRegField *field = (ARM64SysRegField *)l->data; + + if (i >= field->lower && i <= field->upper) { + return field; + } + } + return NULL; +} + +static void set_sysreg_prop(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + ARM64SysRegField *field = (ARM64SysRegField *)opaque; + ARMCPU *cpu = ARM_CPU(obj); + uint64_t *idregs = cpu->isar.idregs; + uint64_t old, value, mask; + int lower = field->lower; + int upper = field->upper; + int length = upper - lower + 1; + int index = field->index; + + if (!visit_type_uint64(v, name, &value, errp)) { + return; + } + + if (length < 64 && value > ((1 << length) - 1)) { + error_setg(errp, + "idreg %s set value (0x%lx) exceeds length of field (%d)!", + name, value, length); + return; + } + + mask = MAKE_64BIT_MASK(lower, length); + value = value << lower; + old = idregs[index]; + idregs[index] = old & ~mask; + idregs[index] |= value; + trace_set_sysreg_prop(name, old, mask, value, idregs[index]); +} + +static void get_sysreg_prop(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + ARM64SysRegField *field = (ARM64SysRegField *)opaque; + ARMCPU *cpu = ARM_CPU(obj); + uint64_t *idregs = cpu->isar.idregs; + uint64_t value, mask; + int lower = field->lower; + int upper = field->upper; + int length = upper - lower + 1; + int index = field->index; + + mask = MAKE_64BIT_MASK(lower, length); + value = (idregs[index] & mask) >> lower; + visit_type_uint64(v, name, &value, errp); + trace_get_sysreg_prop(name, value); +} + +/* + * decode_idreg_writemap: Generate props for writable fields + * + * @obj: CPU object + * @index: index of the sysreg + * @map: writable map for the sysreg + * @reg: description of the sysreg + */ +static int +decode_idreg_writemap(Object *obj, int index, uint64_t map, ARM64SysReg *reg) +{ + int i = ctz64(map); + int nb_sysreg_props = 0; + + while (map) { + + ARM64SysRegField *field = get_field(i, reg); + int lower, upper; + uint64_t mask; + char *prop_name; + + if (!field) { + /* the field cannot be matched to any know id named field */ + warn_report("%s bit %d of %s is writable but cannot be matched", + __func__, i, reg->name); + warn_report("%s is cpu-sysreg-properties.c up to date?", __func__); + map = map & ~BIT_ULL(i); + i = ctz64(map); + continue; + } + lower = field->lower; + upper = field->upper; + prop_name = g_strdup_printf("SYSREG_%s_%s", reg->name, field->name); + trace_decode_idreg_writemap(field->name, lower, upper, prop_name); + object_property_add(obj, prop_name, "uint64", + get_sysreg_prop, set_sysreg_prop, NULL, field); + nb_sysreg_props++; + + mask = MAKE_64BIT_MASK(lower, upper - lower + 1); + map = map & ~mask; + i = ctz64(map); + } + trace_nb_sysreg_props(reg->name, nb_sysreg_props); + return 0; +} + +/* analyze the writable mask and generate properties for writable fields */ +void kvm_arm_expose_idreg_properties(ARMCPU *cpu, ARM64SysReg *regs) +{ + int i, idx; + IdRegMap *map = cpu->writable_map; + Object *obj = OBJECT(cpu); + + for (i = 0; i < NR_ID_REGS; i++) { + uint64_t mask = map->regs[i]; + + if (mask) { + /* reg @i has some writable fields, decode them */ + idx = kvm_idx_to_idregs_idx(i); + if (idx < 0) { + /* no matching reg? */ + warn_report("%s: reg %d writable, but not in list of idregs?", + __func__, i); + } else { + decode_idreg_writemap(obj, i, mask, ®s[idx]); + } + } + } +} + +bool kvm_arm_get_host_cpu_features(ARMCPU *cpu, ARMHostCPUFeatures *ahcf, + bool exhaustive) { /* Identify the feature bits corresponding to the host CPU, and * fill out the ARMHostCPUClass fields accordingly. To do this @@ -310,9 +535,9 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) ahcf->target = init.target; ahcf->dtb_compatible = "arm,arm-v8"; + int fd = fdarray[2]; - err = read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr0, - ARM64_SYS_REG(3, 0, 0, 4, 0)); + err = get_host_cpu_reg(fd, ahcf, ID_AA64PFR0_EL1_IDX); if (unlikely(err < 0)) { /* * Before v4.15, the kernel only exposed a limited number of system @@ -330,29 +555,19 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) * ??? Either of these sounds like too much effort just * to work around running a modern host kernel. */ - ahcf->isar.id_aa64pfr0 = 0x00000011; /* EL1&0, AArch64 only */ + SET_IDREG(&ahcf->isar, ID_AA64PFR0, 0x00000011); /* EL1&0, AArch64 only */ err = 0; } else { - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr1, - ARM64_SYS_REG(3, 0, 0, 4, 1)); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64smfr0, - ARM64_SYS_REG(3, 0, 0, 4, 5)); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr0, - KVM_REG_ARM_ID_AA64DFR0_EL1); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr1, - ARM64_SYS_REG(3, 0, 0, 5, 1)); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar0, - ARM64_SYS_REG(3, 0, 0, 6, 0)); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar1, - ARM64_SYS_REG(3, 0, 0, 6, 1)); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar2, - ARM64_SYS_REG(3, 0, 0, 6, 2)); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr0, - ARM64_SYS_REG(3, 0, 0, 7, 0)); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1, - ARM64_SYS_REG(3, 0, 0, 7, 1)); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr2, - ARM64_SYS_REG(3, 0, 0, 7, 2)); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64PFR1_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64SMFR0_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64DFR0_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64DFR1_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64ISAR0_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64ISAR1_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64ISAR2_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64MMFR0_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64MMFR1_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64MMFR2_EL1_IDX); /* * Note that if AArch32 support is not present in the host, @@ -361,49 +576,36 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) * than skipping the reads and leaving 0, as we must avoid * considering the values in every case. */ - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr0, - ARM64_SYS_REG(3, 0, 0, 1, 0)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr1, - ARM64_SYS_REG(3, 0, 0, 1, 1)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0, - ARM64_SYS_REG(3, 0, 0, 1, 2)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0, - ARM64_SYS_REG(3, 0, 0, 1, 4)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1, - ARM64_SYS_REG(3, 0, 0, 1, 5)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2, - ARM64_SYS_REG(3, 0, 0, 1, 6)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3, - ARM64_SYS_REG(3, 0, 0, 1, 7)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0, - ARM64_SYS_REG(3, 0, 0, 2, 0)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1, - ARM64_SYS_REG(3, 0, 0, 2, 1)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar2, - ARM64_SYS_REG(3, 0, 0, 2, 2)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar3, - ARM64_SYS_REG(3, 0, 0, 2, 3)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar4, - ARM64_SYS_REG(3, 0, 0, 2, 4)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5, - ARM64_SYS_REG(3, 0, 0, 2, 5)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4, - ARM64_SYS_REG(3, 0, 0, 2, 6)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6, - ARM64_SYS_REG(3, 0, 0, 2, 7)); - - err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0, + err |= get_host_cpu_reg(fd, ahcf, ID_PFR0_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_PFR1_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_DFR0_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_MMFR0_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_MMFR1_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_MMFR2_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_MMFR3_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_ISAR0_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_ISAR1_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_ISAR2_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_ISAR3_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_ISAR4_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_ISAR5_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_ISAR6_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_MMFR4_EL1_IDX); + + err |= read_sys_reg32(fd, &ahcf->isar.mvfr0, ARM64_SYS_REG(3, 0, 0, 3, 0)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr1, + err |= read_sys_reg32(fd, &ahcf->isar.mvfr1, ARM64_SYS_REG(3, 0, 0, 3, 1)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr2, + err |= read_sys_reg32(fd, &ahcf->isar.mvfr2, ARM64_SYS_REG(3, 0, 0, 3, 2)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr2, - ARM64_SYS_REG(3, 0, 0, 3, 4)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr1, - ARM64_SYS_REG(3, 0, 0, 3, 5)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr5, - ARM64_SYS_REG(3, 0, 0, 3, 6)); + err |= get_host_cpu_reg(fd, ahcf, ID_PFR2_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_DFR1_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_MMFR5_EL1_IDX); + + /* Make sure writable ID reg values are read */ + if (exhaustive) { + err |= get_host_cpu_idregs(cpu, fd, ahcf); + } /* * DBGDIDR is a bit complicated because the kernel doesn't @@ -415,14 +617,14 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) * arch/arm64/kvm/sys_regs.c:trap_dbgidr() does. * We only do this if the CPU supports AArch32 at EL1. */ - if (FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL1) >= 2) { - int wrps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, WRPS); - int brps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, BRPS); + if (FIELD_EX32_IDREG(&ahcf->isar, ID_AA64PFR0, EL1) >= 2) { + int wrps = FIELD_EX64_IDREG(&ahcf->isar, ID_AA64DFR0, WRPS); + int brps = FIELD_EX64_IDREG(&ahcf->isar, ID_AA64DFR0, BRPS); int ctx_cmps = - FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS); + FIELD_EX64_IDREG(&ahcf->isar, ID_AA64DFR0, CTX_CMPS); int version = 6; /* ARMv8 debug architecture */ bool has_el3 = - !!FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL3); + !!FIELD_EX32_IDREG(&ahcf->isar, ID_AA64PFR0, EL3); uint32_t dbgdidr = 0; dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, WRPS, wrps); @@ -437,7 +639,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) if (pmu_supported) { /* PMCR_EL0 is only accessible if the vCPU has feature PMU_V3 */ - err |= read_sys_reg64(fdarray[2], &ahcf->isar.reset_pmcr_el0, + err |= read_sys_reg64(fd, &ahcf->isar.reset_pmcr_el0, KVM_REG_ARM_PMCR_EL0); } @@ -449,8 +651,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) * enabled SVE support, which resulted in an error rather than RAZ. * So only read the register if we set KVM_ARM_VCPU_SVE above. */ - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64zfr0, - ARM64_SYS_REG(3, 0, 0, 4, 4)); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64ZFR0_EL1_IDX); } } @@ -592,6 +793,14 @@ static int kvm_arm_sve_set_vls(CPUState *cs) return kvm_set_one_reg(cs, KVM_REG_ARM64_SVE_VLS, &vls[0]); } +static int kvm_arm_set_vend_hyp_bmap_2(ARMCPU *cpu) +{ + /* Set DISCOVER_IMPL_* hypercalls */ + uint64_t bmap_2 = MAKE_64BIT_MASK(0, 2); + + return kvm_set_one_reg(CPU(cpu), KVM_REG_ARM_VENDOR_HYP_BMAP_2, &bmap_2); +} + #define ARM_CPU_ID_MPIDR 3, 0, 0, 0, 5 int kvm_arch_init_vcpu(CPUState *cs) @@ -668,6 +877,7 @@ int kvm_arch_init_vcpu(CPUState *cs) } } + kvm_arm_set_vend_hyp_bmap_2(cpu); /* * KVM reports the exact PSCI version it is implementing via a * special sysreg. If it is present, use its contents to determine @@ -692,7 +902,16 @@ int kvm_arch_init_vcpu(CPUState *cs) /* Check whether user space can specify guest syndrome value */ kvm_arm_init_serror_injection(cs); - return kvm_arm_init_cpreg_list(cpu); + ret = kvm_arm_init_cpreg_list(cpu); + if (ret) { + return ret; + } + /* overwrite writable ID regs with their updated property values */ + kvm_arm_writable_idregs_to_cpreg_list(cpu); + + write_list_to_kvmstate(cpu, 3); + + return 0; } int kvm_arch_destroy_vcpu(CPUState *cs) diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h index 8e9b2039c4dcad02c88ba1b6807b0c83aadb4d4d..8c69957fbf0801c54517a4cb425d8d1cfa5b3a49 100644 --- a/target/arm/kvm_arm.h +++ b/target/arm/kvm_arm.h @@ -21,6 +21,12 @@ #define KVM_REG_ARM_ID_AA64DFR0_EL1 ARM64_SYS_REG(3, 0, 0, 5, 0) #define KVM_REG_ARM_PMCR_EL0 ARM64_SYS_REG(3, 3, 9, 12, 0) +#define MAX_TARGET_IMPL_CPUS 8 +typedef struct TargetImplCpu { + uint32_t midr; + uint32_t revidr; +} TargetImplCpu; + /** * kvm_arm_init_debug() - initialize guest debug capabilities * @s: KVMState @@ -237,14 +243,18 @@ typedef struct ARMHostCPUFeatures { /** * kvm_arm_get_host_cpu_features: + * @cpu: cpu object * @ahcf: ARMHostCPUClass to fill in - * + * @exhaustive: if true, all the feature ID regs are queried instead of + * a subset + * Probe the capabilities of the host kernel's preferred CPU and fill * in the ARMHostCPUClass struct accordingly. * * Returns true on success and false otherwise. */ -bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf); +bool kvm_arm_get_host_cpu_features(ARMCPU *cpu, ARMHostCPUFeatures *ahcf, + bool exhaustive); /** * kvm_arm_sve_get_vls: @@ -262,8 +272,12 @@ uint32_t kvm_arm_sve_get_vls(CPUState *cs); * * Set up the ARMCPU struct fields up to match the information probed * from the host CPU. + * + * @cpu: cpu object + * @exhaustive: if true, all the feature ID regs are queried instead of + * a subset */ -void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu); +void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu, bool exhaustive); /** * kvm_arm_add_vcpu_properties: @@ -274,6 +288,16 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu); */ void kvm_arm_add_vcpu_properties(Object *obj); +typedef struct ARM64SysReg ARM64SysReg; +/** + * kvm_arm_expose_idreg_properties: + * @cpu: The CPU object to generate the properties for + * @reg: registers from the host + * + * analyze the writable mask and generate properties for writable fields + */ +void kvm_arm_expose_idreg_properties(ARMCPU *cpu, ARM64SysReg *regs); + /** * @cs: CPUState * @feature: a KVM_ARM_VCPU_* feature @@ -461,6 +485,10 @@ void kvm_arm_rme_init_gpa_space(hwaddr highest_gpa, PCIBus *pci_bus); */ Object *kvm_arm_rme_get_measurement_log(void); +int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap); + +void kvm_arm_writable_idregs_to_cpreg_list(ARMCPU *cpu); + #else /* @@ -501,10 +529,20 @@ static inline Object *kvm_arm_rme_get_measurement_log(void) return NULL; } +static inline int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap) +{ + return -ENOSYS; +} + +void kvm_arm_writable_idregs_to_cpreg_list(ARMCPU *cpu) +{ + g_assert_not_reached(); +} /* * These functions should never actually be called without KVM support. */ -static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) +static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu, + bool exhaustive) { g_assert_not_reached(); } diff --git a/target/arm/meson.build b/target/arm/meson.build index 7973b35ccacf6097b528e2f501cfba416053c1d4..963ad9592b767ced177a23cf6daa990da6927454 100644 --- a/target/arm/meson.build +++ b/target/arm/meson.build @@ -15,6 +15,7 @@ arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c', 'kvm-tmm.c'), arm_ss.add(when: 'TARGET_AARCH64', if_true: files( 'cpu64.c', 'gdbstub64.c', + 'cpu-sysreg-properties.c', )) arm_system_ss = ss.source_set() diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 1762b058aecfc0e61e58a50160d0e2bef92787f4..0fe20ddea6e9bd6f88f28580c6b94efad4155203 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -100,7 +100,7 @@ unsigned int arm_pamax(ARMCPU *cpu) { if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { unsigned int parange = - FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE); + FIELD_EX64_IDREG(&cpu->isar, ID_AA64MMFR0, PARANGE); /* * id_aa64mmfr0 is a read-only register so values outside of the @@ -313,7 +313,7 @@ static bool granule_protection_check(CPUARMState *env, uint64_t paddress, * physical address size is invalid. */ pps = FIELD_EX64(gpccr, GPCCR, PPS); - if (pps > FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE)) { + if (pps > FIELD_EX64_IDREG(&cpu->isar, ID_AA64MMFR0, PARANGE)) { goto fault_walk; } pps = pamax_map[pps]; @@ -1651,7 +1651,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw, * ID_AA64MMFR0 is a read-only register so values outside of the * supported mappings can be considered an implementation error. */ - ps = FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE); + ps = FIELD_EX64_IDREG(&cpu->isar, ID_AA64MMFR0, PARANGE); ps = MIN(ps, param.ps); assert(ps < ARRAY_SIZE(pamax_map)); outputsize = pamax_map[ps]; diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c index d9e0e2a4ddff3f9f0616bf9001e7e96d2d9b1766..f58c20e81d2f350bc07d9ded12dd2671e3cf7087 100644 --- a/target/arm/tcg/cpu32.c +++ b/target/arm/tcg/cpu32.c @@ -26,18 +26,19 @@ void aa32_max_features(ARMCPU *cpu) { uint32_t t; + ARMISARegisters *isar = &cpu->isar; /* Add additional features supported by QEMU */ - t = cpu->isar.id_isar5; + t = GET_IDREG(isar, ID_ISAR5); t = FIELD_DP32(t, ID_ISAR5, AES, 2); /* FEAT_PMULL */ t = FIELD_DP32(t, ID_ISAR5, SHA1, 1); /* FEAT_SHA1 */ t = FIELD_DP32(t, ID_ISAR5, SHA2, 1); /* FEAT_SHA256 */ t = FIELD_DP32(t, ID_ISAR5, CRC32, 1); t = FIELD_DP32(t, ID_ISAR5, RDM, 1); /* FEAT_RDM */ t = FIELD_DP32(t, ID_ISAR5, VCMA, 1); /* FEAT_FCMA */ - cpu->isar.id_isar5 = t; + SET_IDREG(isar, ID_ISAR5, t); - t = cpu->isar.id_isar6; + t = GET_IDREG(isar, ID_ISAR6); t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1); /* FEAT_JSCVT */ t = FIELD_DP32(t, ID_ISAR6, DP, 1); /* Feat_DotProd */ t = FIELD_DP32(t, ID_ISAR6, FHM, 1); /* FEAT_FHM */ @@ -45,7 +46,7 @@ void aa32_max_features(ARMCPU *cpu) t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1); /* FEAT_SPECRES */ t = FIELD_DP32(t, ID_ISAR6, BF16, 1); /* FEAT_AA32BF16 */ t = FIELD_DP32(t, ID_ISAR6, I8MM, 1); /* FEAT_AA32I8MM */ - cpu->isar.id_isar6 = t; + SET_IDREG(isar, ID_ISAR6, t); t = cpu->isar.mvfr1; t = FIELD_DP32(t, MVFR1, FPHP, 3); /* FEAT_FP16 */ @@ -57,42 +58,36 @@ void aa32_max_features(ARMCPU *cpu) t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */ cpu->isar.mvfr2 = t; - t = cpu->isar.id_mmfr3; - t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* FEAT_PAN2 */ - cpu->isar.id_mmfr3 = t; + FIELD_DP32_IDREG(isar, ID_MMFR3, PAN, 2); /* FEAT_PAN2 */ - t = cpu->isar.id_mmfr4; + t = GET_IDREG(isar, ID_MMFR4); t = FIELD_DP32(t, ID_MMFR4, HPDS, 2); /* FEAT_HPDS2 */ t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */ t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* FEAT_TTCNP */ t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* FEAT_XNX */ t = FIELD_DP32(t, ID_MMFR4, EVT, 2); /* FEAT_EVT */ - cpu->isar.id_mmfr4 = t; + SET_IDREG(isar, ID_MMFR4, t); - t = cpu->isar.id_mmfr5; - t = FIELD_DP32(t, ID_MMFR5, ETS, 1); /* FEAT_ETS */ - cpu->isar.id_mmfr5 = t; + FIELD_DP32_IDREG(isar, ID_MMFR5, ETS, 1); /* FEAT_ETS */ - t = cpu->isar.id_pfr0; + t = GET_IDREG(isar, ID_PFR0); t = FIELD_DP32(t, ID_PFR0, CSV2, 2); /* FEAT_CVS2 */ t = FIELD_DP32(t, ID_PFR0, DIT, 1); /* FEAT_DIT */ t = FIELD_DP32(t, ID_PFR0, RAS, 1); /* FEAT_RAS */ - cpu->isar.id_pfr0 = t; + SET_IDREG(isar, ID_PFR0, t); - t = cpu->isar.id_pfr2; + t = GET_IDREG(isar, ID_PFR2); t = FIELD_DP32(t, ID_PFR2, CSV3, 1); /* FEAT_CSV3 */ t = FIELD_DP32(t, ID_PFR2, SSBS, 1); /* FEAT_SSBS */ - cpu->isar.id_pfr2 = t; + SET_IDREG(isar, ID_PFR2, t); - t = cpu->isar.id_dfr0; + t = GET_IDREG(isar, ID_DFR0); t = FIELD_DP32(t, ID_DFR0, COPDBG, 9); /* FEAT_Debugv8p4 */ t = FIELD_DP32(t, ID_DFR0, COPSDBG, 9); /* FEAT_Debugv8p4 */ t = FIELD_DP32(t, ID_DFR0, PERFMON, 6); /* FEAT_PMUv3p5 */ - cpu->isar.id_dfr0 = t; + SET_IDREG(isar, ID_DFR0, t); - t = cpu->isar.id_dfr1; - t = FIELD_DP32(t, ID_DFR1, HPMN0, 1); /* FEAT_HPMN0 */ - cpu->isar.id_dfr1 = t; + FIELD_DP32_IDREG(isar, ID_DFR1, HPMN0, 1); /* FEAT_HPMN0 */ } /* CPU models. These are not needed for the AArch64 linux-user build. */ @@ -141,7 +136,7 @@ static void arm926_initfn(Object *obj) * ARMv5 does not have the ID_ISAR registers, but we can still * set the field to indicate Jazelle support within QEMU. */ - cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1); + FIELD_DP32_IDREG(&cpu->isar, ID_ISAR1, JAZELLE, 1); /* * Similarly, we need to set MVFR0 fields to enable vfp and short vector * support even though ARMv5 doesn't have this register. @@ -183,7 +178,7 @@ static void arm1026_initfn(Object *obj) * ARMv5 does not have the ID_ISAR registers, but we can still * set the field to indicate Jazelle support within QEMU. */ - cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1); + FIELD_DP32_IDREG(&cpu->isar, ID_ISAR1, JAZELLE, 1); /* * Similarly, we need to set MVFR0 fields to enable vfp and short vector * support even though ARMv5 doesn't have this register. @@ -207,6 +202,7 @@ static void arm1026_initfn(Object *obj) static void arm1136_r2_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; /* * What qemu calls "arm1136_r2" is actually the 1136 r0p2, ie an * older core than plain "arm1136". In particular this does not @@ -227,24 +223,25 @@ static void arm1136_r2_initfn(Object *obj) cpu->isar.mvfr1 = 0x00000000; cpu->ctr = 0x1dd20d2; cpu->reset_sctlr = 0x00050078; - cpu->isar.id_pfr0 = 0x111; - cpu->isar.id_pfr1 = 0x1; - cpu->isar.id_dfr0 = 0x2; + SET_IDREG(isar, ID_PFR0, 0x111); + SET_IDREG(isar, ID_PFR1, 0x1); + SET_IDREG(isar, ID_DFR0, 0x2); cpu->id_afr0 = 0x3; - cpu->isar.id_mmfr0 = 0x01130003; - cpu->isar.id_mmfr1 = 0x10030302; - cpu->isar.id_mmfr2 = 0x01222110; - cpu->isar.id_isar0 = 0x00140011; - cpu->isar.id_isar1 = 0x12002111; - cpu->isar.id_isar2 = 0x11231111; - cpu->isar.id_isar3 = 0x01102131; - cpu->isar.id_isar4 = 0x141; + SET_IDREG(isar, ID_MMFR0, 0x01130003); + SET_IDREG(isar, ID_MMFR1, 0x10030302); + SET_IDREG(isar, ID_MMFR2, 0x01222110); + SET_IDREG(isar, ID_ISAR0, 0x00140011); + SET_IDREG(isar, ID_ISAR1, 0x12002111); + SET_IDREG(isar, ID_ISAR2, 0x11231111); + SET_IDREG(isar, ID_ISAR3, 0x01102131); + SET_IDREG(isar, ID_ISAR4, 0x141); cpu->reset_auxcr = 7; } static void arm1136_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; cpu->dtb_compatible = "arm,arm1136"; set_feature(&cpu->env, ARM_FEATURE_V6K); @@ -258,24 +255,25 @@ static void arm1136_initfn(Object *obj) cpu->isar.mvfr1 = 0x00000000; cpu->ctr = 0x1dd20d2; cpu->reset_sctlr = 0x00050078; - cpu->isar.id_pfr0 = 0x111; - cpu->isar.id_pfr1 = 0x1; - cpu->isar.id_dfr0 = 0x2; + SET_IDREG(isar, ID_PFR0, 0x111); + SET_IDREG(isar, ID_PFR1, 0x1); + SET_IDREG(isar, ID_DFR0, 0x2); cpu->id_afr0 = 0x3; - cpu->isar.id_mmfr0 = 0x01130003; - cpu->isar.id_mmfr1 = 0x10030302; - cpu->isar.id_mmfr2 = 0x01222110; - cpu->isar.id_isar0 = 0x00140011; - cpu->isar.id_isar1 = 0x12002111; - cpu->isar.id_isar2 = 0x11231111; - cpu->isar.id_isar3 = 0x01102131; - cpu->isar.id_isar4 = 0x141; + SET_IDREG(isar, ID_MMFR0, 0x01130003); + SET_IDREG(isar, ID_MMFR1, 0x10030302); + SET_IDREG(isar, ID_MMFR2, 0x01222110); + SET_IDREG(isar, ID_ISAR0, 0x00140011); + SET_IDREG(isar, ID_ISAR1, 0x12002111); + SET_IDREG(isar, ID_ISAR2, 0x11231111); + SET_IDREG(isar, ID_ISAR3, 0x01102131); + SET_IDREG(isar, ID_ISAR4, 0x141); cpu->reset_auxcr = 7; } static void arm1176_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; cpu->dtb_compatible = "arm,arm1176"; set_feature(&cpu->env, ARM_FEATURE_V6K); @@ -290,24 +288,25 @@ static void arm1176_initfn(Object *obj) cpu->isar.mvfr1 = 0x00000000; cpu->ctr = 0x1dd20d2; cpu->reset_sctlr = 0x00050078; - cpu->isar.id_pfr0 = 0x111; - cpu->isar.id_pfr1 = 0x11; - cpu->isar.id_dfr0 = 0x33; + SET_IDREG(isar, ID_PFR0, 0x111); + SET_IDREG(isar, ID_PFR1, 0x11); + SET_IDREG(isar, ID_DFR0, 0x33); cpu->id_afr0 = 0; - cpu->isar.id_mmfr0 = 0x01130003; - cpu->isar.id_mmfr1 = 0x10030302; - cpu->isar.id_mmfr2 = 0x01222100; - cpu->isar.id_isar0 = 0x0140011; - cpu->isar.id_isar1 = 0x12002111; - cpu->isar.id_isar2 = 0x11231121; - cpu->isar.id_isar3 = 0x01102131; - cpu->isar.id_isar4 = 0x01141; + SET_IDREG(isar, ID_MMFR0, 0x01130003); + SET_IDREG(isar, ID_MMFR1, 0x10030302); + SET_IDREG(isar, ID_MMFR2, 0x01222100); + SET_IDREG(isar, ID_ISAR0, 0x0140011); + SET_IDREG(isar, ID_ISAR1, 0x12002111); + SET_IDREG(isar, ID_ISAR2, 0x11231121); + SET_IDREG(isar, ID_ISAR3, 0x01102131); + SET_IDREG(isar, ID_ISAR4, 0x01141); cpu->reset_auxcr = 7; } static void arm11mpcore_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; cpu->dtb_compatible = "arm,arm11mpcore"; set_feature(&cpu->env, ARM_FEATURE_V6K); @@ -319,18 +318,18 @@ static void arm11mpcore_initfn(Object *obj) cpu->isar.mvfr0 = 0x11111111; cpu->isar.mvfr1 = 0x00000000; cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */ - cpu->isar.id_pfr0 = 0x111; - cpu->isar.id_pfr1 = 0x1; - cpu->isar.id_dfr0 = 0; + SET_IDREG(isar, ID_PFR0, 0x111); + SET_IDREG(isar, ID_PFR1, 0x1); + SET_IDREG(isar, ID_DFR0, 0); cpu->id_afr0 = 0x2; - cpu->isar.id_mmfr0 = 0x01100103; - cpu->isar.id_mmfr1 = 0x10020302; - cpu->isar.id_mmfr2 = 0x01222000; - cpu->isar.id_isar0 = 0x00100011; - cpu->isar.id_isar1 = 0x12002111; - cpu->isar.id_isar2 = 0x11221011; - cpu->isar.id_isar3 = 0x01102131; - cpu->isar.id_isar4 = 0x141; + SET_IDREG(isar, ID_MMFR0, 0x01100103); + SET_IDREG(isar, ID_MMFR1, 0x10020302); + SET_IDREG(isar, ID_MMFR2, 0x01222000); + SET_IDREG(isar, ID_ISAR0, 0x00100011); + SET_IDREG(isar, ID_ISAR1, 0x12002111); + SET_IDREG(isar, ID_ISAR2, 0x11221011); + SET_IDREG(isar, ID_ISAR3, 0x01102131); + SET_IDREG(isar, ID_ISAR4, 0x141); cpu->reset_auxcr = 1; } @@ -344,6 +343,7 @@ static const ARMCPRegInfo cortexa8_cp_reginfo[] = { static void cortex_a8_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; cpu->dtb_compatible = "arm,cortex-a8"; set_feature(&cpu->env, ARM_FEATURE_V7); @@ -358,19 +358,19 @@ static void cortex_a8_initfn(Object *obj) cpu->isar.mvfr1 = 0x00011111; cpu->ctr = 0x82048004; cpu->reset_sctlr = 0x00c50078; - cpu->isar.id_pfr0 = 0x1031; - cpu->isar.id_pfr1 = 0x11; - cpu->isar.id_dfr0 = 0x400; + SET_IDREG(isar, ID_PFR0, 0x1031); + SET_IDREG(isar, ID_PFR1, 0x11); + SET_IDREG(isar, ID_DFR0, 0x400); cpu->id_afr0 = 0; - cpu->isar.id_mmfr0 = 0x31100003; - cpu->isar.id_mmfr1 = 0x20000000; - cpu->isar.id_mmfr2 = 0x01202000; - cpu->isar.id_mmfr3 = 0x11; - cpu->isar.id_isar0 = 0x00101111; - cpu->isar.id_isar1 = 0x12112111; - cpu->isar.id_isar2 = 0x21232031; - cpu->isar.id_isar3 = 0x11112131; - cpu->isar.id_isar4 = 0x00111142; + SET_IDREG(isar, ID_MMFR0, 0x31100003); + SET_IDREG(isar, ID_MMFR1, 0x20000000); + SET_IDREG(isar, ID_MMFR2, 0x01202000); + SET_IDREG(isar, ID_MMFR3, 0x11); + SET_IDREG(isar, ID_ISAR0, 0x00101111); + SET_IDREG(isar, ID_ISAR1, 0x12112111); + SET_IDREG(isar, ID_ISAR2, 0x21232031); + SET_IDREG(isar, ID_ISAR3, 0x11112131); + SET_IDREG(isar, ID_ISAR4, 0x00111142); cpu->isar.dbgdidr = 0x15141000; cpu->clidr = (1 << 27) | (2 << 24) | 3; cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */ @@ -413,6 +413,7 @@ static const ARMCPRegInfo cortexa9_cp_reginfo[] = { static void cortex_a9_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; cpu->dtb_compatible = "arm,cortex-a9"; set_feature(&cpu->env, ARM_FEATURE_V7); @@ -433,19 +434,19 @@ static void cortex_a9_initfn(Object *obj) cpu->isar.mvfr1 = 0x01111111; cpu->ctr = 0x80038003; cpu->reset_sctlr = 0x00c50078; - cpu->isar.id_pfr0 = 0x1031; - cpu->isar.id_pfr1 = 0x11; - cpu->isar.id_dfr0 = 0x000; + SET_IDREG(isar, ID_PFR0, 0x1031); + SET_IDREG(isar, ID_PFR1, 0x11); + SET_IDREG(isar, ID_DFR0, 0x000); cpu->id_afr0 = 0; - cpu->isar.id_mmfr0 = 0x00100103; - cpu->isar.id_mmfr1 = 0x20000000; - cpu->isar.id_mmfr2 = 0x01230000; - cpu->isar.id_mmfr3 = 0x00002111; - cpu->isar.id_isar0 = 0x00101111; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232041; - cpu->isar.id_isar3 = 0x11112131; - cpu->isar.id_isar4 = 0x00111142; + SET_IDREG(isar, ID_MMFR0, 0x00100103); + SET_IDREG(isar, ID_MMFR1, 0x20000000); + SET_IDREG(isar, ID_MMFR2, 0x01230000); + SET_IDREG(isar, ID_MMFR3, 0x00002111); + SET_IDREG(isar, ID_ISAR0, 0x00101111); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232041); + SET_IDREG(isar, ID_ISAR3, 0x11112131); + SET_IDREG(isar, ID_ISAR4, 0x00111142); cpu->isar.dbgdidr = 0x35141000; cpu->clidr = (1 << 27) | (1 << 24) | 3; cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */ @@ -480,6 +481,7 @@ static const ARMCPRegInfo cortexa15_cp_reginfo[] = { static void cortex_a7_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; cpu->dtb_compatible = "arm,cortex-a7"; set_feature(&cpu->env, ARM_FEATURE_V7VE); @@ -497,23 +499,23 @@ static void cortex_a7_initfn(Object *obj) cpu->isar.mvfr1 = 0x11111111; cpu->ctr = 0x84448003; cpu->reset_sctlr = 0x00c50078; - cpu->isar.id_pfr0 = 0x00001131; - cpu->isar.id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x02010555; + SET_IDREG(isar, ID_PFR0, 0x00001131); + SET_IDREG(isar, ID_PFR1, 0x00011011); + SET_IDREG(isar, ID_DFR0, 0x02010555); cpu->id_afr0 = 0x00000000; - cpu->isar.id_mmfr0 = 0x10101105; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01240000; - cpu->isar.id_mmfr3 = 0x02102211; + SET_IDREG(isar, ID_MMFR0, 0x10101105); + SET_IDREG(isar, ID_MMFR1, 0x40000000); + SET_IDREG(isar, ID_MMFR2, 0x01240000); + SET_IDREG(isar, ID_MMFR3, 0x02102211); /* * a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but * table 4-41 gives 0x02101110, which includes the arm div insns. */ - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232041; - cpu->isar.id_isar3 = 0x11112131; - cpu->isar.id_isar4 = 0x10011142; + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232041); + SET_IDREG(isar, ID_ISAR3, 0x11112131); + SET_IDREG(isar, ID_ISAR4, 0x10011142); cpu->isar.dbgdidr = 0x3515f005; cpu->isar.dbgdevid = 0x01110f13; cpu->isar.dbgdevid1 = 0x1; @@ -528,6 +530,7 @@ static void cortex_a7_initfn(Object *obj) static void cortex_a15_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; cpu->dtb_compatible = "arm,cortex-a15"; set_feature(&cpu->env, ARM_FEATURE_V7VE); @@ -547,19 +550,19 @@ static void cortex_a15_initfn(Object *obj) cpu->isar.mvfr1 = 0x11111111; cpu->ctr = 0x8444c004; cpu->reset_sctlr = 0x00c50078; - cpu->isar.id_pfr0 = 0x00001131; - cpu->isar.id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x02010555; + SET_IDREG(isar, ID_PFR0, 0x00001131); + SET_IDREG(isar, ID_PFR1, 0x00011011); + SET_IDREG(isar, ID_DFR0, 0x02010555); cpu->id_afr0 = 0x00000000; - cpu->isar.id_mmfr0 = 0x10201105; - cpu->isar.id_mmfr1 = 0x20000000; - cpu->isar.id_mmfr2 = 0x01240000; - cpu->isar.id_mmfr3 = 0x02102211; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232041; - cpu->isar.id_isar3 = 0x11112131; - cpu->isar.id_isar4 = 0x10011142; + SET_IDREG(isar, ID_MMFR0, 0x10201105); + SET_IDREG(isar, ID_MMFR1, 0x20000000); + SET_IDREG(isar, ID_MMFR2, 0x01240000); + SET_IDREG(isar, ID_MMFR3, 0x02102211); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232041); + SET_IDREG(isar, ID_ISAR3, 0x11112131); + SET_IDREG(isar, ID_ISAR4, 0x10011142); cpu->isar.dbgdidr = 0x3515f021; cpu->isar.dbgdevid = 0x01110f13; cpu->isar.dbgdevid1 = 0x0; @@ -574,6 +577,8 @@ static void cortex_a15_initfn(Object *obj) static void cortex_m0_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; + set_feature(&cpu->env, ARM_FEATURE_V6); set_feature(&cpu->env, ARM_FEATURE_M); @@ -587,51 +592,54 @@ static void cortex_m0_initfn(Object *obj) * by looking at ID register fields. We use the same values as * for the M3. */ - cpu->isar.id_pfr0 = 0x00000030; - cpu->isar.id_pfr1 = 0x00000200; - cpu->isar.id_dfr0 = 0x00100000; + SET_IDREG(&cpu->isar, ID_PFR0, 0x00000030); + SET_IDREG(&cpu->isar, ID_PFR1, 0x00000200); + SET_IDREG(&cpu->isar, ID_DFR0, 0x00100000); cpu->id_afr0 = 0x00000000; - cpu->isar.id_mmfr0 = 0x00000030; - cpu->isar.id_mmfr1 = 0x00000000; - cpu->isar.id_mmfr2 = 0x00000000; - cpu->isar.id_mmfr3 = 0x00000000; - cpu->isar.id_isar0 = 0x01141110; - cpu->isar.id_isar1 = 0x02111000; - cpu->isar.id_isar2 = 0x21112231; - cpu->isar.id_isar3 = 0x01111110; - cpu->isar.id_isar4 = 0x01310102; - cpu->isar.id_isar5 = 0x00000000; - cpu->isar.id_isar6 = 0x00000000; + SET_IDREG(&cpu->isar, ID_MMFR0, 0x00000030); + SET_IDREG(&cpu->isar, ID_MMFR1, 0x00000000); + SET_IDREG(&cpu->isar, ID_MMFR2, 0x00000000); + SET_IDREG(&cpu->isar, ID_MMFR3, 0x00000000); + SET_IDREG(isar, ID_ISAR0, 0x01141110); + SET_IDREG(isar, ID_ISAR1, 0x02111000); + SET_IDREG(isar, ID_ISAR2, 0x21112231); + SET_IDREG(isar, ID_ISAR3, 0x01111110); + SET_IDREG(isar, ID_ISAR4, 0x01310102); + SET_IDREG(isar, ID_ISAR5, 0); + SET_IDREG(isar, ID_ISAR6, 0); } static void cortex_m3_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; + set_feature(&cpu->env, ARM_FEATURE_V7); set_feature(&cpu->env, ARM_FEATURE_M); set_feature(&cpu->env, ARM_FEATURE_M_MAIN); cpu->midr = 0x410fc231; cpu->pmsav7_dregion = 8; - cpu->isar.id_pfr0 = 0x00000030; - cpu->isar.id_pfr1 = 0x00000200; - cpu->isar.id_dfr0 = 0x00100000; + SET_IDREG(&cpu->isar, ID_PFR0, 0x00000030); + SET_IDREG(&cpu->isar, ID_PFR1, 0x00000200); + SET_IDREG(&cpu->isar, ID_DFR0, 0x00100000); cpu->id_afr0 = 0x00000000; - cpu->isar.id_mmfr0 = 0x00000030; - cpu->isar.id_mmfr1 = 0x00000000; - cpu->isar.id_mmfr2 = 0x00000000; - cpu->isar.id_mmfr3 = 0x00000000; - cpu->isar.id_isar0 = 0x01141110; - cpu->isar.id_isar1 = 0x02111000; - cpu->isar.id_isar2 = 0x21112231; - cpu->isar.id_isar3 = 0x01111110; - cpu->isar.id_isar4 = 0x01310102; - cpu->isar.id_isar5 = 0x00000000; - cpu->isar.id_isar6 = 0x00000000; + SET_IDREG(&cpu->isar, ID_MMFR0, 0x00000030); + SET_IDREG(&cpu->isar, ID_MMFR1, 0x00000000); + SET_IDREG(&cpu->isar, ID_MMFR2, 0x00000000); + SET_IDREG(&cpu->isar, ID_MMFR3, 0x00000000); + SET_IDREG(isar, ID_ISAR0, 0x01141110); + SET_IDREG(isar, ID_ISAR1, 0x02111000); + SET_IDREG(isar, ID_ISAR2, 0x21112231); + SET_IDREG(isar, ID_ISAR3, 0x01111110); + SET_IDREG(isar, ID_ISAR4, 0x01310102); + SET_IDREG(isar, ID_ISAR5, 0); + SET_IDREG(isar, ID_ISAR6, 0); } static void cortex_m4_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; set_feature(&cpu->env, ARM_FEATURE_V7); set_feature(&cpu->env, ARM_FEATURE_M); @@ -642,26 +650,27 @@ static void cortex_m4_initfn(Object *obj) cpu->isar.mvfr0 = 0x10110021; cpu->isar.mvfr1 = 0x11000011; cpu->isar.mvfr2 = 0x00000000; - cpu->isar.id_pfr0 = 0x00000030; - cpu->isar.id_pfr1 = 0x00000200; - cpu->isar.id_dfr0 = 0x00100000; + SET_IDREG(&cpu->isar, ID_PFR0, 0x00000030); + SET_IDREG(&cpu->isar, ID_PFR1, 0x00000200); + SET_IDREG(&cpu->isar, ID_DFR0, 0x00100000); cpu->id_afr0 = 0x00000000; - cpu->isar.id_mmfr0 = 0x00000030; - cpu->isar.id_mmfr1 = 0x00000000; - cpu->isar.id_mmfr2 = 0x00000000; - cpu->isar.id_mmfr3 = 0x00000000; - cpu->isar.id_isar0 = 0x01141110; - cpu->isar.id_isar1 = 0x02111000; - cpu->isar.id_isar2 = 0x21112231; - cpu->isar.id_isar3 = 0x01111110; - cpu->isar.id_isar4 = 0x01310102; - cpu->isar.id_isar5 = 0x00000000; - cpu->isar.id_isar6 = 0x00000000; + SET_IDREG(&cpu->isar, ID_MMFR0, 0x00000030); + SET_IDREG(&cpu->isar, ID_MMFR1, 0x00000000); + SET_IDREG(&cpu->isar, ID_MMFR2, 0x00000000); + SET_IDREG(&cpu->isar, ID_MMFR3, 0x00000000); + SET_IDREG(isar, ID_ISAR0, 0x01141110); + SET_IDREG(isar, ID_ISAR1, 0x02111000); + SET_IDREG(isar, ID_ISAR2, 0x21112231); + SET_IDREG(isar, ID_ISAR3, 0x01111110); + SET_IDREG(isar, ID_ISAR4, 0x01310102); + SET_IDREG(isar, ID_ISAR5, 0); + SET_IDREG(isar, ID_ISAR6, 0); } static void cortex_m7_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; set_feature(&cpu->env, ARM_FEATURE_V7); set_feature(&cpu->env, ARM_FEATURE_M); @@ -672,26 +681,27 @@ static void cortex_m7_initfn(Object *obj) cpu->isar.mvfr0 = 0x10110221; cpu->isar.mvfr1 = 0x12000011; cpu->isar.mvfr2 = 0x00000040; - cpu->isar.id_pfr0 = 0x00000030; - cpu->isar.id_pfr1 = 0x00000200; - cpu->isar.id_dfr0 = 0x00100000; + SET_IDREG(&cpu->isar, ID_PFR0, 0x00000030); + SET_IDREG(&cpu->isar, ID_PFR1, 0x00000200); + SET_IDREG(&cpu->isar, ID_DFR0, 0x00100000); cpu->id_afr0 = 0x00000000; - cpu->isar.id_mmfr0 = 0x00100030; - cpu->isar.id_mmfr1 = 0x00000000; - cpu->isar.id_mmfr2 = 0x01000000; - cpu->isar.id_mmfr3 = 0x00000000; - cpu->isar.id_isar0 = 0x01101110; - cpu->isar.id_isar1 = 0x02112000; - cpu->isar.id_isar2 = 0x20232231; - cpu->isar.id_isar3 = 0x01111131; - cpu->isar.id_isar4 = 0x01310132; - cpu->isar.id_isar5 = 0x00000000; - cpu->isar.id_isar6 = 0x00000000; + SET_IDREG(&cpu->isar, ID_MMFR0, 0x00100030); + SET_IDREG(&cpu->isar, ID_MMFR1, 0x00000000); + SET_IDREG(&cpu->isar, ID_MMFR2, 0x01000000); + SET_IDREG(&cpu->isar, ID_MMFR3, 0x00000000); + SET_IDREG(isar, ID_ISAR0, 0x01101110); + SET_IDREG(isar, ID_ISAR1, 0x02112000); + SET_IDREG(isar, ID_ISAR2, 0x20232231); + SET_IDREG(isar, ID_ISAR3, 0x01111131); + SET_IDREG(isar, ID_ISAR4, 0x01310132); + SET_IDREG(isar, ID_ISAR5, 0); + SET_IDREG(isar, ID_ISAR6, 0); } static void cortex_m33_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; set_feature(&cpu->env, ARM_FEATURE_V8); set_feature(&cpu->env, ARM_FEATURE_M); @@ -704,21 +714,21 @@ static void cortex_m33_initfn(Object *obj) cpu->isar.mvfr0 = 0x10110021; cpu->isar.mvfr1 = 0x11000011; cpu->isar.mvfr2 = 0x00000040; - cpu->isar.id_pfr0 = 0x00000030; - cpu->isar.id_pfr1 = 0x00000210; - cpu->isar.id_dfr0 = 0x00200000; + SET_IDREG(&cpu->isar, ID_PFR0, 0x00000030); + SET_IDREG(&cpu->isar, ID_PFR1, 0x00000210); + SET_IDREG(&cpu->isar, ID_DFR0, 0x00200000); cpu->id_afr0 = 0x00000000; - cpu->isar.id_mmfr0 = 0x00101F40; - cpu->isar.id_mmfr1 = 0x00000000; - cpu->isar.id_mmfr2 = 0x01000000; - cpu->isar.id_mmfr3 = 0x00000000; - cpu->isar.id_isar0 = 0x01101110; - cpu->isar.id_isar1 = 0x02212000; - cpu->isar.id_isar2 = 0x20232232; - cpu->isar.id_isar3 = 0x01111131; - cpu->isar.id_isar4 = 0x01310132; - cpu->isar.id_isar5 = 0x00000000; - cpu->isar.id_isar6 = 0x00000000; + SET_IDREG(&cpu->isar, ID_MMFR0, 0x00101F40); + SET_IDREG(&cpu->isar, ID_MMFR1, 0x00000000); + SET_IDREG(&cpu->isar, ID_MMFR2, 0x01000000); + SET_IDREG(&cpu->isar, ID_MMFR3, 0x00000000); + SET_IDREG(isar, ID_ISAR0, 0x01101110); + SET_IDREG(isar, ID_ISAR1, 0x02212000); + SET_IDREG(isar, ID_ISAR2, 0x20232232); + SET_IDREG(isar, ID_ISAR3, 0x01111131); + SET_IDREG(isar, ID_ISAR4, 0x01310132); + SET_IDREG(isar, ID_ISAR5, 0); + SET_IDREG(isar, ID_ISAR6, 0); cpu->clidr = 0x00000000; cpu->ctr = 0x8000c000; } @@ -726,7 +736,8 @@ static void cortex_m33_initfn(Object *obj) static void cortex_m55_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); - + ARMISARegisters *isar = &cpu->isar; + set_feature(&cpu->env, ARM_FEATURE_V8); set_feature(&cpu->env, ARM_FEATURE_V8_1M); set_feature(&cpu->env, ARM_FEATURE_M); @@ -741,21 +752,21 @@ static void cortex_m55_initfn(Object *obj) cpu->isar.mvfr0 = 0x10110221; cpu->isar.mvfr1 = 0x12100211; cpu->isar.mvfr2 = 0x00000040; - cpu->isar.id_pfr0 = 0x20000030; - cpu->isar.id_pfr1 = 0x00000230; - cpu->isar.id_dfr0 = 0x10200000; + SET_IDREG(&cpu->isar, ID_PFR0, 0x20000030); + SET_IDREG(&cpu->isar, ID_PFR1, 0x00000230); + SET_IDREG(&cpu->isar, ID_DFR0, 0x10200000); cpu->id_afr0 = 0x00000000; - cpu->isar.id_mmfr0 = 0x00111040; - cpu->isar.id_mmfr1 = 0x00000000; - cpu->isar.id_mmfr2 = 0x01000000; - cpu->isar.id_mmfr3 = 0x00000011; - cpu->isar.id_isar0 = 0x01103110; - cpu->isar.id_isar1 = 0x02212000; - cpu->isar.id_isar2 = 0x20232232; - cpu->isar.id_isar3 = 0x01111131; - cpu->isar.id_isar4 = 0x01310132; - cpu->isar.id_isar5 = 0x00000000; - cpu->isar.id_isar6 = 0x00000000; + SET_IDREG(&cpu->isar, ID_MMFR0, 0x00111040); + SET_IDREG(&cpu->isar, ID_MMFR1, 0x00000000); + SET_IDREG(&cpu->isar, ID_MMFR2, 0x01000000); + SET_IDREG(&cpu->isar, ID_MMFR3, 0x00000011); + SET_IDREG(isar, ID_ISAR0, 0x01103110); + SET_IDREG(isar, ID_ISAR1, 0x02212000); + SET_IDREG(isar, ID_ISAR2, 0x20232232); + SET_IDREG(isar, ID_ISAR3, 0x01111131); + SET_IDREG(isar, ID_ISAR4, 0x01310132); + SET_IDREG(isar, ID_ISAR5, 0); + SET_IDREG(isar, ID_ISAR6, 0); cpu->clidr = 0x00000000; /* caches not implemented */ cpu->ctr = 0x8303c003; } @@ -773,27 +784,28 @@ static const ARMCPRegInfo cortexr5_cp_reginfo[] = { static void cortex_r5_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; set_feature(&cpu->env, ARM_FEATURE_V7); set_feature(&cpu->env, ARM_FEATURE_V7MP); set_feature(&cpu->env, ARM_FEATURE_PMSA); set_feature(&cpu->env, ARM_FEATURE_PMU); cpu->midr = 0x411fc153; /* r1p3 */ - cpu->isar.id_pfr0 = 0x0131; - cpu->isar.id_pfr1 = 0x001; - cpu->isar.id_dfr0 = 0x010400; + SET_IDREG(isar, ID_PFR0, 0x0131); + SET_IDREG(isar, ID_PFR1, 0x001); + SET_IDREG(isar, ID_DFR0, 0x010400); cpu->id_afr0 = 0x0; - cpu->isar.id_mmfr0 = 0x0210030; - cpu->isar.id_mmfr1 = 0x00000000; - cpu->isar.id_mmfr2 = 0x01200000; - cpu->isar.id_mmfr3 = 0x0211; - cpu->isar.id_isar0 = 0x02101111; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232141; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x0010142; - cpu->isar.id_isar5 = 0x0; - cpu->isar.id_isar6 = 0x0; + SET_IDREG(isar, ID_MMFR0, 0x0210030); + SET_IDREG(isar, ID_MMFR1, 0x00000000); + SET_IDREG(isar, ID_MMFR2, 0x01200000); + SET_IDREG(isar, ID_MMFR3, 0x0211); + SET_IDREG(isar, ID_ISAR0, 0x02101111); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232141); + SET_IDREG(isar, ID_ISAR3, 0x01112131); + SET_IDREG(isar, ID_ISAR4, 0x0010142); + SET_IDREG(isar, ID_ISAR5, 0x0); + SET_IDREG(isar, ID_ISAR6, 0x0); cpu->mp_is_up = true; cpu->pmsav7_dregion = 16; cpu->isar.reset_pmcr_el0 = 0x41151800; @@ -803,6 +815,7 @@ static void cortex_r5_initfn(Object *obj) static void cortex_r52_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; set_feature(&cpu->env, ARM_FEATURE_V8); set_feature(&cpu->env, ARM_FEATURE_EL2); @@ -817,21 +830,21 @@ static void cortex_r52_initfn(Object *obj) cpu->isar.mvfr2 = 0x00000043; cpu->ctr = 0x8144c004; cpu->reset_sctlr = 0x30c50838; - cpu->isar.id_pfr0 = 0x00000131; - cpu->isar.id_pfr1 = 0x10111001; - cpu->isar.id_dfr0 = 0x03010006; + SET_IDREG(isar, ID_PFR0, 0x00000131); + SET_IDREG(isar, ID_PFR1, 0x10111001); + SET_IDREG(isar, ID_DFR0, 0x03010006); cpu->id_afr0 = 0x00000000; - cpu->isar.id_mmfr0 = 0x00211040; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01200000; - cpu->isar.id_mmfr3 = 0xf0102211; - cpu->isar.id_mmfr4 = 0x00000010; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232142; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x00010142; - cpu->isar.id_isar5 = 0x00010001; + SET_IDREG(isar, ID_MMFR0, 0x00211040); + SET_IDREG(isar, ID_MMFR1, 0x40000000); + SET_IDREG(isar, ID_MMFR2, 0x01200000); + SET_IDREG(isar, ID_MMFR3, 0xf0102211); + SET_IDREG(isar, ID_MMFR4, 0x00000010); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232142); + SET_IDREG(isar, ID_ISAR3, 0x01112131); + SET_IDREG(isar, ID_ISAR4, 0x00010142); + SET_IDREG(isar, ID_ISAR5, 0x00010001); cpu->isar.dbgdidr = 0x77168000; cpu->clidr = (1 << 27) | (1 << 24) | 0x3; cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */ @@ -1058,6 +1071,7 @@ static void arm_v7m_class_init(ObjectClass *oc, void *data) static void arm_max_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; /* aarch64_a57_initfn, advertising none of the aarch64 features */ cpu->dtb_compatible = "arm,cortex-a57"; @@ -1076,21 +1090,21 @@ static void arm_max_initfn(Object *obj) cpu->isar.mvfr2 = 0x00000043; cpu->ctr = 0x8444c004; cpu->reset_sctlr = 0x00c50838; - cpu->isar.id_pfr0 = 0x00000131; - cpu->isar.id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x03010066; + SET_IDREG(isar, ID_PFR0, 0x00000131); + SET_IDREG(isar, ID_PFR1, 0x00011011); + SET_IDREG(isar, ID_DFR0, 0x03010066); cpu->id_afr0 = 0x00000000; - cpu->isar.id_mmfr0 = 0x10101105; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01260000; - cpu->isar.id_mmfr3 = 0x02102211; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x00011142; - cpu->isar.id_isar5 = 0x00011121; - cpu->isar.id_isar6 = 0; + SET_IDREG(isar, ID_MMFR0, 0x10101105); + SET_IDREG(isar, ID_MMFR1, 0x40000000); + SET_IDREG(isar, ID_MMFR2, 0x01260000); + SET_IDREG(isar, ID_MMFR3, 0x02102211); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); + SET_IDREG(isar, ID_ISAR3, 0x01112131); + SET_IDREG(isar, ID_ISAR4, 0x00011142); + SET_IDREG(isar, ID_ISAR5, 0x00011121); + SET_IDREG(isar, ID_ISAR6, 0); cpu->isar.dbgdidr = 0x3516d000; cpu->isar.dbgdevid = 0x00110f13; cpu->isar.dbgdevid1 = 0x2; diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c index fcda99e1583d5e4916b7b1fb4a61cdd017b12ed6..31a5a6b9c54ff470ac9d2e7070ad5f1919c3ab97 100644 --- a/target/arm/tcg/cpu64.c +++ b/target/arm/tcg/cpu64.c @@ -58,6 +58,7 @@ static uint64_t make_ccsidr64(unsigned assoc, unsigned linesize, static void aarch64_a35_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; cpu->dtb_compatible = "arm,cortex-a35"; set_feature(&cpu->env, ARM_FEATURE_V8); @@ -73,28 +74,28 @@ static void aarch64_a35_initfn(Object *obj) cpu->midr = 0x411fd040; cpu->revidr = 0; cpu->ctr = 0x84448004; - cpu->isar.id_pfr0 = 0x00000131; - cpu->isar.id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x03010066; + SET_IDREG(isar, ID_PFR0, 0x00000131); + SET_IDREG(isar, ID_PFR1, 0x00011011); + SET_IDREG(isar, ID_DFR0, 0x03010066); cpu->id_afr0 = 0; - cpu->isar.id_mmfr0 = 0x10201105; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01260000; - cpu->isar.id_mmfr3 = 0x02102211; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x00011142; - cpu->isar.id_isar5 = 0x00011121; - cpu->isar.id_aa64pfr0 = 0x00002222; - cpu->isar.id_aa64pfr1 = 0; - cpu->isar.id_aa64dfr0 = 0x10305106; - cpu->isar.id_aa64dfr1 = 0; - cpu->isar.id_aa64isar0 = 0x00011120; - cpu->isar.id_aa64isar1 = 0; - cpu->isar.id_aa64mmfr0 = 0x00101122; - cpu->isar.id_aa64mmfr1 = 0; + SET_IDREG(isar, ID_MMFR0, 0x10201105); + SET_IDREG(isar, ID_MMFR1, 0x40000000); + SET_IDREG(isar, ID_MMFR2, 0x01260000); + SET_IDREG(isar, ID_MMFR3, 0x02102211); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); + SET_IDREG(isar, ID_ISAR3, 0x01112131); + SET_IDREG(isar, ID_ISAR4, 0x00011142); + SET_IDREG(isar, ID_ISAR5, 0x00011121); + SET_IDREG(isar, ID_AA64PFR0, 0x00002222); + SET_IDREG(isar, ID_AA64PFR1, 0); + SET_IDREG(isar, ID_AA64DFR0, 0x10305106); + SET_IDREG(isar, ID_AA64DFR1, 0); + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); + SET_IDREG(isar, ID_AA64ISAR1, 0); + SET_IDREG(isar, ID_AA64MMFR0, 0x00101122); + SET_IDREG(isar, ID_AA64MMFR1, 0); cpu->clidr = 0x0a200023; cpu->dcz_blocksize = 4; @@ -179,11 +180,8 @@ static bool cpu_arm_get_rme(Object *obj, Error **errp) static void cpu_arm_set_rme(Object *obj, bool value, Error **errp) { ARMCPU *cpu = ARM_CPU(obj); - uint64_t t; - t = cpu->isar.id_aa64pfr0; - t = FIELD_DP64(t, ID_AA64PFR0, RME, value); - cpu->isar.id_aa64pfr0 = t; + FIELD_DP64_IDREG(&cpu->isar, ID_AA64PFR0, RME, value); } static void cpu_max_set_l0gptsz(Object *obj, Visitor *v, const char *name, @@ -226,6 +224,7 @@ static Property arm_cpu_lpa2_property = static void aarch64_a55_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; cpu->dtb_compatible = "arm,cortex-a55"; set_feature(&cpu->env, ARM_FEATURE_V8); @@ -241,31 +240,31 @@ static void aarch64_a55_initfn(Object *obj) cpu->clidr = 0x82000023; cpu->ctr = 0x84448004; /* L1Ip = VIPT */ cpu->dcz_blocksize = 4; /* 64 bytes */ - cpu->isar.id_aa64dfr0 = 0x0000000010305408ull; - cpu->isar.id_aa64isar0 = 0x0000100010211120ull; - cpu->isar.id_aa64isar1 = 0x0000000000100001ull; - cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull; - cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; - cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; - cpu->isar.id_aa64pfr0 = 0x0000000010112222ull; - cpu->isar.id_aa64pfr1 = 0x0000000000000010ull; + SET_IDREG(isar, ID_AA64DFR0, 0x0000000010305408ull); + SET_IDREG(isar, ID_AA64ISAR0, 0x0000100010211120ull); + SET_IDREG(isar, ID_AA64ISAR1, 0x0000000000100001ull); + SET_IDREG(isar, ID_AA64MMFR0, 0x0000000000101122ull); + SET_IDREG(isar, ID_AA64MMFR1, 0x0000000010212122ull); + SET_IDREG(isar, ID_AA64MMFR2, 0x0000000000001011ull); + SET_IDREG(isar, ID_AA64PFR0, 0x0000000010112222ull); + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000010ull); cpu->id_afr0 = 0x00000000; - cpu->isar.id_dfr0 = 0x04010088; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x00011142; - cpu->isar.id_isar5 = 0x01011121; - cpu->isar.id_isar6 = 0x00000010; - cpu->isar.id_mmfr0 = 0x10201105; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01260000; - cpu->isar.id_mmfr3 = 0x02122211; - cpu->isar.id_mmfr4 = 0x00021110; - cpu->isar.id_pfr0 = 0x10010131; - cpu->isar.id_pfr1 = 0x00011011; - cpu->isar.id_pfr2 = 0x00000011; + SET_IDREG(isar, ID_DFR0, 0x04010088); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); + SET_IDREG(isar, ID_ISAR3, 0x01112131); + SET_IDREG(isar, ID_ISAR4, 0x00011142); + SET_IDREG(isar, ID_ISAR5, 0x01011121); + SET_IDREG(isar, ID_ISAR6, 0x00000010); + SET_IDREG(isar, ID_MMFR0, 0x10201105); + SET_IDREG(isar, ID_MMFR1, 0x40000000); + SET_IDREG(isar, ID_MMFR2, 0x01260000); + SET_IDREG(isar, ID_MMFR3, 0x02122211); + SET_IDREG(isar, ID_MMFR4, 0x00021110); + SET_IDREG(isar, ID_PFR0, 0x10010131); + SET_IDREG(isar, ID_PFR1, 0x00011011); + SET_IDREG(isar, ID_PFR2, 0x00000011); cpu->midr = 0x412FD050; /* r2p0 */ cpu->revidr = 0; @@ -294,6 +293,7 @@ static void aarch64_a55_initfn(Object *obj) static void aarch64_a72_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; cpu->dtb_compatible = "arm,cortex-a72"; set_feature(&cpu->env, ARM_FEATURE_V8); @@ -312,24 +312,24 @@ static void aarch64_a72_initfn(Object *obj) cpu->isar.mvfr2 = 0x00000043; cpu->ctr = 0x8444c004; cpu->reset_sctlr = 0x00c50838; - cpu->isar.id_pfr0 = 0x00000131; - cpu->isar.id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x03010066; + SET_IDREG(isar, ID_PFR0, 0x00000131); + SET_IDREG(isar, ID_PFR1, 0x00011011); + SET_IDREG(isar, ID_DFR0, 0x03010066); cpu->id_afr0 = 0x00000000; - cpu->isar.id_mmfr0 = 0x10201105; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01260000; - cpu->isar.id_mmfr3 = 0x02102211; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x00011142; - cpu->isar.id_isar5 = 0x00011121; - cpu->isar.id_aa64pfr0 = 0x00002222; - cpu->isar.id_aa64dfr0 = 0x10305106; - cpu->isar.id_aa64isar0 = 0x00011120; - cpu->isar.id_aa64mmfr0 = 0x00001124; + SET_IDREG(isar, ID_MMFR0, 0x10201105); + SET_IDREG(isar, ID_MMFR1, 0x40000000); + SET_IDREG(isar, ID_MMFR2, 0x01260000); + SET_IDREG(isar, ID_MMFR3, 0x02102211); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); + SET_IDREG(isar, ID_ISAR3, 0x01112131); + SET_IDREG(isar, ID_ISAR4, 0x00011142); + SET_IDREG(isar, ID_ISAR5, 0x00011121); + SET_IDREG(isar, ID_AA64PFR0, 0x00002222); + SET_IDREG(isar, ID_AA64DFR0, 0x10305106); + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); + SET_IDREG(isar, ID_AA64MMFR0, 0x00001124); cpu->isar.dbgdidr = 0x3516d000; cpu->isar.dbgdevid = 0x01110f13; cpu->isar.dbgdevid1 = 0x2; @@ -349,6 +349,7 @@ static void aarch64_a72_initfn(Object *obj) static void aarch64_a76_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; cpu->dtb_compatible = "arm,cortex-a76"; set_feature(&cpu->env, ARM_FEATURE_V8); @@ -364,31 +365,31 @@ static void aarch64_a76_initfn(Object *obj) cpu->clidr = 0x82000023; cpu->ctr = 0x8444C004; cpu->dcz_blocksize = 4; - cpu->isar.id_aa64dfr0 = 0x0000000010305408ull; - cpu->isar.id_aa64isar0 = 0x0000100010211120ull; - cpu->isar.id_aa64isar1 = 0x0000000000100001ull; - cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull; - cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; - cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; - cpu->isar.id_aa64pfr0 = 0x1100000010111112ull; /* GIC filled in later */ - cpu->isar.id_aa64pfr1 = 0x0000000000000010ull; + SET_IDREG(isar, ID_AA64DFR0, 0x0000000010305408ull), + SET_IDREG(isar, ID_AA64ISAR0, 0x0000100010211120ull); + SET_IDREG(isar, ID_AA64ISAR1, 0x0000000000100001ull); + SET_IDREG(isar, ID_AA64MMFR0, 0x0000000000101122ull); + SET_IDREG(isar, ID_AA64MMFR1, 0x0000000010212122ull); + SET_IDREG(isar, ID_AA64MMFR2, 0x0000000000001011ull); + SET_IDREG(isar, ID_AA64PFR0, 0x1100000010111112ull); /* GIC filled in later */ + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000010ull); cpu->id_afr0 = 0x00000000; - cpu->isar.id_dfr0 = 0x04010088; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x00010142; - cpu->isar.id_isar5 = 0x01011121; - cpu->isar.id_isar6 = 0x00000010; - cpu->isar.id_mmfr0 = 0x10201105; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01260000; - cpu->isar.id_mmfr3 = 0x02122211; - cpu->isar.id_mmfr4 = 0x00021110; - cpu->isar.id_pfr0 = 0x10010131; - cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */ - cpu->isar.id_pfr2 = 0x00000011; + SET_IDREG(isar, ID_DFR0, 0x04010088); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); + SET_IDREG(isar, ID_ISAR3, 0x01112131); + SET_IDREG(isar, ID_ISAR4, 0x00010142); + SET_IDREG(isar, ID_ISAR5, 0x01011121); + SET_IDREG(isar, ID_ISAR6, 0x00000010); + SET_IDREG(isar, ID_MMFR0, 0x10201105); + SET_IDREG(isar, ID_MMFR1, 0x40000000); + SET_IDREG(isar, ID_MMFR2, 0x01260000); + SET_IDREG(isar, ID_MMFR3, 0x02122211); + SET_IDREG(isar, ID_MMFR4, 0x00021110); + SET_IDREG(isar, ID_PFR0, 0x10010131); + SET_IDREG(isar, ID_PFR1, 0x00010000); /* GIC filled in later */ + SET_IDREG(isar, ID_PFR2, 0x00000011); cpu->midr = 0x414fd0b1; /* r4p1 */ cpu->revidr = 0; @@ -418,6 +419,7 @@ static void aarch64_a76_initfn(Object *obj) static void aarch64_a64fx_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; cpu->dtb_compatible = "arm,a64fx"; set_feature(&cpu->env, ARM_FEATURE_V8); @@ -431,18 +433,18 @@ static void aarch64_a64fx_initfn(Object *obj) cpu->revidr = 0x00000000; cpu->ctr = 0x86668006; cpu->reset_sctlr = 0x30000180; - cpu->isar.id_aa64pfr0 = 0x0000000101111111; /* No RAS Extensions */ - cpu->isar.id_aa64pfr1 = 0x0000000000000000; - cpu->isar.id_aa64dfr0 = 0x0000000010305408; - cpu->isar.id_aa64dfr1 = 0x0000000000000000; + SET_IDREG(isar, ID_AA64PFR0, 0x0000000101111111); /* No RAS Extensions */ + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000000); + SET_IDREG(isar, ID_AA64DFR0, 0x0000000010305408), + SET_IDREG(isar, ID_AA64DFR1, 0x0000000000000000), cpu->id_aa64afr0 = 0x0000000000000000; cpu->id_aa64afr1 = 0x0000000000000000; - cpu->isar.id_aa64mmfr0 = 0x0000000000001122; - cpu->isar.id_aa64mmfr1 = 0x0000000011212100; - cpu->isar.id_aa64mmfr2 = 0x0000000000001011; - cpu->isar.id_aa64isar0 = 0x0000000010211120; - cpu->isar.id_aa64isar1 = 0x0000000000010001; - cpu->isar.id_aa64zfr0 = 0x0000000000000000; + SET_IDREG(isar, ID_AA64MMFR0, 0x0000000000001122); + SET_IDREG(isar, ID_AA64MMFR1, 0x0000000011212100); + SET_IDREG(isar, ID_AA64MMFR2, 0x0000000000001011); + SET_IDREG(isar, ID_AA64ISAR0, 0x0000000010211120); + SET_IDREG(isar, ID_AA64ISAR1, 0x0000000000010001); + SET_IDREG(isar, ID_AA64ZFR0, 0x0000000000000000); cpu->clidr = 0x0000000080000023; cpu->ccsidr[0] = 0x7007e01c; /* 64KB L1 dcache */ cpu->ccsidr[1] = 0x2007e01c; /* 64KB L1 icache */ @@ -587,6 +589,7 @@ static void define_neoverse_v1_cp_reginfo(ARMCPU *cpu) static void aarch64_neoverse_n1_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; cpu->dtb_compatible = "arm,neoverse-n1"; set_feature(&cpu->env, ARM_FEATURE_V8); @@ -602,31 +605,31 @@ static void aarch64_neoverse_n1_initfn(Object *obj) cpu->clidr = 0x82000023; cpu->ctr = 0x8444c004; cpu->dcz_blocksize = 4; - cpu->isar.id_aa64dfr0 = 0x0000000110305408ull; - cpu->isar.id_aa64isar0 = 0x0000100010211120ull; - cpu->isar.id_aa64isar1 = 0x0000000000100001ull; - cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull; - cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; - cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; - cpu->isar.id_aa64pfr0 = 0x1100000010111112ull; /* GIC filled in later */ - cpu->isar.id_aa64pfr1 = 0x0000000000000020ull; + SET_IDREG(isar, ID_AA64DFR0, 0x0000000110305408ull); + SET_IDREG(isar, ID_AA64ISAR0, 0x0000100010211120ull); + SET_IDREG(isar, ID_AA64ISAR1, 0x0000000000100001ull); + SET_IDREG(isar, ID_AA64MMFR0, 0x0000000000101125ull); + SET_IDREG(isar, ID_AA64MMFR1, 0x0000000010212122ull); + SET_IDREG(isar, ID_AA64MMFR2, 0x0000000000001011ull); + SET_IDREG(isar, ID_AA64PFR0, 0x1100000010111112ull); /* GIC filled in later */ + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000020ull); cpu->id_afr0 = 0x00000000; - cpu->isar.id_dfr0 = 0x04010088; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x00010142; - cpu->isar.id_isar5 = 0x01011121; - cpu->isar.id_isar6 = 0x00000010; - cpu->isar.id_mmfr0 = 0x10201105; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01260000; - cpu->isar.id_mmfr3 = 0x02122211; - cpu->isar.id_mmfr4 = 0x00021110; - cpu->isar.id_pfr0 = 0x10010131; - cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */ - cpu->isar.id_pfr2 = 0x00000011; + SET_IDREG(isar, ID_DFR0, 0x04010088); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); + SET_IDREG(isar, ID_ISAR3, 0x01112131); + SET_IDREG(isar, ID_ISAR4, 0x00010142); + SET_IDREG(isar, ID_ISAR5, 0x01011121); + SET_IDREG(isar, ID_ISAR6, 0x00000010); + SET_IDREG(isar, ID_MMFR0, 0x10201105); + SET_IDREG(isar, ID_MMFR1, 0x40000000); + SET_IDREG(isar, ID_MMFR2, 0x01260000); + SET_IDREG(isar, ID_MMFR3, 0x02122211); + SET_IDREG(isar, ID_MMFR4, 0x00021110); + SET_IDREG(isar, ID_PFR0, 0x10010131); + SET_IDREG(isar, ID_PFR1, 0x00010000); /* GIC filled in later */ + SET_IDREG(isar, ID_PFR2, 0x00000011); cpu->midr = 0x414fd0c1; /* r4p1 */ cpu->revidr = 0; @@ -658,6 +661,7 @@ static void aarch64_neoverse_n1_initfn(Object *obj) static void aarch64_neoverse_v1_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; cpu->dtb_compatible = "arm,neoverse-v1"; set_feature(&cpu->env, ARM_FEATURE_V8); @@ -675,32 +679,32 @@ static void aarch64_neoverse_v1_initfn(Object *obj) cpu->dcz_blocksize = 4; cpu->id_aa64afr0 = 0x00000000; cpu->id_aa64afr1 = 0x00000000; - cpu->isar.id_aa64dfr0 = 0x000001f210305519ull; - cpu->isar.id_aa64dfr1 = 0x00000000; - cpu->isar.id_aa64isar0 = 0x1011111110212120ull; /* with FEAT_RNG */ - cpu->isar.id_aa64isar1 = 0x0111000001211032ull; - cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull; - cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; - cpu->isar.id_aa64mmfr2 = 0x0220011102101011ull; - cpu->isar.id_aa64pfr0 = 0x1101110120111112ull; /* GIC filled in later */ - cpu->isar.id_aa64pfr1 = 0x0000000000000020ull; + SET_IDREG(isar, ID_AA64DFR0, 0x000001f210305519ull), + SET_IDREG(isar, ID_AA64DFR1, 0x00000000), + SET_IDREG(isar, ID_AA64ISAR0, 0x1011111110212120ull); /* with FEAT_RNG */ + SET_IDREG(&cpu->isar, ID_AA64ISAR1, 0x0111000001211032ull); + SET_IDREG(&cpu->isar, ID_AA64MMFR0, 0x0000000000101125ull); + SET_IDREG(&cpu->isar, ID_AA64MMFR1, 0x0000000010212122ull); + SET_IDREG(&cpu->isar, ID_AA64MMFR2, 0x0220011102101011ull); + SET_IDREG(isar, ID_AA64PFR0, 0x1101110120111112ull); /* GIC filled in later */ + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000020ull); cpu->id_afr0 = 0x00000000; - cpu->isar.id_dfr0 = 0x15011099; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x00010142; - cpu->isar.id_isar5 = 0x11011121; - cpu->isar.id_isar6 = 0x01100111; - cpu->isar.id_mmfr0 = 0x10201105; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01260000; - cpu->isar.id_mmfr3 = 0x02122211; - cpu->isar.id_mmfr4 = 0x01021110; - cpu->isar.id_pfr0 = 0x21110131; - cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */ - cpu->isar.id_pfr2 = 0x00000011; + SET_IDREG(isar, ID_DFR0, 0x15011099); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); + SET_IDREG(isar, ID_ISAR3, 0x01112131); + SET_IDREG(isar, ID_ISAR4, 0x00010142); + SET_IDREG(isar, ID_ISAR5, 0x11011121); + SET_IDREG(isar, ID_ISAR6, 0x01100111); + SET_IDREG(isar, ID_MMFR0, 0x10201105); + SET_IDREG(isar, ID_MMFR1, 0x40000000); + SET_IDREG(isar, ID_MMFR2, 0x01260000); + SET_IDREG(isar, ID_MMFR3, 0x02122211); + SET_IDREG(isar, ID_MMFR4, 0x01021110); + SET_IDREG(isar, ID_PFR0, 0x21110131); + SET_IDREG(isar, ID_PFR1, 0x00010000); /* GIC filled in later */ + SET_IDREG(isar, ID_PFR2, 0x00000011); cpu->midr = 0x411FD402; /* r1p2 */ cpu->revidr = 0; @@ -733,7 +737,7 @@ static void aarch64_neoverse_v1_initfn(Object *obj) cpu->isar.mvfr2 = 0x00000043; /* From 3.7.5 ID_AA64ZFR0_EL1 */ - cpu->isar.id_aa64zfr0 = 0x0000100000100000; + SET_IDREG(isar, ID_AA64ZFR0, 0x0000100000100000); cpu->sve_vq.supported = (1 << 0) /* 128bit */ | (1 << 1); /* 256bit */ @@ -880,6 +884,7 @@ static const ARMCPRegInfo cortex_a710_cp_reginfo[] = { static void aarch64_a710_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; cpu->dtb_compatible = "arm,cortex-a710"; set_feature(&cpu->env, ARM_FEATURE_V8); @@ -894,38 +899,38 @@ static void aarch64_a710_initfn(Object *obj) /* Ordered by Section B.4: AArch64 registers */ cpu->midr = 0x412FD471; /* r2p1 */ cpu->revidr = 0; - cpu->isar.id_pfr0 = 0x21110131; - cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */ - cpu->isar.id_dfr0 = 0x16011099; + SET_IDREG(isar, ID_PFR0, 0x21110131); + SET_IDREG(isar, ID_PFR1, 0x00010000); /* GIC filled in later */ + SET_IDREG(isar, ID_DFR0, 0x16011099); cpu->id_afr0 = 0; - cpu->isar.id_mmfr0 = 0x10201105; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01260000; - cpu->isar.id_mmfr3 = 0x02122211; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x00010142; - cpu->isar.id_isar5 = 0x11011121; /* with Crypto */ - cpu->isar.id_mmfr4 = 0x21021110; - cpu->isar.id_isar6 = 0x01111111; + SET_IDREG(isar, ID_MMFR0, 0x10201105); + SET_IDREG(isar, ID_MMFR1, 0x40000000); + SET_IDREG(isar, ID_MMFR2, 0x01260000); + SET_IDREG(isar, ID_MMFR3, 0x02122211); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); + SET_IDREG(isar, ID_ISAR3, 0x01112131); + SET_IDREG(isar, ID_ISAR4, 0x00010142); + SET_IDREG(isar, ID_ISAR5, 0x11011121); /* with Crypto */ + SET_IDREG(isar, ID_MMFR4, 0x21021110); + SET_IDREG(isar, ID_ISAR6, 0x01111111); cpu->isar.mvfr0 = 0x10110222; cpu->isar.mvfr1 = 0x13211111; cpu->isar.mvfr2 = 0x00000043; - cpu->isar.id_pfr2 = 0x00000011; - cpu->isar.id_aa64pfr0 = 0x1201111120111112ull; /* GIC filled in later */ - cpu->isar.id_aa64pfr1 = 0x0000000000000221ull; - cpu->isar.id_aa64zfr0 = 0x0000110100110021ull; /* with Crypto */ - cpu->isar.id_aa64dfr0 = 0x000011f010305619ull; - cpu->isar.id_aa64dfr1 = 0; + SET_IDREG(isar, ID_PFR2, 0x00000011); + SET_IDREG(isar, ID_AA64PFR0, 0x1201111120111112ull); /* GIC filled in later */ + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000221ull); + SET_IDREG(isar, ID_AA64ZFR0, 0x0000110100110021ull); /* with Crypto */ + SET_IDREG(isar, ID_AA64DFR0, 0x000011f010305619ull); + SET_IDREG(isar, ID_AA64DFR1, 0); cpu->id_aa64afr0 = 0; cpu->id_aa64afr1 = 0; - cpu->isar.id_aa64isar0 = 0x0221111110212120ull; /* with Crypto */ - cpu->isar.id_aa64isar1 = 0x0010111101211052ull; - cpu->isar.id_aa64mmfr0 = 0x0000022200101122ull; - cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; - cpu->isar.id_aa64mmfr2 = 0x1221011110101011ull; + SET_IDREG(isar, ID_AA64ISAR0, 0x0221111110212120ull); /* with Crypto */ + SET_IDREG(isar, ID_AA64ISAR1, 0x0010111101211052ull); + SET_IDREG(isar, ID_AA64MMFR0, 0x0000022200101122ull); + SET_IDREG(isar, ID_AA64MMFR1, 0x0000000010212122ull); + SET_IDREG(isar, ID_AA64MMFR2, 0x1221011110101011ull); cpu->clidr = 0x0000001482000023ull; cpu->gm_blocksize = 4; cpu->ctr = 0x000000049444c004ull; @@ -977,6 +982,7 @@ static const ARMCPRegInfo neoverse_n2_cp_reginfo[] = { static void aarch64_neoverse_n2_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; cpu->dtb_compatible = "arm,neoverse-n2"; set_feature(&cpu->env, ARM_FEATURE_V8); @@ -991,38 +997,38 @@ static void aarch64_neoverse_n2_initfn(Object *obj) /* Ordered by Section B.5: AArch64 ID registers */ cpu->midr = 0x410FD493; /* r0p3 */ cpu->revidr = 0; - cpu->isar.id_pfr0 = 0x21110131; - cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */ - cpu->isar.id_dfr0 = 0x16011099; + SET_IDREG(isar, ID_PFR0, 0x21110131); + SET_IDREG(isar, ID_PFR1, 0x00010000); /* GIC filled in later */ + SET_IDREG(isar, ID_DFR0, 0x16011099); cpu->id_afr0 = 0; - cpu->isar.id_mmfr0 = 0x10201105; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01260000; - cpu->isar.id_mmfr3 = 0x02122211; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x00010142; - cpu->isar.id_isar5 = 0x11011121; /* with Crypto */ - cpu->isar.id_mmfr4 = 0x01021110; - cpu->isar.id_isar6 = 0x01111111; + SET_IDREG(isar, ID_MMFR0, 0x10201105); + SET_IDREG(isar, ID_MMFR1, 0x40000000); + SET_IDREG(isar, ID_MMFR2, 0x01260000); + SET_IDREG(isar, ID_MMFR3, 0x02122211); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); + SET_IDREG(isar, ID_ISAR3, 0x01112131); + SET_IDREG(isar, ID_ISAR4, 0x00010142); + SET_IDREG(isar, ID_ISAR5, 0x11011121); /* with Crypto */ + SET_IDREG(isar, ID_MMFR4, 0x01021110); + SET_IDREG(isar, ID_ISAR6, 0x01111111); cpu->isar.mvfr0 = 0x10110222; cpu->isar.mvfr1 = 0x13211111; cpu->isar.mvfr2 = 0x00000043; - cpu->isar.id_pfr2 = 0x00000011; - cpu->isar.id_aa64pfr0 = 0x1201111120111112ull; /* GIC filled in later */ - cpu->isar.id_aa64pfr1 = 0x0000000000000221ull; - cpu->isar.id_aa64zfr0 = 0x0000110100110021ull; /* with Crypto */ - cpu->isar.id_aa64dfr0 = 0x000011f210305619ull; - cpu->isar.id_aa64dfr1 = 0; + SET_IDREG(isar, ID_PFR2, 0x00000011); + SET_IDREG(isar, ID_AA64PFR0, 0x1201111120111112ull); /* GIC filled in later */ + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000221ull); + SET_IDREG(isar, ID_AA64ZFR0, 0x0000110100110021ull); /* with Crypto */ + SET_IDREG(isar, ID_AA64DFR0, 0x000011f210305619ull); + SET_IDREG(isar, ID_AA64DFR1, 0); cpu->id_aa64afr0 = 0; cpu->id_aa64afr1 = 0; - cpu->isar.id_aa64isar0 = 0x1221111110212120ull; /* with Crypto and FEAT_RNG */ - cpu->isar.id_aa64isar1 = 0x0011111101211052ull; - cpu->isar.id_aa64mmfr0 = 0x0000022200101125ull; - cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; - cpu->isar.id_aa64mmfr2 = 0x1221011112101011ull; + SET_IDREG(isar, ID_AA64ISAR0, 0x1221111110212120ull); /* with Crypto and FEAT_RNG */ + SET_IDREG(isar, ID_AA64ISAR1, 0x0011111101211052ull); + SET_IDREG(isar, ID_AA64MMFR0, 0x0000022200101125ull); + SET_IDREG(isar, ID_AA64MMFR1, 0x0000000010212122ull); + SET_IDREG(isar, ID_AA64MMFR2, 0x1221011112101011ull); cpu->clidr = 0x0000001482000023ull; cpu->gm_blocksize = 4; cpu->ctr = 0x00000004b444c004ull; @@ -1074,6 +1080,7 @@ static void aarch64_neoverse_n2_initfn(Object *obj) void aarch64_max_tcg_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; uint64_t t; uint32_t u; @@ -1105,7 +1112,7 @@ void aarch64_max_tcg_initfn(Object *obj) u = FIELD_DP32(u, CLIDR_EL1, LOUU, 0); cpu->clidr = u; - t = cpu->isar.id_aa64isar0; + t = GET_IDREG(isar, ID_AA64ISAR0); t = FIELD_DP64(t, ID_AA64ISAR0, AES, 2); /* FEAT_PMULL */ t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 1); /* FEAT_SHA1 */ t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 2); /* FEAT_SHA512 */ @@ -1120,9 +1127,9 @@ void aarch64_max_tcg_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* FEAT_FlagM2 */ t = FIELD_DP64(t, ID_AA64ISAR0, TLB, 2); /* FEAT_TLBIRANGE */ t = FIELD_DP64(t, ID_AA64ISAR0, RNDR, 1); /* FEAT_RNG */ - cpu->isar.id_aa64isar0 = t; + SET_IDREG(isar, ID_AA64ISAR0, t); - t = cpu->isar.id_aa64isar1; + t = GET_IDREG(isar, ID_AA64ISAR1); t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2); /* FEAT_DPB2 */ t = FIELD_DP64(t, ID_AA64ISAR1, APA, PauthFeat_FPACCOMBINED); t = FIELD_DP64(t, ID_AA64ISAR1, API, 1); @@ -1135,14 +1142,14 @@ void aarch64_max_tcg_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64ISAR1, BF16, 1); /* FEAT_BF16 */ t = FIELD_DP64(t, ID_AA64ISAR1, DGH, 1); /* FEAT_DGH */ t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 1); /* FEAT_I8MM */ - cpu->isar.id_aa64isar1 = t; + SET_IDREG(&cpu->isar, ID_AA64ISAR1, t); - t = cpu->isar.id_aa64isar2; + t = GET_IDREG(isar, ID_AA64ISAR2); t = FIELD_DP64(t, ID_AA64ISAR2, MOPS, 1); /* FEAT_MOPS */ t = FIELD_DP64(t, ID_AA64ISAR2, BC, 1); /* FEAT_HBC */ - cpu->isar.id_aa64isar2 = t; + SET_IDREG(&cpu->isar, ID_AA64ISAR2, t); - t = cpu->isar.id_aa64pfr0; + t = GET_IDREG(isar, ID_AA64PFR0); t = FIELD_DP64(t, ID_AA64PFR0, FP, 1); /* FEAT_FP16 */ t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1); /* FEAT_FP16 */ t = FIELD_DP64(t, ID_AA64PFR0, RAS, 2); /* FEAT_RASv1p1 + FEAT_DoubleFault */ @@ -1151,9 +1158,9 @@ void aarch64_max_tcg_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1); /* FEAT_DIT */ t = FIELD_DP64(t, ID_AA64PFR0, CSV2, 2); /* FEAT_CSV2_2 */ t = FIELD_DP64(t, ID_AA64PFR0, CSV3, 1); /* FEAT_CSV3 */ - cpu->isar.id_aa64pfr0 = t; + SET_IDREG(isar, ID_AA64PFR0, t); - t = cpu->isar.id_aa64pfr1; + t = GET_IDREG(isar, ID_AA64PFR1); t = FIELD_DP64(t, ID_AA64PFR1, BT, 1); /* FEAT_BTI */ t = FIELD_DP64(t, ID_AA64PFR1, SSBS, 2); /* FEAT_SSBS2 */ /* @@ -1165,18 +1172,18 @@ void aarch64_max_tcg_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64PFR1, RAS_FRAC, 0); /* FEAT_RASv1p1 + FEAT_DoubleFault */ t = FIELD_DP64(t, ID_AA64PFR1, SME, 1); /* FEAT_SME */ t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_2 */ - cpu->isar.id_aa64pfr1 = t; + SET_IDREG(isar, ID_AA64PFR1, t); - t = cpu->isar.id_aa64mmfr0; + t = GET_IDREG(isar, ID_AA64MMFR0); t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 6); /* FEAT_LPA: 52 bits */ t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16, 1); /* 16k pages supported */ t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16_2, 2); /* 16k stage2 supported */ t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN64_2, 2); /* 64k stage2 supported */ t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 2); /* 4k stage2 supported */ t = FIELD_DP64(t, ID_AA64MMFR0, FGT, 1); /* FEAT_FGT */ - cpu->isar.id_aa64mmfr0 = t; + SET_IDREG(isar, ID_AA64MMFR0, t); - t = cpu->isar.id_aa64mmfr1; + t = GET_IDREG(isar, ID_AA64MMFR1); t = FIELD_DP64(t, ID_AA64MMFR1, HAFDBS, 2); /* FEAT_HAFDBS */ t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* FEAT_VMID16 */ t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1); /* FEAT_VHE */ @@ -1187,9 +1194,9 @@ void aarch64_max_tcg_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64MMFR1, ETS, 1); /* FEAT_ETS */ t = FIELD_DP64(t, ID_AA64MMFR1, HCX, 1); /* FEAT_HCX */ t = FIELD_DP64(t, ID_AA64MMFR1, TIDCP1, 1); /* FEAT_TIDCP1 */ - cpu->isar.id_aa64mmfr1 = t; + SET_IDREG(isar, ID_AA64MMFR1, t); - t = cpu->isar.id_aa64mmfr2; + t = GET_IDREG(isar, ID_AA64MMFR2); t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* FEAT_TTCNP */ t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1); /* FEAT_UAO */ t = FIELD_DP64(t, ID_AA64MMFR2, IESB, 1); /* FEAT_IESB */ @@ -1202,9 +1209,9 @@ void aarch64_max_tcg_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64MMFR2, BBM, 2); /* FEAT_BBM at level 2 */ t = FIELD_DP64(t, ID_AA64MMFR2, EVT, 2); /* FEAT_EVT */ t = FIELD_DP64(t, ID_AA64MMFR2, E0PD, 1); /* FEAT_E0PD */ - cpu->isar.id_aa64mmfr2 = t; + SET_IDREG(isar, ID_AA64MMFR2, t); - t = cpu->isar.id_aa64zfr0; + t = GET_IDREG(isar, ID_AA64ZFR0); t = FIELD_DP64(t, ID_AA64ZFR0, SVEVER, 1); t = FIELD_DP64(t, ID_AA64ZFR0, AES, 2); /* FEAT_SVE_PMULL128 */ t = FIELD_DP64(t, ID_AA64ZFR0, BITPERM, 1); /* FEAT_SVE_BitPerm */ @@ -1214,15 +1221,15 @@ void aarch64_max_tcg_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64ZFR0, I8MM, 1); /* FEAT_I8MM */ t = FIELD_DP64(t, ID_AA64ZFR0, F32MM, 1); /* FEAT_F32MM */ t = FIELD_DP64(t, ID_AA64ZFR0, F64MM, 1); /* FEAT_F64MM */ - cpu->isar.id_aa64zfr0 = t; + SET_IDREG(isar, ID_AA64ZFR0, t); - t = cpu->isar.id_aa64dfr0; + t = GET_IDREG(isar, ID_AA64DFR0); t = FIELD_DP64(t, ID_AA64DFR0, DEBUGVER, 9); /* FEAT_Debugv8p4 */ t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 6); /* FEAT_PMUv3p5 */ t = FIELD_DP64(t, ID_AA64DFR0, HPMN0, 1); /* FEAT_HPMN0 */ - cpu->isar.id_aa64dfr0 = t; + SET_IDREG(isar, ID_AA64DFR0, t); - t = cpu->isar.id_aa64smfr0; + t = GET_IDREG(isar, ID_AA64SMFR0); t = FIELD_DP64(t, ID_AA64SMFR0, F32F32, 1); /* FEAT_SME */ t = FIELD_DP64(t, ID_AA64SMFR0, B16F32, 1); /* FEAT_SME */ t = FIELD_DP64(t, ID_AA64SMFR0, F16F32, 1); /* FEAT_SME */ @@ -1230,7 +1237,7 @@ void aarch64_max_tcg_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64SMFR0, F64F64, 1); /* FEAT_SME_F64F64 */ t = FIELD_DP64(t, ID_AA64SMFR0, I16I64, 0xf); /* FEAT_SME_I16I64 */ t = FIELD_DP64(t, ID_AA64SMFR0, FA64, 1); /* FEAT_SME_FA64 */ - cpu->isar.id_aa64smfr0 = t; + SET_IDREG(isar, ID_AA64SMFR0, t); /* Replicate the same data to the 32-bit id registers. */ aa32_max_features(cpu); diff --git a/target/arm/trace-events b/target/arm/trace-events index 48cc0512dbe79ca36b31568fe4b2fbe4a320ae58..a5f08547a7dcd0639fbb33e40b25eaf34ad13df1 100644 --- a/target/arm/trace-events +++ b/target/arm/trace-events @@ -10,5 +10,13 @@ arm_gt_imask_toggle(int timer) "gt_ctl_write: timer %d IMASK toggle" arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value 0x%" PRIx64 arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d" +# kvm64.c +get_host_cpu_idregs(const char *name, uint64_t value) "scratch vcpu host value for %s is 0x%"PRIx64 +decode_idreg_writemap(const char* name, int lower, int upper, char *prop_name) "%s [%d:%d] is writable (prop %s)" +get_sysreg_prop(const char *name, uint64_t value) "%s 0x%"PRIx64 +set_sysreg_prop(const char *name, uint64_t old, uint64_t mask, uint64_t field_value, uint64_t new) "%s old reg value=0x%"PRIx64" mask=0x%"PRIx64" new field value=0x%"PRIx64" new reg value=0x%"PRIx64 +nb_sysreg_props(const char *name, int count) "%s: %d SYSREG properties" + # kvm.c kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = 0x%"PRIx64" is translated into 0x%"PRIx64 +kvm_arm_writable_idregs_to_cpreg_list(const char *name, uint64_t previous, uint64_t new) "%s overwrite default 0x%"PRIx64" with 0x%"PRIx64