diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2022-05-06 17:03:34 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2022-05-06 17:03:34 +0100 |
commit | e9746b5fa4117a29147385bf41c601e8cab01eaf (patch) | |
tree | e581e6f951d9209690ed713b1157e58591415577 | |
parent | 58ff8f4f5942ccc3e95808db282e637954fa0082 (diff) |
hw/intc/arm_gicv3: Use correct number of priority bits for the CPU
Make the GICv3 set its number of bits of physical priority from the
implementation-specific value provided in the CPU state struct, in
the same way we already do for virtual priority bits. Because this
would be a migration compatibility break, we provide a property
force-8-bit-prio which is enabled for 7.0 and earlier versioned board
models to retain the legacy "always use 8 bits" behaviour.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
I have guessed at the right value for the A64FX, but if we can
find the correct ICC_CTLR_EL1 value that would be better.
-rw-r--r-- | hw/core/machine.c | 4 | ||||
-rw-r--r-- | hw/intc/arm_gicv3_common.c | 5 | ||||
-rw-r--r-- | hw/intc/arm_gicv3_cpuif.c | 14 | ||||
-rw-r--r-- | include/hw/intc/arm_gicv3_common.h | 1 | ||||
-rw-r--r-- | target/arm/cpu.h | 1 | ||||
-rw-r--r-- | target/arm/cpu64.c | 9 |
6 files changed, 29 insertions, 5 deletions
diff --git a/hw/core/machine.c b/hw/core/machine.c index cb9bbc844d..db01237678 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -37,7 +37,9 @@ #include "hw/virtio/virtio.h" #include "hw/virtio/virtio-pci.h" -GlobalProperty hw_compat_7_0[] = {}; +GlobalProperty hw_compat_7_0[] = { + { "arm-gicv3-common", "force-8-bit-prio", "on" }, +}; const size_t hw_compat_7_0_len = G_N_ELEMENTS(hw_compat_7_0); GlobalProperty hw_compat_6_2[] = { diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c index 5634c6fc78..351843db4a 100644 --- a/hw/intc/arm_gicv3_common.c +++ b/hw/intc/arm_gicv3_common.c @@ -563,6 +563,11 @@ static Property arm_gicv3_common_properties[] = { DEFINE_PROP_UINT32("revision", GICv3State, revision, 3), DEFINE_PROP_BOOL("has-lpi", GICv3State, lpi_enable, 0), DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0), + /* + * Compatibility property: force 8 bits of physical priority, even + * if the CPU being emulated should have fewer. + */ + DEFINE_PROP_BOOL("force-8-bit-prio", GICv3State, force_8bit_prio, 0), DEFINE_PROP_ARRAY("redist-region-count", GICv3State, nb_redist_regions, redist_region_count, qdev_prop_uint32, uint32_t), DEFINE_PROP_LINK("sysmem", GICv3State, dma, TYPE_MEMORY_REGION, diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c index 8499a49be3..e277a807bd 100644 --- a/hw/intc/arm_gicv3_cpuif.c +++ b/hw/intc/arm_gicv3_cpuif.c @@ -2801,11 +2801,17 @@ void gicv3_init_cpuif(GICv3State *s) define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); /* - * For the moment, retain the existing behaviour of 8 priority bits; - * in a following commit we will take this from the CPU state, - * as we do for the virtual priority bits. + * The CPU implementation specifies the number of supported + * bits of physical priority. For backwards compatibility + * of migration, we have a compat property that forces use + * of 8 priority bits regardless of what the CPU really has. */ - cs->pribits = 8; + if (s->force_8bit_prio) { + cs->pribits = 8; + } else { + cs->pribits = cpu->gic_pribits; + } + /* * The GICv3 has separate ID register fields for virtual priority * and preemption bit values, but only a single ID register field diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h index 46677ec345..ab5182a28a 100644 --- a/include/hw/intc/arm_gicv3_common.h +++ b/include/hw/intc/arm_gicv3_common.h @@ -248,6 +248,7 @@ struct GICv3State { uint32_t revision; bool lpi_enable; bool security_extn; + bool force_8bit_prio; bool irq_reset_nonsecure; bool gicd_no_migration_shift_bug; diff --git a/target/arm/cpu.h b/target/arm/cpu.h index ca01f909a8..f8873bdbb9 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -993,6 +993,7 @@ struct ArchCPU { int gic_num_lrs; /* number of list registers */ int gic_vpribits; /* number of virtual priority bits */ int gic_vprebits; /* number of virtual preemption bits */ + int gic_pribits; /* number of physical priority bits */ /* Whether the cfgend input is high (i.e. this CPU should reset into * big-endian mode). This setting isn't used directly: instead it modifies diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index c841d55d0e..490231b90f 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -143,6 +143,7 @@ static void aarch64_a57_initfn(Object *obj) cpu->gic_num_lrs = 4; cpu->gic_vpribits = 5; cpu->gic_vprebits = 5; + cpu->gic_pribits = 5; define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo); } @@ -196,6 +197,7 @@ static void aarch64_a53_initfn(Object *obj) cpu->gic_num_lrs = 4; cpu->gic_vpribits = 5; cpu->gic_vprebits = 5; + cpu->gic_pribits = 5; define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo); } @@ -247,6 +249,7 @@ static void aarch64_a72_initfn(Object *obj) cpu->gic_num_lrs = 4; cpu->gic_vpribits = 5; cpu->gic_vprebits = 5; + cpu->gic_pribits = 5; define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo); } @@ -961,6 +964,12 @@ static void aarch64_a64fx_initfn(Object *obj) cpu->gic_num_lrs = 4; cpu->gic_vpribits = 5; cpu->gic_vprebits = 5; + /* + * TODO: What does the real A64FX GICv3 provide ? + * This is a guess based on what other Arm CPUs do; to find the correct + * answer we need the value of the A64FX's ICC_CTLR_EL1 register. + */ + cpu->gic_pribits = 5; /* Suppport of A64FX's vector length are 128,256 and 512bit only */ aarch64_add_sve_properties(obj); |