From 50d84584d3c77e3a9104826a53a691318aeaf038 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 8 Apr 2022 15:15:16 +0100 Subject: hw/intc/arm_gicv3_its: Implement GITS_BASER2 for GICv4 The GICv4 defines a new in-guest-memory table for the ITS: this is the vPE table. Implement the new GITS_BASER2 register which the guest uses to tell the ITS where the vPE table is located, including the decode of the register fields into the TableDesc structure which we do for the GITS_BASER when the guest enables the ITS. We guard provision of the new register with the its_feature_virtual() function, which does a check of the GITS_TYPER.Virtual bit which indicates presence of ITS support for virtual LPIs. Since this bit is currently always zero, GICv4-specific features will not be accessible to the guest yet. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20220408141550.1271295-8-peter.maydell@linaro.org --- include/hw/intc/arm_gicv3_its_common.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/hw/intc') diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h index 0f13049..7d1cc0f 100644 --- a/include/hw/intc/arm_gicv3_its_common.h +++ b/include/hw/intc/arm_gicv3_its_common.h @@ -78,6 +78,7 @@ struct GICv3ITSState { TableDesc dt; TableDesc ct; + TableDesc vpet; CmdQDesc cq; Error *migration_blocker; -- cgit v1.1 From 7c087bd33073503914cd0c17084de459f68ac002 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 8 Apr 2022 15:15:24 +0100 Subject: hw/intc/arm_gicv3: Keep pointers to every connected ITS The GICv4 ITS VMOVP command's semantics require it to perform the operation on every ITS connected to the same GIC that the ITS that received the command is attached to. This means that the GIC object needs to keep a pointer to every ITS that is connected to it (previously it was sufficient for the ITS to have a pointer to its GIC). Add a glib ptrarray to the GICv3 object which holds pointers to every connected ITS, and make the ITS add itself to the array for the GIC it is connected to when it is realized. Note that currently all QEMU machine types with an ITS have exactly one ITS in the system, so typically the length of this ptrarray will be 1. Multiple ITSes are typically used to improve performance on real hardware, so we wouldn't need to have more than one unless we were modelling a real machine type that had multile ITSes. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson [PMM: Moved gicv3_add_its() to arm_gicv3_its_common.h to avoid compilation error building the KVM ITS] Message-id: 20220408141550.1271295-16-peter.maydell@linaro.org --- include/hw/intc/arm_gicv3_common.h | 2 ++ include/hw/intc/arm_gicv3_its_common.h | 9 +++++++++ 2 files changed, 11 insertions(+) (limited to 'include/hw/intc') diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h index fc38e4b..08b2778 100644 --- a/include/hw/intc/arm_gicv3_common.h +++ b/include/hw/intc/arm_gicv3_common.h @@ -272,6 +272,8 @@ struct GICv3State { uint32_t gicd_nsacr[DIV_ROUND_UP(GICV3_MAXIRQ, 16)]; GICv3CPUState *cpu; + /* List of all ITSes connected to this GIC */ + GPtrArray *itslist; }; #define GICV3_BITMAP_ACCESSORS(BMP) \ diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h index 7d1cc0f..2b1c08b 100644 --- a/include/hw/intc/arm_gicv3_its_common.h +++ b/include/hw/intc/arm_gicv3_its_common.h @@ -89,6 +89,15 @@ typedef struct GICv3ITSState GICv3ITSState; void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops, const MemoryRegionOps *tops); +/* + * The ITS should call this when it is realized to add itself + * to its GIC's list of connected ITSes. + */ +static inline void gicv3_add_its(GICv3State *s, DeviceState *its) +{ + g_ptr_array_add(s->itslist, its); +} + #define TYPE_ARM_GICV3_ITS_COMMON "arm-gicv3-its-common" typedef struct GICv3ITSCommonClass GICv3ITSCommonClass; DECLARE_OBJ_CHECKERS(GICv3ITSState, GICv3ITSCommonClass, -- cgit v1.1 From 3851af45858a03391c74361bc69bf7a31ad30fbd Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 8 Apr 2022 15:15:25 +0100 Subject: hw/intc/arm_gicv3_its: Implement VMOVP Implement the GICv4 VMOVP command, which updates an entry in the vPE table to change its rdbase field. This command is unique in the ITS command set because its effects must be propagated to all the other ITSes connected to the same GIC as the ITS which executes the VMOVP command. The GICv4 spec allows two implementation choices for handling the propagation to other ITSes: * If GITS_TYPER.VMOVP is 1, the guest only needs to issue the command on one ITS, and the implementation handles the propagation to all ITSes * If GITS_TYPER.VMOVP is 0, the guest must issue the command on every ITS, and arrange for the ITSes to synchronize the updates with each other by setting ITSList and Sequence Number fields in the command packets We choose the GITS_TYPER.VMOVP = 1 approach, and synchronously execute the update on every ITS. For GICv4.1 this command has extra fields in the command packet and additional behaviour. We define the 4.1-only fields with the FIELD macro, but only implement the GICv4.0 version of the command. Note that we don't update the reported GITS_TYPER value here; we'll do that later in a commit which updates all the reported feature bit and ID register values for GICv4. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20220408141550.1271295-17-peter.maydell@linaro.org [PMM: Moved gicv3_foreach_its() to arm_gicv3_its_common.h, for consistency with gicv3_add_its()] --- include/hw/intc/arm_gicv3_its_common.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'include/hw/intc') diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h index 2b1c08b..a11a0f6 100644 --- a/include/hw/intc/arm_gicv3_its_common.h +++ b/include/hw/intc/arm_gicv3_its_common.h @@ -98,6 +98,15 @@ static inline void gicv3_add_its(GICv3State *s, DeviceState *its) g_ptr_array_add(s->itslist, its); } +/* + * The ITS can use this for operations that must be performed on + * every ITS connected to the same GIC that it is + */ +static inline void gicv3_foreach_its(GICv3State *s, GFunc func, void *opaque) +{ + g_ptr_array_foreach(s->itslist, func, opaque); +} + #define TYPE_ARM_GICV3_ITS_COMMON "arm-gicv3-its-common" typedef struct GICv3ITSCommonClass GICv3ITSCommonClass; DECLARE_OBJ_CHECKERS(GICv3ITSState, GICv3ITSCommonClass, -- cgit v1.1 From ae3b3ba15c73320f75c121b08266a25a9e5d4edb Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 8 Apr 2022 15:15:31 +0100 Subject: hw/intc/arm_gicv3: Implement GICv4's new redistributor frame The GICv4 extends the redistributor register map -- where GICv3 had two 64KB frames per CPU, GICv4 has four frames. Add support for the extra frame by using a new gicv3_redist_size() function in the places in the GIC implementation which currently use a fixed constant size for the redistributor register block. (Until we implement the extra registers they will RAZ/WI.) Any board that wants to use a GICv4 will need to also adjust to handle the different sized redistributor register block; that will be done separately. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20220408141550.1271295-23-peter.maydell@linaro.org --- include/hw/intc/arm_gicv3_common.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/hw/intc') diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h index 08b2778..40bc404 100644 --- a/include/hw/intc/arm_gicv3_common.h +++ b/include/hw/intc/arm_gicv3_common.h @@ -38,7 +38,12 @@ #define GICV3_LPI_INTID_START 8192 +/* + * The redistributor in GICv3 has two 64KB frames per CPU; in + * GICv4 it has four 64KB frames per CPU. + */ #define GICV3_REDIST_SIZE 0x20000 +#define GICV4_REDIST_SIZE 0x40000 /* Number of SGI target-list bits */ #define GICV3_TARGETLIST_BITS 16 -- cgit v1.1 From 641be69745c49d3c35efb62ee41d21d701b210ba Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 8 Apr 2022 15:15:32 +0100 Subject: hw/intc/arm_gicv3: Implement new GICv4 redistributor registers Implement the new GICv4 redistributor registers: GICR_VPROPBASER and GICR_VPENDBASER; for the moment we implement these as simple reads-as-written stubs, together with the necessary migration and reset handling. We don't put ID-register checks on the handling of these registers, because they are all in the only-in-v4 extra register frames, so they're not accessible in a GICv3. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20220408141550.1271295-24-peter.maydell@linaro.org --- include/hw/intc/arm_gicv3_common.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/hw/intc') diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h index 40bc404..7ff5a1a 100644 --- a/include/hw/intc/arm_gicv3_common.h +++ b/include/hw/intc/arm_gicv3_common.h @@ -179,6 +179,9 @@ struct GICv3CPUState { uint32_t gicr_igrpmodr0; uint32_t gicr_nsacr; uint8_t gicr_ipriorityr[GIC_INTERNAL]; + /* VLPI_base page registers */ + uint64_t gicr_vpropbaser; + uint64_t gicr_vpendbaser; /* CPU interface */ uint64_t icc_sre_el1; -- cgit v1.1 From c3f21b065a41c14b6a18a38e417379ac75b9fc0e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 8 Apr 2022 15:15:34 +0100 Subject: hw/intc/arm_gicv3_cpuif: Support vLPIs The CPU interface changes to support vLPIs are fairly minor: in the parts of the code that currently look at the list registers to determine the highest priority pending virtual interrupt, we must also look at the highest priority pending vLPI. To do this we change hppvi_index() to check the vLPI and return a special-case value if that is the right virtual interrupt to take. The callsites (which handle HPPIR and IAR registers and the "raise vIRQ and vFIQ lines" code) then have to handle this special-case value. This commit includes two interfaces with the as-yet-unwritten redistributor code: * the new GICv3CPUState::hppvlpi will be set by the redistributor (in the same way as the existing hpplpi does for physical LPIs) * when the CPU interface acknowledges a vLPI it needs to set it to non-pending; the new gicv3_redist_vlpi_pending() function (which matches the existing gicv3_redist_lpi_pending() used for physical LPIs) is a stub that will be filled in later Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20220408141550.1271295-26-peter.maydell@linaro.org --- include/hw/intc/arm_gicv3_common.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/hw/intc') diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h index 7ff5a1a..4e41610 100644 --- a/include/hw/intc/arm_gicv3_common.h +++ b/include/hw/intc/arm_gicv3_common.h @@ -219,6 +219,9 @@ struct GICv3CPUState { */ PendingIrq hpplpi; + /* Cached information recalculated from vLPI tables in guest memory */ + PendingIrq hppvlpi; + /* This is temporary working state, to avoid a malloc in gicv3_update() */ bool seenbetter; }; -- cgit v1.1