diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 13df002ce4dbc708cc326c8776a39163d2b680de..4b12b209b79fc8dcb3942d16771c3180625e8509 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -1273,17 +1273,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 cpu->isar.regs[ID_PFR0]; case 0xd44: /* PFR1. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_pfr1; + return cpu->isar.regs[ID_PFR1]; case 0xd48: /* DFR0. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_dfr0; + return cpu->isar.regs[ID_DFR0]; case 0xd4c: /* AFR0. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; @@ -1293,52 +1293,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 cpu->isar.regs[ID_MMFR0]; case 0xd54: /* MMFR1. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_mmfr1; + return cpu->isar.regs[ID_MMFR1]; case 0xd58: /* MMFR2. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_mmfr2; + return cpu->isar.regs[ID_MMFR2]; case 0xd5c: /* MMFR3. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_mmfr3; + return cpu->isar.regs[ID_MMFR3]; case 0xd60: /* ISAR0. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_isar0; + return cpu->isar.regs[ID_ISAR0]; case 0xd64: /* ISAR1. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_isar1; + return cpu->isar.regs[ID_ISAR1]; case 0xd68: /* ISAR2. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_isar2; + return cpu->isar.regs[ID_ISAR2]; case 0xd6c: /* ISAR3. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_isar3; + return cpu->isar.regs[ID_ISAR3]; case 0xd70: /* ISAR4. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_isar4; + return cpu->isar.regs[ID_ISAR4]; case 0xd74: /* ISAR5. */ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { goto bad_offset; } - return cpu->isar.id_isar5; + return cpu->isar.regs[ID_ISAR5]; case 0xd78: /* CLIDR */ return cpu->clidr; case 0xd7c: /* CTR */ @@ -1548,11 +1548,11 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) } return cpu->env.v7m.fpdscr[attrs.secure]; case 0xf40: /* MVFR0 */ - return cpu->isar.mvfr0; + return cpu->isar.regs[MVFR0]; case 0xf44: /* MVFR1 */ - return cpu->isar.mvfr1; + return cpu->isar.regs[MVFR1]; case 0xf48: /* MVFR2 */ - return cpu->isar.mvfr2; + return cpu->isar.regs[MVFR2]; default: bad_offset: qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset); diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index bcaf66cc4d2a06a861322b0ee82c2c5b38454b98..5d8e42b8f81d42339601e54c6eda71fff4d81623 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -1113,6 +1113,8 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204 #define KVM_CAP_ARM_MTE 205 +#define KVM_CAP_ARM_CPU_FEATURE 555 + #ifdef KVM_CAP_IRQ_ROUTING struct kvm_irq_routing_irqchip { diff --git a/target/arm/cpu.c b/target/arm/cpu.c index a211804fd3df9f3694ddb7a9c8ed7a754fea29ac..65163f51354351ab7abccf6bbdca2721ac888ada 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -25,6 +25,8 @@ #include "qemu/module.h" #include "qapi/error.h" #include "qapi/visitor.h" +#include "qapi/qmp/qdict.h" +#include "qom/qom-qobject.h" #include "cpu.h" #ifdef CONFIG_TCG #include "hw/core/tcg-cpu-ops.h" @@ -176,9 +178,9 @@ static void arm_cpu_reset(DeviceState *dev) g_hash_table_foreach(cpu->cp_regs, cp_reg_check_reset, cpu); env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid; - env->vfp.xregs[ARM_VFP_MVFR0] = cpu->isar.mvfr0; - env->vfp.xregs[ARM_VFP_MVFR1] = cpu->isar.mvfr1; - env->vfp.xregs[ARM_VFP_MVFR2] = cpu->isar.mvfr2; + env->vfp.xregs[ARM_VFP_MVFR0] = cpu->isar.regs[MVFR0]; + env->vfp.xregs[ARM_VFP_MVFR1] = cpu->isar.regs[MVFR1]; + env->vfp.xregs[ARM_VFP_MVFR2] = cpu->isar.regs[MVFR2]; cpu->power_state = s->start_powered_off ? PSCI_OFF : PSCI_ON; @@ -1211,6 +1213,509 @@ unsigned int gt_cntfrq_period_ns(ARMCPU *cpu) NANOSECONDS_PER_SECOND / cpu->gt_cntfrq_hz : 1; } +/** + * CPUFeatureInfo: + * @reg: The ID register where the ID field is in. + * @name: The name of the CPU feature. + * @length: The bit length of the ID field. + * @shift: The bit shift of the ID field in the ID register. + * @min_value: The minimum value equal to or larger than which means the CPU + * feature is implemented. + * @ni_value: Not-implemented value. It will be set to the ID field when + * disabling the CPU feature. Usually, it's min_value - 1. + * @sign: Whether the ID field is signed. + * @is_32bit: Whether the CPU feature is for 32-bit. + * + * In ARM, a CPU feature is described by an ID field, which is a 4-bit field in + * an ID register. + */ +typedef struct CPUFeatureInfo { + CPUIDReg reg; + const char *name; + int length; + int shift; + int min_value; + int ni_value; + bool sign; + bool is_32bit; +} CPUFeatureInfo; + +#define FIELD_INFO(feature_name, id_reg, field, s, min_val, ni_val, is32bit) { \ + .reg = id_reg, \ + .length = R_ ## id_reg ## _ ## field ## _LENGTH, \ + .shift = R_ ## id_reg ## _ ## field ## _SHIFT, \ + .sign = s, \ + .min_value = min_val, \ + .ni_value = ni_val, \ + .name = feature_name, \ + .is_32bit = is32bit, \ +} + +static struct CPUFeatureInfo cpu_features[] = { + FIELD_INFO("swap", ID_ISAR0, SWAP, false, 1, 0, true), + FIELD_INFO("bitcount", ID_ISAR0, BITCOUNT, false, 1, 0, true), + FIELD_INFO("bitfield", ID_ISAR0, BITFIELD, false, 1, 0, true), + FIELD_INFO("cmpbranch", ID_ISAR0, CMPBRANCH, false, 1, 0, true), + FIELD_INFO("coproc", ID_ISAR0, COPROC, false, 1, 0, true), + FIELD_INFO("debug", ID_ISAR0, DEBUG, false, 1, 0, true), + FIELD_INFO("device", ID_ISAR0, DIVIDE, false, 1, 0, true), + + FIELD_INFO("endian", ID_ISAR1, ENDIAN, false, 1, 0, true), + FIELD_INFO("except", ID_ISAR1, EXCEPT, false, 1, 0, true), + FIELD_INFO("except_ar", ID_ISAR1, EXCEPT_AR, false, 1, 0, true), + FIELD_INFO("extend", ID_ISAR1, EXTEND, false, 1, 0, true), + FIELD_INFO("ifthen", ID_ISAR1, IFTHEN, false, 1, 0, true), + FIELD_INFO("immediate", ID_ISAR1, IMMEDIATE, false, 1, 0, true), + FIELD_INFO("interwork", ID_ISAR1, INTERWORK, false, 1, 0, true), + FIELD_INFO("jazelle", ID_ISAR1, JAZELLE, false, 1, 0, true), + + FIELD_INFO("loadstore", ID_ISAR2, LOADSTORE, false, 1, 0, true), + FIELD_INFO("memhint", ID_ISAR2, MEMHINT, false, 1, 0, true), + FIELD_INFO("multiaccessint", ID_ISAR2, MULTIACCESSINT, false, 1, 0, true), + FIELD_INFO("mult", ID_ISAR2, MULT, false, 1, 0, true), + FIELD_INFO("mults", ID_ISAR2, MULTS, false, 1, 0, true), + FIELD_INFO("multu", ID_ISAR2, MULTU, false, 1, 0, true), + FIELD_INFO("psr_ar", ID_ISAR2, PSR_AR, false, 1, 0, true), + FIELD_INFO("reversal", ID_ISAR2, REVERSAL, false, 1, 0, true), + + FIELD_INFO("saturate", ID_ISAR3, SATURATE, false, 1, 0, true), + FIELD_INFO("simd", ID_ISAR3, SIMD, false, 1, 0, true), + FIELD_INFO("svc", ID_ISAR3, SVC, false, 1, 0, true), + FIELD_INFO("synchprim", ID_ISAR3, SYNCHPRIM, false, 1, 0, true), + FIELD_INFO("tabbranch", ID_ISAR3, TABBRANCH, false, 1, 0, true), + FIELD_INFO("t32copy", ID_ISAR3, T32COPY, false, 1, 0, true), + FIELD_INFO("truenop", ID_ISAR3, TRUENOP, false, 1, 0, true), + FIELD_INFO("t32ee", ID_ISAR3, T32EE, false, 1, 0, true), + + FIELD_INFO("unpriv", ID_ISAR4, UNPRIV, false, 1, 0, true), + FIELD_INFO("withshifts", ID_ISAR4, WITHSHIFTS, false, 1, 0, true), + FIELD_INFO("writeback", ID_ISAR4, WRITEBACK, false, 1, 0, true), + FIELD_INFO("smc", ID_ISAR4, SMC, false, 1, 0, true), + FIELD_INFO("barrier", ID_ISAR4, BARRIER, false, 1, 0, true), + FIELD_INFO("synchprim_frac", ID_ISAR4, SYNCHPRIM_FRAC, false, 1, 0, true), + FIELD_INFO("psr_m", ID_ISAR4, PSR_M, false, 1, 0, true), + FIELD_INFO("swp_frac", ID_ISAR4, SWP_FRAC, false, 1, 0, true), + + FIELD_INFO("sevl", ID_ISAR5, SEVL, false, 1, 0, true), + FIELD_INFO("aes", ID_ISAR5, AES, false, 1, 0, true), + FIELD_INFO("sha1", ID_ISAR5, SHA1, false, 1, 0, true), + FIELD_INFO("sha2", ID_ISAR5, SHA2, false, 1, 0, true), + FIELD_INFO("crc32", ID_ISAR5, CRC32, false, 1, 0, true), + FIELD_INFO("rdm", ID_ISAR5, RDM, false, 1, 0, true), + FIELD_INFO("vcma", ID_ISAR5, VCMA, false, 1, 0, true), + + FIELD_INFO("jscvt", ID_ISAR6, JSCVT, false, 1, 0, true), + FIELD_INFO("dp", ID_ISAR6, DP, false, 1, 0, true), + FIELD_INFO("fhm", ID_ISAR6, FHM, false, 1, 0, true), + FIELD_INFO("sb", ID_ISAR6, SB, false, 1, 0, true), + FIELD_INFO("specres", ID_ISAR6, SPECRES, false, 1, 0, true), + FIELD_INFO("i8mm", ID_AA64ISAR1, I8MM, false, 1, 0, false), + FIELD_INFO("bf16", ID_AA64ISAR1, BF16, false, 1, 0, false), + FIELD_INFO("dgh", ID_AA64ISAR1, DGH, false, 1, 0, false), + + FIELD_INFO("cmaintva", ID_MMFR3, CMAINTVA, false, 1, 0, true), + FIELD_INFO("cmaintsw", ID_MMFR3, CMAINTSW, false, 1, 0, true), + FIELD_INFO("bpmaint", ID_MMFR3, BPMAINT, false, 1, 0, true), + FIELD_INFO("maintbcst", ID_MMFR3, MAINTBCST, false, 1, 0, true), + FIELD_INFO("pan", ID_MMFR3, PAN, false, 1, 0, true), + FIELD_INFO("cohwalk", ID_MMFR3, COHWALK, false, 1, 0, true), + FIELD_INFO("cmemsz", ID_MMFR3, CMEMSZ, false, 1, 0, true), + FIELD_INFO("supersec", ID_MMFR3, SUPERSEC, false, 1, 0, true), + + FIELD_INFO("specsei", ID_MMFR4, SPECSEI, false, 1, 0, true), + FIELD_INFO("ac2", ID_MMFR4, AC2, false, 1, 0, true), + FIELD_INFO("xnx", ID_MMFR4, XNX, false, 1, 0, true), + FIELD_INFO("cnp", ID_MMFR4, CNP, false, 1, 0, true), + FIELD_INFO("hpds", ID_MMFR4, HPDS, false, 1, 0, true), + FIELD_INFO("lsm", ID_MMFR4, LSM, false, 1, 0, true), + FIELD_INFO("ccidx", ID_MMFR4, CCIDX, false, 1, 0, true), + FIELD_INFO("evt", ID_MMFR4, EVT, false, 1, 0, true), + + FIELD_INFO("simdreg", MVFR0, SIMDREG, false, 1, 0, true), + FIELD_INFO("fpsp", MVFR0, FPSP, false, 1, 0, true), + FIELD_INFO("fpdp", MVFR0, FPDP, false, 1, 0, true), + FIELD_INFO("fptrap", MVFR0, FPTRAP, false, 1, 0, true), + FIELD_INFO("fpdivide", MVFR0, FPDIVIDE, false, 1, 0, true), + FIELD_INFO("fpsqrt", MVFR0, FPSQRT, false, 1, 0, true), + FIELD_INFO("fpshvec", MVFR0, FPSHVEC, false, 1, 0, true), + FIELD_INFO("fpround", MVFR0, FPROUND, false, 1, 0, true), + + FIELD_INFO("fpftz", MVFR1, FPFTZ, false, 1, 0, true), + FIELD_INFO("fpdnan", MVFR1, FPDNAN, false, 1, 0, true), + FIELD_INFO("simdls", MVFR1, SIMDLS, false, 1, 0, true), + FIELD_INFO("simdint", MVFR1, SIMDINT, false, 1, 0, true), + FIELD_INFO("simdsp", MVFR1, SIMDSP, false, 1, 0, true), + FIELD_INFO("simdhp", MVFR1, SIMDHP, false, 1, 0, true), + FIELD_INFO("fphp", MVFR1, FPHP, false, 1, 0, true), + FIELD_INFO("simdfmac", MVFR1, SIMDFMAC, false, 1, 0, true), + + FIELD_INFO("simdmisc", MVFR2, SIMDMISC, false, 1, 0, true), + FIELD_INFO("fpmisc", MVFR2, FPMISC, false, 1, 0, true), + + FIELD_INFO("debugver", ID_AA64DFR0, DEBUGVER, false, 1, 0, false), + FIELD_INFO("tracever", ID_AA64DFR0, TRACEVER, false, 1, 0, false), + FIELD_INFO("pmuver", ID_AA64DFR0, PMUVER, false, 1, 0, false), + FIELD_INFO("brps", ID_AA64DFR0, BRPS, false, 1, 0, false), + FIELD_INFO("wrps", ID_AA64DFR0, WRPS, false, 1, 0, false), + FIELD_INFO("ctx_cmps", ID_AA64DFR0, CTX_CMPS, false, 1, 0, false), + FIELD_INFO("pmsver", ID_AA64DFR0, PMSVER, false, 1, 0, false), + FIELD_INFO("doublelock", ID_AA64DFR0, DOUBLELOCK, false, 1, 0, false), + FIELD_INFO("tracefilt", ID_AA64DFR0, TRACEFILT, false, 1, 0, false), + + FIELD_INFO("aes", ID_AA64ISAR0, AES, false, 1, 0, false), + FIELD_INFO("sha1", ID_AA64ISAR0, SHA1, false, 1, 0, false), + FIELD_INFO("sha2", ID_AA64ISAR0, SHA2, false, 1, 0, false), + FIELD_INFO("crc32", ID_AA64ISAR0, CRC32, false, 1, 0, false), + FIELD_INFO("atomics", ID_AA64ISAR0, ATOMIC, false, 1, 0, false), + FIELD_INFO("asimdrdm", ID_AA64ISAR0, RDM, false, 1, 0, false), + FIELD_INFO("sha3", ID_AA64ISAR0, SHA3, false, 1, 0, false), + FIELD_INFO("sm3", ID_AA64ISAR0, SM3, false, 1, 0, false), + FIELD_INFO("sm4", ID_AA64ISAR0, SM4, false, 1, 0, false), + FIELD_INFO("asimddp", ID_AA64ISAR0, DP, false, 1, 0, false), + FIELD_INFO("asimdfhm", ID_AA64ISAR0, FHM, false, 1, 0, false), + FIELD_INFO("flagm", ID_AA64ISAR0, TS, false, 1, 0, false), + FIELD_INFO("tlb", ID_AA64ISAR0, TLB, false, 1, 0, false), + FIELD_INFO("rng", ID_AA64ISAR0, RNDR, false, 1, 0, false), + + FIELD_INFO("dcpop", ID_AA64ISAR1, DPB, false, 1, 0, false), + FIELD_INFO("papa", ID_AA64ISAR1, APA, false, 1, 0, false), + FIELD_INFO("api", ID_AA64ISAR1, API, false, 1, 0, false), + FIELD_INFO("jscvt", ID_AA64ISAR1, JSCVT, false, 1, 0, false), + FIELD_INFO("fcma", ID_AA64ISAR1, FCMA, false, 1, 0, false), + FIELD_INFO("lrcpc", ID_AA64ISAR1, LRCPC, false, 1, 0, false), + FIELD_INFO("pacg", ID_AA64ISAR1, GPA, false, 1, 0, false), + FIELD_INFO("gpi", ID_AA64ISAR1, GPI, false, 1, 0, false), + FIELD_INFO("frint", ID_AA64ISAR1, FRINTTS, false, 1, 0, false), + FIELD_INFO("sb", ID_AA64ISAR1, SB, false, 1, 0, false), + FIELD_INFO("specres", ID_AA64ISAR1, SPECRES, false, 1, 0, false), + + FIELD_INFO("el0", ID_AA64PFR0, EL0, false, 1, 0, false), + FIELD_INFO("el1", ID_AA64PFR0, EL1, false, 1, 0, false), + FIELD_INFO("el2", ID_AA64PFR0, EL2, false, 1, 0, false), + FIELD_INFO("el3", ID_AA64PFR0, EL3, false, 1, 0, false), + FIELD_INFO("fp", ID_AA64PFR0, FP, true, 0, 0xf, false), + FIELD_INFO("asimd", ID_AA64PFR0, ADVSIMD, true, 0, 0xf, false), + FIELD_INFO("gic", ID_AA64PFR0, GIC, false, 1, 0, false), + FIELD_INFO("ras", ID_AA64PFR0, RAS, false, 1, 0, false), + FIELD_INFO("sve", ID_AA64PFR0, SVE, false, 1, 0, false), + + FIELD_INFO("bti", ID_AA64PFR1, BT, false, 1, 0, false), + FIELD_INFO("ssbs", ID_AA64PFR1, SSBS, false, 1, 0, false), + FIELD_INFO("mte", ID_AA64PFR1, MTE, false, 1, 0, false), + FIELD_INFO("ras_frac", ID_AA64PFR1, RAS_FRAC, false, 1, 0, false), + + FIELD_INFO("parange", ID_AA64MMFR0, PARANGE, false, 1, 0, false), + FIELD_INFO("asidbits", ID_AA64MMFR0, ASIDBITS, false, 1, 0, false), + FIELD_INFO("bigend", ID_AA64MMFR0, BIGEND, false, 1, 0, false), + FIELD_INFO("snsmem", ID_AA64MMFR0, SNSMEM, false, 1, 0, false), + FIELD_INFO("bigendel0", ID_AA64MMFR0, BIGENDEL0, false, 1, 0, false), + FIELD_INFO("tgran16", ID_AA64MMFR0, TGRAN16, false, 1, 0, false), + FIELD_INFO("tgran64", ID_AA64MMFR0, TGRAN64, false, 1, 0, false), + FIELD_INFO("tgran4", ID_AA64MMFR0, TGRAN4, false, 1, 0, false), + FIELD_INFO("tgran16_2", ID_AA64MMFR0, TGRAN16_2, false, 1, 0, false), + FIELD_INFO("tgran64_2", ID_AA64MMFR0, TGRAN64_2, false, 1, 0, false), + FIELD_INFO("tgran4_2", ID_AA64MMFR0, TGRAN4_2, false, 1, 0, false), + FIELD_INFO("exs", ID_AA64MMFR0, EXS, false, 1, 0, false), + + FIELD_INFO("hafdbs", ID_AA64MMFR1, HAFDBS, false, 1, 0, false), + FIELD_INFO("vmidbits", ID_AA64MMFR1, VMIDBITS, false, 1, 0, false), + FIELD_INFO("vh", ID_AA64MMFR1, VH, false, 1, 0, false), + FIELD_INFO("hpds", ID_AA64MMFR1, HPDS, false, 1, 0, false), + FIELD_INFO("lo", ID_AA64MMFR1, LO, false, 1, 0, false), + FIELD_INFO("pan", ID_AA64MMFR1, PAN, false, 1, 0, false), + FIELD_INFO("specsei", ID_AA64MMFR1, SPECSEI, false, 1, 0, false), + FIELD_INFO("xnx", ID_AA64MMFR1, XNX, false, 1, 0, false), + + FIELD_INFO("cnp", ID_AA64MMFR2, CNP, false, 1, 0, false), + FIELD_INFO("uao", ID_AA64MMFR2, UAO, false, 1, 0, false), + FIELD_INFO("lsm", ID_AA64MMFR2, LSM, false, 1, 0, false), + FIELD_INFO("iesb", ID_AA64MMFR2, IESB, false, 1, 0, false), + FIELD_INFO("varange", ID_AA64MMFR2, VARANGE, false, 1, 0, false), + FIELD_INFO("ccidx", ID_AA64MMFR2, CCIDX, false, 1, 0, false), + FIELD_INFO("nv", ID_AA64MMFR2, NV, false, 1, 0, false), + FIELD_INFO("st", ID_AA64MMFR2, ST, false, 1, 0, false), + FIELD_INFO("uscat", ID_AA64MMFR2, AT, false, 1, 0, false), + FIELD_INFO("ids", ID_AA64MMFR2, IDS, false, 1, 0, false), + FIELD_INFO("fwb", ID_AA64MMFR2, FWB, false, 1, 0, false), + FIELD_INFO("ttl", ID_AA64MMFR2, TTL, false, 1, 0, false), + FIELD_INFO("bbm", ID_AA64MMFR2, BBM, false, 1, 0, false), + FIELD_INFO("evt", ID_AA64MMFR2, EVT, false, 1, 0, false), + FIELD_INFO("e0pd", ID_AA64MMFR2, E0PD, false, 1, 0, false), + + FIELD_INFO("copdbg", ID_DFR0, COPDBG, false, 1, 0, false), + FIELD_INFO("copsdbg", ID_DFR0, COPSDBG, false, 1, 0, false), + FIELD_INFO("mmapdbg", ID_DFR0, MMAPDBG, false, 1, 0, false), + FIELD_INFO("coptrc", ID_DFR0, COPTRC, false, 1, 0, false), + FIELD_INFO("mmaptrc", ID_DFR0, MMAPTRC, false, 1, 0, false), + FIELD_INFO("mprofdbg", ID_DFR0, MPROFDBG, false, 1, 0, false), + FIELD_INFO("perfmon", ID_DFR0, PERFMON, false, 1, 0, false), + FIELD_INFO("tracefilt", ID_DFR0, TRACEFILT, false, 1, 0, false), + + { + .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_FP_LENGTH, + .shift = R_ID_AA64PFR0_FP_SHIFT, .sign = true, .min_value = 1, + .ni_value = 0, .name = "fphp", .is_32bit = false, + }, + { + .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_ADVSIMD_LENGTH, + .shift = R_ID_AA64PFR0_ADVSIMD_SHIFT, .sign = true, .min_value = 1, + .ni_value = 0, .name = "asimdhp", .is_32bit = false, + }, + { + .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_AES_LENGTH, + .shift = R_ID_AA64ISAR0_AES_SHIFT, .sign = false, .min_value = 2, + .ni_value = 1, .name = "pmull", .is_32bit = false, + }, + { + .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_SHA2_LENGTH, + .shift = R_ID_AA64ISAR0_SHA2_SHIFT, .sign = false, .min_value = 2, + .ni_value = 1, .name = "sha512", .is_32bit = false, + }, + { + .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_TS_LENGTH, + .shift = R_ID_AA64ISAR0_TS_SHIFT, .sign = false, .min_value = 2, + .ni_value = 1, .name = "flagm2", .is_32bit = false, + }, + { + .reg = ID_AA64ISAR1, .length = R_ID_AA64ISAR1_DPB_LENGTH, + .shift = R_ID_AA64ISAR1_DPB_SHIFT, .sign = false, .min_value = 2, + .ni_value = 1, .name = "dcpodp", .is_32bit = false, + }, + { + .reg = ID_AA64ISAR1, .length = R_ID_AA64ISAR1_LRCPC_LENGTH, + .shift = R_ID_AA64ISAR1_LRCPC_SHIFT, .sign = false, .min_value = 2, + .ni_value = 1, .name = "ilrcpc", .is_32bit = false, + }, +}; + +typedef struct CPUFeatureDep { + CPUFeatureInfo from, to; +} CPUFeatureDep; + +static const CPUFeatureDep feature_dependencies[] = { + { + .from = FIELD_INFO("fp", ID_AA64PFR0, FP, true, 0, 0xf, false), + .to = FIELD_INFO("asimd", ID_AA64PFR0, ADVSIMD, true, 0, 0xf, false), + }, + { + .from = FIELD_INFO("asimd", ID_AA64PFR0, ADVSIMD, true, 0, 0xf, false), + .to = FIELD_INFO("fp", ID_AA64PFR0, FP, true, 0, 0xf, false), + }, + { + .from = { + .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_FP_LENGTH, + .shift = R_ID_AA64PFR0_FP_SHIFT, .sign = true, .min_value = 1, + .ni_value = 0, .name = "fphp", .is_32bit = false, + }, + .to = { + .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_ADVSIMD_LENGTH, + .shift = R_ID_AA64PFR0_ADVSIMD_SHIFT, .sign = true, .min_value = 1, + .ni_value = 0, .name = "asimdhp", .is_32bit = false, + }, + }, + { + .from = { + .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_ADVSIMD_LENGTH, + .shift = R_ID_AA64PFR0_ADVSIMD_SHIFT, .sign = true, .min_value = 1, + .ni_value = 0, .name = "asimdhp", .is_32bit = false, + }, + .to = { + .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_FP_LENGTH, + .shift = R_ID_AA64PFR0_FP_SHIFT, .sign = true, .min_value = 1, + .ni_value = 0, .name = "fphp", .is_32bit = false, + }, + }, + { + + .from = FIELD_INFO("aes", ID_AA64ISAR0, AES, false, 1, 0, false), + .to = { + .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_AES_LENGTH, + .shift = R_ID_AA64ISAR0_AES_SHIFT, .sign = false, .min_value = 2, + .ni_value = 1, .name = "pmull", .is_32bit = false, + }, + }, + { + + .from = FIELD_INFO("sha2", ID_AA64ISAR0, SHA2, false, 1, 0, false), + .to = { + .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_SHA2_LENGTH, + .shift = R_ID_AA64ISAR0_SHA2_SHIFT, .sign = false, .min_value = 2, + .ni_value = 1, .name = "sha512", .is_32bit = false, + }, + }, + { + .from = FIELD_INFO("lrcpc", ID_AA64ISAR1, LRCPC, false, 1, 0, false), + .to = { + .reg = ID_AA64ISAR1, .length = R_ID_AA64ISAR1_LRCPC_LENGTH, + .shift = R_ID_AA64ISAR1_LRCPC_SHIFT, .sign = false, .min_value = 2, + .ni_value = 1, .name = "ilrcpc", .is_32bit = false, + }, + }, + { + .from = FIELD_INFO("sm3", ID_AA64ISAR0, SM3, false, 1, 0, false), + .to = FIELD_INFO("sm4", ID_AA64ISAR0, SM4, false, 1, 0, false), + }, + { + .from = FIELD_INFO("sm4", ID_AA64ISAR0, SM4, false, 1, 0, false), + .to = FIELD_INFO("sm3", ID_AA64ISAR0, SM3, false, 1, 0, false), + }, + { + .from = FIELD_INFO("sha1", ID_AA64ISAR0, SHA1, false, 1, 0, false), + .to = FIELD_INFO("sha2", ID_AA64ISAR0, SHA2, false, 1, 0, false), + }, + { + .from = FIELD_INFO("sha1", ID_AA64ISAR0, SHA1, false, 1, 0, false), + .to = FIELD_INFO("sha3", ID_AA64ISAR0, SHA3, false, 1, 0, false), + }, + { + .from = FIELD_INFO("sha3", ID_AA64ISAR0, SHA3, false, 1, 0, false), + .to = { + .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_SHA2_LENGTH, + .shift = R_ID_AA64ISAR0_SHA2_SHIFT, .sign = false, .min_value = 2, + .ni_value = 1, .name = "sha512", .is_32bit = false, + }, + }, + { + .from = { + .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_SHA2_LENGTH, + .shift = R_ID_AA64ISAR0_SHA2_SHIFT, .sign = false, .min_value = 2, + .ni_value = 1, .name = "sha512", .is_32bit = false, + }, + .to = FIELD_INFO("sha3", ID_AA64ISAR0, SHA3, false, 1, 0, false), + }, +}; + +void arm_cpu_features_to_dict(ARMCPU *cpu, QDict *features) +{ + Object *obj = OBJECT(cpu); + const char *name; + ObjectProperty *prop; + bool is_32bit = !arm_feature(&cpu->env, ARM_FEATURE_AARCH64); + int i; + + for (i = 0; i < ARRAY_SIZE(cpu_features); ++i) { + if (is_32bit != cpu_features[i].is_32bit) { + continue; + } + + name = cpu_features[i].name; + prop = object_property_find(obj, name); + if (prop) { + QObject *value; + + assert(prop->get); + value = object_property_get_qobject(obj, name, &error_abort); + qdict_put_obj(features, name, value); + } + } +} + +static void arm_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + ARMCPU *cpu = ARM_CPU(obj); + CPUFeatureInfo *feat = opaque; + int field_value = feat->sign ? sextract64(cpu->isar.regs[feat->reg], + feat->shift, feat->length) : + extract64(cpu->isar.regs[feat->reg], + feat->shift, feat->length); + bool value = field_value >= feat->min_value; + + visit_type_bool(v, name, &value, errp); +} + +static void arm_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; + CPUFeatureInfo *feat = opaque; + Error *local_err = NULL; + bool value; + + if (!kvm_arm_cpu_feature_supported()) { + warn_report("KVM doesn't support to set CPU feature in arm. " + "Setting to `%s` is ignored.", name); + return; + } + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + visit_type_bool(v, name, &value, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + if (value) { + if (object_property_get_bool(obj, feat->name, NULL)) { + return; + } + isar->regs[feat->reg] = deposit64(isar->regs[feat->reg], + feat->shift, feat->length, + feat->min_value); + /* Auto enable the features which current feature is dependent on. */ + for (int i = 0; i < ARRAY_SIZE(feature_dependencies); ++i) { + const CPUFeatureDep *d = &feature_dependencies[i]; + if (strcmp(d->to.name, feat->name) != 0) { + continue; + } + + object_property_set_bool(obj, d->from.name, true, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + } + } else { + if (!object_property_get_bool(obj, feat->name, NULL)) { + return; + } + isar->regs[feat->reg] = deposit64(isar->regs[feat->reg], + feat->shift, feat->length, + feat->ni_value); + /* Auto disable the features which are dependent on current feature. */ + for (int i = 0; i < ARRAY_SIZE(feature_dependencies); ++i) { + const CPUFeatureDep *d = &feature_dependencies[i]; + if (strcmp(d->from.name, feat->name) != 0) { + continue; + } + + object_property_set_bool(obj, d->to.name, false, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + } + } +} + +static void arm_cpu_register_feature_props(ARMCPU *cpu) +{ + int i; + int num = ARRAY_SIZE(cpu_features); + ObjectProperty *op; + CPUARMState *env = &cpu->env; + + for (i = 0; i < num; i++) { + if ((arm_feature(env, ARM_FEATURE_AARCH64) && cpu_features[i].is_32bit) + || (!arm_feature(env, ARM_FEATURE_AARCH64) && + cpu_features[i].is_32bit)) { + continue; + } + op = object_property_find(OBJECT(cpu), cpu_features[i].name); + if (!op) { + object_property_add(OBJECT(cpu), cpu_features[i].name, "bool", + arm_cpu_get_bit_prop, + arm_cpu_set_bit_prop, + NULL, &cpu_features[i]); + } + } +} + void arm_cpu_post_init(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); @@ -1319,6 +1824,8 @@ void arm_cpu_post_init(Object *obj) qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property); + arm_cpu_register_feature_props(cpu); + if (arm_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER)) { qdev_property_add_static(DEVICE(cpu), &arm_cpu_gt_cntfrq_property); } @@ -1520,20 +2027,20 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) uint64_t t; uint32_t u; - t = cpu->isar.id_aa64isar1; + t = cpu->isar.regs[ID_AA64ISAR1]; t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 0); - cpu->isar.id_aa64isar1 = t; + cpu->isar.regs[ID_AA64ISAR1] = t; - t = cpu->isar.id_aa64pfr0; + t = cpu->isar.regs[ID_AA64PFR0]; t = FIELD_DP64(t, ID_AA64PFR0, FP, 0xf); - cpu->isar.id_aa64pfr0 = t; + cpu->isar.regs[ID_AA64PFR0] = t; - u = cpu->isar.id_isar6; + u = cpu->isar.regs[ID_ISAR6]; u = FIELD_DP32(u, ID_ISAR6, JSCVT, 0); u = FIELD_DP32(u, ID_ISAR6, BF16, 0); - cpu->isar.id_isar6 = u; + cpu->isar.regs[ID_ISAR6] = u; - u = cpu->isar.mvfr0; + u = cpu->isar.regs[MVFR0]; u = FIELD_DP32(u, MVFR0, FPSP, 0); u = FIELD_DP32(u, MVFR0, FPDP, 0); u = FIELD_DP32(u, MVFR0, FPDIVIDE, 0); @@ -1543,20 +2050,20 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) u = FIELD_DP32(u, MVFR0, FPTRAP, 0); u = FIELD_DP32(u, MVFR0, FPSHVEC, 0); } - cpu->isar.mvfr0 = u; + cpu->isar.regs[MVFR0] = u; - u = cpu->isar.mvfr1; + u = cpu->isar.regs[MVFR1]; u = FIELD_DP32(u, MVFR1, FPFTZ, 0); u = FIELD_DP32(u, MVFR1, FPDNAN, 0); u = FIELD_DP32(u, MVFR1, FPHP, 0); if (arm_feature(env, ARM_FEATURE_M)) { u = FIELD_DP32(u, MVFR1, FP16, 0); } - cpu->isar.mvfr1 = u; + cpu->isar.regs[MVFR1] = u; - u = cpu->isar.mvfr2; + u = cpu->isar.regs[MVFR2]; u = FIELD_DP32(u, MVFR2, FPMISC, 0); - cpu->isar.mvfr2 = u; + cpu->isar.regs[MVFR2] = u; } if (!cpu->has_neon) { @@ -1565,43 +2072,43 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) unset_feature(env, ARM_FEATURE_NEON); - t = cpu->isar.id_aa64isar0; + t = cpu->isar.regs[ID_AA64ISAR0]; t = FIELD_DP64(t, ID_AA64ISAR0, DP, 0); - cpu->isar.id_aa64isar0 = t; + cpu->isar.regs[ID_AA64ISAR0] = t; - t = cpu->isar.id_aa64isar1; + t = cpu->isar.regs[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; + cpu->isar.regs[ID_AA64ISAR1] = t; - t = cpu->isar.id_aa64pfr0; + t = cpu->isar.regs[ID_AA64PFR0]; t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 0xf); - cpu->isar.id_aa64pfr0 = t; + cpu->isar.regs[ID_AA64PFR0] = t; - u = cpu->isar.id_isar5; + u = cpu->isar.regs[ID_ISAR5]; u = FIELD_DP32(u, ID_ISAR5, RDM, 0); u = FIELD_DP32(u, ID_ISAR5, VCMA, 0); - cpu->isar.id_isar5 = u; + cpu->isar.regs[ID_ISAR5] = u; - u = cpu->isar.id_isar6; + u = cpu->isar.regs[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; + cpu->isar.regs[ID_ISAR6] = u; if (!arm_feature(env, ARM_FEATURE_M)) { - u = cpu->isar.mvfr1; + u = cpu->isar.regs[MVFR1]; u = FIELD_DP32(u, MVFR1, SIMDLS, 0); u = FIELD_DP32(u, MVFR1, SIMDINT, 0); u = FIELD_DP32(u, MVFR1, SIMDSP, 0); u = FIELD_DP32(u, MVFR1, SIMDHP, 0); - cpu->isar.mvfr1 = u; + cpu->isar.regs[MVFR1] = u; - u = cpu->isar.mvfr2; + u = cpu->isar.regs[MVFR2]; u = FIELD_DP32(u, MVFR2, SIMDMISC, 0); - cpu->isar.mvfr2 = u; + cpu->isar.regs[MVFR2] = u; } } @@ -1609,22 +2116,22 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) uint64_t t; uint32_t u; - t = cpu->isar.id_aa64isar0; + t = cpu->isar.regs[ID_AA64ISAR0]; t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 0); - cpu->isar.id_aa64isar0 = t; + cpu->isar.regs[ID_AA64ISAR0] = t; - t = cpu->isar.id_aa64isar1; + t = cpu->isar.regs[ID_AA64ISAR1]; t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 0); - cpu->isar.id_aa64isar1 = t; + cpu->isar.regs[ID_AA64ISAR1] = t; - u = cpu->isar.mvfr0; + u = cpu->isar.regs[MVFR0]; u = FIELD_DP32(u, MVFR0, SIMDREG, 0); - cpu->isar.mvfr0 = u; + cpu->isar.regs[MVFR0] = u; /* Despite the name, this field covers both VFP and Neon */ - u = cpu->isar.mvfr1; + u = cpu->isar.regs[MVFR1]; u = FIELD_DP32(u, MVFR1, SIMDFMAC, 0); - cpu->isar.mvfr1 = u; + cpu->isar.regs[MVFR1] = u; } if (arm_feature(env, ARM_FEATURE_M) && !cpu->has_dsp) { @@ -1632,19 +2139,19 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) unset_feature(env, ARM_FEATURE_THUMB_DSP); - u = cpu->isar.id_isar1; + u = cpu->isar.regs[ID_ISAR1]; u = FIELD_DP32(u, ID_ISAR1, EXTEND, 1); - cpu->isar.id_isar1 = u; + cpu->isar.regs[ID_ISAR1] = u; - u = cpu->isar.id_isar2; + u = cpu->isar.regs[ID_ISAR2]; u = FIELD_DP32(u, ID_ISAR2, MULTU, 1); u = FIELD_DP32(u, ID_ISAR2, MULTS, 1); - cpu->isar.id_isar2 = u; + cpu->isar.regs[ID_ISAR2] = u; - u = cpu->isar.id_isar3; + u = cpu->isar.regs[ID_ISAR3]; u = FIELD_DP32(u, ID_ISAR3, SIMD, 1); u = FIELD_DP32(u, ID_ISAR3, SATURATE, 0); - cpu->isar.id_isar3 = u; + cpu->isar.regs[ID_ISAR3] = u; } /* Some features automatically imply others: */ @@ -1776,7 +2283,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) } } - if (!arm_feature(env, ARM_FEATURE_M) && !cpu->has_el3) { + if (!arm_feature(env, ARM_FEATURE_M) && !cpu->has_el3 && !kvm_enabled()) { /* If the has_el3 CPU property is disabled then we need to disable the * feature. */ @@ -1785,8 +2292,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) /* Disable the security extension feature bits in the processor feature * registers as well. These are id_pfr1[7:4] and id_aa64pfr0[15:12]. */ - cpu->isar.id_pfr1 &= ~0xf0; - cpu->isar.id_aa64pfr0 &= ~0xf000; + cpu->isar.regs[ID_PFR1] &= ~0xf0; + cpu->isar.regs[ID_AA64PFR0] &= ~0xf000; } if (!cpu->has_el2) { @@ -1809,20 +2316,21 @@ 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); + cpu->isar.regs[ID_AA64DFR0] = + FIELD_DP64(cpu->isar.regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER, 0); + cpu->isar.regs[ID_DFR0] = FIELD_DP32(cpu->isar.regs[ID_DFR0], ID_DFR0, + PERFMON, 0); cpu->pmceid0 = 0; cpu->pmceid1 = 0; } - if (!arm_feature(env, ARM_FEATURE_EL2)) { + if (!arm_feature(env, ARM_FEATURE_EL2) && !kvm_enabled()) { /* Disable the hypervisor feature bits in the processor feature * registers if we don't have EL2. These are id_pfr1[15:12] and * id_aa64pfr0_el1[11:8]. */ - cpu->isar.id_aa64pfr0 &= ~0xf00; - cpu->isar.id_pfr1 &= ~0xf000; + cpu->isar.regs[ID_AA64PFR0] &= ~0xf00; + cpu->isar.regs[ID_PFR1] &= ~0xf000; } #ifndef CONFIG_USER_ONLY @@ -1831,8 +2339,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) * Disable the MTE feature bits if we do not have tag-memory * provided by the machine. */ - cpu->isar.id_aa64pfr1 = - FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 0); + cpu->isar.regs[ID_AA64PFR1] = + FIELD_DP64(cpu->isar.regs[ID_AA64PFR1], ID_AA64PFR1, MTE, 0); } #endif diff --git a/target/arm/cpu.h b/target/arm/cpu.h index e33f37b70adaef0a49debcf703e4e1be66dc3055..947897d5acc144867591b72cbaf0c80a36770f43 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -69,6 +69,41 @@ #define ARMV7M_EXCP_PENDSV 14 #define ARMV7M_EXCP_SYSTICK 15 +typedef enum CPUIDReg { + MIDR_EL1, + ID_ISAR0, + ID_ISAR1, + ID_ISAR2, + ID_ISAR3, + ID_ISAR4, + ID_ISAR5, + ID_ISAR6, + ID_PFR0, + ID_PFR1, + ID_PFR2, + ID_MMFR0, + ID_MMFR1, + ID_MMFR2, + ID_MMFR3, + ID_MMFR4, + ID_AA64ISAR0, + ID_AA64ISAR1, + ID_AA64PFR0, + ID_AA64PFR1, + ID_AA64MMFR0, + ID_AA64MMFR1, + ID_AA64MMFR2, + ID_AA64DFR0, + ID_AA64DFR1, + ID_AA64ZFR0, + ID_DFR0, + MVFR0, + MVFR1, + MVFR2, + DBGDIDR, + ID_MAX, +} CPUIDReg; + /* For M profile, some registers are banked secure vs non-secure; * these are represented as a 2-element array where the first element * is the non-secure copy and the second is the secure copy. @@ -922,36 +957,7 @@ struct ARMCPU { * 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_pfr0; - uint32_t id_pfr1; - uint32_t id_pfr2; - uint32_t mvfr0; - uint32_t mvfr1; - uint32_t mvfr2; - uint32_t id_dfr0; - uint32_t dbgdidr; - uint64_t id_aa64isar0; - uint64_t id_aa64isar1; - 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 regs[ID_MAX]; } isar; uint64_t midr; uint32_t revidr; @@ -3729,103 +3735,103 @@ static inline target_ulong cpu_untagged_addr(CPUState *cs, target_ulong x) */ static inline bool isar_feature_aa32_thumb_div(const ARMISARegisters *id) { - return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) != 0; + return FIELD_EX32(id->regs[ID_ISAR0], 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(id->regs[ID_ISAR0], 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(id->regs[ID_ISAR0], 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(id->regs[ID_ISAR1], 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(id->regs[ID_ISAR5], 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(id->regs[ID_ISAR5], 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(id->regs[ID_ISAR5], 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(id->regs[ID_ISAR5], 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(id->regs[ID_ISAR5], 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(id->regs[ID_ISAR5], 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(id->regs[ID_ISAR5], 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(id->regs[ID_ISAR6], 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(id->regs[ID_ISAR6], 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(id->regs[ID_ISAR6], 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(id->regs[ID_ISAR6], 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(id->regs[ID_ISAR6], 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(id->regs[ID_ISAR6], 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(id->regs[ID_ISAR6], 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(id->regs[ID_PFR0], 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(id->regs[ID_PFR1], ID_PFR1, MPROGMOD) != 0; } static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id) @@ -3834,16 +3840,16 @@ 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(id->regs[ID_PFR1], ID_PFR1, SECURITY) >= 3; } static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id) { /* Sadly this is encoded differently for A-profile and M-profile */ if (isar_feature_aa32_mprofile(id)) { - return FIELD_EX32(id->mvfr1, MVFR1, FP16) > 0; + return FIELD_EX32(id->regs[MVFR1], MVFR1, FP16) > 0; } else { - return FIELD_EX32(id->mvfr1, MVFR1, FPHP) >= 3; + return FIELD_EX32(id->regs[MVFR1], MVFR1, FPHP) >= 3; } } @@ -3855,7 +3861,7 @@ static inline bool isar_feature_aa32_mve(const ARMISARegisters *id) * else for A-profile. */ return isar_feature_aa32_mprofile(id) && - FIELD_EX32(id->mvfr1, MVFR1, MVE) > 0; + FIELD_EX32(id->regs[MVFR1], MVFR1, MVE) > 0; } static inline bool isar_feature_aa32_mve_fp(const ARMISARegisters *id) @@ -3866,7 +3872,7 @@ static inline bool isar_feature_aa32_mve_fp(const ARMISARegisters *id) * else for A-profile. */ return isar_feature_aa32_mprofile(id) && - FIELD_EX32(id->mvfr1, MVFR1, MVE) >= 2; + FIELD_EX32(id->regs[MVFR1], MVFR1, MVE) >= 2; } static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id) @@ -3875,42 +3881,42 @@ static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id) * Return true if either VFP or SIMD is implemented. * In this case, a minimum of VFP w/ D0-D15. */ - return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) > 0; + return FIELD_EX32(id->regs[MVFR0], MVFR0, SIMDREG) > 0; } static inline bool isar_feature_aa32_simd_r32(const ARMISARegisters *id) { /* Return true if D16-D31 are implemented */ - return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) >= 2; + return FIELD_EX32(id->regs[MVFR0], MVFR0, SIMDREG) >= 2; } static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id) { - return FIELD_EX32(id->mvfr0, MVFR0, FPSHVEC) > 0; + return FIELD_EX32(id->regs[MVFR0], MVFR0, FPSHVEC) > 0; } static inline bool isar_feature_aa32_fpsp_v2(const ARMISARegisters *id) { /* Return true if CPU supports single precision floating point, VFPv2 */ - return FIELD_EX32(id->mvfr0, MVFR0, FPSP) > 0; + return FIELD_EX32(id->regs[MVFR0], MVFR0, FPSP) > 0; } static inline bool isar_feature_aa32_fpsp_v3(const ARMISARegisters *id) { /* Return true if CPU supports single precision floating point, VFPv3 */ - return FIELD_EX32(id->mvfr0, MVFR0, FPSP) >= 2; + return FIELD_EX32(id->regs[MVFR0], MVFR0, FPSP) >= 2; } static inline bool isar_feature_aa32_fpdp_v2(const ARMISARegisters *id) { /* Return true if CPU supports double precision floating point, VFPv2 */ - return FIELD_EX32(id->mvfr0, MVFR0, FPDP) > 0; + return FIELD_EX32(id->regs[MVFR0], MVFR0, FPDP) > 0; } static inline bool isar_feature_aa32_fpdp_v3(const ARMISARegisters *id) { /* Return true if CPU supports double precision floating point, VFPv3 */ - return FIELD_EX32(id->mvfr0, MVFR0, FPDP) >= 2; + return FIELD_EX32(id->regs[MVFR0], MVFR0, FPDP) >= 2; } static inline bool isar_feature_aa32_vfp(const ARMISARegisters *id) @@ -3925,12 +3931,12 @@ static inline bool isar_feature_aa32_vfp(const ARMISARegisters *id) */ static inline bool isar_feature_aa32_fp16_spconv(const ARMISARegisters *id) { - return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 0; + return FIELD_EX32(id->regs[MVFR1], MVFR1, FPHP) > 0; } static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id) { - return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 1; + return FIELD_EX32(id->regs[MVFR1], MVFR1, FPHP) > 1; } /* @@ -3942,86 +3948,86 @@ static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id) */ static inline bool isar_feature_aa32_simdfmac(const ARMISARegisters *id) { - return FIELD_EX32(id->mvfr1, MVFR1, SIMDFMAC) != 0; + return FIELD_EX32(id->regs[MVFR1], MVFR1, SIMDFMAC) != 0; } static inline bool isar_feature_aa32_vsel(const ARMISARegisters *id) { - return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 1; + return FIELD_EX32(id->regs[MVFR2], MVFR2, FPMISC) >= 1; } static inline bool isar_feature_aa32_vcvt_dr(const ARMISARegisters *id) { - return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 2; + return FIELD_EX32(id->regs[MVFR2], MVFR2, FPMISC) >= 2; } static inline bool isar_feature_aa32_vrint(const ARMISARegisters *id) { - return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 3; + return FIELD_EX32(id->regs[MVFR2], MVFR2, FPMISC) >= 3; } static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id) { - return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 4; + return FIELD_EX32(id->regs[MVFR2], MVFR2, FPMISC) >= 4; } static inline bool isar_feature_aa32_pxn(const ARMISARegisters *id) { - return FIELD_EX32(id->id_mmfr0, ID_MMFR0, VMSA) >= 4; + return FIELD_EX32(id->regs[ID_MMFR0], 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(id->regs[ID_MMFR3], 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(id->regs[ID_MMFR3], ID_MMFR3, PAN) >= 2; } static inline bool isar_feature_aa32_pmu_8_1(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(id->regs[ID_DFR0], ID_DFR0, PERFMON) >= 4 && + FIELD_EX32(id->regs[ID_DFR0], ID_DFR0, PERFMON) != 0xf; } static inline bool isar_feature_aa32_pmu_8_4(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(id->regs[ID_DFR0], ID_DFR0, PERFMON) >= 5 && + FIELD_EX32(id->regs[ID_DFR0], 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(id->regs[ID_MMFR4], 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(id->regs[ID_MMFR4], 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(id->regs[ID_MMFR4], 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(id->regs[ID_MMFR4], ID_MMFR4, XNX) != 0; } static inline bool isar_feature_aa32_dit(const ARMISARegisters *id) { - return FIELD_EX32(id->id_pfr0, ID_PFR0, DIT) != 0; + return FIELD_EX32(id->regs[ID_PFR0], 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(id->regs[ID_PFR2], ID_PFR2, SSBS) != 0; } /* @@ -4029,92 +4035,92 @@ static inline bool isar_feature_aa32_ssbs(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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, RNDR) != 0; } static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0; + return FIELD_EX64(id->regs[ID_AA64ISAR1], 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(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, FCMA) != 0; } static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id) @@ -4123,7 +4129,7 @@ static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id) * Return true if any form of pauth is enabled, as this * predicate controls migration of the 128-bit keys. */ - return (id->id_aa64isar1 & + return (id->regs[ID_AA64ISAR1] & (FIELD_DP64(0, ID_AA64ISAR1, APA, 0xf) | FIELD_DP64(0, ID_AA64ISAR1, API, 0xf) | FIELD_DP64(0, ID_AA64ISAR1, GPA, 0xf) | @@ -4136,221 +4142,221 @@ static inline bool isar_feature_aa64_pauth_arch(const ARMISARegisters *id) * Return true if pauth is enabled with the architected QARMA algorithm. * QEMU will always set APA+GPA to the same value. */ - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) != 0; + return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, APA) != 0; } static inline bool isar_feature_aa64_tlbirange(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) == 2; + return FIELD_EX64(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, TLB) != 0; } static inline bool isar_feature_aa64_sb(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SB) != 0; + return FIELD_EX64(id->regs[ID_AA64ISAR1], 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(id->regs[ID_AA64ISAR1], 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(id->regs[ID_AA64ISAR1], 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(id->regs[ID_AA64ISAR1], 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(id->regs[ID_AA64ISAR1], 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(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, BF16) != 0; } 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(id->regs[ID_AA64PFR0], 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(id->regs[ID_AA64PFR0], 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(id->regs[ID_AA64PFR0], 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(id->regs[ID_AA64PFR0], ID_AA64PFR0, EL1) >= 2; } static inline bool isar_feature_aa64_sve(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0; + return FIELD_EX64(id->regs[ID_AA64PFR0], 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(id->regs[ID_AA64PFR0], ID_AA64PFR0, SEL2) != 0; } static inline bool isar_feature_aa64_vh(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0; + return FIELD_EX64(id->regs[ID_AA64MMFR1], 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(id->regs[ID_AA64MMFR1], 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(id->regs[ID_AA64MMFR1], 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(id->regs[ID_AA64MMFR1], ID_AA64MMFR1, PAN) >= 2; } static inline bool isar_feature_aa64_uao(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0; + return FIELD_EX64(id->regs[ID_AA64MMFR2], 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(id->regs[ID_AA64MMFR2], ID_AA64MMFR2, ST) != 0; } static inline bool isar_feature_aa64_bti(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0; + return FIELD_EX64(id->regs[ID_AA64PFR1], 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(id->regs[ID_AA64PFR1], 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(id->regs[ID_AA64PFR1], ID_AA64PFR1, MTE) >= 2; } static inline bool isar_feature_aa64_pmu_8_1(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(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) >= 4 && + FIELD_EX64(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) != 0xf; } static inline bool isar_feature_aa64_pmu_8_4(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(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) >= 5 && + FIELD_EX64(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) != 0xf; } 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(id->regs[ID_AA64ISAR1], 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(id->regs[ID_AA64ISAR1], 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(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, I8MM) != 0; } static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0; + return FIELD_EX64(id->regs[ID_AA64MMFR2], ID_AA64MMFR2, CCIDX) != 0; } static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0; + return FIELD_EX64(id->regs[ID_AA64MMFR1], ID_AA64MMFR1, XNX) != 0; } static inline bool isar_feature_aa64_dit(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0; + return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, DIT) != 0; } static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0; + return FIELD_EX64(id->regs[ID_AA64PFR1], ID_AA64PFR1, SSBS) != 0; } static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SVEVER) != 0; + return FIELD_EX64(id->regs[ID_AA64ZFR0], 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(id->regs[ID_AA64ZFR0], 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(id->regs[ID_AA64ZFR0], 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(id->regs[ID_AA64ZFR0], 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(id->regs[ID_AA64ZFR0], 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(id->regs[ID_AA64ZFR0], 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(id->regs[ID_AA64ZFR0], 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(id->regs[ID_AA64ZFR0], 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(id->regs[ID_AA64ZFR0], 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(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, F64MM) != 0; } /* @@ -4392,4 +4398,6 @@ static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id) #define cpu_isar_feature(name, cpu) \ ({ ARMCPU *cpu_ = (cpu); isar_feature_##name(&cpu_->isar); }) +void arm_cpu_features_to_dict(ARMCPU *cpu, QDict *features); + #endif diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 1b56261964c0f2b62bbccfb74e7c59cb079a0a13..3ec788fc298be4adb0db74d70a54b491b290f433 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -108,31 +108,31 @@ static void aarch64_a57_initfn(Object *obj) cpu->midr = 0x411fd070; cpu->revidr = 0x00000000; cpu->reset_fpsid = 0x41034070; - cpu->isar.mvfr0 = 0x10110222; - cpu->isar.mvfr1 = 0x12111111; - cpu->isar.mvfr2 = 0x00000043; + cpu->isar.regs[MVFR0] = 0x10110222; + cpu->isar.regs[MVFR1] = 0x12111111; + cpu->isar.regs[MVFR2] = 0x00000043; cpu->ctr = 0x8444c004; cpu->reset_sctlr = 0x00c50838; - cpu->isar.id_pfr0 = 0x00000131; - cpu->isar.id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x03010066; + cpu->isar.regs[ID_PFR0] = 0x00000131; + cpu->isar.regs[ID_PFR1] = 0x00011011; + cpu->isar.regs[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; - cpu->isar.dbgdidr = 0x3516d000; + cpu->isar.regs[ID_MMFR0] = 0x10101105; + cpu->isar.regs[ID_MMFR1] = 0x40000000; + cpu->isar.regs[ID_MMFR2] = 0x01260000; + cpu->isar.regs[ID_MMFR3] = 0x02102211; + cpu->isar.regs[ID_ISAR0] = 0x02101110; + cpu->isar.regs[ID_ISAR1] = 0x13112111; + cpu->isar.regs[ID_ISAR2] = 0x21232042; + cpu->isar.regs[ID_ISAR3] = 0x01112131; + cpu->isar.regs[ID_ISAR4] = 0x00011142; + cpu->isar.regs[ID_ISAR5] = 0x00011121; + cpu->isar.regs[ID_ISAR6] = 0; + cpu->isar.regs[ID_AA64PFR0] = 0x00002222; + cpu->isar.regs[ID_AA64DFR0] = 0x10305106; + cpu->isar.regs[ID_AA64ISAR0] = 0x00011120; + cpu->isar.regs[ID_AA64MMFR0] = 0x00001124; + cpu->isar.regs[DBGDIDR] = 0x3516d000; cpu->clidr = 0x0a200023; cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */ @@ -161,31 +161,31 @@ static void aarch64_a53_initfn(Object *obj) cpu->midr = 0x410fd034; cpu->revidr = 0x00000000; cpu->reset_fpsid = 0x41034070; - cpu->isar.mvfr0 = 0x10110222; - cpu->isar.mvfr1 = 0x12111111; - cpu->isar.mvfr2 = 0x00000043; + cpu->isar.regs[MVFR0] = 0x10110222; + cpu->isar.regs[MVFR1] = 0x12111111; + cpu->isar.regs[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; + cpu->isar.regs[ID_PFR0] = 0x00000131; + cpu->isar.regs[ID_PFR1] = 0x00011011; + cpu->isar.regs[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 */ - cpu->isar.dbgdidr = 0x3516d000; + cpu->isar.regs[ID_MMFR0] = 0x10101105; + cpu->isar.regs[ID_MMFR1] = 0x40000000; + cpu->isar.regs[ID_MMFR2] = 0x01260000; + cpu->isar.regs[ID_MMFR3] = 0x02102211; + cpu->isar.regs[ID_ISAR0] = 0x02101110; + cpu->isar.regs[ID_ISAR1] = 0x13112111; + cpu->isar.regs[ID_ISAR2] = 0x21232042; + cpu->isar.regs[ID_ISAR3] = 0x01112131; + cpu->isar.regs[ID_ISAR4] = 0x00011142; + cpu->isar.regs[ID_ISAR5] = 0x00011121; + cpu->isar.regs[ID_ISAR6] = 0; + cpu->isar.regs[ID_AA64PFR0] = 0x00002222; + cpu->isar.regs[ID_AA64DFR0] = 0x10305106; + cpu->isar.regs[ID_AA64ISAR0] = 0x00011120; + cpu->isar.regs[ID_AA64MMFR0] = 0x00001122; /* 40 bit physical addr */ + cpu->isar.regs[DBGDIDR] = 0x3516d000; cpu->clidr = 0x0a200023; cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */ cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */ @@ -214,30 +214,30 @@ static void aarch64_a72_initfn(Object *obj) cpu->midr = 0x410fd083; cpu->revidr = 0x00000000; cpu->reset_fpsid = 0x41034080; - cpu->isar.mvfr0 = 0x10110222; - cpu->isar.mvfr1 = 0x12111111; - cpu->isar.mvfr2 = 0x00000043; + cpu->isar.regs[MVFR0] = 0x10110222; + cpu->isar.regs[MVFR1] = 0x12111111; + cpu->isar.regs[MVFR2] = 0x00000043; cpu->ctr = 0x8444c004; cpu->reset_sctlr = 0x00c50838; - cpu->isar.id_pfr0 = 0x00000131; - cpu->isar.id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x03010066; + cpu->isar.regs[ID_PFR0] = 0x00000131; + cpu->isar.regs[ID_PFR1] = 0x00011011; + cpu->isar.regs[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; - cpu->isar.dbgdidr = 0x3516d000; + cpu->isar.regs[ID_MMFR0] = 0x10201105; + cpu->isar.regs[ID_MMFR1] = 0x40000000; + cpu->isar.regs[ID_MMFR2] = 0x01260000; + cpu->isar.regs[ID_MMFR3] = 0x02102211; + cpu->isar.regs[ID_ISAR0] = 0x02101110; + cpu->isar.regs[ID_ISAR1] = 0x13112111; + cpu->isar.regs[ID_ISAR2] = 0x21232042; + cpu->isar.regs[ID_ISAR3] = 0x01112131; + cpu->isar.regs[ID_ISAR4] = 0x00011142; + cpu->isar.regs[ID_ISAR5] = 0x00011121; + cpu->isar.regs[ID_AA64PFR0] = 0x00002222; + cpu->isar.regs[ID_AA64DFR0] = 0x10305106; + cpu->isar.regs[ID_AA64ISAR0] = 0x00011120; + cpu->isar.regs[ID_AA64MMFR0] = 0x00001124; + cpu->isar.regs[DBGDIDR] = 0x3516d000; cpu->clidr = 0x0a200023; cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */ @@ -262,10 +262,33 @@ 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; + cpu->isar.regs[ID_ISAR0] = 0; + cpu->isar.regs[ID_ISAR1] = 0; + cpu->isar.regs[ID_ISAR2] = 0; + cpu->isar.regs[ID_ISAR3] = 0; + cpu->isar.regs[ID_ISAR4] = 0; + cpu->isar.regs[ID_ISAR5] = 0; + cpu->isar.regs[ID_MMFR0] = 0; + cpu->isar.regs[ID_MMFR1] = 0; + cpu->isar.regs[ID_MMFR2] = 0; + cpu->isar.regs[ID_MMFR3] = 0; + cpu->isar.regs[ID_MMFR4] = 0; + cpu->isar.regs[MVFR0] = 0; + cpu->isar.regs[MVFR1] = 0; + cpu->isar.regs[MVFR2] = 0; + cpu->isar.regs[ID_DFR0] = 0; + cpu->isar.regs[MVFR2] = 0; + cpu->isar.regs[MVFR2] = 0; + cpu->isar.regs[MVFR2] = 0; + cpu->isar.regs[ID_PFR0] = 0; + cpu->isar.regs[ID_PFR1] = 0; + cpu->isar.regs[ID_AA64PFR0] = 0x0000010011111111; + cpu->isar.regs[ID_AA64DFR0] = 0x110305408; + cpu->isar.regs[ID_AA64ISAR0] = 0x0001100010211120; + cpu->isar.regs[ID_AA64ISAR1] = 0x00011001; + cpu->isar.regs[ID_AA64MMFR0] = 0x101125; + cpu->isar.regs[ID_AA64MMFR1] = 0x10211122; + cpu->isar.regs[ID_AA64MMFR2] = 0x00001011; } void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) @@ -566,9 +589,9 @@ static void cpu_arm_set_sve(Object *obj, bool value, Error **errp) return; } - t = cpu->isar.id_aa64pfr0; + t = cpu->isar.regs[ID_AA64PFR0]; t = FIELD_DP64(t, ID_AA64PFR0, SVE, value); - cpu->isar.id_aa64pfr0 = t; + cpu->isar.regs[ID_AA64PFR0] = t; } #ifdef CONFIG_USER_ONLY @@ -662,12 +685,12 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) error_append_hint(errp, "Add pauth=on to the CPU property list.\n"); } - t = cpu->isar.id_aa64isar1; + t = cpu->isar.regs[ID_AA64ISAR1]; t = FIELD_DP64(t, ID_AA64ISAR1, APA, arch_val); t = FIELD_DP64(t, ID_AA64ISAR1, GPA, arch_val); t = FIELD_DP64(t, ID_AA64ISAR1, API, impdef_val); t = FIELD_DP64(t, ID_AA64ISAR1, GPI, impdef_val); - cpu->isar.id_aa64isar1 = t; + cpu->isar.regs[ID_AA64ISAR1] = t; } static Property arm_cpu_pauth_property = @@ -736,7 +759,7 @@ static void aarch64_max_initfn(Object *obj) t = FIELD_DP64(t, MIDR_EL1, REVISION, 0); cpu->midr = t; - t = cpu->isar.id_aa64isar0; + t = cpu->isar.regs[ID_AA64ISAR0]; t = FIELD_DP64(t, ID_AA64ISAR0, AES, 2); /* AES + PMULL */ t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 1); t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 2); /* SHA512 */ @@ -751,9 +774,9 @@ static void aarch64_max_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* v8.5-CondM */ t = FIELD_DP64(t, ID_AA64ISAR0, TLB, 2); /* FEAT_TLBIRANGE */ t = FIELD_DP64(t, ID_AA64ISAR0, RNDR, 1); - cpu->isar.id_aa64isar0 = t; + cpu->isar.regs[ID_AA64ISAR0] = t; - t = cpu->isar.id_aa64isar1; + t = cpu->isar.regs[ID_AA64ISAR1]; t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2); t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1); t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1); @@ -763,17 +786,17 @@ static void aarch64_max_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1); t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 2); /* ARMv8.4-RCPC */ t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 1); - cpu->isar.id_aa64isar1 = t; + cpu->isar.regs[ID_AA64ISAR1] = t; - t = cpu->isar.id_aa64pfr0; + t = cpu->isar.regs[ID_AA64PFR0]; t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1); t = FIELD_DP64(t, ID_AA64PFR0, FP, 1); t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1); t = FIELD_DP64(t, ID_AA64PFR0, SEL2, 1); t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1); - cpu->isar.id_aa64pfr0 = t; + cpu->isar.regs[ID_AA64PFR0] = t; - t = cpu->isar.id_aa64pfr1; + t = cpu->isar.regs[ID_AA64PFR1]; t = FIELD_DP64(t, ID_AA64PFR1, BT, 1); t = FIELD_DP64(t, ID_AA64PFR1, SSBS, 2); /* @@ -782,28 +805,28 @@ static void aarch64_max_initfn(Object *obj) * we do for EL2 with the virtualization=on property. */ t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3); - cpu->isar.id_aa64pfr1 = t; + cpu->isar.regs[ID_AA64PFR1] = t; - t = cpu->isar.id_aa64mmfr0; + t = cpu->isar.regs[ID_AA64MMFR0]; t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 5); /* PARange: 48 bits */ - cpu->isar.id_aa64mmfr0 = t; + cpu->isar.regs[ID_AA64MMFR0] = t; - t = cpu->isar.id_aa64mmfr1; + t = cpu->isar.regs[ID_AA64MMFR1]; t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */ t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1); t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1); t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* ATS1E1 */ t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* VMID16 */ t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* TTS2UXN */ - cpu->isar.id_aa64mmfr1 = t; + cpu->isar.regs[ID_AA64MMFR1] = t; - t = cpu->isar.id_aa64mmfr2; + t = cpu->isar.regs[ID_AA64MMFR2]; t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1); t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* TTCNP */ t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* TTST */ - cpu->isar.id_aa64mmfr2 = t; + cpu->isar.regs[ID_AA64MMFR2] = t; - t = cpu->isar.id_aa64zfr0; + t = cpu->isar.regs[ID_AA64ZFR0]; t = FIELD_DP64(t, ID_AA64ZFR0, SVEVER, 1); t = FIELD_DP64(t, ID_AA64ZFR0, AES, 2); /* PMULL */ t = FIELD_DP64(t, ID_AA64ZFR0, BITPERM, 1); @@ -813,19 +836,19 @@ static void aarch64_max_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64ZFR0, I8MM, 1); t = FIELD_DP64(t, ID_AA64ZFR0, F32MM, 1); t = FIELD_DP64(t, ID_AA64ZFR0, F64MM, 1); - cpu->isar.id_aa64zfr0 = t; + cpu->isar.regs[ID_AA64ZFR0] = t; /* Replicate the same data to the 32-bit id registers. */ - u = cpu->isar.id_isar5; + u = cpu->isar.regs[ID_ISAR5]; u = FIELD_DP32(u, ID_ISAR5, AES, 2); /* AES + PMULL */ u = FIELD_DP32(u, ID_ISAR5, SHA1, 1); u = FIELD_DP32(u, ID_ISAR5, SHA2, 1); u = FIELD_DP32(u, ID_ISAR5, CRC32, 1); u = FIELD_DP32(u, ID_ISAR5, RDM, 1); u = FIELD_DP32(u, ID_ISAR5, VCMA, 1); - cpu->isar.id_isar5 = u; + cpu->isar.regs[ID_ISAR5] = u; - u = cpu->isar.id_isar6; + u = cpu->isar.regs[ID_ISAR6]; u = FIELD_DP32(u, ID_ISAR6, JSCVT, 1); u = FIELD_DP32(u, ID_ISAR6, DP, 1); u = FIELD_DP32(u, ID_ISAR6, FHM, 1); @@ -833,39 +856,39 @@ static void aarch64_max_initfn(Object *obj) u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1); u = FIELD_DP32(u, ID_ISAR6, BF16, 1); u = FIELD_DP32(u, ID_ISAR6, I8MM, 1); - cpu->isar.id_isar6 = u; + cpu->isar.regs[ID_ISAR6] = u; - u = cpu->isar.id_pfr0; + u = cpu->isar.regs[ID_PFR0]; u = FIELD_DP32(u, ID_PFR0, DIT, 1); - cpu->isar.id_pfr0 = u; + cpu->isar.regs[ID_PFR0] = u; - u = cpu->isar.id_pfr2; + u = cpu->isar.regs[ID_PFR2]; u = FIELD_DP32(u, ID_PFR2, SSBS, 1); - cpu->isar.id_pfr2 = u; + cpu->isar.regs[ID_PFR2] = u; - u = cpu->isar.id_mmfr3; + u = cpu->isar.regs[ID_MMFR3]; u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */ - cpu->isar.id_mmfr3 = u; + cpu->isar.regs[ID_MMFR3] = u; - u = cpu->isar.id_mmfr4; + u = cpu->isar.regs[ID_MMFR4]; u = FIELD_DP32(u, ID_MMFR4, HPDS, 1); /* AA32HPD */ u = FIELD_DP32(u, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */ u = FIELD_DP32(u, ID_MMFR4, CNP, 1); /* TTCNP */ u = FIELD_DP32(u, ID_MMFR4, XNX, 1); /* TTS2UXN */ - cpu->isar.id_mmfr4 = u; + cpu->isar.regs[ID_MMFR4] = u; - t = cpu->isar.id_aa64dfr0; + t = cpu->isar.regs[ID_AA64DFR0]; t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 5); /* v8.4-PMU */ - cpu->isar.id_aa64dfr0 = t; + cpu->isar.regs[ID_AA64DFR0] = t; - u = cpu->isar.id_dfr0; + u = cpu->isar.regs[ID_DFR0]; u = FIELD_DP32(u, ID_DFR0, PERFMON, 5); /* v8.4-PMU */ - cpu->isar.id_dfr0 = u; + cpu->isar.regs[ID_DFR0] = u; - u = cpu->isar.mvfr1; + u = cpu->isar.regs[MVFR1]; u = FIELD_DP32(u, MVFR1, FPHP, 3); /* v8.2-FP16 */ u = FIELD_DP32(u, MVFR1, SIMDHP, 2); /* v8.2-FP16 */ - cpu->isar.mvfr1 = u; + cpu->isar.regs[MVFR1] = u; #ifdef CONFIG_USER_ONLY /* For usermode -cpu max we can use a larger and more efficient DCZ @@ -903,18 +926,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; + cpu->isar.regs[ID_AA64PFR0] = 0x0000000101111111; /* No RAS Extensions */ + cpu->isar.regs[ID_AA64PFR1] = 0x0000000000000000; + cpu->isar.regs[ID_AA64DFR0] = 0x0000000010305408; + cpu->isar.regs[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; + cpu->isar.regs[ID_AA64MMFR0] = 0x0000000000001122; + cpu->isar.regs[ID_AA64MMFR1] = 0x0000000011212100; + cpu->isar.regs[ID_AA64MMFR2] = 0x0000000000001011; + cpu->isar.regs[ID_AA64ISAR0] = 0x0000000010211120; + cpu->isar.regs[ID_AA64ISAR1] = 0x0000000000010001; + cpu->isar.regs[ID_AA64ZFR0] = 0x0000000000000000; cpu->clidr = 0x0000000080000023; cpu->ccsidr[0] = 0x7007e01c; /* 64KB L1 dcache */ cpu->ccsidr[1] = 0x2007e01c; /* 64KB L1 icache */ @@ -982,6 +1005,115 @@ static gchar *aarch64_gdb_arch_name(CPUState *cs) return g_strdup("aarch64"); } +static const char *unconfigurable_feats[] = { + "evtstrm", + "cpuid", + NULL +}; + +static bool is_configurable_feat(const char *name) +{ + int i; + + for (i = 0; unconfigurable_feats[i]; ++i) { + if (g_strcmp0(unconfigurable_feats[i], name) == 0) { + return false; + } + } + + return true; +} + +static void +cpu_add_feat_as_prop(const char *typename, const char *name, const char *val) +{ + GlobalProperty *prop; + + if (!is_configurable_feat(name)) { + info_report("CPU feature '%s' is not configurable by QEMU. Ignore it.", + name); + return; + } + + prop = g_new0(typeof(*prop), 1); + prop->driver = typename; + prop->property = g_strdup(name); + prop->value = g_strdup(val); + qdev_prop_register_global(prop); +} + +static gint compare_string(gconstpointer a, gconstpointer b) +{ + return g_strcmp0(a, b); +} + +static GList *plus_features, *minus_features; + +static void aarch64_cpu_parse_features(const char *typename, char *features, + Error **errp) +{ + GList *l; + char *featurestr; /* Single 'key=value" string being parsed */ + static bool cpu_globals_initialized; + + if (cpu_globals_initialized) { + return; + } + cpu_globals_initialized = true; + + if (!features) { + return; + } + for (featurestr = strtok(features, ","); + featurestr; + featurestr = strtok(NULL, ",")) { + const char *name; + const char *val = NULL; + char *eq = NULL; + + /* Compatibility syntax: */ + if (featurestr[0] == '+') { + plus_features = g_list_append(plus_features, + g_strdup(featurestr + 1)); + continue; + } else if (featurestr[0] == '-') { + minus_features = g_list_append(minus_features, + g_strdup(featurestr + 1)); + continue; + } + + eq = strchr(featurestr, '='); + name = featurestr; + if (eq) { + *eq++ = 0; + val = eq; + } else { + error_setg(errp, "Unsupported property format: %s", name); + return; + } + + if (g_list_find_custom(plus_features, name, compare_string)) { + warn_report("Ambiguous CPU model string. " + "Don't mix both \"+%s\" and \"%s=%s\"", + name, name, val); + } + if (g_list_find_custom(minus_features, name, compare_string)) { + warn_report("Ambiguous CPU model string. " + "Don't mix both \"-%s\" and \"%s=%s\"", + name, name, val); + } + cpu_add_feat_as_prop(typename, name, val); + } + + for (l = plus_features; l; l = l->next) { + cpu_add_feat_as_prop(typename, l->data, "on"); + } + + for (l = minus_features; l; l = l->next) { + cpu_add_feat_as_prop(typename, l->data, "off"); + } +} + static void aarch64_cpu_class_init(ObjectClass *oc, void *data) { CPUClass *cc = CPU_CLASS(oc); @@ -991,6 +1123,7 @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data) cc->gdb_num_core_regs = 34; cc->gdb_core_xml_file = "aarch64-core.xml"; cc->gdb_arch_name = aarch64_gdb_arch_name; + cc->parse_features = aarch64_cpu_parse_features; object_class_property_add_bool(oc, "aarch64", aarch64_cpu_get_aarch64, aarch64_cpu_set_aarch64); diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c index 13d0e9b1954a826737d0975034d3e4d46f63e5aa..be9c3166fb6373325bcc7fe1168c549d4ea8424c 100644 --- a/target/arm/cpu_tcg.c +++ b/target/arm/cpu_tcg.c @@ -65,14 +65,16 @@ 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); + cpu->isar.regs[ID_ISAR1] = FIELD_DP32(cpu->isar.regs[ID_ISAR1], 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. */ - cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); - cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSP, 1); - cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1); + cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPSHVEC, + 1); + cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPSP, 1); + cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPDP, 1); } static void arm946_initfn(Object *obj) @@ -107,14 +109,16 @@ 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); + cpu->isar.regs[ID_ISAR1] = FIELD_DP32(cpu->isar.regs[ID_ISAR1], 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. */ - cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); - cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSP, 1); - cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1); + cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPSHVEC, + 1); + cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPSP, 1); + cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPDP, 1); { /* The 1026 had an IFAR at c6,c0,0,1 rather than the ARMv6 c6,c0,0,2 */ @@ -147,22 +151,22 @@ static void arm1136_r2_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); cpu->midr = 0x4107b362; cpu->reset_fpsid = 0x410120b4; - cpu->isar.mvfr0 = 0x11111111; - cpu->isar.mvfr1 = 0x00000000; + cpu->isar.regs[MVFR0] = 0x11111111; + cpu->isar.regs[MVFR1] = 0x00000000; cpu->ctr = 0x1dd20d2; cpu->reset_sctlr = 0x00050078; - cpu->isar.id_pfr0 = 0x111; - cpu->isar.id_pfr1 = 0x1; - cpu->isar.id_dfr0 = 0x2; + cpu->isar.regs[ID_PFR0] = 0x111; + cpu->isar.regs[ID_PFR1] = 0x1; + cpu->isar.regs[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; + cpu->isar.regs[ID_MMFR0] = 0x01130003; + cpu->isar.regs[ID_MMFR1] = 0x10030302; + cpu->isar.regs[ID_MMFR2] = 0x01222110; + cpu->isar.regs[ID_ISAR0] = 0x00140011; + cpu->isar.regs[ID_ISAR1] = 0x12002111; + cpu->isar.regs[ID_ISAR2] = 0x11231111; + cpu->isar.regs[ID_ISAR3] = 0x01102131; + cpu->isar.regs[ID_ISAR4] = 0x141; cpu->reset_auxcr = 7; } @@ -178,22 +182,22 @@ static void arm1136_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); cpu->midr = 0x4117b363; cpu->reset_fpsid = 0x410120b4; - cpu->isar.mvfr0 = 0x11111111; - cpu->isar.mvfr1 = 0x00000000; + cpu->isar.regs[MVFR0] = 0x11111111; + cpu->isar.regs[MVFR1] = 0x00000000; cpu->ctr = 0x1dd20d2; cpu->reset_sctlr = 0x00050078; - cpu->isar.id_pfr0 = 0x111; - cpu->isar.id_pfr1 = 0x1; - cpu->isar.id_dfr0 = 0x2; + cpu->isar.regs[ID_PFR0] = 0x111; + cpu->isar.regs[ID_PFR1] = 0x1; + cpu->isar.regs[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; + cpu->isar.regs[ID_MMFR0] = 0x01130003; + cpu->isar.regs[ID_MMFR1] = 0x10030302; + cpu->isar.regs[ID_MMFR2] = 0x01222110; + cpu->isar.regs[ID_ISAR0] = 0x00140011; + cpu->isar.regs[ID_ISAR1] = 0x12002111; + cpu->isar.regs[ID_ISAR2] = 0x11231111; + cpu->isar.regs[ID_ISAR3] = 0x01102131; + cpu->isar.regs[ID_ISAR4] = 0x141; cpu->reset_auxcr = 7; } @@ -210,22 +214,22 @@ static void arm1176_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_EL3); cpu->midr = 0x410fb767; cpu->reset_fpsid = 0x410120b5; - cpu->isar.mvfr0 = 0x11111111; - cpu->isar.mvfr1 = 0x00000000; + cpu->isar.regs[MVFR0] = 0x11111111; + cpu->isar.regs[MVFR1] = 0x00000000; cpu->ctr = 0x1dd20d2; cpu->reset_sctlr = 0x00050078; - cpu->isar.id_pfr0 = 0x111; - cpu->isar.id_pfr1 = 0x11; - cpu->isar.id_dfr0 = 0x33; + cpu->isar.regs[ID_PFR0] = 0x111; + cpu->isar.regs[ID_PFR1] = 0x11; + cpu->isar.regs[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; + cpu->isar.regs[ID_MMFR0] = 0x01130003; + cpu->isar.regs[ID_MMFR1] = 0x10030302; + cpu->isar.regs[ID_MMFR2] = 0x01222100; + cpu->isar.regs[ID_ISAR0] = 0x0140011; + cpu->isar.regs[ID_ISAR1] = 0x12002111; + cpu->isar.regs[ID_ISAR2] = 0x11231121; + cpu->isar.regs[ID_ISAR3] = 0x01102131; + cpu->isar.regs[ID_ISAR4] = 0x01141; cpu->reset_auxcr = 7; } @@ -240,21 +244,21 @@ static void arm11mpcore_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); cpu->midr = 0x410fb022; cpu->reset_fpsid = 0x410120b4; - cpu->isar.mvfr0 = 0x11111111; - cpu->isar.mvfr1 = 0x00000000; + cpu->isar.regs[MVFR0] = 0x11111111; + cpu->isar.regs[MVFR1] = 0x00000000; cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */ - cpu->isar.id_pfr0 = 0x111; - cpu->isar.id_pfr1 = 0x1; - cpu->isar.id_dfr0 = 0; + cpu->isar.regs[ID_PFR0] = 0x111; + cpu->isar.regs[ID_PFR1] = 0x1; + cpu->isar.regs[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; + cpu->isar.regs[ID_MMFR0] = 0x01100103; + cpu->isar.regs[ID_MMFR1] = 0x10020302; + cpu->isar.regs[ID_MMFR2] = 0x01222000; + cpu->isar.regs[ID_ISAR0] = 0x00100011; + cpu->isar.regs[ID_ISAR1] = 0x12002111; + cpu->isar.regs[ID_ISAR2] = 0x11221011; + cpu->isar.regs[ID_ISAR3] = 0x01102131; + cpu->isar.regs[ID_ISAR4] = 0x141; cpu->reset_auxcr = 1; } @@ -278,24 +282,24 @@ static void cortex_a8_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_EL3); cpu->midr = 0x410fc080; cpu->reset_fpsid = 0x410330c0; - cpu->isar.mvfr0 = 0x11110222; - cpu->isar.mvfr1 = 0x00011111; + cpu->isar.regs[MVFR0] = 0x11110222; + cpu->isar.regs[MVFR1] = 0x00011111; cpu->ctr = 0x82048004; cpu->reset_sctlr = 0x00c50078; - cpu->isar.id_pfr0 = 0x1031; - cpu->isar.id_pfr1 = 0x11; - cpu->isar.id_dfr0 = 0x400; + cpu->isar.regs[ID_PFR0] = 0x1031; + cpu->isar.regs[ID_PFR1] = 0x11; + cpu->isar.regs[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; - cpu->isar.dbgdidr = 0x15141000; + cpu->isar.regs[ID_MMFR0] = 0x31100003; + cpu->isar.regs[ID_MMFR1] = 0x20000000; + cpu->isar.regs[ID_MMFR2] = 0x01202000; + cpu->isar.regs[ID_MMFR3] = 0x11; + cpu->isar.regs[ID_ISAR0] = 0x00101111; + cpu->isar.regs[ID_ISAR1] = 0x12112111; + cpu->isar.regs[ID_ISAR2] = 0x21232031; + cpu->isar.regs[ID_ISAR3] = 0x11112131; + cpu->isar.regs[ID_ISAR4] = 0x00111142; + cpu->isar.regs[DBGDIDR] = 0x15141000; cpu->clidr = (1 << 27) | (2 << 24) | 3; cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */ cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */ @@ -352,24 +356,24 @@ static void cortex_a9_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_CBAR); cpu->midr = 0x410fc090; cpu->reset_fpsid = 0x41033090; - cpu->isar.mvfr0 = 0x11110222; - cpu->isar.mvfr1 = 0x01111111; + cpu->isar.regs[MVFR0] = 0x11110222; + cpu->isar.regs[MVFR1] = 0x01111111; cpu->ctr = 0x80038003; cpu->reset_sctlr = 0x00c50078; - cpu->isar.id_pfr0 = 0x1031; - cpu->isar.id_pfr1 = 0x11; - cpu->isar.id_dfr0 = 0x000; + cpu->isar.regs[ID_PFR0] = 0x1031; + cpu->isar.regs[ID_PFR1] = 0x11; + cpu->isar.regs[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; - cpu->isar.dbgdidr = 0x35141000; + cpu->isar.regs[ID_MMFR0] = 0x00100103; + cpu->isar.regs[ID_MMFR1] = 0x20000000; + cpu->isar.regs[ID_MMFR2] = 0x01230000; + cpu->isar.regs[ID_MMFR3] = 0x00002111; + cpu->isar.regs[ID_ISAR0] = 0x00101111; + cpu->isar.regs[ID_ISAR1] = 0x13112111; + cpu->isar.regs[ID_ISAR2] = 0x21232041; + cpu->isar.regs[ID_ISAR3] = 0x11112131; + cpu->isar.regs[ID_ISAR4] = 0x00111142; + cpu->isar.regs[DBGDIDR] = 0x35141000; cpu->clidr = (1 << 27) | (1 << 24) | 3; cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */ cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */ @@ -417,28 +421,28 @@ static void cortex_a7_initfn(Object *obj) cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7; cpu->midr = 0x410fc075; cpu->reset_fpsid = 0x41023075; - cpu->isar.mvfr0 = 0x10110222; - cpu->isar.mvfr1 = 0x11111111; + cpu->isar.regs[MVFR0] = 0x10110222; + cpu->isar.regs[MVFR1] = 0x11111111; cpu->ctr = 0x84448003; cpu->reset_sctlr = 0x00c50078; - cpu->isar.id_pfr0 = 0x00001131; - cpu->isar.id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x02010555; + cpu->isar.regs[ID_PFR0] = 0x00001131; + cpu->isar.regs[ID_PFR1] = 0x00011011; + cpu->isar.regs[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; + cpu->isar.regs[ID_MMFR0] = 0x10101105; + cpu->isar.regs[ID_MMFR1] = 0x40000000; + cpu->isar.regs[ID_MMFR2] = 0x01240000; + cpu->isar.regs[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; - cpu->isar.dbgdidr = 0x3515f005; + cpu->isar.regs[ID_ISAR0] = 0x02101110; + cpu->isar.regs[ID_ISAR1] = 0x13112111; + cpu->isar.regs[ID_ISAR2] = 0x21232041; + cpu->isar.regs[ID_ISAR3] = 0x11112131; + cpu->isar.regs[ID_ISAR4] = 0x10011142; + cpu->isar.regs[DBGDIDR] = 0x3515f005; cpu->clidr = 0x0a200023; cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */ cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */ @@ -463,24 +467,24 @@ static void cortex_a15_initfn(Object *obj) cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15; cpu->midr = 0x412fc0f1; cpu->reset_fpsid = 0x410430f0; - cpu->isar.mvfr0 = 0x10110222; - cpu->isar.mvfr1 = 0x11111111; + cpu->isar.regs[MVFR0] = 0x10110222; + cpu->isar.regs[MVFR1] = 0x11111111; cpu->ctr = 0x8444c004; cpu->reset_sctlr = 0x00c50078; - cpu->isar.id_pfr0 = 0x00001131; - cpu->isar.id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x02010555; + cpu->isar.regs[ID_PFR0] = 0x00001131; + cpu->isar.regs[ID_PFR1] = 0x00011011; + cpu->isar.regs[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; - cpu->isar.dbgdidr = 0x3515f021; + cpu->isar.regs[ID_MMFR0] = 0x10201105; + cpu->isar.regs[ID_MMFR1] = 0x20000000; + cpu->isar.regs[ID_MMFR2] = 0x01240000; + cpu->isar.regs[ID_MMFR3] = 0x02102211; + cpu->isar.regs[ID_ISAR0] = 0x02101110; + cpu->isar.regs[ID_ISAR1] = 0x13112111; + cpu->isar.regs[ID_ISAR2] = 0x21232041; + cpu->isar.regs[ID_ISAR3] = 0x11112131; + cpu->isar.regs[ID_ISAR4] = 0x10011142; + cpu->isar.regs[DBGDIDR] = 0x3515f021; cpu->clidr = 0x0a200023; cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */ cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */ @@ -504,21 +508,21 @@ 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; + cpu->isar.regs[ID_PFR0] = 0x00000030; + cpu->isar.regs[ID_PFR1] = 0x00000200; + cpu->isar.regs[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; + cpu->isar.regs[ID_MMFR0] = 0x00000030; + cpu->isar.regs[ID_MMFR1] = 0x00000000; + cpu->isar.regs[ID_MMFR2] = 0x00000000; + cpu->isar.regs[ID_MMFR3] = 0x00000000; + cpu->isar.regs[ID_ISAR0] = 0x01141110; + cpu->isar.regs[ID_ISAR1] = 0x02111000; + cpu->isar.regs[ID_ISAR2] = 0x21112231; + cpu->isar.regs[ID_ISAR3] = 0x01111110; + cpu->isar.regs[ID_ISAR4] = 0x01310102; + cpu->isar.regs[ID_ISAR5] = 0x00000000; + cpu->isar.regs[ID_ISAR6] = 0x00000000; } static void cortex_m3_initfn(Object *obj) @@ -529,21 +533,21 @@ static void cortex_m3_initfn(Object *obj) 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; + cpu->isar.regs[ID_PFR0] = 0x00000030; + cpu->isar.regs[ID_PFR1] = 0x00000200; + cpu->isar.regs[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; + cpu->isar.regs[ID_MMFR0] = 0x00000030; + cpu->isar.regs[ID_MMFR1] = 0x00000000; + cpu->isar.regs[ID_MMFR2] = 0x00000000; + cpu->isar.regs[ID_MMFR3] = 0x00000000; + cpu->isar.regs[ID_ISAR0] = 0x01141110; + cpu->isar.regs[ID_ISAR1] = 0x02111000; + cpu->isar.regs[ID_ISAR2] = 0x21112231; + cpu->isar.regs[ID_ISAR3] = 0x01111110; + cpu->isar.regs[ID_ISAR4] = 0x01310102; + cpu->isar.regs[ID_ISAR5] = 0x00000000; + cpu->isar.regs[ID_ISAR6] = 0x00000000; } static void cortex_m4_initfn(Object *obj) @@ -556,24 +560,24 @@ static void cortex_m4_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); cpu->midr = 0x410fc240; /* r0p0 */ cpu->pmsav7_dregion = 8; - 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; + cpu->isar.regs[MVFR0] = 0x10110021; + cpu->isar.regs[MVFR1] = 0x11000011; + cpu->isar.regs[MVFR2] = 0x00000000; + cpu->isar.regs[ID_PFR0] = 0x00000030; + cpu->isar.regs[ID_PFR1] = 0x00000200; + cpu->isar.regs[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; + cpu->isar.regs[ID_MMFR0] = 0x00000030; + cpu->isar.regs[ID_MMFR1] = 0x00000000; + cpu->isar.regs[ID_MMFR2] = 0x00000000; + cpu->isar.regs[ID_MMFR3] = 0x00000000; + cpu->isar.regs[ID_ISAR0] = 0x01141110; + cpu->isar.regs[ID_ISAR1] = 0x02111000; + cpu->isar.regs[ID_ISAR2] = 0x21112231; + cpu->isar.regs[ID_ISAR3] = 0x01111110; + cpu->isar.regs[ID_ISAR4] = 0x01310102; + cpu->isar.regs[ID_ISAR5] = 0x00000000; + cpu->isar.regs[ID_ISAR6] = 0x00000000; } static void cortex_m7_initfn(Object *obj) @@ -586,24 +590,24 @@ static void cortex_m7_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); cpu->midr = 0x411fc272; /* r1p2 */ cpu->pmsav7_dregion = 8; - 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; + cpu->isar.regs[MVFR0] = 0x10110221; + cpu->isar.regs[MVFR1] = 0x12000011; + cpu->isar.regs[MVFR2] = 0x00000040; + cpu->isar.regs[ID_PFR0] = 0x00000030; + cpu->isar.regs[ID_PFR1] = 0x00000200; + cpu->isar.regs[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; + cpu->isar.regs[ID_MMFR0] = 0x00100030; + cpu->isar.regs[ID_MMFR1] = 0x00000000; + cpu->isar.regs[ID_MMFR2] = 0x01000000; + cpu->isar.regs[ID_MMFR3] = 0x00000000; + cpu->isar.regs[ID_ISAR0] = 0x01101110; + cpu->isar.regs[ID_ISAR1] = 0x02112000; + cpu->isar.regs[ID_ISAR2] = 0x20232231; + cpu->isar.regs[ID_ISAR3] = 0x01111131; + cpu->isar.regs[ID_ISAR4] = 0x01310132; + cpu->isar.regs[ID_ISAR5] = 0x00000000; + cpu->isar.regs[ID_ISAR6] = 0x00000000; } static void cortex_m33_initfn(Object *obj) @@ -618,24 +622,24 @@ static void cortex_m33_initfn(Object *obj) cpu->midr = 0x410fd213; /* r0p3 */ cpu->pmsav7_dregion = 16; cpu->sau_sregion = 8; - 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; + cpu->isar.regs[MVFR0] = 0x10110021; + cpu->isar.regs[MVFR1] = 0x11000011; + cpu->isar.regs[MVFR2] = 0x00000040; + cpu->isar.regs[ID_PFR0] = 0x00000030; + cpu->isar.regs[ID_PFR1] = 0x00000210; + cpu->isar.regs[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; + cpu->isar.regs[ID_MMFR0] = 0x00101F40; + cpu->isar.regs[ID_MMFR1] = 0x00000000; + cpu->isar.regs[ID_MMFR2] = 0x01000000; + cpu->isar.regs[ID_MMFR3] = 0x00000000; + cpu->isar.regs[ID_ISAR0] = 0x01101110; + cpu->isar.regs[ID_ISAR1] = 0x02212000; + cpu->isar.regs[ID_ISAR2] = 0x20232232; + cpu->isar.regs[ID_ISAR3] = 0x01111131; + cpu->isar.regs[ID_ISAR4] = 0x01310132; + cpu->isar.regs[ID_ISAR5] = 0x00000000; + cpu->isar.regs[ID_ISAR6] = 0x00000000; cpu->clidr = 0x00000000; cpu->ctr = 0x8000c000; } @@ -655,24 +659,24 @@ static void cortex_m55_initfn(Object *obj) cpu->pmsav7_dregion = 16; cpu->sau_sregion = 8; /* These are the MVFR* values for the FPU + full MVE configuration */ - 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; + cpu->isar.regs[MVFR0] = 0x10110221; + cpu->isar.regs[MVFR1] = 0x12100211; + cpu->isar.regs[MVFR2] = 0x00000040; + cpu->isar.regs[ID_PFR0] = 0x20000030; + cpu->isar.regs[ID_PFR1] = 0x00000230; + cpu->isar.regs[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; + cpu->isar.regs[ID_MMFR0] = 0x00111040; + cpu->isar.regs[ID_MMFR1] = 0x00000000; + cpu->isar.regs[ID_MMFR2] = 0x01000000; + cpu->isar.regs[ID_MMFR3] = 0x00000011; + cpu->isar.regs[ID_ISAR0] = 0x01103110; + cpu->isar.regs[ID_ISAR1] = 0x02212000; + cpu->isar.regs[ID_ISAR2] = 0x20232232; + cpu->isar.regs[ID_ISAR3] = 0x01111131; + cpu->isar.regs[ID_ISAR4] = 0x01310132; + cpu->isar.regs[ID_ISAR5] = 0x00000000; + cpu->isar.regs[ID_ISAR6] = 0x00000000; cpu->clidr = 0x00000000; /* caches not implemented */ cpu->ctr = 0x8303c003; } @@ -697,21 +701,21 @@ static void cortex_r5_initfn(Object *obj) 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; + cpu->isar.regs[ID_PFR0] = 0x0131; + cpu->isar.regs[ID_PFR1] = 0x001; + cpu->isar.regs[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; + cpu->isar.regs[ID_MMFR0] = 0x0210030; + cpu->isar.regs[ID_MMFR1] = 0x00000000; + cpu->isar.regs[ID_MMFR2] = 0x01200000; + cpu->isar.regs[ID_MMFR3] = 0x0211; + cpu->isar.regs[ID_ISAR0] = 0x02101111; + cpu->isar.regs[ID_ISAR1] = 0x13112111; + cpu->isar.regs[ID_ISAR2] = 0x21232141; + cpu->isar.regs[ID_ISAR3] = 0x01112131; + cpu->isar.regs[ID_ISAR4] = 0x0010142; + cpu->isar.regs[ID_ISAR5] = 0x0; + cpu->isar.regs[ID_ISAR6] = 0x0; cpu->mp_is_up = true; cpu->pmsav7_dregion = 16; define_arm_cp_regs(cpu, cortexr5_cp_reginfo); @@ -722,8 +726,8 @@ static void cortex_r5f_initfn(Object *obj) ARMCPU *cpu = ARM_CPU(obj); cortex_r5_initfn(obj); - cpu->isar.mvfr0 = 0x10110221; - cpu->isar.mvfr1 = 0x00000011; + cpu->isar.regs[MVFR0] = 0x10110221; + cpu->isar.regs[MVFR1] = 0x00000011; } static void ti925t_initfn(Object *obj) @@ -942,7 +946,8 @@ static void arm_max_initfn(Object *obj) cortex_a15_initfn(obj); /* old-style VFP short-vector support */ - cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); + cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPSHVEC, + 1); #ifdef CONFIG_USER_ONLY /* @@ -954,16 +959,16 @@ static void arm_max_initfn(Object *obj) { uint32_t t; - t = cpu->isar.id_isar5; + t = cpu->isar.regs[ID_ISAR5]; t = FIELD_DP32(t, ID_ISAR5, AES, 2); t = FIELD_DP32(t, ID_ISAR5, SHA1, 1); t = FIELD_DP32(t, ID_ISAR5, SHA2, 1); t = FIELD_DP32(t, ID_ISAR5, CRC32, 1); t = FIELD_DP32(t, ID_ISAR5, RDM, 1); t = FIELD_DP32(t, ID_ISAR5, VCMA, 1); - cpu->isar.id_isar5 = t; + cpu->isar.regs[ID_ISAR5] = t; - t = cpu->isar.id_isar6; + t = cpu->isar.regs[ID_ISAR6]; t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1); t = FIELD_DP32(t, ID_ISAR6, DP, 1); t = FIELD_DP32(t, ID_ISAR6, FHM, 1); @@ -971,36 +976,36 @@ static void arm_max_initfn(Object *obj) t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1); t = FIELD_DP32(t, ID_ISAR6, BF16, 1); t = FIELD_DP32(t, ID_ISAR6, I8MM, 1); - cpu->isar.id_isar6 = t; + cpu->isar.regs[ID_ISAR6] = t; - t = cpu->isar.mvfr1; + t = cpu->isar.regs[MVFR1]; t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */ t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */ - cpu->isar.mvfr1 = t; + cpu->isar.regs[MVFR1] = t; - t = cpu->isar.mvfr2; + t = cpu->isar.regs[MVFR2]; t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */ t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */ - cpu->isar.mvfr2 = t; + cpu->isar.regs[MVFR2] = t; - t = cpu->isar.id_mmfr3; + t = cpu->isar.regs[ID_MMFR3]; t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */ - cpu->isar.id_mmfr3 = t; + cpu->isar.regs[ID_MMFR3] = t; - t = cpu->isar.id_mmfr4; + t = cpu->isar.regs[ID_MMFR4]; t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */ t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */ t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */ t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */ - cpu->isar.id_mmfr4 = t; + cpu->isar.regs[ID_MMFR4] = t; - t = cpu->isar.id_pfr0; + t = cpu->isar.regs[ID_PFR0]; t = FIELD_DP32(t, ID_PFR0, DIT, 1); - cpu->isar.id_pfr0 = t; + cpu->isar.regs[ID_PFR0] = t; - t = cpu->isar.id_pfr2; + t = cpu->isar.regs[ID_PFR2]; t = FIELD_DP32(t, ID_PFR2, SSBS, 1); - cpu->isar.id_pfr2 = t; + cpu->isar.regs[ID_PFR2] = t; } #endif /* CONFIG_USER_ONLY */ } diff --git a/target/arm/helper.c b/target/arm/helper.c index 9b317899a66b66fbe7203b8df8b490b69236d54a..1dd5d64d963cc52ccb22264ff7a7d66210aca75d 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -35,6 +35,7 @@ #include "exec/cpu_ldst.h" #include "semihosting/common-semi.h" #endif +#include "kvm_arm.h" #define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */ #define PMCR_NUM_COUNTERS 4 /* QEMU IMPDEF choice */ @@ -133,6 +134,16 @@ static bool raw_accessors_invalid(const ARMCPRegInfo *ri) return true; } +static bool is_id_reg(const ARMCPRegInfo *ri) +{ + /* + * (Op0, Op1, CRn, CRm, Op2) of ID registers is (3, 0, 0, crm, op2), + * where 1<=crm<8, 0<=op2<8. + */ + return ri->opc0 == 3 && ri->opc1 == 0 && ri->crn == 0 && + ri->crm > 0 && ri->crm < 8; +} + bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync) { /* Write the coprocessor state from cpu->env to the (index,value) list. */ @@ -149,30 +160,53 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync) ok = false; continue; } - if (ri->type & ARM_CP_NO_RAW) { + if ((ri->type & ARM_CP_NO_RAW) && !(kvm_sync && is_id_reg(ri))) { continue; } newval = read_raw_cp_reg(&cpu->env, ri); if (kvm_sync) { - /* - * Only sync if the previous list->cpustate sync succeeded. - * Rather than tracking the success/failure state for every - * item in the list, we just recheck "does the raw write we must - * have made in write_list_to_cpustate() read back OK" here. - */ - uint64_t oldval = cpu->cpreg_values[i]; + if (is_id_reg(ri)) { + /* Only sync if we can sync to KVM successfully. */ + uint64_t oldval; + uint64_t kvmval; - if (oldval == newval) { - continue; - } + if (kvm_arm_get_one_reg(cpu, cpu->cpreg_indexes[i], &oldval)) { + continue; + } + if (oldval == newval) { + continue; + } - write_raw_cp_reg(&cpu->env, ri, oldval); - if (read_raw_cp_reg(&cpu->env, ri) != oldval) { - continue; - } + if (kvm_arm_set_one_reg(cpu, cpu->cpreg_indexes[i], &newval)) { + continue; + } + if (kvm_arm_get_one_reg(cpu, cpu->cpreg_indexes[i], &kvmval) || + kvmval != newval) { + continue; + } + + kvm_arm_set_one_reg(cpu, cpu->cpreg_indexes[i], &oldval); + } else { + /* + * Only sync if the previous list->cpustate sync succeeded. + * Rather than tracking the success/failure state for every + * item in the list, we just recheck "does the raw write we must + * have made in write_list_to_cpustate() read back OK" here. + */ + uint64_t oldval = cpu->cpreg_values[i]; - write_raw_cp_reg(&cpu->env, ri, newval); + if (oldval == newval) { + continue; + } + + write_raw_cp_reg(&cpu->env, ri, oldval); + if (read_raw_cp_reg(&cpu->env, ri) != oldval) { + continue; + } + + write_raw_cp_reg(&cpu->env, ri, newval); + } } cpu->cpreg_values[i] = newval; } @@ -6547,12 +6581,12 @@ static void define_debug_regs(ARMCPU *cpu) * use AArch32. Given that bit 15 is RES1, if the value is 0 then * the register must not exist for this cpu. */ - if (cpu->isar.dbgdidr != 0) { + if (cpu->isar.regs[DBGDIDR] != 0) { ARMCPRegInfo dbgdidr = { .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0, .access = PL0_R, .accessfn = access_tda, - .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr, + .type = ARM_CP_CONST, .resetvalue = cpu->isar.regs[DBGDIDR], }; define_one_arm_cp_reg(cpu, &dbgdidr); } @@ -6707,9 +6741,9 @@ 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 = cpu->isar.regs[ID_PFR1]; - if (env->gicv3state) { + if (!arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && env->gicv3state) { pfr1 |= 1 << 28; } return pfr1; @@ -6719,7 +6753,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 = cpu->isar.regs[ID_AA64PFR0]; if (env->gicv3state) { pfr0 |= 1 << 24; @@ -7501,7 +7535,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 = cpu->isar.regs[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. */ @@ -7515,7 +7549,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 = cpu->isar.regs[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, @@ -7525,62 +7559,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 = cpu->isar.regs[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 = cpu->isar.regs[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 = cpu->isar.regs[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 = cpu->isar.regs[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 = cpu->isar.regs[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 = cpu->isar.regs[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 = cpu->isar.regs[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 = cpu->isar.regs[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 = cpu->isar.regs[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 = cpu->isar.regs[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 = cpu->isar.regs[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 = cpu->isar.regs[ID_ISAR6] }, REGINFO_SENTINEL }; define_arm_cp_regs(cpu, v6_idregs); @@ -7630,7 +7664,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 = cpu->isar.regs[ID_AA64PFR0] #else .type = ARM_CP_NO_RAW, .accessfn = access_aa64_tid3, @@ -7642,7 +7676,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 = cpu->isar.regs[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, @@ -7657,7 +7691,7 @@ 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 = cpu->isar.regs[ID_AA64ZFR0] }, { .name = "ID_AA64PFR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 5, .access = PL1_R, .type = ARM_CP_CONST, @@ -7677,12 +7711,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 = cpu->isar.regs[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 = cpu->isar.regs[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, @@ -7717,12 +7751,12 @@ 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 = cpu->isar.regs[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 = cpu->isar.regs[ID_AA64ISAR1] }, { .name = "ID_AA64ISAR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST, @@ -7757,17 +7791,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 = cpu->isar.regs[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 = cpu->isar.regs[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 = cpu->isar.regs[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, @@ -7797,17 +7831,17 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 0, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.mvfr0 }, + .resetvalue = cpu->isar.regs[MVFR0] }, { .name = "MVFR1_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 1, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.mvfr1 }, + .resetvalue = cpu->isar.regs[MVFR1] }, { .name = "MVFR2_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.mvfr2 }, + .resetvalue = cpu->isar.regs[MVFR2] }, { .name = "MVFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 3, .access = PL1_R, .type = ARM_CP_CONST, @@ -7817,7 +7851,7 @@ 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 = cpu->isar.regs[ID_PFR2] }, { .name = "MVFR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 5, .access = PL1_R, .type = ARM_CP_CONST, diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index 0dc96560d3469316907f70efcc971b540687a570..66ad698df118acd7faa5c276772a542815d34c12 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -449,15 +449,15 @@ 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_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_AA64PFR0_EL1, &host_isar.regs[ID_AA64PFR0] }, + { HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.regs[ID_AA64PFR1] }, + { HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.regs[ID_AA64DFR0] }, + { HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.regs[ID_AA64DFR1] }, + { HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.regs[ID_AA64ISAR0] }, + { HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.regs[ID_AA64ISAR1] }, + { HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.regs[ID_AA64MMFR0] }, + { HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.regs[ID_AA64MMFR1] }, + { HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.regs[ID_AA64MMFR2] }, }; hv_vcpu_t fd; hv_return_t r = HV_SUCCESS; @@ -593,7 +593,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->hvf->fd, HV_SYS_REG_ID_AA64MMFR0_EL1, - &arm_cpu->isar.id_aa64mmfr0); + &arm_cpu->isar.regs[ID_AA64MMFR0]); assert_hvf_ok(ret); return 0; diff --git a/target/arm/internals.h b/target/arm/internals.h index 89f7610ebc542b90aac8513d77e13ba03ba1f3e2..0ea225e480795e27e177c9d032ea79e1d2497030 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -254,7 +254,7 @@ static inline unsigned int arm_pamax(ARMCPU *cpu) [5] = 48, }; unsigned int parange = - FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE); + FIELD_EX64(cpu->isar.regs[ID_AA64MMFR0], ID_AA64MMFR0, PARANGE); /* id_aa64mmfr0 is a read-only register so values outside of the * supported mappings can be considered an implementation error. */ @@ -808,9 +808,9 @@ static inline uint32_t arm_debug_exception_fsr(CPUARMState *env) 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(cpu->isar.regs[ID_AA64DFR0], ID_AA64DFR0, BRPS) + 1; } else { - return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, BRPS) + 1; + return FIELD_EX32(cpu->isar.regs[DBGDIDR], DBGDIDR, BRPS) + 1; } } @@ -822,9 +822,9 @@ 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(cpu->isar.regs[ID_AA64DFR0], ID_AA64DFR0, WRPS) + 1; } else { - return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, WRPS) + 1; + return FIELD_EX32(cpu->isar.regs[DBGDIDR], DBGDIDR, WRPS) + 1; } } @@ -836,9 +836,9 @@ 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(cpu->isar.regs[ID_AA64DFR0], ID_AA64DFR0, CTX_CMPS) + 1; } else { - return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, CTX_CMPS) + 1; + return FIELD_EX32(cpu->isar.regs[DBGDIDR], DBGDIDR, CTX_CMPS) + 1; } } diff --git a/target/arm/kvm.c b/target/arm/kvm.c index bbf1ce7ba3bc337908aa257b259b008a0ed4b5a8..59d556724fd6cdb9b7bac4f503de5600c55b0efa 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -514,6 +514,44 @@ out: return ret; } +int kvm_arm_get_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *target) +{ + uint32_t v32; + int ret; + + switch (regidx & KVM_REG_SIZE_MASK) { + case KVM_REG_SIZE_U32: + ret = kvm_get_one_reg(CPU(cpu), regidx, &v32); + if (ret == 0) { + *target = v32; + } + return ret; + case KVM_REG_SIZE_U64: + return kvm_get_one_reg(CPU(cpu), regidx, target); + default: + return -1; + } +} + +int kvm_arm_set_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *source) +{ + uint32_t v32; + + switch (regidx & KVM_REG_SIZE_MASK) { + case KVM_REG_SIZE_U32: + v32 = *source; + if (v32 != *source) { + error_report("the value of source is too large"); + return -1; + } + return kvm_set_one_reg(CPU(cpu), regidx, &v32); + case KVM_REG_SIZE_U64: + return kvm_set_one_reg(CPU(cpu), regidx, source); + default: + return -1; + } +} + bool write_kvmstate_to_list(ARMCPU *cpu) { CPUState *cs = CPU(cpu); diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index e790d6c9a5732a58a060760154f8514252f4b38c..b34a87fd2408a5a3089a4b6e27e5e2625f3613e3 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -468,7 +468,7 @@ void kvm_arm_pvtime_init(CPUState *cs, uint64_t ipa) } } -static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id) +static int read_sys_reg32(int fd, uint64_t *pret, uint64_t id) { uint64_t ret; struct kvm_one_reg idreg = { .id = id, .addr = (uintptr_t)&ret }; @@ -528,7 +528,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) ahcf->target = init.target; ahcf->dtb_compatible = "arm,arm-v8"; - err = read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr0, + err = read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64PFR0], ARM64_SYS_REG(3, 0, 0, 4, 0)); if (unlikely(err < 0)) { /* @@ -547,24 +547,24 @@ 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 */ + ahcf->isar.regs[ID_AA64PFR0] = 0x00000011; /* EL1&0, AArch64 only */ err = 0; } else { - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr1, + err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64PFR1], ARM64_SYS_REG(3, 0, 0, 4, 1)); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr0, + err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64DFR0], ARM64_SYS_REG(3, 0, 0, 5, 0)); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr1, + err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64DFR1], ARM64_SYS_REG(3, 0, 0, 5, 1)); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar0, + err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64ISAR0], ARM64_SYS_REG(3, 0, 0, 6, 0)); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar1, + err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64ISAR1], ARM64_SYS_REG(3, 0, 0, 6, 1)); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr0, + err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64MMFR0], ARM64_SYS_REG(3, 0, 0, 7, 0)); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1, + err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64MMFR1], ARM64_SYS_REG(3, 0, 0, 7, 1)); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr2, + err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64MMFR2], ARM64_SYS_REG(3, 0, 0, 7, 2)); /* @@ -574,44 +574,44 @@ 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, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_PFR0], ARM64_SYS_REG(3, 0, 0, 1, 0)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr1, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_PFR1], ARM64_SYS_REG(3, 0, 0, 1, 1)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr2, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_PFR2], ARM64_SYS_REG(3, 0, 0, 3, 4)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_DFR0], ARM64_SYS_REG(3, 0, 0, 1, 2)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR0], ARM64_SYS_REG(3, 0, 0, 1, 4)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR1], ARM64_SYS_REG(3, 0, 0, 1, 5)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR2], ARM64_SYS_REG(3, 0, 0, 1, 6)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR3], ARM64_SYS_REG(3, 0, 0, 1, 7)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR0], ARM64_SYS_REG(3, 0, 0, 2, 0)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR1], ARM64_SYS_REG(3, 0, 0, 2, 1)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar2, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR2], ARM64_SYS_REG(3, 0, 0, 2, 2)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar3, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR3], ARM64_SYS_REG(3, 0, 0, 2, 3)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar4, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR4], ARM64_SYS_REG(3, 0, 0, 2, 4)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR5], ARM64_SYS_REG(3, 0, 0, 2, 5)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR4], ARM64_SYS_REG(3, 0, 0, 2, 6)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR6], ARM64_SYS_REG(3, 0, 0, 2, 7)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[MVFR0], ARM64_SYS_REG(3, 0, 0, 3, 0)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr1, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[MVFR1], ARM64_SYS_REG(3, 0, 0, 3, 1)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr2, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[MVFR2], ARM64_SYS_REG(3, 0, 0, 3, 2)); /* @@ -624,14 +624,17 @@ 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(ahcf->isar.regs[ID_AA64PFR0], ID_AA64PFR0, EL1) >= 2) { + int wrps = FIELD_EX64(ahcf->isar.regs[ID_AA64DFR0], ID_AA64DFR0, + WRPS); + int brps = FIELD_EX64(ahcf->isar.regs[ID_AA64DFR0], ID_AA64DFR0, + BRPS); int ctx_cmps = - FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS); + FIELD_EX64(ahcf->isar.regs[ID_AA64DFR0], ID_AA64DFR0, + CTX_CMPS); int version = 6; /* ARMv8 debug architecture */ bool has_el3 = - !!FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL3); + !!FIELD_EX32(ahcf->isar.regs[ID_AA64PFR0], ID_AA64PFR0, EL3); uint32_t dbgdidr = 0; dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, WRPS, wrps); @@ -641,7 +644,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, NSUHD_IMP, has_el3); dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, SE_IMP, has_el3); dbgdidr |= (1 << 15); /* RES1 bit */ - ahcf->isar.dbgdidr = dbgdidr; + ahcf->isar.regs[DBGDIDR] = dbgdidr; } } @@ -649,9 +652,9 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) /* Add feature bits that can't appear until after VCPU init. */ if (sve_supported) { - t = ahcf->isar.id_aa64pfr0; + t = ahcf->isar.regs[ID_AA64PFR0]; t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1); - ahcf->isar.id_aa64pfr0 = t; + ahcf->isar.regs[ID_AA64PFR0] = t; /* * Before v5.1, KVM did not support SVE and did not expose @@ -659,7 +662,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) * not expose the register to "user" requests like this * unless the host supports SVE. */ - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64zfr0, + err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64ZFR0], ARM64_SYS_REG(3, 0, 0, 4, 4)); } @@ -824,6 +827,20 @@ static int kvm_arm_sve_set_vls(CPUState *cs) return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); } +bool kvm_arm_cpu_feature_supported(void) +{ + static bool cpu_feature_initialized; + static bool cpu_feature_supported; + + if (!cpu_feature_initialized) { + cpu_feature_supported = kvm_check_extension(kvm_state, + KVM_CAP_ARM_CPU_FEATURE); + cpu_feature_initialized = true; + } + + return cpu_feature_supported; +} + #define ARM_CPU_ID_MPIDR 3, 0, 0, 0, 5 int kvm_arch_init_vcpu(CPUState *cs) diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h index b7f78b5215456291a582e7ab3dea56ae711e13fe..82145607ecaa39bb5d7b3a3b018099824a3ff0c7 100644 --- a/target/arm/kvm_arm.h +++ b/target/arm/kvm_arm.h @@ -306,6 +306,13 @@ bool kvm_arm_pmu_supported(void); */ bool kvm_arm_sve_supported(void); +/** + * kvm_arm_cpu_feature_supported: + * + * Returns true if KVM can set CPU features and false otherwise. + */ +bool kvm_arm_cpu_feature_supported(void); + /** * kvm_arm_get_max_vm_ipa_size: * @ms: Machine state handle @@ -528,4 +535,7 @@ static inline const char *its_class_name(void) } } +int kvm_arm_get_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *target); +int kvm_arm_set_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *source); + #endif diff --git a/target/arm/monitor.c b/target/arm/monitor.c index 80c64fa3556d84cc5da1f5d3756fa261852811d7..4c6f1181d9259ff99bebdd01ceb0145d6f899991 100644 --- a/target/arm/monitor.c +++ b/target/arm/monitor.c @@ -217,6 +217,8 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, } } + arm_cpu_features_to_dict(ARM_CPU(obj), qdict_out); + if (!qdict_size(qdict_out)) { qobject_unref(qdict_out); } else {