diff options
Diffstat (limited to 'target/arm/helper.c')
-rw-r--r-- | target/arm/helper.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c index c83f7c1109..e3946562aa 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1179,6 +1179,7 @@ static void pmcntenclr_write(CPUARMState *env, const ARMCPRegInfo *ri, static void pmovsr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { + value &= pmu_counter_mask(env); env->cp15.c9_pmovsr &= ~value; } @@ -1423,12 +1424,14 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { .writefn = pmintenset_write, .raw_writefn = raw_write, .resetvalue = 0x0 }, { .name = "PMINTENCLR", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 2, - .access = PL1_RW, .accessfn = access_tpm, .type = ARM_CP_ALIAS, + .access = PL1_RW, .accessfn = access_tpm, + .type = ARM_CP_ALIAS | ARM_CP_IO, .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten), .writefn = pmintenclr_write, }, { .name = "PMINTENCLR_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 2, - .access = PL1_RW, .accessfn = access_tpm, .type = ARM_CP_ALIAS, + .access = PL1_RW, .accessfn = access_tpm, + .type = ARM_CP_ALIAS | ARM_CP_IO, .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten), .writefn = pmintenclr_write }, { .name = "CCSIDR", .state = ARM_CP_STATE_BOTH, @@ -6469,7 +6472,7 @@ static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value, target_ulong page_size; hwaddr physaddr; int prot; - ARMMMUFaultInfo fi; + ARMMMUFaultInfo fi = {}; bool secure = mmu_idx & ARM_MMU_IDX_M_S; int exc; bool exc_secure; @@ -6531,7 +6534,7 @@ static bool v7m_stack_read(ARMCPU *cpu, uint32_t *dest, uint32_t addr, target_ulong page_size; hwaddr physaddr; int prot; - ARMMMUFaultInfo fi; + ARMMMUFaultInfo fi = {}; bool secure = mmu_idx & ARM_MMU_IDX_M_S; int exc; bool exc_secure; @@ -8374,7 +8377,11 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs) unsigned int new_mode = aarch64_pstate_mode(new_el, true); unsigned int cur_el = arm_current_el(env); - aarch64_sve_change_el(env, cur_el, new_el); + /* + * Note that new_el can never be 0. If cur_el is 0, then + * el0_a64 is is_a64(), else el0_a64 is ignored. + */ + aarch64_sve_change_el(env, cur_el, new_el, is_a64(env)); if (cur_el < new_el) { /* Entry vector offset depends on whether the implemented EL @@ -12791,9 +12798,11 @@ void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq) /* * Notice a change in SVE vector size when changing EL. */ -void aarch64_sve_change_el(CPUARMState *env, int old_el, int new_el) +void aarch64_sve_change_el(CPUARMState *env, int old_el, + int new_el, bool el0_a64) { int old_len, new_len; + bool old_a64, new_a64; /* Nothing to do if no SVE. */ if (!arm_feature(env, ARM_FEATURE_SVE)) { @@ -12817,9 +12826,11 @@ void aarch64_sve_change_el(CPUARMState *env, int old_el, int new_el) * we already have the correct register contents when encountering the * vq0->vq0 transition between EL0->EL1. */ - old_len = (arm_el_is_aa64(env, old_el) && !sve_exception_el(env, old_el) + old_a64 = old_el ? arm_el_is_aa64(env, old_el) : el0_a64; + old_len = (old_a64 && !sve_exception_el(env, old_el) ? sve_zcr_len_for_el(env, old_el) : 0); - new_len = (arm_el_is_aa64(env, new_el) && !sve_exception_el(env, new_el) + new_a64 = new_el ? arm_el_is_aa64(env, new_el) : el0_a64; + new_len = (new_a64 && !sve_exception_el(env, new_el) ? sve_zcr_len_for_el(env, new_el) : 0); /* When changing vector length, clear inaccessible state. */ |