aboutsummaryrefslogtreecommitdiff
path: root/hw/intc/armv7m_nvic.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-08-03 17:55:03 +0100
committerPeter Maydell <peter.maydell@linaro.org>2020-08-03 17:55:03 +0100
commit9e60d759d38d1faae1d85de2c53411e635be3cf2 (patch)
tree5e90a2b63fbc1a1a169ff06c3a49144d40c13764 /hw/intc/armv7m_nvic.c
parentfaf7c6de34fb8eaa566726cc658ba5ad81fb32af (diff)
hw/intc/armv7m_nvic: Provide default "reset the system" behaviour for SYSRESETREQ
The NVIC provides an outbound qemu_irq "SYSRESETREQ" which it signals when the guest sets the SYSRESETREQ bit in the AIRCR register. This matches the hardware design (where the CPU has a signal of this name and it is up to the SoC to connect that up to an actual reset mechanism), but in QEMU it mostly results in duplicated code in SoC objects and bugs where SoC model implementors forget to wire up the SYSRESETREQ line. Provide a default behaviour for the case where SYSRESETREQ is not actually connected to anything: use qemu_system_reset_request() to perform a system reset. This will allow us to remove the implementations of SYSRESETREQ handling from the boards where that's exactly what it does, and also fixes the bugs in the board models which forgot to wire up the signal: * microbit * mps2-an385 * mps2-an505 * mps2-an511 * mps2-an521 * musca-a * musca-b1 * netduino * netduinoplus2 We still allow the board to wire up the signal if it needs to, in case we need to model more complicated reset controller logic or to model buggy SoC hardware which forgot to wire up the line itself. But defaulting to "reset the system" is more often going to be correct than defaulting to "do nothing". Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-id: 20200728103744.6909-3-peter.maydell@linaro.org
Diffstat (limited to 'hw/intc/armv7m_nvic.c')
-rw-r--r--hw/intc/armv7m_nvic.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 3c4b6e6d70..277a98b87b 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -19,6 +19,7 @@
#include "hw/intc/armv7m_nvic.h"
#include "hw/irq.h"
#include "hw/qdev-properties.h"
+#include "sysemu/runstate.h"
#include "target/arm/cpu.h"
#include "exec/exec-all.h"
#include "exec/memop.h"
@@ -64,6 +65,20 @@ static const uint8_t nvic_id[] = {
0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1
};
+static void signal_sysresetreq(NVICState *s)
+{
+ if (qemu_irq_is_connected(s->sysresetreq)) {
+ qemu_irq_pulse(s->sysresetreq);
+ } else {
+ /*
+ * Default behaviour if the SoC doesn't need to wire up
+ * SYSRESETREQ (eg to a system reset controller of some kind):
+ * perform a system reset via the usual QEMU API.
+ */
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+ }
+}
+
static int nvic_pending_prio(NVICState *s)
{
/* return the group priority of the current pending interrupt,
@@ -1524,7 +1539,7 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
if (value & R_V7M_AIRCR_SYSRESETREQ_MASK) {
if (attrs.secure ||
!(cpu->env.v7m.aircr & R_V7M_AIRCR_SYSRESETREQS_MASK)) {
- qemu_irq_pulse(s->sysresetreq);
+ signal_sysresetreq(s);
}
}
if (value & R_V7M_AIRCR_VECTCLRACTIVE_MASK) {