[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 07/33] hvf: arm: Add support for GICv3
From: |
Peter Maydell |
Subject: |
[PULL 07/33] hvf: arm: Add support for GICv3 |
Date: |
Fri, 3 Feb 2023 14:29:01 +0000 |
From: Alexander Graf <agraf@csgraf.de>
We currently only support GICv2 emulation. To also support GICv3, we will
need to pass a few system registers into their respective handler functions.
This patch adds support for HVF to call into the TCG callbacks for GICv3
system register handlers. This is safe because the GICv3 TCG code is generic
as long as we limit ourselves to EL0 and EL1 - which are the only modes
supported by HVF.
To make sure nobody trips over that, we also annotate callbacks that don't
work in HVF mode, such as EL state change hooks.
With GICv3 support in place, we can run with more than 8 vCPUs.
Signed-off-by: Alexander Graf <agraf@csgraf.de>
Message-id: 20230128224459.70676-1-agraf@csgraf.de
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
hw/intc/arm_gicv3_cpuif.c | 16 +++-
target/arm/hvf/hvf.c | 151 ++++++++++++++++++++++++++++++++++++
target/arm/hvf/trace-events | 2 +
3 files changed, 168 insertions(+), 1 deletion(-)
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index b17b29288c7..9a7fc190994 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -21,6 +21,8 @@
#include "hw/irq.h"
#include "cpu.h"
#include "target/arm/cpregs.h"
+#include "sysemu/tcg.h"
+#include "sysemu/qtest.h"
/*
* Special case return value from hppvi_index(); must be larger than
@@ -2810,6 +2812,8 @@ void gicv3_init_cpuif(GICv3State *s)
* which case we'd get the wrong value.
* So instead we define the regs with no ri->opaque info, and
* get back to the GICv3CPUState from the CPUARMState.
+ *
+ * These CP regs callbacks can be called from either TCG or HVF code.
*/
define_arm_cp_regs(cpu, gicv3_cpuif_reginfo);
@@ -2905,6 +2909,16 @@ void gicv3_init_cpuif(GICv3State *s)
define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr23_reginfo);
}
}
- arm_register_el_change_hook(cpu, gicv3_cpuif_el_change_hook, cs);
+ if (tcg_enabled() || qtest_enabled()) {
+ /*
+ * We can only trap EL changes with TCG. However the GIC interrupt
+ * state only changes on EL changes involving EL2 or EL3, so for
+ * the non-TCG case this is OK, as EL2 and EL3 can't exist.
+ */
+ arm_register_el_change_hook(cpu, gicv3_cpuif_el_change_hook, cs);
+ } else {
+ assert(!arm_feature(&cpu->env, ARM_FEATURE_EL2));
+ assert(!arm_feature(&cpu->env, ARM_FEATURE_EL3));
+ }
}
}
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index 060aa0ccf4b..ad65603445e 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -80,6 +80,33 @@
#define SYSREG_PMCCNTR_EL0 SYSREG(3, 3, 9, 13, 0)
#define SYSREG_PMCCFILTR_EL0 SYSREG(3, 3, 14, 15, 7)
+#define SYSREG_ICC_AP0R0_EL1 SYSREG(3, 0, 12, 8, 4)
+#define SYSREG_ICC_AP0R1_EL1 SYSREG(3, 0, 12, 8, 5)
+#define SYSREG_ICC_AP0R2_EL1 SYSREG(3, 0, 12, 8, 6)
+#define SYSREG_ICC_AP0R3_EL1 SYSREG(3, 0, 12, 8, 7)
+#define SYSREG_ICC_AP1R0_EL1 SYSREG(3, 0, 12, 9, 0)
+#define SYSREG_ICC_AP1R1_EL1 SYSREG(3, 0, 12, 9, 1)
+#define SYSREG_ICC_AP1R2_EL1 SYSREG(3, 0, 12, 9, 2)
+#define SYSREG_ICC_AP1R3_EL1 SYSREG(3, 0, 12, 9, 3)
+#define SYSREG_ICC_ASGI1R_EL1 SYSREG(3, 0, 12, 11, 6)
+#define SYSREG_ICC_BPR0_EL1 SYSREG(3, 0, 12, 8, 3)
+#define SYSREG_ICC_BPR1_EL1 SYSREG(3, 0, 12, 12, 3)
+#define SYSREG_ICC_CTLR_EL1 SYSREG(3, 0, 12, 12, 4)
+#define SYSREG_ICC_DIR_EL1 SYSREG(3, 0, 12, 11, 1)
+#define SYSREG_ICC_EOIR0_EL1 SYSREG(3, 0, 12, 8, 1)
+#define SYSREG_ICC_EOIR1_EL1 SYSREG(3, 0, 12, 12, 1)
+#define SYSREG_ICC_HPPIR0_EL1 SYSREG(3, 0, 12, 8, 2)
+#define SYSREG_ICC_HPPIR1_EL1 SYSREG(3, 0, 12, 12, 2)
+#define SYSREG_ICC_IAR0_EL1 SYSREG(3, 0, 12, 8, 0)
+#define SYSREG_ICC_IAR1_EL1 SYSREG(3, 0, 12, 12, 0)
+#define SYSREG_ICC_IGRPEN0_EL1 SYSREG(3, 0, 12, 12, 6)
+#define SYSREG_ICC_IGRPEN1_EL1 SYSREG(3, 0, 12, 12, 7)
+#define SYSREG_ICC_PMR_EL1 SYSREG(3, 0, 4, 6, 0)
+#define SYSREG_ICC_RPR_EL1 SYSREG(3, 0, 12, 11, 3)
+#define SYSREG_ICC_SGI0R_EL1 SYSREG(3, 0, 12, 11, 7)
+#define SYSREG_ICC_SGI1R_EL1 SYSREG(3, 0, 12, 11, 5)
+#define SYSREG_ICC_SRE_EL1 SYSREG(3, 0, 12, 12, 5)
+
#define WFX_IS_WFE (1 << 0)
#define TMR_CTL_ENABLE (1 << 0)
@@ -788,6 +815,43 @@ static bool is_id_sysreg(uint32_t reg)
SYSREG_CRM(reg) < 8;
}
+static uint32_t hvf_reg2cp_reg(uint32_t reg)
+{
+ return ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP,
+ (reg >> SYSREG_CRN_SHIFT) & SYSREG_CRN_MASK,
+ (reg >> SYSREG_CRM_SHIFT) & SYSREG_CRM_MASK,
+ (reg >> SYSREG_OP0_SHIFT) & SYSREG_OP0_MASK,
+ (reg >> SYSREG_OP1_SHIFT) & SYSREG_OP1_MASK,
+ (reg >> SYSREG_OP2_SHIFT) & SYSREG_OP2_MASK);
+}
+
+static bool hvf_sysreg_read_cp(CPUState *cpu, uint32_t reg, uint64_t *val)
+{
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
+ CPUARMState *env = &arm_cpu->env;
+ const ARMCPRegInfo *ri;
+
+ ri = get_arm_cp_reginfo(arm_cpu->cp_regs, hvf_reg2cp_reg(reg));
+ if (ri) {
+ if (ri->accessfn) {
+ if (ri->accessfn(env, ri, true) != CP_ACCESS_OK) {
+ return false;
+ }
+ }
+ if (ri->type & ARM_CP_CONST) {
+ *val = ri->resetvalue;
+ } else if (ri->readfn) {
+ *val = ri->readfn(env, ri);
+ } else {
+ *val = CPREG_FIELD64(env, ri);
+ }
+ trace_hvf_vgic_read(ri->name, *val);
+ return true;
+ }
+
+ return false;
+}
+
static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint32_t rt)
{
ARMCPU *arm_cpu = ARM_CPU(cpu);
@@ -839,6 +903,36 @@ static int hvf_sysreg_read(CPUState *cpu, uint32_t reg,
uint32_t rt)
case SYSREG_OSDLR_EL1:
/* Dummy register */
break;
+ case SYSREG_ICC_AP0R0_EL1:
+ case SYSREG_ICC_AP0R1_EL1:
+ case SYSREG_ICC_AP0R2_EL1:
+ case SYSREG_ICC_AP0R3_EL1:
+ case SYSREG_ICC_AP1R0_EL1:
+ case SYSREG_ICC_AP1R1_EL1:
+ case SYSREG_ICC_AP1R2_EL1:
+ case SYSREG_ICC_AP1R3_EL1:
+ case SYSREG_ICC_ASGI1R_EL1:
+ case SYSREG_ICC_BPR0_EL1:
+ case SYSREG_ICC_BPR1_EL1:
+ case SYSREG_ICC_DIR_EL1:
+ case SYSREG_ICC_EOIR0_EL1:
+ case SYSREG_ICC_EOIR1_EL1:
+ case SYSREG_ICC_HPPIR0_EL1:
+ case SYSREG_ICC_HPPIR1_EL1:
+ case SYSREG_ICC_IAR0_EL1:
+ case SYSREG_ICC_IAR1_EL1:
+ case SYSREG_ICC_IGRPEN0_EL1:
+ case SYSREG_ICC_IGRPEN1_EL1:
+ case SYSREG_ICC_PMR_EL1:
+ case SYSREG_ICC_SGI0R_EL1:
+ case SYSREG_ICC_SGI1R_EL1:
+ case SYSREG_ICC_SRE_EL1:
+ case SYSREG_ICC_CTLR_EL1:
+ /* Call the TCG sysreg handler. This is only safe for GICv3 regs. */
+ if (!hvf_sysreg_read_cp(cpu, reg, &val)) {
+ hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
+ }
+ break;
default:
if (is_id_sysreg(reg)) {
/* ID system registers read as RES0 */
@@ -944,6 +1038,33 @@ static void pmswinc_write(CPUARMState *env, uint64_t
value)
}
}
+static bool hvf_sysreg_write_cp(CPUState *cpu, uint32_t reg, uint64_t val)
+{
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
+ CPUARMState *env = &arm_cpu->env;
+ const ARMCPRegInfo *ri;
+
+ ri = get_arm_cp_reginfo(arm_cpu->cp_regs, hvf_reg2cp_reg(reg));
+
+ if (ri) {
+ if (ri->accessfn) {
+ if (ri->accessfn(env, ri, false) != CP_ACCESS_OK) {
+ return false;
+ }
+ }
+ if (ri->writefn) {
+ ri->writefn(env, ri, val);
+ } else {
+ CPREG_FIELD64(env, ri) = val;
+ }
+
+ trace_hvf_vgic_write(ri->name, val);
+ return true;
+ }
+
+ return false;
+}
+
static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val)
{
ARMCPU *arm_cpu = ARM_CPU(cpu);
@@ -1021,6 +1142,36 @@ static int hvf_sysreg_write(CPUState *cpu, uint32_t reg,
uint64_t val)
case SYSREG_OSDLR_EL1:
/* Dummy register */
break;
+ case SYSREG_ICC_AP0R0_EL1:
+ case SYSREG_ICC_AP0R1_EL1:
+ case SYSREG_ICC_AP0R2_EL1:
+ case SYSREG_ICC_AP0R3_EL1:
+ case SYSREG_ICC_AP1R0_EL1:
+ case SYSREG_ICC_AP1R1_EL1:
+ case SYSREG_ICC_AP1R2_EL1:
+ case SYSREG_ICC_AP1R3_EL1:
+ case SYSREG_ICC_ASGI1R_EL1:
+ case SYSREG_ICC_BPR0_EL1:
+ case SYSREG_ICC_BPR1_EL1:
+ case SYSREG_ICC_CTLR_EL1:
+ case SYSREG_ICC_DIR_EL1:
+ case SYSREG_ICC_EOIR0_EL1:
+ case SYSREG_ICC_EOIR1_EL1:
+ case SYSREG_ICC_HPPIR0_EL1:
+ case SYSREG_ICC_HPPIR1_EL1:
+ case SYSREG_ICC_IAR0_EL1:
+ case SYSREG_ICC_IAR1_EL1:
+ case SYSREG_ICC_IGRPEN0_EL1:
+ case SYSREG_ICC_IGRPEN1_EL1:
+ case SYSREG_ICC_PMR_EL1:
+ case SYSREG_ICC_SGI0R_EL1:
+ case SYSREG_ICC_SGI1R_EL1:
+ case SYSREG_ICC_SRE_EL1:
+ /* Call the TCG sysreg handler. This is only safe for GICv3 regs. */
+ if (!hvf_sysreg_write_cp(cpu, reg, val)) {
+ hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
+ }
+ break;
default:
cpu_synchronize_state(cpu);
trace_hvf_unhandled_sysreg_write(env->pc, reg,
diff --git a/target/arm/hvf/trace-events b/target/arm/hvf/trace-events
index 820e8e02979..4fbbe4b45ec 100644
--- a/target/arm/hvf/trace-events
+++ b/target/arm/hvf/trace-events
@@ -9,3 +9,5 @@ hvf_unknown_hvc(uint64_t x0) "unknown HVC! 0x%016"PRIx64
hvf_unknown_smc(uint64_t x0) "unknown SMC! 0x%016"PRIx64
hvf_exit(uint64_t syndrome, uint32_t ec, uint64_t pc) "exit: 0x%"PRIx64"
[ec=0x%x pc=0x%"PRIx64"]"
hvf_psci_call(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3, uint32_t
cpuid) "PSCI Call x0=0x%016"PRIx64" x1=0x%016"PRIx64" x2=0x%016"PRIx64"
x3=0x%016"PRIx64" cpu=0x%x"
+hvf_vgic_write(const char *name, uint64_t val) "vgic write to %s
[val=0x%016"PRIx64"]"
+hvf_vgic_read(const char *name, uint64_t val) "vgic read from %s
[val=0x%016"PRIx64"]"
--
2.34.1
- [PULL 00/33] target-arm queue, Peter Maydell, 2023/02/03
- [PULL 05/33] hw/char/pl011: implement a reset method, Peter Maydell, 2023/02/03
- [PULL 01/33] hw/arm: Use TYPE_ARM_SMMUV3, Peter Maydell, 2023/02/03
- [PULL 02/33] target/arm: Fix physical address resolution for Stage2, Peter Maydell, 2023/02/03
- [PULL 07/33] hvf: arm: Add support for GICv3,
Peter Maydell <=
- [PULL 03/33] hw/char/pl011: refactor FIFO depth handling code, Peter Maydell, 2023/02/03
- [PULL 04/33] hw/char/pl011: add post_load hook for backwards-compatibility, Peter Maydell, 2023/02/03
- [PULL 06/33] hw/char/pl011: better handling of FIFO flags on LCR reset, Peter Maydell, 2023/02/03
- [PULL 17/33] target/arm: Disable HSTR_EL2 traps if EL2 is not enabled, Peter Maydell, 2023/02/03
- [PULL 19/33] target/arm: Implement FGT trapping infrastructure, Peter Maydell, 2023/02/03
- [PULL 11/33] target/arm: Name AT_S1E1RP and AT_S1E1WP cpregs correctly, Peter Maydell, 2023/02/03
- [PULL 26/33] target/arm: Mark up sysregs for HFGITR bits 0..11, Peter Maydell, 2023/02/03
- [PULL 21/33] target/arm: Mark up sysregs for HFGRTR bits 12..23, Peter Maydell, 2023/02/03
- [PULL 22/33] target/arm: Mark up sysregs for HFGRTR bits 24..35, Peter Maydell, 2023/02/03
- [PULL 29/33] target/arm: Mark up sysregs for HFGITR bits 48..63, Peter Maydell, 2023/02/03