aboutsummaryrefslogtreecommitdiff
path: root/hw/intc
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2022-04-08 15:15:22 +0100
committerPeter Maydell <peter.maydell@linaro.org>2022-04-22 09:24:44 +0100
commit2d692e2b314e212664e9ce72787ce0ecea615c61 (patch)
tree6ded84c80fd66ee6623d51bef22fc95f2bcdade0 /hw/intc
parentc411db7bf75d0a2ecd7249533c74babf2af51afe (diff)
downloadqemu-2d692e2b314e212664e9ce72787ce0ecea615c61.zip
qemu-2d692e2b314e212664e9ce72787ce0ecea615c61.tar.gz
qemu-2d692e2b314e212664e9ce72787ce0ecea615c61.tar.bz2
hw/intc/arm_gicv3_its: Split out process_its_cmd() physical interrupt code
Split the part of process_its_cmd() which is specific to physical interrupts into its own function. This is the part which starts by taking the ICID and looking it up in the collection table. The handling of virtual interrupts is significantly different (involving a lookup in the vPE table) so structuring the code with one sub-function for the physical interrupt case and one for the virtual interrupt case will be clearer than putting both cases in one large function. The code for handling the "remove mapping from ITE" for the DISCARD command remains in process_its_cmd() because it is common to both virtual and physical interrupts. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20220408141550.1271295-14-peter.maydell@linaro.org
Diffstat (limited to 'hw/intc')
-rw-r--r--hw/intc/arm_gicv3_its.c49
1 files changed, 32 insertions, 17 deletions
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index a2a4e3d..e7e1769 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -397,6 +397,19 @@ static ItsCmdResult lookup_cte(GICv3ITSState *s, const char *who,
return CMD_CONTINUE_OK;
}
+static ItsCmdResult process_its_cmd_phys(GICv3ITSState *s, const ITEntry *ite,
+ int irqlevel)
+{
+ CTEntry cte;
+ ItsCmdResult cmdres;
+
+ cmdres = lookup_cte(s, __func__, ite->icid, &cte);
+ if (cmdres != CMD_CONTINUE_OK) {
+ return cmdres;
+ }
+ gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], ite->intid, irqlevel);
+ return CMD_CONTINUE_OK;
+}
/*
* This function handles the processing of following commands based on
@@ -410,34 +423,36 @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
uint32_t eventid, ItsCmdType cmd)
{
DTEntry dte;
- CTEntry cte;
ITEntry ite;
ItsCmdResult cmdres;
+ int irqlevel;
cmdres = lookup_ite(s, __func__, devid, eventid, &ite, &dte);
if (cmdres != CMD_CONTINUE_OK) {
return cmdres;
}
- if (ite.inttype != ITE_INTTYPE_PHYSICAL) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: invalid command attributes: invalid ITE\n",
- __func__);
- return CMD_CONTINUE;
- }
-
- cmdres = lookup_cte(s, __func__, ite.icid, &cte);
- if (cmdres != CMD_CONTINUE_OK) {
- return cmdres;
- }
+ irqlevel = (cmd == CLEAR || cmd == DISCARD) ? 0 : 1;
- if ((cmd == CLEAR) || (cmd == DISCARD)) {
- gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], ite.intid, 0);
- } else {
- gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], ite.intid, 1);
+ switch (ite.inttype) {
+ case ITE_INTTYPE_PHYSICAL:
+ cmdres = process_its_cmd_phys(s, &ite, irqlevel);
+ break;
+ case ITE_INTTYPE_VIRTUAL:
+ if (!its_feature_virtual(s)) {
+ /* Can't happen unless guest is illegally writing to table memory */
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: invalid type %d in ITE (table corrupted?)\n",
+ __func__, ite.inttype);
+ return CMD_CONTINUE;
+ }
+ /* The GICv4 virtual interrupt handling will go here */
+ g_assert_not_reached();
+ default:
+ g_assert_not_reached();
}
- if (cmd == DISCARD) {
+ if (cmdres == CMD_CONTINUE_OK && cmd == DISCARD) {
ITEntry ite = {};
/* remove mapping from interrupt translation table */
ite.valid = false;