diff options
author | Petr Pavlu <petr.pavlu@suse.com> | 2022-01-13 16:19:16 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2022-01-20 11:47:52 +0000 |
commit | 5e66daec9ef0cd0107ba30225e23224c66ed24f3 (patch) | |
tree | 498f0d424eccf642a9240619f00433ffdcadddaa /hw | |
parent | a66a24585fae7036dc2f358c9addd1630be5c50c (diff) | |
download | qemu-5e66daec9ef0cd0107ba30225e23224c66ed24f3.zip qemu-5e66daec9ef0cd0107ba30225e23224c66ed24f3.tar.gz qemu-5e66daec9ef0cd0107ba30225e23224c66ed24f3.tar.bz2 |
hw/intc/arm_gic: Allow reset of the running priority
When running Linux on a machine with GICv2, the kernel can crash while
processing an interrupt and can subsequently start a kdump kernel from
the active interrupt handler. In such a case, the crashed kernel might
not gracefully signal the end of interrupt to the GICv2 hardware. The
kdump kernel will however try to reset the GIC state on startup to get
the controller into a sane state, in particular the kernel writes ones
to GICD_ICACTIVERn and wipes out GICC_APRn to make sure that no
interrupt is active.
The patch adds a logic to recalculate the running priority when
GICC_APRn/GICC_NSAPRn is written which makes sure that the mentioned
reset works with the GICv2 emulation in QEMU too and the kdump kernel
starts receiving interrupts.
The described scenario can be reproduced on an AArch64 QEMU virt machine
with a kdump-enabled Linux system by using the softdog module. The kdump
kernel will hang at some point because QEMU still thinks the running
priority is that of the timer interrupt and asserts no new interrupts to
the system:
$ modprobe softdog soft_margin=10 soft_panic=1
$ cat > /dev/watchdog
[Press Enter to start the watchdog, wait for its timeout and observe
that the kdump kernel hangs on startup.]
Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
Message-id: 20220113151916.17978-3-ppavlu@suse.cz
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/intc/arm_gic.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 0cd9cec..492b242 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -1736,6 +1736,7 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset, } else { s->apr[regno][cpu] = value; } + s->running_priority[cpu] = gic_get_prio_from_apr_bits(s, cpu); break; } case 0xe0: case 0xe4: case 0xe8: case 0xec: @@ -1752,6 +1753,7 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset, return MEMTX_OK; } s->nsapr[regno][cpu] = value; + s->running_priority[cpu] = gic_get_prio_from_apr_bits(s, cpu); break; } case 0x1000: |