diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2021-02-11 19:57:50 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-02-11 19:57:50 +0000 |
commit | eac92d316351b855ba79eb374dd21cc367f1f9c1 (patch) | |
tree | 3dd45330cd46e965e5ac5dfff8379a55df7d497f | |
parent | c973f06521b07af0f82893b75a1d55562fffb4b5 (diff) | |
parent | d3c1183ffeb71ca3a783eae3d7e1c51e71e8a621 (diff) |
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20210211-1' into staging
target-arm queue:
* Correctly initialize MDCR_EL2.HPMN
* versal: Use nr_apu_cpus in favor of hard coding 2
* accel/tcg: Add URL of clang bug to comment about our workaround
* Add support for FEAT_DIT, Data Independent Timing
* Remove GPIO from unimplemented NPCM7XX
* Fix SCR RES1 handling
* Don't migrate CPUARMState.features
# gpg: Signature made Thu 11 Feb 2021 19:56:40 GMT
# gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg: issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE
* remotes/pmaydell/tags/pull-target-arm-20210211-1:
target/arm: Correctly initialize MDCR_EL2.HPMN
hw/arm: versal: Use nr_apu_cpus in favor of hard coding 2
accel/tcg: Add URL of clang bug to comment about our workaround
arm: Update infocenter.arm.com URLs
target/arm: Set ID_PFR0.DIT to 1 for "max" 32-bit CPU
target/arm: Set ID_AA64PFR0.DIT and ID_PFR0.DIT to 1 for "max" AA64 CPU
target/arm: Support AA32 DIT by moving PSTATE_SS from cpsr into env->pstate
target/arm: Add support for FEAT_DIT, Data Independent Timing
hw/arm: Remove GPIO from unimplemented NPCM7XX
target/arm: Fix SCR RES1 handling
target/arm: Don't migrate CPUARMState.features
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | accel/tcg/cpu-exec.c | 25 | ||||
-rw-r--r-- | hw/arm/aspeed_ast2600.c | 2 | ||||
-rw-r--r-- | hw/arm/musca.c | 4 | ||||
-rw-r--r-- | hw/arm/npcm7xx.c | 8 | ||||
-rw-r--r-- | hw/arm/xlnx-versal.c | 4 | ||||
-rw-r--r-- | hw/misc/arm_integrator_debug.c | 2 | ||||
-rw-r--r-- | hw/timer/arm_timer.c | 7 | ||||
-rw-r--r-- | include/hw/dma/pl080.h | 7 | ||||
-rw-r--r-- | include/hw/misc/arm_integrator_debug.h | 2 | ||||
-rw-r--r-- | include/hw/ssi/pl022.h | 5 | ||||
-rw-r--r-- | target/arm/cpu.c | 4 | ||||
-rw-r--r-- | target/arm/cpu.h | 17 | ||||
-rw-r--r-- | target/arm/cpu64.c | 5 | ||||
-rw-r--r-- | target/arm/helper-a64.c | 27 | ||||
-rw-r--r-- | target/arm/helper.c | 71 | ||||
-rw-r--r-- | target/arm/internals.h | 6 | ||||
-rw-r--r-- | target/arm/machine.c | 2 | ||||
-rw-r--r-- | target/arm/op_helper.c | 9 | ||||
-rw-r--r-- | target/arm/translate-a64.c | 12 |
19 files changed, 164 insertions, 55 deletions
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index d9ef69121c..f2819eec7d 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -773,17 +773,30 @@ int cpu_exec(CPUState *cpu) /* prepare setjmp context for exception handling */ if (sigsetjmp(cpu->jmp_env, 0) != 0) { #if defined(__clang__) - /* Some compilers wrongly smash all local variables after - * siglongjmp. There were bug reports for gcc 4.5.0 and clang. + /* + * Some compilers wrongly smash all local variables after + * siglongjmp (the spec requires that only non-volatile locals + * which are changed between the sigsetjmp and siglongjmp are + * permitted to be trashed). There were bug reports for gcc + * 4.5.0 and clang. The bug is fixed in all versions of gcc + * that we support, but is still unfixed in clang: + * https://bugs.llvm.org/show_bug.cgi?id=21183 + * * Reload essential local variables here for those compilers. - * Newer versions of gcc would complain about this code (-Wclobbered). */ + * Newer versions of gcc would complain about this code (-Wclobbered), + * so we only perform the workaround for clang. + */ cpu = current_cpu; cc = CPU_GET_CLASS(cpu); -#else /* buggy compiler */ - /* Assert that the compiler does not smash local variables. */ +#else + /* + * Non-buggy compilers preserve these locals; assert that + * they have the correct value. + */ g_assert(cpu == current_cpu); g_assert(cc == CPU_GET_CLASS(cpu)); -#endif /* buggy compiler */ +#endif + #ifndef CONFIG_SOFTMMU tcg_debug_assert(!have_mmap_lock()); #endif diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index 12e4a16d37..bf31ca351f 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -216,7 +216,7 @@ static void aspeed_soc_ast2600_init(Object *obj) /* * ASPEED ast2600 has 0xf as cluster ID * - * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0388e/CIHEBGFG.html + * https://developer.arm.com/documentation/ddi0388/e/the-system-control-coprocessors/summary-of-system-control-coprocessor-registers/multiprocessor-affinity-register */ static uint64_t aspeed_calc_affinity(int cpu) { diff --git a/hw/arm/musca.c b/hw/arm/musca.c index 945643c3cd..7a83f7dda7 100644 --- a/hw/arm/musca.c +++ b/hw/arm/musca.c @@ -15,8 +15,8 @@ * https://developer.arm.com/products/system-design/development-boards/iot-test-chips-and-boards/musca-a-test-chip-board * https://developer.arm.com/products/system-design/development-boards/iot-test-chips-and-boards/musca-b-test-chip-board * We model the A and B1 variants of this board, as described in the TRMs: - * http://infocenter.arm.com/help/topic/com.arm.doc.101107_0000_00_en/index.html - * http://infocenter.arm.com/help/topic/com.arm.doc.101312_0000_00_en/index.html + * https://developer.arm.com/documentation/101107/latest/ + * https://developer.arm.com/documentation/101312/latest/ */ #include "qemu/osdep.h" diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c index 72040d4079..d1fe9bd1df 100644 --- a/hw/arm/npcm7xx.c +++ b/hw/arm/npcm7xx.c @@ -576,14 +576,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp) create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB); create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * KiB); create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * KiB); - create_unimplemented_device("npcm7xx.gpio[0]", 0xf0010000, 4 * KiB); - create_unimplemented_device("npcm7xx.gpio[1]", 0xf0011000, 4 * KiB); - create_unimplemented_device("npcm7xx.gpio[2]", 0xf0012000, 4 * KiB); - create_unimplemented_device("npcm7xx.gpio[3]", 0xf0013000, 4 * KiB); - create_unimplemented_device("npcm7xx.gpio[4]", 0xf0014000, 4 * KiB); - create_unimplemented_device("npcm7xx.gpio[5]", 0xf0015000, 4 * KiB); - create_unimplemented_device("npcm7xx.gpio[6]", 0xf0016000, 4 * KiB); - create_unimplemented_device("npcm7xx.gpio[7]", 0xf0017000, 4 * KiB); create_unimplemented_device("npcm7xx.smbus[0]", 0xf0080000, 4 * KiB); create_unimplemented_device("npcm7xx.smbus[1]", 0xf0081000, 4 * KiB); create_unimplemented_device("npcm7xx.smbus[2]", 0xf0082000, 4 * KiB); diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index b0777166e8..628e77ef66 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -67,10 +67,10 @@ static void versal_create_apu_gic(Versal *s, qemu_irq *pic) gicbusdev = SYS_BUS_DEVICE(&s->fpd.apu.gic); gicdev = DEVICE(&s->fpd.apu.gic); qdev_prop_set_uint32(gicdev, "revision", 3); - qdev_prop_set_uint32(gicdev, "num-cpu", 2); + qdev_prop_set_uint32(gicdev, "num-cpu", nr_apu_cpus); qdev_prop_set_uint32(gicdev, "num-irq", XLNX_VERSAL_NR_IRQS + 32); qdev_prop_set_uint32(gicdev, "len-redist-region-count", 1); - qdev_prop_set_uint32(gicdev, "redist-region-count[0]", 2); + qdev_prop_set_uint32(gicdev, "redist-region-count[0]", nr_apu_cpus); qdev_prop_set_bit(gicdev, "has-security-extensions", true); sysbus_realize(SYS_BUS_DEVICE(&s->fpd.apu.gic), &error_fatal); diff --git a/hw/misc/arm_integrator_debug.c b/hw/misc/arm_integrator_debug.c index ec0d4b90d3..9a19727829 100644 --- a/hw/misc/arm_integrator_debug.c +++ b/hw/misc/arm_integrator_debug.c @@ -6,7 +6,7 @@ * to this area. * * The real h/w is described at: - * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0159b/Babbfijf.html + * https://developer.arm.com/documentation/dui0159/b/peripherals-and-interfaces/debug-leds-and-dip-switch-interface * * Copyright (c) 2013 Alex Bennée <alex@bennee.com> * diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c index 98e70b2d26..15caff0e41 100644 --- a/hw/timer/arm_timer.c +++ b/hw/timer/arm_timer.c @@ -185,10 +185,11 @@ static arm_timer_state *arm_timer_init(uint32_t freq) return s; } -/* ARM PrimeCell SP804 dual timer module. +/* + * ARM PrimeCell SP804 dual timer module. * Docs at - * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0271d/index.html -*/ + * https://developer.arm.com/documentation/ddi0271/latest/ + */ #define TYPE_SP804 "sp804" OBJECT_DECLARE_SIMPLE_TYPE(SP804State, SP804) diff --git a/include/hw/dma/pl080.h b/include/hw/dma/pl080.h index 1883f04270..3c9659e438 100644 --- a/include/hw/dma/pl080.h +++ b/include/hw/dma/pl080.h @@ -10,11 +10,12 @@ * (at your option) any later version. */ -/* This is a model of the Arm PrimeCell PL080/PL081 DMA controller: +/* + * This is a model of the Arm PrimeCell PL080/PL081 DMA controller: * The PL080 TRM is: - * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0196g/DDI0196.pdf + * https://developer.arm.com/documentation/ddi0196/latest * and the PL081 TRM is: - * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0218e/DDI0218.pdf + * https://developer.arm.com/documentation/ddi0218/latest * * QEMU interface: * + sysbus IRQ 0: DMACINTR combined interrupt line diff --git a/include/hw/misc/arm_integrator_debug.h b/include/hw/misc/arm_integrator_debug.h index 0077dacb44..798b082164 100644 --- a/include/hw/misc/arm_integrator_debug.h +++ b/include/hw/misc/arm_integrator_debug.h @@ -3,7 +3,7 @@ * * Browse the data sheet: * - * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0159b/Babbfijf.html + * https://developer.arm.com/documentation/dui0159/b/peripherals-and-interfaces/debug-leds-and-dip-switch-interface * * Copyright (c) 2013 Alex Bennée <alex@bennee.com> * diff --git a/include/hw/ssi/pl022.h b/include/hw/ssi/pl022.h index 545b52689c..25d58db5f3 100644 --- a/include/hw/ssi/pl022.h +++ b/include/hw/ssi/pl022.h @@ -9,9 +9,10 @@ * (at your option) any later version. */ -/* This is a model of the Arm PrimeCell PL022 synchronous serial port. +/* + * This is a model of the Arm PrimeCell PL022 synchronous serial port. * The PL022 TRM is: - * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0194h/DDI0194H_ssp_pl022_trm.pdf + * https://developer.arm.com/documentation/ddi0194/latest * * QEMU interface: * + sysbus IRQ: SSPINTR combined interrupt line diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 8ddb2556f8..5cf6c056c5 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -2202,6 +2202,10 @@ static void arm_max_initfn(Object *obj) t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */ t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */ cpu->isar.id_mmfr4 = t; + + t = cpu->isar.id_pfr0; + t = FIELD_DP32(t, ID_PFR0, DIT, 1); + cpu->isar.id_pfr0 = t; } #endif } diff --git a/target/arm/cpu.h b/target/arm/cpu.h index d080239863..f240275407 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1243,6 +1243,7 @@ void pmu_init(ARMCPU *cpu); #define CPSR_IT_2_7 (0xfc00U) #define CPSR_GE (0xfU << 16) #define CPSR_IL (1U << 20) +#define CPSR_DIT (1U << 21) #define CPSR_PAN (1U << 22) #define CPSR_J (1U << 24) #define CPSR_IT_0_1 (3U << 25) @@ -1310,6 +1311,7 @@ void pmu_init(ARMCPU *cpu); #define PSTATE_SS (1U << 21) #define PSTATE_PAN (1U << 22) #define PSTATE_UAO (1U << 23) +#define PSTATE_DIT (1U << 24) #define PSTATE_TCO (1U << 25) #define PSTATE_V (1U << 28) #define PSTATE_C (1U << 29) @@ -3876,6 +3878,11 @@ static inline bool isar_feature_aa32_tts2uxn(const ARMISARegisters *id) return FIELD_EX32(id->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; +} + /* * 64-bit feature tests via id registers. */ @@ -4033,6 +4040,11 @@ static inline bool isar_feature_aa64_aa32(const ARMISARegisters *id) return FIELD_EX64(id->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; +} + static inline bool isar_feature_aa64_sve(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0; @@ -4120,6 +4132,11 @@ static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id) return FIELD_EX64(id->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; +} + /* * Feature tests for "does this exist in either 32-bit or 64-bit?" */ diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 10c5118176..c255f1bcc3 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -669,6 +669,7 @@ static void aarch64_max_initfn(Object *obj) 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; t = cpu->isar.id_aa64pfr1; @@ -718,6 +719,10 @@ static void aarch64_max_initfn(Object *obj) u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1); cpu->isar.id_isar6 = u; + u = cpu->isar.id_pfr0; + u = FIELD_DP32(u, ID_PFR0, DIT, 1); + cpu->isar.id_pfr0 = u; + u = cpu->isar.id_mmfr3; u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */ cpu->isar.id_mmfr3 = u; diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c index c426c23d2c..ae611d73c2 100644 --- a/target/arm/helper-a64.c +++ b/target/arm/helper-a64.c @@ -945,11 +945,31 @@ static int el_from_spsr(uint32_t spsr) } } +static void cpsr_write_from_spsr_elx(CPUARMState *env, + uint32_t val) +{ + uint32_t mask; + + /* Save SPSR_ELx.SS into PSTATE. */ + env->pstate = (env->pstate & ~PSTATE_SS) | (val & PSTATE_SS); + val &= ~PSTATE_SS; + + /* Move DIT to the correct location for CPSR */ + if (val & PSTATE_DIT) { + val &= ~PSTATE_DIT; + val |= CPSR_DIT; + } + + mask = aarch32_cpsr_valid_mask(env->features, \ + &env_archcpu(env)->isar); + cpsr_write(env, val, mask, CPSRWriteRaw); +} + void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc) { int cur_el = arm_current_el(env); unsigned int spsr_idx = aarch64_banked_spsr_index(cur_el); - uint32_t mask, spsr = env->banked_spsr[spsr_idx]; + uint32_t spsr = env->banked_spsr[spsr_idx]; int new_el; bool return_to_aa64 = (spsr & PSTATE_nRW) == 0; @@ -998,10 +1018,9 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc) * will sort the register banks out for us, and we've already * caught all the bad-mode cases in el_from_spsr(). */ - mask = aarch32_cpsr_valid_mask(env->features, &env_archcpu(env)->isar); - cpsr_write(env, spsr, mask, CPSRWriteRaw); + cpsr_write_from_spsr_elx(env, spsr); if (!arm_singlestep_active(env)) { - env->uncached_cpsr &= ~PSTATE_SS; + env->pstate &= ~PSTATE_SS; } aarch64_sync_64_to_32(env); diff --git a/target/arm/helper.c b/target/arm/helper.c index 1a64bd748c..0e1a3b9421 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -38,6 +38,7 @@ #endif #define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */ +#define PMCR_NUM_COUNTERS 4 /* QEMU IMPDEF choice */ #ifndef CONFIG_USER_ONLY @@ -2024,7 +2025,10 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) ARMCPU *cpu = env_archcpu(env); if (ri->state == ARM_CP_STATE_AA64) { - value |= SCR_FW | SCR_AW; /* these two bits are RES1. */ + if (arm_feature(env, ARM_FEATURE_AARCH64) && + !cpu_isar_feature(aa64_aa32_el1, cpu)) { + value |= SCR_FW | SCR_AW; /* these two bits are RES1. */ + } valid_mask &= ~SCR_NET; if (cpu_isar_feature(aa64_lor, cpu)) { @@ -2063,6 +2067,15 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) raw_write(env, ri, value); } +static void scr_reset(CPUARMState *env, const ARMCPRegInfo *ri) +{ + /* + * scr_write will set the RES1 bits on an AArch64-only CPU. + * The reset value will be 0x30 on an AArch64-only CPU and 0 otherwise. + */ + scr_write(env, ri, 0); +} + static CPAccessResult access_aa64_tid2(CPUARMState *env, const ARMCPRegInfo *ri, bool isread) @@ -4419,6 +4432,24 @@ static const ARMCPRegInfo uao_reginfo = { .readfn = aa64_uao_read, .writefn = aa64_uao_write }; +static uint64_t aa64_dit_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return env->pstate & PSTATE_DIT; +} + +static void aa64_dit_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + env->pstate = (env->pstate & ~PSTATE_DIT) | (value & PSTATE_DIT); +} + +static const ARMCPRegInfo dit_reginfo = { + .name = "DIT", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 5, + .type = ARM_CP_NO_RAW, .access = PL0_RW, + .readfn = aa64_dit_read, .writefn = aa64_dit_write +}; + static CPAccessResult aa64_cacheop_poc_access(CPUARMState *env, const ARMCPRegInfo *ri, bool isread) @@ -5705,13 +5736,11 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { .writefn = gt_hyp_ctl_write, .raw_writefn = raw_write }, #endif /* The only field of MDCR_EL2 that has a defined architectural reset value - * is MDCR_EL2.HPMN which should reset to the value of PMCR_EL0.N; but we - * don't implement any PMU event counters, so using zero as a reset - * value for MDCR_EL2 is okay + * is MDCR_EL2.HPMN which should reset to the value of PMCR_EL0.N. */ { .name = "MDCR_EL2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 1, - .access = PL2_RW, .resetvalue = 0, + .access = PL2_RW, .resetvalue = PMCR_NUM_COUNTERS, .fieldoffset = offsetof(CPUARMState, cp15.mdcr_el2), }, { .name = "HPFAR", .state = ARM_CP_STATE_AA32, .cp = 15, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 4, @@ -5785,7 +5814,7 @@ static const ARMCPRegInfo el3_cp_reginfo[] = { { .name = "SCR_EL3", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 0, .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.scr_el3), - .resetvalue = 0, .writefn = scr_write }, + .resetfn = scr_reset, .writefn = scr_write }, { .name = "SCR", .type = ARM_CP_ALIAS | ARM_CP_NEWEL, .cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 0, .access = PL1_RW, .accessfn = access_trap_aa32s_el1, @@ -6642,7 +6671,7 @@ static void define_pmu_regs(ARMCPU *cpu) * field as main ID register, and we implement four counters in * addition to the cycle count register. */ - unsigned int i, pmcrn = 4; + unsigned int i, pmcrn = PMCR_NUM_COUNTERS; ARMCPRegInfo pmcr = { .name = "PMCR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 0, .access = PL0_RW, @@ -8212,6 +8241,10 @@ void register_cp_regs_for_features(ARMCPU *cpu) define_one_arm_cp_reg(cpu, &uao_reginfo); } + if (cpu_isar_feature(aa64_dit, cpu)) { + define_one_arm_cp_reg(cpu, &dit_reginfo); + } + if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) { define_arm_cp_regs(cpu, vhe_reginfo); } @@ -9411,7 +9444,7 @@ static void take_aarch32_exception(CPUARMState *env, int new_mode, * For exceptions taken to AArch32 we must clear the SS bit in both * PSTATE and in the old-state value we save to SPSR_<mode>, so zero it now. */ - env->uncached_cpsr &= ~PSTATE_SS; + env->pstate &= ~PSTATE_SS; env->spsr = cpsr_read(env); /* Clear IT bits. */ env->condexec_bits = 0; @@ -9767,6 +9800,21 @@ static int aarch64_regnum(CPUARMState *env, int aarch32_reg) } } +static uint32_t cpsr_read_for_spsr_elx(CPUARMState *env) +{ + uint32_t ret = cpsr_read(env); + + /* Move DIT to the correct location for SPSR_ELx */ + if (ret & CPSR_DIT) { + ret &= ~CPSR_DIT; + ret |= PSTATE_DIT; + } + /* Merge PSTATE.SS into SPSR_ELx */ + ret |= env->pstate & PSTATE_SS; + + return ret; +} + /* Handle exception entry to a target EL which is using AArch64 */ static void arm_cpu_do_interrupt_aarch64(CPUState *cs) { @@ -9889,7 +9937,7 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs) aarch64_save_sp(env, arm_current_el(env)); env->elr_el[new_el] = env->pc; } else { - old_mode = cpsr_read(env); + old_mode = cpsr_read_for_spsr_elx(env); env->elr_el[new_el] = env->regs[15]; aarch64_sync_32_to_64(env); @@ -13183,7 +13231,6 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *pflags) { uint32_t flags = env->hflags; - uint32_t pstate_for_ss; *cs_base = 0; assert_hflags_rebuild_correctly(env); @@ -13193,7 +13240,6 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, if (cpu_isar_feature(aa64_bti, env_archcpu(env))) { flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype); } - pstate_for_ss = env->pstate; } else { *pc = env->regs[15]; @@ -13241,7 +13287,6 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, flags = FIELD_DP32(flags, TBFLAG_AM32, THUMB, env->thumb); flags = FIELD_DP32(flags, TBFLAG_AM32, CONDEXEC, env->condexec_bits); - pstate_for_ss = env->uncached_cpsr; } /* @@ -13254,7 +13299,7 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, * SS_ACTIVE is set in hflags; PSTATE_SS is computed every TB. */ if (FIELD_EX32(flags, TBFLAG_ANY, SS_ACTIVE) && - (pstate_for_ss & PSTATE_SS)) { + (env->pstate & PSTATE_SS)) { flags = FIELD_DP32(flags, TBFLAG_ANY, PSTATE_SS, 1); } diff --git a/target/arm/internals.h b/target/arm/internals.h index 448982dd2f..b251fe4450 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1228,6 +1228,9 @@ static inline uint32_t aarch32_cpsr_valid_mask(uint64_t features, if (isar_feature_aa32_pan(id)) { valid |= CPSR_PAN; } + if (isar_feature_aa32_dit(id)) { + valid |= CPSR_DIT; + } return valid; } @@ -1246,6 +1249,9 @@ static inline uint32_t aarch64_pstate_valid_mask(const ARMISARegisters *id) if (isar_feature_aa64_uao(id)) { valid |= PSTATE_UAO; } + if (isar_feature_aa64_dit(id)) { + valid |= PSTATE_DIT; + } if (isar_feature_aa64_mte(id)) { valid |= PSTATE_TCO; } diff --git a/target/arm/machine.c b/target/arm/machine.c index 581852bc53..6ad1d306b1 100644 --- a/target/arm/machine.c +++ b/target/arm/machine.c @@ -810,7 +810,7 @@ const VMStateDescription vmstate_arm_cpu = { VMSTATE_UINT64(env.exclusive_addr, ARMCPU), VMSTATE_UINT64(env.exclusive_val, ARMCPU), VMSTATE_UINT64(env.exclusive_high, ARMCPU), - VMSTATE_UINT64(env.features, ARMCPU), + VMSTATE_UNUSED(sizeof(uint64_t)), VMSTATE_UINT32(env.exception.syndrome, ARMCPU), VMSTATE_UINT32(env.exception.fsr, ARMCPU), VMSTATE_UINT64(env.exception.vaddress, ARMCPU), diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index 5e0f123043..65cb37d088 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -389,14 +389,7 @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome) uint32_t HELPER(cpsr_read)(CPUARMState *env) { - /* - * We store the ARMv8 PSTATE.SS bit in env->uncached_cpsr. - * This is convenient for populating SPSR_ELx, but must be - * hidden from aarch32 mode, where it is not visible. - * - * TODO: ARMv8.4-DIT -- need to move SS somewhere else. - */ - return cpsr_read(env) & ~(CPSR_EXEC | PSTATE_SS); + return cpsr_read(env) & ~CPSR_EXEC; } void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index ffc060e5d7..1c4b8d02f3 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -1700,6 +1700,18 @@ static void handle_msr_i(DisasContext *s, uint32_t insn, tcg_temp_free_i32(t1); break; + case 0x1a: /* DIT */ + if (!dc_isar_feature(aa64_dit, s)) { + goto do_unallocated; + } + if (crm & 1) { + set_pstate_bits(PSTATE_DIT); + } else { + clear_pstate_bits(PSTATE_DIT); + } + /* There's no need to rebuild hflags because DIT is a nop */ + break; + case 0x1e: /* DAIFSet */ t1 = tcg_const_i32(crm); gen_helper_msr_i_daifset(cpu_env, t1); |