[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 20/41] hw/intc/arm_gicv3_its: Implement VMOVI
From: |
Peter Maydell |
Subject: |
[PATCH 20/41] hw/intc/arm_gicv3_its: Implement VMOVI |
Date: |
Fri, 8 Apr 2022 15:15:29 +0100 |
Implement the GICv4 VMOVI command, which moves the pending state
of a virtual interrupt from one redistributor to another. As with
MOVI, we handle the "parse and validate command arguments and
table lookups" part in the ITS source file, and pass the final
results to a function in the redistributor which will do the
actual operation. As with the "make a VLPI pending" change,
for the moment we leave that redistributor function as a stub,
to be implemented in a later commit.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
hw/intc/gicv3_internal.h | 23 +++++++++++
hw/intc/arm_gicv3_its.c | 82 ++++++++++++++++++++++++++++++++++++++
hw/intc/arm_gicv3_redist.c | 10 +++++
hw/intc/trace-events | 1 +
4 files changed, 116 insertions(+)
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index 2f653a9b917..050e19d133b 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -329,6 +329,7 @@ FIELD(GITS_TYPER, CIL, 36, 1)
#define GITS_CMD_INVALL 0x0D
#define GITS_CMD_MOVALL 0x0E
#define GITS_CMD_DISCARD 0x0F
+#define GITS_CMD_VMOVI 0x21
#define GITS_CMD_VMOVP 0x22
#define GITS_CMD_VSYNC 0x25
#define GITS_CMD_VMAPP 0x29
@@ -403,6 +404,13 @@ FIELD(VMOVP_2, RDBASE, 16, 36)
FIELD(VMOVP_2, DB, 63, 1) /* GICv4.1 only */
FIELD(VMOVP_3, DEFAULT_DOORBELL, 0, 32) /* GICv4.1 only */
+/* VMOVI command fields */
+FIELD(VMOVI_0, DEVICEID, 32, 32)
+FIELD(VMOVI_1, EVENTID, 0, 32)
+FIELD(VMOVI_1, VPEID, 32, 16)
+FIELD(VMOVI_2, D, 0, 1)
+FIELD(VMOVI_2, DOORBELL, 32, 32)
+
/*
* 12 bytes Interrupt translation Table Entry size
* as per Table 5.3 in GICv3 spec
@@ -614,6 +622,21 @@ void gicv3_redist_mov_lpi(GICv3CPUState *src,
GICv3CPUState *dest, int irq);
* by the ITS MOVALL command.
*/
void gicv3_redist_movall_lpis(GICv3CPUState *src, GICv3CPUState *dest);
+/**
+ * gicv3_redist_mov_vlpi:
+ * @src: source redistributor
+ * @src_vptaddr: (guest) address of source VLPI table
+ * @dest: destination redistributor
+ * @dest_vptaddr: (guest) address of destination VLPI table
+ * @irq: VLPI to update
+ * @doorbell: doorbell for destination (1023 for "no doorbell")
+ *
+ * Move the pending state of the specified VLPI from @src to @dest,
+ * as required by the ITS VMOVI command.
+ */
+void gicv3_redist_mov_vlpi(GICv3CPUState *src, uint64_t src_vptaddr,
+ GICv3CPUState *dest, uint64_t dest_vptaddr,
+ int irq, int doorbell);
void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns);
void gicv3_init_cpuif(GICv3State *s);
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index c8b90e6b0d9..aef024009b2 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -1084,6 +1084,85 @@ static ItsCmdResult process_vmovp(GICv3ITSState *s,
const uint64_t *cmdpkt)
return cbdata.result;
}
+static ItsCmdResult process_vmovi(GICv3ITSState *s, const uint64_t *cmdpkt)
+{
+ uint32_t devid, eventid, vpeid, doorbell;
+ bool doorbell_valid;
+ DTEntry dte;
+ ITEntry ite;
+ VTEntry old_vte, new_vte;
+ ItsCmdResult cmdres;
+
+ if (!its_feature_virtual(s)) {
+ return CMD_CONTINUE;
+ }
+
+ devid = FIELD_EX64(cmdpkt[0], VMOVI_0, DEVICEID);
+ eventid = FIELD_EX64(cmdpkt[1], VMOVI_1, EVENTID);
+ vpeid = FIELD_EX64(cmdpkt[1], VMOVI_1, VPEID);
+ doorbell_valid = FIELD_EX64(cmdpkt[2], VMOVI_2, D);
+ doorbell = FIELD_EX64(cmdpkt[2], VMOVI_2, DOORBELL);
+
+ trace_gicv3_its_cmd_vmovi(devid, eventid, vpeid, doorbell_valid, doorbell);
+
+ if (doorbell_valid && !valid_doorbell(doorbell)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: invalid doorbell 0x%x\n", __func__, doorbell);
+ return CMD_CONTINUE;
+ }
+
+ cmdres = lookup_ite(s, __func__, devid, eventid, &ite, &dte);
+ if (cmdres != CMD_CONTINUE_OK) {
+ return cmdres;
+ }
+
+ if (ite.inttype != ITE_INTTYPE_VIRTUAL) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: ITE is not for virtual
interrupt\n",
+ __func__);
+ return CMD_CONTINUE;
+ }
+
+ cmdres = lookup_vte(s, __func__, ite.vpeid, &old_vte);
+ if (cmdres != CMD_CONTINUE_OK) {
+ return cmdres;
+ }
+ cmdres = lookup_vte(s, __func__, vpeid, &new_vte);
+ if (cmdres != CMD_CONTINUE_OK) {
+ return cmdres;
+ }
+
+ if (!intid_in_lpi_range(ite.intid) ||
+ ite.intid >= (1ULL << (old_vte.vptsize + 1)) ||
+ ite.intid >= (1ULL << (new_vte.vptsize + 1))) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: ITE intid 0x%x out of range\n",
+ __func__, ite.intid);
+ return CMD_CONTINUE;
+ }
+
+ ite.vpeid = vpeid;
+ if (doorbell_valid) {
+ ite.doorbell = doorbell;
+ }
+
+ /*
+ * Move the LPI from the old redistributor to the new one. We don't
+ * need to do anything if the guest somehow specified the
+ * same pending table for source and destination.
+ */
+ if (old_vte.vptaddr != new_vte.vptaddr) {
+ gicv3_redist_mov_vlpi(&s->gicv3->cpu[old_vte.rdbase],
+ old_vte.vptaddr << 16,
+ &s->gicv3->cpu[new_vte.rdbase],
+ new_vte.vptaddr << 16,
+ ite.intid,
+ ite.doorbell);
+ }
+
+ /* Update the ITE to the new VPEID and possibly doorbell values */
+ return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE_OK : CMD_STALL;
+}
+
static ItsCmdResult process_inv(GICv3ITSState *s, const uint64_t *cmdpkt)
{
uint32_t devid, eventid;
@@ -1282,6 +1361,9 @@ static void process_cmdq(GICv3ITSState *s)
case GITS_CMD_VMOVP:
result = process_vmovp(s, cmdpkt);
break;
+ case GITS_CMD_VMOVI:
+ result = process_vmovi(s, cmdpkt);
+ break;
default:
trace_gicv3_its_cmd_unknown(cmd);
break;
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
index 856494b4e8f..dc25997d1f9 100644
--- a/hw/intc/arm_gicv3_redist.c
+++ b/hw/intc/arm_gicv3_redist.c
@@ -808,6 +808,16 @@ void gicv3_redist_process_vlpi(GICv3CPUState *cs, int irq,
uint64_t vptaddr,
*/
}
+void gicv3_redist_mov_vlpi(GICv3CPUState *src, uint64_t src_vptaddr,
+ GICv3CPUState *dest, uint64_t dest_vptaddr,
+ int irq, int doorbell)
+{
+ /*
+ * The redistributor handling for moving a VLPI will be added
+ * in a subsequent commit.
+ */
+}
+
void gicv3_redist_inv_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr)
{
/*
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index ae4a3cfb004..9894756e55a 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -193,6 +193,7 @@ gicv3_its_cmd_vmapti(uint32_t devid, uint32_t eventid,
uint32_t vpeid, uint32_t
gicv3_its_cmd_vmapp(uint32_t vpeid, uint64_t rdbase, int valid, uint64_t
vptaddr, uint32_t vptsize) "GICv3 ITS: command VMAPP vPEID 0x%x RDbase 0x%"
PRIx64 " V %d VPT_addr 0x%" PRIx64 " VPT_size 0x%x"
gicv3_its_cmd_vmovp(uint32_t vpeid, uint64_t rdbase) "GICv3 ITS: command VMOVP
vPEID 0x%x RDbase 0x%" PRIx64
gicv3_its_cmd_vsync(void) "GICv3 ITS: command VSYNC"
+gicv3_its_cmd_vmovi(uint32_t devid, uint32_t eventid, uint32_t vpeid, int
dbvalid, uint32_t doorbell) "GICv3 ITS: command VMOVI DeviceID 0x%x EventID
0x%x vPEID 0x%x D %d Dbell_pINTID 0x%x"
gicv3_its_cmd_unknown(unsigned cmd) "GICv3 ITS: unknown command 0x%x"
gicv3_its_cte_read(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS:
Collection Table read for ICID 0x%x: valid %d RDBase 0x%x"
gicv3_its_cte_write(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS:
Collection Table write for ICID 0x%x: valid %d RDBase 0x%x"
--
2.25.1
- [PATCH 18/41] hw/intc/arm_gicv3_its: Implement INV command properly, (continued)
- [PATCH 18/41] hw/intc/arm_gicv3_its: Implement INV command properly, Peter Maydell, 2022/04/08
- [PATCH 23/41] hw/intc/arm_gicv3: Implement new GICv4 redistributor registers, Peter Maydell, 2022/04/08
- [PATCH 28/41] hw/intc/arm_gicv3_redist: Factor out "update hpplpi for all LPIs" logic, Peter Maydell, 2022/04/08
- [PATCH 21/41] hw/intc/arm_gicv3_its: Implement VINVALL, Peter Maydell, 2022/04/08
- [PATCH 19/41] hw/intc/arm_gicv3_its: Implement INV for virtual interrupts, Peter Maydell, 2022/04/08
- [PATCH 20/41] hw/intc/arm_gicv3_its: Implement VMOVI,
Peter Maydell <=
- [PATCH 22/41] hw/intc/arm_gicv3: Implement GICv4's new redistributor frame, Peter Maydell, 2022/04/08
- [PATCH 24/41] hw/intc/arm_gicv3_cpuif: Split "update vIRQ/vFIQ" from gicv3_cpuif_virt_update(), Peter Maydell, 2022/04/08
- [PATCH 27/41] hw/intc/arm_gicv3_redist: Factor out "update hpplpi for one LPI" logic, Peter Maydell, 2022/04/08
- [PATCH 29/41] hw/intc/arm_gicv3_redist: Recalculate hppvlpi on VPENDBASER writes, Peter Maydell, 2022/04/08