[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 33/35] target/arm/helper: Implement CNTHCTL_EL2.CNT[VP]MASK
From: |
Peter Maydell |
Subject: |
[PULL 33/35] target/arm/helper: Implement CNTHCTL_EL2.CNT[VP]MASK |
Date: |
Thu, 24 Aug 2023 10:28:34 +0100 |
From: Jean-Philippe Brucker <jean-philippe@linaro.org>
When FEAT_RME is implemented, these bits override the value of
CNT[VP]_CTL_EL0.IMASK in Realm and Root state. Move the IRQ state update
into a new gt_update_irq() function and test those bits every time we
recompute the IRQ state.
Since we're removing the IRQ state from some trace events, add a new
trace event for gt_update_irq().
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
Message-id: 20230809123706.1842548-7-jean-philippe@linaro.org
[PMM: only register change hook if not USER_ONLY and if TCG]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
target/arm/cpu.h | 4 +++
target/arm/cpu.c | 6 ++++
target/arm/helper.c | 65 ++++++++++++++++++++++++++++++++++-------
target/arm/trace-events | 7 +++--
4 files changed, 68 insertions(+), 14 deletions(-)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 02bc8f0e8e0..cdf8600b96a 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1115,6 +1115,7 @@ struct ArchCPU {
};
unsigned int gt_cntfrq_period_ns(ARMCPU *cpu);
+void gt_rme_post_el_change(ARMCPU *cpu, void *opaque);
void arm_cpu_post_init(Object *obj);
@@ -1743,6 +1744,9 @@ static inline void xpsr_write(CPUARMState *env, uint32_t
val, uint32_t mask)
#define HSTR_TTEE (1 << 16)
#define HSTR_TJDBX (1 << 17)
+#define CNTHCTL_CNTVMASK (1 << 18)
+#define CNTHCTL_CNTPMASK (1 << 19)
+
/* Return the current FPSCR value. */
uint32_t vfp_get_fpscr(CPUARMState *env);
void vfp_set_fpscr(CPUARMState *env, uint32_t val);
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 93c28d50e58..d906d2b1caa 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2169,6 +2169,12 @@ static void arm_cpu_realizefn(DeviceState *dev, Error
**errp)
set_feature(env, ARM_FEATURE_VBAR);
}
+#ifndef CONFIG_USER_ONLY
+ if (tcg_enabled() && cpu_isar_feature(aa64_rme, cpu)) {
+ arm_register_el_change_hook(cpu, >_rme_post_el_change, 0);
+ }
+#endif
+
register_cp_regs_for_features(cpu);
arm_cpu_register_gdb_regs_for_features(cpu);
diff --git a/target/arm/helper.c b/target/arm/helper.c
index b4618ee2b95..85291d5b8e2 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2608,6 +2608,39 @@ static uint64_t gt_get_countervalue(CPUARMState *env)
return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / gt_cntfrq_period_ns(cpu);
}
+static void gt_update_irq(ARMCPU *cpu, int timeridx)
+{
+ CPUARMState *env = &cpu->env;
+ uint64_t cnthctl = env->cp15.cnthctl_el2;
+ ARMSecuritySpace ss = arm_security_space(env);
+ /* ISTATUS && !IMASK */
+ int irqstate = (env->cp15.c14_timer[timeridx].ctl & 6) == 4;
+
+ /*
+ * If bit CNTHCTL_EL2.CNT[VP]MASK is set, it overrides IMASK.
+ * It is RES0 in Secure and NonSecure state.
+ */
+ if ((ss == ARMSS_Root || ss == ARMSS_Realm) &&
+ ((timeridx == GTIMER_VIRT && (cnthctl & CNTHCTL_CNTVMASK)) ||
+ (timeridx == GTIMER_PHYS && (cnthctl & CNTHCTL_CNTPMASK)))) {
+ irqstate = 0;
+ }
+
+ qemu_set_irq(cpu->gt_timer_outputs[timeridx], irqstate);
+ trace_arm_gt_update_irq(timeridx, irqstate);
+}
+
+void gt_rme_post_el_change(ARMCPU *cpu, void *ignored)
+{
+ /*
+ * Changing security state between Root and Secure/NonSecure, which may
+ * happen when switching EL, can change the effective value of CNTHCTL_EL2
+ * mask bits. Update the IRQ state accordingly.
+ */
+ gt_update_irq(cpu, GTIMER_VIRT);
+ gt_update_irq(cpu, GTIMER_PHYS);
+}
+
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
{
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
@@ -2623,13 +2656,9 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
/* Note that this must be unsigned 64 bit arithmetic: */
int istatus = count - offset >= gt->cval;
uint64_t nexttick;
- int irqstate;
gt->ctl = deposit32(gt->ctl, 2, 1, istatus);
- irqstate = (istatus && !(gt->ctl & 2));
- qemu_set_irq(cpu->gt_timer_outputs[timeridx], irqstate);
-
if (istatus) {
/* Next transition is when count rolls back over to zero */
nexttick = UINT64_MAX;
@@ -2648,14 +2677,14 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
} else {
timer_mod(cpu->gt_timer[timeridx], nexttick);
}
- trace_arm_gt_recalc(timeridx, irqstate, nexttick);
+ trace_arm_gt_recalc(timeridx, nexttick);
} else {
/* Timer disabled: ISTATUS and timer output always clear */
gt->ctl &= ~4;
- qemu_set_irq(cpu->gt_timer_outputs[timeridx], 0);
timer_del(cpu->gt_timer[timeridx]);
trace_arm_gt_recalc_disabled(timeridx);
}
+ gt_update_irq(cpu, timeridx);
}
static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -2759,10 +2788,8 @@ static void gt_ctl_write(CPUARMState *env, const
ARMCPRegInfo *ri,
* IMASK toggled: don't need to recalculate,
* just set the interrupt line based on ISTATUS
*/
- int irqstate = (oldval & 4) && !(value & 2);
-
- trace_arm_gt_imask_toggle(timeridx, irqstate);
- qemu_set_irq(cpu->gt_timer_outputs[timeridx], irqstate);
+ trace_arm_gt_imask_toggle(timeridx);
+ gt_update_irq(cpu, timeridx);
}
}
@@ -2888,6 +2915,21 @@ static void gt_virt_ctl_write(CPUARMState *env, const
ARMCPRegInfo *ri,
gt_ctl_write(env, ri, GTIMER_VIRT, value);
}
+static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ ARMCPU *cpu = env_archcpu(env);
+ uint32_t oldval = env->cp15.cnthctl_el2;
+
+ raw_write(env, ri, value);
+
+ if ((oldval ^ value) & CNTHCTL_CNTVMASK) {
+ gt_update_irq(cpu, GTIMER_VIRT);
+ } else if ((oldval ^ value) & CNTHCTL_CNTPMASK) {
+ gt_update_irq(cpu, GTIMER_PHYS);
+ }
+}
+
static void gt_cntvoff_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
@@ -6203,7 +6245,8 @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
* reset values as IMPDEF. We choose to reset to 3 to comply with
* both ARMv7 and ARMv8.
*/
- .access = PL2_RW, .resetvalue = 3,
+ .access = PL2_RW, .type = ARM_CP_IO, .resetvalue = 3,
+ .writefn = gt_cnthctl_write, .raw_writefn = raw_write,
.fieldoffset = offsetof(CPUARMState, cp15.cnthctl_el2) },
{ .name = "CNTVOFF_EL2", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 4, .crn = 14, .crm = 0, .opc2 = 3,
diff --git a/target/arm/trace-events b/target/arm/trace-events
index 2a0ba7bffc1..48cc0512dbe 100644
--- a/target/arm/trace-events
+++ b/target/arm/trace-events
@@ -1,13 +1,14 @@
# See docs/devel/tracing.rst for syntax documentation.
# helper.c
-arm_gt_recalc(int timer, int irqstate, uint64_t nexttick) "gt recalc: timer %d
irqstate %d next tick 0x%" PRIx64
-arm_gt_recalc_disabled(int timer) "gt recalc: timer %d irqstate 0 timer
disabled"
+arm_gt_recalc(int timer, uint64_t nexttick) "gt recalc: timer %d next tick
0x%" PRIx64
+arm_gt_recalc_disabled(int timer) "gt recalc: timer %d timer disabled"
arm_gt_cval_write(int timer, uint64_t value) "gt_cval_write: timer %d value
0x%" PRIx64
arm_gt_tval_write(int timer, uint64_t value) "gt_tval_write: timer %d value
0x%" PRIx64
arm_gt_ctl_write(int timer, uint64_t value) "gt_ctl_write: timer %d value 0x%"
PRIx64
-arm_gt_imask_toggle(int timer, int irqstate) "gt_ctl_write: timer %d IMASK
toggle, new irqstate %d"
+arm_gt_imask_toggle(int timer) "gt_ctl_write: timer %d IMASK toggle"
arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value 0x%" PRIx64
+arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate
%d"
# kvm.c
kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = 0x%"PRIx64"
is translated into 0x%"PRIx64
--
2.34.1
- [PULL 19/35] target/arm: Pass an ARMSecuritySpace to arm_is_el2_enabled_secstate(), (continued)
- [PULL 19/35] target/arm: Pass an ARMSecuritySpace to arm_is_el2_enabled_secstate(), Peter Maydell, 2023/08/24
- [PULL 25/35] target/arm/ptw: Check for block descriptors at invalid levels, Peter Maydell, 2023/08/24
- [PULL 26/35] target/arm/ptw: Report stage 2 fault level for stage 2 faults on stage 1 ptw, Peter Maydell, 2023/08/24
- [PULL 23/35] target/arm/ptw: Drop S1Translate::out_secure, Peter Maydell, 2023/08/24
- [PULL 22/35] target/arm/ptw: Remove S1Translate::in_secure, Peter Maydell, 2023/08/24
- [PULL 08/35] accel/kvm: Specify default IPA size for arm64, Peter Maydell, 2023/08/24
- [PULL 27/35] target/arm: Adjust PAR_EL1.SH for Device and Normal-NC memory types, Peter Maydell, 2023/08/24
- [PULL 31/35] target/arm: Pass security space rather than flag for AT instructions, Peter Maydell, 2023/08/24
- [PULL 12/35] accel/kvm: Make kvm_dirty_ring_reaper_init() void, Peter Maydell, 2023/08/24
- [PULL 34/35] target/arm: Fix SME ST1Q, Peter Maydell, 2023/08/24
- [PULL 33/35] target/arm/helper: Implement CNTHCTL_EL2.CNT[VP]MASK,
Peter Maydell <=
- [PULL 18/35] target/arm/ptw: Pass an ARMSecuritySpace to arm_hcr_el2_eff_secstate(), Peter Maydell, 2023/08/24
- [PULL 14/35] target/arm/ptw: Don't report GPC faults on stage 1 ptw as stage2 faults, Peter Maydell, 2023/08/24
- [PULL 21/35] target/arm/ptw: Remove last uses of ptw->in_secure, Peter Maydell, 2023/08/24
- [PULL 20/35] target/arm/ptw: Only fold in NSTable bit effects in Secure state, Peter Maydell, 2023/08/24
- [PULL 29/35] target/arm/helper: Fix tlbmask and tlbbits for TLBI VAE2*, Peter Maydell, 2023/08/24
- Re: [PULL 00/35] target-arm queue, Stefan Hajnoczi, 2023/08/24