* [PATCH v3 0/7] hw/nmi: Disconnect of vCPU and disentangle Monitor code
@ 2026-08-11 10:54 Philippe Mathieu-Daudé
2026-08-11 10:54 ` [PATCH v3 1/7] hw/nmi: Use object_child_foreach_recursive() in nmi_children() Philippe Mathieu-Daudé
` (6 more replies)
0 siblings, 7 replies; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-11 10:54 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, qemu-s390x, Dr. David Alan Gilbert,
Thomas Huth, qemu-ppc, Corey Minyard, Markus Armbruster,
Philippe Mathieu-Daudé
- Have s390x always deliver NMI to the first CPU.
- Remove the @cpu_index / @errp arguments from handler.
- Rename API as nmi_trigger() (since not monitor specific).
- Only deliver NMI once
Rationale described by Peter in v1 [*]:
> The current hw/core/nmi.c code is a bit odd because it's partly
> working with a cpu_index and partly not: the code passes cpu_index
> around, but in practice for the QMP command the user can't set
> which CPU to operate on, and for everything except s390 the
> implementation doesn't care anyway. My impression from the IRC
> discussion is that it's not really necessary for the S390 that
> the monitor user be able to specify which CPU to NMI (and in any
> case you can only do that from the HMP command, not the QMP
> command, AIUI), so getting rid of that weird inconsistency makes
> sense to me: and that's what this patchset is doing.
[*] https://lore.kernel.org/qemu-devel/CAFEAcA_0qUFW0MewHC+v+pSOisE-kQDt9Wv4F3RafEkyQ0DGJA@mail.gmail.com/:
Philippe Mathieu-Daudé (7):
hw/nmi: Use object_child_foreach_recursive() in nmi_children()
hw/s390x/virtio-ccw: Always deliver NMI to first CPU
hw/nmi: Remove @cpu_index argument from
NMIClass::nmi_monitor_handler()
hw/nmi: Remove @cpu_index argument from nmi_trigger()
hw/nmi: Rename nmi_monitor_handler() -> deliver_nmi()
hw/nmi: Remove unused @errp argument from deliver_nmi()
hw/nmi: Deliver NMI only once
qapi/run-state.json | 6 +++--
include/hw/core/nmi.h | 32 +++++++++++++++++++++++++--
hw/core/nmi.c | 45 ++++++++++----------------------------
hw/hppa/machine.c | 4 ++--
hw/i386/x86.c | 4 ++--
hw/intc/m68k_irqc.c | 4 ++--
hw/ipmi/ipmi.c | 3 +--
hw/m68k/q800-glue.c | 4 ++--
hw/misc/macio/gpio.c | 4 ++--
hw/ppc/pnv.c | 4 ++--
hw/ppc/spapr.c | 4 ++--
hw/s390x/s390-virtio-ccw.c | 8 +++----
hw/watchdog/watchdog.c | 2 +-
system/cpus.c | 2 +-
hmp-commands.hx | 2 +-
15 files changed, 66 insertions(+), 62 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 1/7] hw/nmi: Use object_child_foreach_recursive() in nmi_children()
2026-08-11 10:54 [PATCH v3 0/7] hw/nmi: Disconnect of vCPU and disentangle Monitor code Philippe Mathieu-Daudé
@ 2026-08-11 10:54 ` Philippe Mathieu-Daudé
2026-08-11 10:54 ` [PATCH v3 2/7] hw/s390x/virtio-ccw: Always deliver NMI to first CPU Philippe Mathieu-Daudé
` (5 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-11 10:54 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, qemu-s390x, Dr. David Alan Gilbert,
Thomas Huth, qemu-ppc, Corey Minyard, Markus Armbruster,
Philippe Mathieu-Daudé, Peter Maydell,
Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé <philmd@linaro.org>
Replace object_child_foreach() and recursion by a single
object_child_foreach_recursive() call.
Propagate the returned value so callers can check it.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/core/nmi.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/hw/core/nmi.c b/hw/core/nmi.c
index 4b447e126ba..22724046575 100644
--- a/hw/core/nmi.c
+++ b/hw/core/nmi.c
@@ -31,8 +31,6 @@ struct do_nmi_s {
bool handled;
};
-static void nmi_children(Object *o, struct do_nmi_s *ns);
-
static int do_nmi(Object *o, void *opaque)
{
struct do_nmi_s *ns = opaque;
@@ -47,14 +45,13 @@ static int do_nmi(Object *o, void *opaque)
return -1;
}
}
- nmi_children(o, ns);
return 0;
}
-static void nmi_children(Object *o, struct do_nmi_s *ns)
+static int nmi_children(Object *o, struct do_nmi_s *ns)
{
- object_child_foreach(o, do_nmi, ns);
+ return object_child_foreach_recursive(o, do_nmi, ns);
}
void nmi_monitor_handle(int cpu_index, Error **errp)
@@ -65,10 +62,9 @@ void nmi_monitor_handle(int cpu_index, Error **errp)
.handled = false
};
- nmi_children(object_get_root(), &ns);
- if (ns.handled) {
+ if (nmi_children(object_get_root(), &ns)) {
error_propagate(errp, ns.err);
- } else {
+ } else if (!ns.handled) {
error_setg(errp, "machine does not provide NMIs");
}
}
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 2/7] hw/s390x/virtio-ccw: Always deliver NMI to first CPU
2026-08-11 10:54 [PATCH v3 0/7] hw/nmi: Disconnect of vCPU and disentangle Monitor code Philippe Mathieu-Daudé
2026-08-11 10:54 ` [PATCH v3 1/7] hw/nmi: Use object_child_foreach_recursive() in nmi_children() Philippe Mathieu-Daudé
@ 2026-08-11 10:54 ` Philippe Mathieu-Daudé
2026-08-11 10:54 ` [PATCH v3 3/7] hw/nmi: Remove @cpu_index argument from NMIClass::nmi_monitor_handler() Philippe Mathieu-Daudé
` (4 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-11 10:54 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, qemu-s390x, Dr. David Alan Gilbert,
Thomas Huth, qemu-ppc, Corey Minyard, Markus Armbruster,
Philippe Mathieu-Daudé, Peter Maydell, David Hildenbrand,
Philippe Mathieu-Daudé, Cornelia Huck, Eric Farman,
Matthew Rosato, Halil Pasic, Christian Borntraeger,
Richard Henderson, Ilya Leoshkevich, David Hildenbrand,
Eric Blake, Paolo Bonzini
From: Philippe Mathieu-Daudé <philmd@linaro.org>
We can trigger NMI from HMP or QMP.
QEMU maps the NMI to the s390x per-CPU 'RESTART' interrupt.
Linux guests usually setup this interrupt to trigger kdump
or crash. Such crashdump can be triggered in QEMU by HMP
"nmi" or QMP "inject-nmi" commands.
Using QMP, since we can not select a particular CPU, the first
CPU is used (CPU#0). See the documentation from commit 795dc6e4
("watchdog: Add new Virtual Watchdog action INJECT-NMI"):
@inject-nmi: a non-maskable interrupt is injected into the
first VCPU (all VCPUS on x86) (since 2.4)
While we can select a particular CPU on HMP, the guest behavior
is expected to be the same if using CPU #N or CPU #0. Since
always using CPU#0 simplifies API maintainance, update s390_nmi()
to deliver NMI to the first CPU.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
qapi/run-state.json | 6 ++++--
hw/s390x/s390-virtio-ccw.c | 4 +---
hmp-commands.hx | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/qapi/run-state.json b/qapi/run-state.json
index a5771ad4681..e4fdead1e0b 100644
--- a/qapi/run-state.json
+++ b/qapi/run-state.json
@@ -317,8 +317,10 @@
#
# @none: nothing is done
#
-# @inject-nmi: a non-maskable interrupt is injected into the first
-# VCPU (all VCPUS on x86) (since 2.4)
+# @inject-nmi: a non-maskable interrupt is injected (machine
+# specific: for example on s390x CCW only the first vCPU
+# receives the NMI, but on x86 machines all vCPUs receive
+# it). (since 2.4)
#
# Since: 2.1
##
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 25a9fa49554..4f7861dbbb7 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -727,9 +727,7 @@ static HotplugHandler *s390_get_hotplug_handler(MachineState *machine,
static void s390_nmi(NMIState *n, int cpu_index, Error **errp)
{
- CPUState *cs = qemu_get_cpu(cpu_index);
-
- s390_cpu_restart(S390_CPU(cs));
+ s390_cpu_restart(S390_CPU(first_cpu));
}
static inline bool machine_get_aes_key_wrap(Object *obj, Error **errp)
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 7ae2468a3d9..3aa159f11ce 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -870,7 +870,7 @@ ERST
},
SRST
``nmi`` *cpu*
- Inject an NMI on the default CPU (x86/s390) or all CPUs (ppc64).
+ Inject an NMI.
ERST
{
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 3/7] hw/nmi: Remove @cpu_index argument from NMIClass::nmi_monitor_handler()
2026-08-11 10:54 [PATCH v3 0/7] hw/nmi: Disconnect of vCPU and disentangle Monitor code Philippe Mathieu-Daudé
2026-08-11 10:54 ` [PATCH v3 1/7] hw/nmi: Use object_child_foreach_recursive() in nmi_children() Philippe Mathieu-Daudé
2026-08-11 10:54 ` [PATCH v3 2/7] hw/s390x/virtio-ccw: Always deliver NMI to first CPU Philippe Mathieu-Daudé
@ 2026-08-11 10:54 ` Philippe Mathieu-Daudé
2026-08-11 13:21 ` Peter Maydell
2026-08-11 10:54 ` [PATCH v3 4/7] hw/nmi: Remove @cpu_index argument from nmi_trigger() Philippe Mathieu-Daudé
` (3 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-11 10:54 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, qemu-s390x, Dr. David Alan Gilbert,
Thomas Huth, qemu-ppc, Corey Minyard, Markus Armbruster,
Philippe Mathieu-Daudé, Philippe Mathieu-Daudé,
Richard Henderson, Helge Deller, Paolo Bonzini,
Michael S. Tsirkin, Laurent Vivier, Mark Cave-Ayland,
Nicholas Piggin, Aditya Gupta, Glenn Miles, Harsh Prateek Bora,
Ilya Leoshkevich, David Hildenbrand, Halil Pasic,
Christian Borntraeger, Eric Farman, Matthew Rosato, Cornelia Huck
From: Philippe Mathieu-Daudé <philmd@linaro.org>
Only s390x was using the 'cpu_index' argument, but since the
previous commit it isn't anymore (it use the first cpu).
Since this argument is now completely unused, remove it.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
include/hw/core/nmi.h | 8 +++++++-
hw/core/nmi.c | 2 +-
hw/hppa/machine.c | 2 +-
hw/i386/x86.c | 2 +-
hw/intc/m68k_irqc.c | 2 +-
hw/m68k/q800-glue.c | 2 +-
hw/misc/macio/gpio.c | 2 +-
hw/ppc/pnv.c | 2 +-
hw/ppc/spapr.c | 2 +-
hw/s390x/s390-virtio-ccw.c | 2 +-
10 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/include/hw/core/nmi.h b/include/hw/core/nmi.h
index fff41bebc69..4c4ce79071d 100644
--- a/include/hw/core/nmi.h
+++ b/include/hw/core/nmi.h
@@ -37,7 +37,13 @@ typedef struct NMIState NMIState;
struct NMIClass {
InterfaceClass parent_class;
- void (*nmi_monitor_handler)(NMIState *n, int cpu_index, Error **errp);
+ /**
+ * nmi_monitor_handler: Callback to handle NMI notifications.
+ *
+ * @ns: Class #NMIState state
+ * @errp: pointer to error object
+ */
+ void (*nmi_monitor_handler)(NMIState *ns, Error **errp);
};
void nmi_monitor_handle(int cpu_index, Error **errp);
diff --git a/hw/core/nmi.c b/hw/core/nmi.c
index 22724046575..ff6454437c1 100644
--- a/hw/core/nmi.c
+++ b/hw/core/nmi.c
@@ -40,7 +40,7 @@ static int do_nmi(Object *o, void *opaque)
NMIClass *nc = NMI_GET_CLASS(n);
ns->handled = true;
- nc->nmi_monitor_handler(n, ns->cpu_index, &ns->err);
+ nc->nmi_monitor_handler(n, &ns->err);
if (ns->err) {
return -1;
}
diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index d762163ddf5..2b44debc388 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -829,7 +829,7 @@ static void hppa_machine_reset(MachineState *ms, ResetType type)
cpu[0]->env.cmdline_or_bootorder = 'c';
}
-static void hppa_nmi(NMIState *n, int cpu_index, Error **errp)
+static void hppa_nmi(NMIState *ns, Error **errp)
{
CPUState *cs;
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index dc7f0d56b01..0ea5453403d 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -147,7 +147,7 @@ static const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
return ms->possible_cpus;
}
-static void x86_nmi(NMIState *n, int cpu_index, Error **errp)
+static void x86_nmi(NMIState *ns, Error **errp)
{
/* cpu index isn't used */
CPUState *cs;
diff --git a/hw/intc/m68k_irqc.c b/hw/intc/m68k_irqc.c
index 68ddb5351be..bc41b44d455 100644
--- a/hw/intc/m68k_irqc.c
+++ b/hw/intc/m68k_irqc.c
@@ -70,7 +70,7 @@ static void m68k_irqc_instance_init(Object *obj)
qdev_init_gpio_in(DEVICE(obj), m68k_set_irq, M68K_IRQC_LEVEL_NUM);
}
-static void m68k_nmi(NMIState *n, int cpu_index, Error **errp)
+static void m68k_nmi(NMIState *n, Error **errp)
{
m68k_set_irq(n, M68K_IRQC_LEVEL_7, 1);
}
diff --git a/hw/m68k/q800-glue.c b/hw/m68k/q800-glue.c
index ac9062c6488..b13e5ef95f1 100644
--- a/hw/m68k/q800-glue.c
+++ b/hw/m68k/q800-glue.c
@@ -159,7 +159,7 @@ static void glue_auxmode_set_irq(void *opaque, int irq, int level)
s->auxmode = level;
}
-static void glue_nmi(NMIState *n, int cpu_index, Error **errp)
+static void glue_nmi(NMIState *n, Error **errp)
{
GLUEState *s = GLUE(n);
diff --git a/hw/misc/macio/gpio.c b/hw/misc/macio/gpio.c
index 1a7c534d652..1bdca728f97 100644
--- a/hw/misc/macio/gpio.c
+++ b/hw/misc/macio/gpio.c
@@ -188,7 +188,7 @@ static void macio_gpio_reset(DeviceState *dev)
macio_set_gpio(s, 1, true);
}
-static void macio_gpio_nmi(NMIState *n, int cpu_index, Error **errp)
+static void macio_gpio_nmi(NMIState *n, Error **errp)
{
macio_set_gpio(MACIO_GPIO(n), 9, true);
macio_set_gpio(MACIO_GPIO(n), 9, false);
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index c0cb45dbfbc..8676be7bbb1 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -3552,7 +3552,7 @@ static void pnv_cpu_do_nmi(PnvChip *chip, PowerPCCPU *cpu, void *opaque)
async_run_on_cpu(CPU(cpu), pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_HOST_INT(0));
}
-static void pnv_nmi(NMIState *n, int cpu_index, Error **errp)
+static void pnv_nmi(NMIState *ns, Error **errp)
{
PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
int i;
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index b79828b4e90..189334b9f0a 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -3550,7 +3550,7 @@ void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg)
}
}
-static void spapr_nmi(NMIState *n, int cpu_index, Error **errp)
+static void spapr_nmi(NMIState *ns, Error **errp)
{
CPUState *cs;
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 4f7861dbbb7..5d8a73a63df 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -725,7 +725,7 @@ static HotplugHandler *s390_get_hotplug_handler(MachineState *machine,
return NULL;
}
-static void s390_nmi(NMIState *n, int cpu_index, Error **errp)
+static void s390_nmi(NMIState *ns, Error **errp)
{
s390_cpu_restart(S390_CPU(first_cpu));
}
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 4/7] hw/nmi: Remove @cpu_index argument from nmi_trigger()
2026-08-11 10:54 [PATCH v3 0/7] hw/nmi: Disconnect of vCPU and disentangle Monitor code Philippe Mathieu-Daudé
` (2 preceding siblings ...)
2026-08-11 10:54 ` [PATCH v3 3/7] hw/nmi: Remove @cpu_index argument from NMIClass::nmi_monitor_handler() Philippe Mathieu-Daudé
@ 2026-08-11 10:54 ` Philippe Mathieu-Daudé
2026-08-11 11:10 ` Marc-André Lureau
2026-08-11 10:54 ` [PATCH v3 5/7] hw/nmi: Rename nmi_monitor_handler() -> deliver_nmi() Philippe Mathieu-Daudé
` (2 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-11 10:54 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, qemu-s390x, Dr. David Alan Gilbert,
Thomas Huth, qemu-ppc, Corey Minyard, Markus Armbruster,
Philippe Mathieu-Daudé, Philippe Mathieu-Daudé,
Richard Henderson, Paolo Bonzini, Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé <philmd@linaro.org>
nmi_monitor_handle() is not related to the monitor, rename
it as nmi_trigger().
Return a boolean value indicating success / failure as
recommended by the Error API since commit e3fe3988d7
("error: Document Error API usage rules").
The 'cpu_index' argument is not used, remove it.
Document nmi_trigger() as suggested by Peter Maydell in
https://lore.kernel.org/qemu-devel/CAFEAcA-yALySmCJLbitCmYpiZKUXJNOavGJG9RYeo8fKqz7gcw@mail.gmail.com/.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
include/hw/core/nmi.h | 25 ++++++++++++++++++++++++-
hw/core/nmi.c | 9 ++++-----
hw/ipmi/ipmi.c | 3 +--
hw/watchdog/watchdog.c | 2 +-
system/cpus.c | 2 +-
5 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/include/hw/core/nmi.h b/include/hw/core/nmi.h
index 4c4ce79071d..e77c382452a 100644
--- a/include/hw/core/nmi.h
+++ b/include/hw/core/nmi.h
@@ -46,6 +46,29 @@ struct NMIClass {
void (*nmi_monitor_handler)(NMIState *ns, Error **errp);
};
-void nmi_monitor_handle(int cpu_index, Error **errp);
+/**
+ * nmi_trigger: Trigger an NMI, in a machine-specific way
+ * @errp: pointer to error object
+ *
+ * This function triggers an NMI, in a machine-specific way. The
+ * intention is that this should typically trigger a guest kernel
+ * dump or reboot, and might happen as a result of user request
+ * from the monitor, watchdog timeouts, and similar events.
+ * (For example on the x86 PC it triggers an NMI on all CPUs,
+ * and on s390 it triggers the RESTART interrupt on the first CPU.)
+ *
+ * The NMI is triggered by looking for QOM objects which
+ * implement the TYPE_NMI interface, and calling their nmi_handler
+ * method. Usually it is the machine model class that implements
+ * this interface.
+ *
+ * Not all machines implement NMI handling; this function
+ * will return an error if used on a machine which does not
+ * implement NMIs.
+ *
+ * On success, return %true.
+ * On failure, store an error through @errp and return %false.
+ */
+bool nmi_trigger(Error **errp);
#endif /* NMI_H */
diff --git a/hw/core/nmi.c b/hw/core/nmi.c
index ff6454437c1..662f2051123 100644
--- a/hw/core/nmi.c
+++ b/hw/core/nmi.c
@@ -22,11 +22,8 @@
#include "qemu/osdep.h"
#include "hw/core/nmi.h"
#include "qapi/error.h"
-#include "qemu/module.h"
-#include "monitor/monitor.h"
struct do_nmi_s {
- int cpu_index;
Error *err;
bool handled;
};
@@ -54,19 +51,21 @@ static int nmi_children(Object *o, struct do_nmi_s *ns)
return object_child_foreach_recursive(o, do_nmi, ns);
}
-void nmi_monitor_handle(int cpu_index, Error **errp)
+bool nmi_trigger(Error **errp)
{
struct do_nmi_s ns = {
- .cpu_index = cpu_index,
.err = NULL,
.handled = false
};
if (nmi_children(object_get_root(), &ns)) {
error_propagate(errp, ns.err);
+ return false;
} else if (!ns.handled) {
error_setg(errp, "machine does not provide NMIs");
+ return false;
}
+ return true;
}
static const TypeInfo nmi_info = {
diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c
index 74818ff3cea..444af726d75 100644
--- a/hw/ipmi/ipmi.c
+++ b/hw/ipmi/ipmi.c
@@ -59,8 +59,7 @@ static int ipmi_do_hw_op(IPMIInterface *s, enum ipmi_op op, int checkonly)
if (checkonly) {
return 0;
}
- /* We don't care what CPU we use. */
- nmi_monitor_handle(0, NULL);
+ nmi_trigger(NULL);
return 0;
case IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP:
diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
index 0842fe373ae..026768e9fb2 100644
--- a/hw/watchdog/watchdog.c
+++ b/hw/watchdog/watchdog.c
@@ -81,7 +81,7 @@ void watchdog_perform_action(void)
case WATCHDOG_ACTION_INJECT_NMI:
qapi_event_send_watchdog(WATCHDOG_ACTION_INJECT_NMI);
- nmi_monitor_handle(0, NULL);
+ nmi_trigger(NULL);
break;
default:
diff --git a/system/cpus.c b/system/cpus.c
index 97e5a5edee2..5c0a192c01e 100644
--- a/system/cpus.c
+++ b/system/cpus.c
@@ -926,6 +926,6 @@ exit:
void qmp_inject_nmi(Error **errp)
{
- nmi_monitor_handle(monitor_get_cpu_index(monitor_cur()), errp);
+ nmi_trigger(errp);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 5/7] hw/nmi: Rename nmi_monitor_handler() -> deliver_nmi()
2026-08-11 10:54 [PATCH v3 0/7] hw/nmi: Disconnect of vCPU and disentangle Monitor code Philippe Mathieu-Daudé
` (3 preceding siblings ...)
2026-08-11 10:54 ` [PATCH v3 4/7] hw/nmi: Remove @cpu_index argument from nmi_trigger() Philippe Mathieu-Daudé
@ 2026-08-11 10:54 ` Philippe Mathieu-Daudé
2026-08-11 10:54 ` [PATCH v3 6/7] hw/nmi: Remove unused @errp argument from deliver_nmi() Philippe Mathieu-Daudé
2026-08-11 10:54 ` [PATCH v3 7/7] hw/nmi: Deliver NMI only once Philippe Mathieu-Daudé
6 siblings, 0 replies; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-11 10:54 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, qemu-s390x, Dr. David Alan Gilbert,
Thomas Huth, qemu-ppc, Corey Minyard, Markus Armbruster,
Philippe Mathieu-Daudé, Richard Henderson, Helge Deller,
Paolo Bonzini, Michael S. Tsirkin, Laurent Vivier,
Mark Cave-Ayland, Nicholas Piggin, Aditya Gupta, Glenn Miles,
Harsh Prateek Bora, Halil Pasic, Christian Borntraeger,
Eric Farman, Matthew Rosato, Ilya Leoshkevich, David Hildenbrand,
Cornelia Huck
nmi_monitor_handler() is not related to the monitor,
rename it as deliver_nmi().
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
include/hw/core/nmi.h | 4 ++--
hw/core/nmi.c | 2 +-
hw/hppa/machine.c | 2 +-
hw/i386/x86.c | 2 +-
hw/intc/m68k_irqc.c | 2 +-
hw/m68k/q800-glue.c | 2 +-
hw/misc/macio/gpio.c | 2 +-
hw/ppc/pnv.c | 2 +-
hw/ppc/spapr.c | 2 +-
hw/s390x/s390-virtio-ccw.c | 2 +-
10 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/include/hw/core/nmi.h b/include/hw/core/nmi.h
index e77c382452a..d6bd2a9fceb 100644
--- a/include/hw/core/nmi.h
+++ b/include/hw/core/nmi.h
@@ -38,12 +38,12 @@ struct NMIClass {
InterfaceClass parent_class;
/**
- * nmi_monitor_handler: Callback to handle NMI notifications.
+ * deliver_nmi: Callback to handle NMI notifications.
*
* @ns: Class #NMIState state
* @errp: pointer to error object
*/
- void (*nmi_monitor_handler)(NMIState *ns, Error **errp);
+ void (*deliver_nmi)(NMIState *ns, Error **errp);
};
/**
diff --git a/hw/core/nmi.c b/hw/core/nmi.c
index 662f2051123..02c0ff2c21d 100644
--- a/hw/core/nmi.c
+++ b/hw/core/nmi.c
@@ -37,7 +37,7 @@ static int do_nmi(Object *o, void *opaque)
NMIClass *nc = NMI_GET_CLASS(n);
ns->handled = true;
- nc->nmi_monitor_handler(n, &ns->err);
+ nc->deliver_nmi(n, &ns->err);
if (ns->err) {
return -1;
}
diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index 2b44debc388..47e0302bac8 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -851,7 +851,7 @@ static void hppa_machine_common_class_init(ObjectClass *oc, const void *data)
mc->default_ram_id = "hppa.ram";
mc->default_nic = "tulip";
- nc->nmi_monitor_handler = hppa_nmi;
+ nc->deliver_nmi = hppa_nmi;
}
static void HP_B160L_machine_init_class_init(ObjectClass *oc, const void *data)
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index 0ea5453403d..48f7575895a 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -389,7 +389,7 @@ static void x86_machine_class_init(ObjectClass *oc, const void *data)
mc->get_default_cpu_node_id = x86_get_default_cpu_node_id;
mc->possible_cpu_arch_ids = x86_possible_cpu_arch_ids;
mc->kvm_type = x86_kvm_type;
- nc->nmi_monitor_handler = x86_nmi;
+ nc->deliver_nmi = x86_nmi;
object_class_property_add(oc, X86_MACHINE_SMM, "OnOffAuto",
x86_machine_get_smm, x86_machine_set_smm,
diff --git a/hw/intc/m68k_irqc.c b/hw/intc/m68k_irqc.c
index bc41b44d455..281542e3997 100644
--- a/hw/intc/m68k_irqc.c
+++ b/hw/intc/m68k_irqc.c
@@ -97,7 +97,7 @@ static void m68k_irqc_class_init(ObjectClass *oc, const void *data)
InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(oc);
device_class_set_props(dc, m68k_irqc_properties);
- nc->nmi_monitor_handler = m68k_nmi;
+ nc->deliver_nmi = m68k_nmi;
device_class_set_legacy_reset(dc, m68k_irqc_reset);
dc->vmsd = &vmstate_m68k_irqc;
ic->get_statistics = m68k_irqc_get_statistics;
diff --git a/hw/m68k/q800-glue.c b/hw/m68k/q800-glue.c
index b13e5ef95f1..b75f7f44d3c 100644
--- a/hw/m68k/q800-glue.c
+++ b/hw/m68k/q800-glue.c
@@ -237,7 +237,7 @@ static void glue_class_init(ObjectClass *klass, const void *data)
dc->vmsd = &vmstate_glue;
device_class_set_props(dc, glue_properties);
rc->phases.hold = glue_reset_hold;
- nc->nmi_monitor_handler = glue_nmi;
+ nc->deliver_nmi = glue_nmi;
}
static const TypeInfo glue_info_types[] = {
diff --git a/hw/misc/macio/gpio.c b/hw/misc/macio/gpio.c
index 1bdca728f97..086d90f20b6 100644
--- a/hw/misc/macio/gpio.c
+++ b/hw/misc/macio/gpio.c
@@ -201,7 +201,7 @@ static void macio_gpio_class_init(ObjectClass *oc, const void *data)
device_class_set_legacy_reset(dc, macio_gpio_reset);
dc->vmsd = &vmstate_macio_gpio;
- nc->nmi_monitor_handler = macio_gpio_nmi;
+ nc->deliver_nmi = macio_gpio_nmi;
}
static const TypeInfo macio_gpio_init_info = {
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 8676be7bbb1..bfb1d45d058 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -3583,7 +3583,7 @@ static void pnv_machine_class_init(ObjectClass *oc, const void *data)
mc->default_ram_size = 1 * GiB;
mc->default_ram_id = "pnv.ram";
ispc->print_info = pnv_pic_print_info;
- nc->nmi_monitor_handler = pnv_nmi;
+ nc->deliver_nmi = pnv_nmi;
object_class_property_add_bool(oc, "hb-mode",
pnv_machine_get_hb, pnv_machine_set_hb);
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 189334b9f0a..ed545acf3c0 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4652,7 +4652,7 @@ static void spapr_machine_class_init(ObjectClass *oc, const void *data)
mc->nvdimm_supported = true;
smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED;
fwc->get_dev_path = spapr_get_fw_dev_path;
- nc->nmi_monitor_handler = spapr_nmi;
+ nc->deliver_nmi = spapr_nmi;
vhc->cpu_in_nested = spapr_cpu_in_nested;
vhc->deliver_hv_excp = spapr_exit_nested;
vhc->hypercall = emulate_spapr_hypercall;
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 5d8a73a63df..f9e8ecb4fe0 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -830,7 +830,7 @@ static void ccw_machine_class_init(ObjectClass *oc, const void *data)
hc->plug = s390_machine_device_plug;
hc->unplug_request = s390_machine_device_unplug_request;
hc->unplug = s390_machine_device_unplug;
- nc->nmi_monitor_handler = s390_nmi;
+ nc->deliver_nmi = s390_nmi;
mc->default_ram_id = "s390.ram";
mc->default_nic = "virtio-net-ccw";
dsi->qmp_dump_skeys = s390_qmp_dump_skeys;
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 6/7] hw/nmi: Remove unused @errp argument from deliver_nmi()
2026-08-11 10:54 [PATCH v3 0/7] hw/nmi: Disconnect of vCPU and disentangle Monitor code Philippe Mathieu-Daudé
` (4 preceding siblings ...)
2026-08-11 10:54 ` [PATCH v3 5/7] hw/nmi: Rename nmi_monitor_handler() -> deliver_nmi() Philippe Mathieu-Daudé
@ 2026-08-11 10:54 ` Philippe Mathieu-Daudé
2026-08-11 13:24 ` Peter Maydell
2026-08-11 10:54 ` [PATCH v3 7/7] hw/nmi: Deliver NMI only once Philippe Mathieu-Daudé
6 siblings, 1 reply; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-11 10:54 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, qemu-s390x, Dr. David Alan Gilbert,
Thomas Huth, qemu-ppc, Corey Minyard, Markus Armbruster,
Philippe Mathieu-Daudé, Richard Henderson, Helge Deller,
Michael S. Tsirkin, Paolo Bonzini, Laurent Vivier,
Mark Cave-Ayland, Nicholas Piggin, Aditya Gupta, Glenn Miles,
Harsh Prateek Bora, Cornelia Huck, Eric Farman, Matthew Rosato,
Halil Pasic, Christian Borntraeger, Ilya Leoshkevich,
David Hildenbrand
Not a single handler update @errp. The single user is
nmi_trigger() filling with "machine does not provide NMIs".
Remove the unused argument from the deliver_nmi() callback,
simplifying the methods in hw/core/nmi.c.
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
include/hw/core/nmi.h | 3 +--
hw/core/nmi.c | 32 ++++++--------------------------
hw/hppa/machine.c | 2 +-
hw/i386/x86.c | 2 +-
hw/intc/m68k_irqc.c | 2 +-
hw/m68k/q800-glue.c | 2 +-
hw/misc/macio/gpio.c | 2 +-
hw/ppc/pnv.c | 2 +-
hw/ppc/spapr.c | 2 +-
hw/s390x/s390-virtio-ccw.c | 2 +-
10 files changed, 15 insertions(+), 36 deletions(-)
diff --git a/include/hw/core/nmi.h b/include/hw/core/nmi.h
index d6bd2a9fceb..b0f58542bcc 100644
--- a/include/hw/core/nmi.h
+++ b/include/hw/core/nmi.h
@@ -41,9 +41,8 @@ struct NMIClass {
* deliver_nmi: Callback to handle NMI notifications.
*
* @ns: Class #NMIState state
- * @errp: pointer to error object
*/
- void (*deliver_nmi)(NMIState *ns, Error **errp);
+ void (*deliver_nmi)(NMIState *ns);
};
/**
diff --git a/hw/core/nmi.c b/hw/core/nmi.c
index 02c0ff2c21d..8eea75ad530 100644
--- a/hw/core/nmi.c
+++ b/hw/core/nmi.c
@@ -23,45 +23,25 @@
#include "hw/core/nmi.h"
#include "qapi/error.h"
-struct do_nmi_s {
- Error *err;
- bool handled;
-};
-
static int do_nmi(Object *o, void *opaque)
{
- struct do_nmi_s *ns = opaque;
+ bool *handled = opaque;
NMIState *n = (NMIState *) object_dynamic_cast(o, TYPE_NMI);
if (n) {
- NMIClass *nc = NMI_GET_CLASS(n);
-
- ns->handled = true;
- nc->deliver_nmi(n, &ns->err);
- if (ns->err) {
- return -1;
- }
+ *handled = true;
+ NMI_GET_CLASS(n)->deliver_nmi(n);
}
return 0;
}
-static int nmi_children(Object *o, struct do_nmi_s *ns)
-{
- return object_child_foreach_recursive(o, do_nmi, ns);
-}
-
bool nmi_trigger(Error **errp)
{
- struct do_nmi_s ns = {
- .err = NULL,
- .handled = false
- };
+ bool handled = false;
- if (nmi_children(object_get_root(), &ns)) {
- error_propagate(errp, ns.err);
- return false;
- } else if (!ns.handled) {
+ object_child_foreach_recursive(object_get_root(), do_nmi, &handled);
+ if (!handled) {
error_setg(errp, "machine does not provide NMIs");
return false;
}
diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index 47e0302bac8..51ecdabdbd5 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -829,7 +829,7 @@ static void hppa_machine_reset(MachineState *ms, ResetType type)
cpu[0]->env.cmdline_or_bootorder = 'c';
}
-static void hppa_nmi(NMIState *ns, Error **errp)
+static void hppa_nmi(NMIState *ns)
{
CPUState *cs;
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index 48f7575895a..8d82bd890da 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -147,7 +147,7 @@ static const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
return ms->possible_cpus;
}
-static void x86_nmi(NMIState *ns, Error **errp)
+static void x86_nmi(NMIState *ns)
{
/* cpu index isn't used */
CPUState *cs;
diff --git a/hw/intc/m68k_irqc.c b/hw/intc/m68k_irqc.c
index 281542e3997..b78ca5ca11b 100644
--- a/hw/intc/m68k_irqc.c
+++ b/hw/intc/m68k_irqc.c
@@ -70,7 +70,7 @@ static void m68k_irqc_instance_init(Object *obj)
qdev_init_gpio_in(DEVICE(obj), m68k_set_irq, M68K_IRQC_LEVEL_NUM);
}
-static void m68k_nmi(NMIState *n, Error **errp)
+static void m68k_nmi(NMIState *n)
{
m68k_set_irq(n, M68K_IRQC_LEVEL_7, 1);
}
diff --git a/hw/m68k/q800-glue.c b/hw/m68k/q800-glue.c
index b75f7f44d3c..8be7696777e 100644
--- a/hw/m68k/q800-glue.c
+++ b/hw/m68k/q800-glue.c
@@ -159,7 +159,7 @@ static void glue_auxmode_set_irq(void *opaque, int irq, int level)
s->auxmode = level;
}
-static void glue_nmi(NMIState *n, Error **errp)
+static void glue_nmi(NMIState *n)
{
GLUEState *s = GLUE(n);
diff --git a/hw/misc/macio/gpio.c b/hw/misc/macio/gpio.c
index 086d90f20b6..ba4df62c674 100644
--- a/hw/misc/macio/gpio.c
+++ b/hw/misc/macio/gpio.c
@@ -188,7 +188,7 @@ static void macio_gpio_reset(DeviceState *dev)
macio_set_gpio(s, 1, true);
}
-static void macio_gpio_nmi(NMIState *n, Error **errp)
+static void macio_gpio_nmi(NMIState *n)
{
macio_set_gpio(MACIO_GPIO(n), 9, true);
macio_set_gpio(MACIO_GPIO(n), 9, false);
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index bfb1d45d058..2ec0c198fa5 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -3552,7 +3552,7 @@ static void pnv_cpu_do_nmi(PnvChip *chip, PowerPCCPU *cpu, void *opaque)
async_run_on_cpu(CPU(cpu), pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_HOST_INT(0));
}
-static void pnv_nmi(NMIState *ns, Error **errp)
+static void pnv_nmi(NMIState *ns)
{
PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
int i;
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index ed545acf3c0..477054d8c85 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -3550,7 +3550,7 @@ void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg)
}
}
-static void spapr_nmi(NMIState *ns, Error **errp)
+static void spapr_nmi(NMIState *ns)
{
CPUState *cs;
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index f9e8ecb4fe0..255698fd7ed 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -725,7 +725,7 @@ static HotplugHandler *s390_get_hotplug_handler(MachineState *machine,
return NULL;
}
-static void s390_nmi(NMIState *ns, Error **errp)
+static void s390_nmi(NMIState *ns)
{
s390_cpu_restart(S390_CPU(first_cpu));
}
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 7/7] hw/nmi: Deliver NMI only once
2026-08-11 10:54 [PATCH v3 0/7] hw/nmi: Disconnect of vCPU and disentangle Monitor code Philippe Mathieu-Daudé
` (5 preceding siblings ...)
2026-08-11 10:54 ` [PATCH v3 6/7] hw/nmi: Remove unused @errp argument from deliver_nmi() Philippe Mathieu-Daudé
@ 2026-08-11 10:54 ` Philippe Mathieu-Daudé
2026-08-11 13:34 ` Peter Maydell
6 siblings, 1 reply; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-11 10:54 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, qemu-s390x, Dr. David Alan Gilbert,
Thomas Huth, qemu-ppc, Corey Minyard, Markus Armbruster,
Philippe Mathieu-Daudé, Peter Maydell
Use the first handler available to deliver NMI only once.
If anothers handlers are available, no need to keep delivering.
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/core/nmi.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/hw/core/nmi.c b/hw/core/nmi.c
index 8eea75ad530..4fe5ee75bfc 100644
--- a/hw/core/nmi.c
+++ b/hw/core/nmi.c
@@ -31,6 +31,8 @@ static int do_nmi(Object *o, void *opaque)
if (n) {
*handled = true;
NMI_GET_CLASS(n)->deliver_nmi(n);
+ /* We only need to deliver NMI once */
+ return 1;
}
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v3 4/7] hw/nmi: Remove @cpu_index argument from nmi_trigger()
2026-08-11 10:54 ` [PATCH v3 4/7] hw/nmi: Remove @cpu_index argument from nmi_trigger() Philippe Mathieu-Daudé
@ 2026-08-11 11:10 ` Marc-André Lureau
2026-08-11 13:55 ` Philippe Mathieu-Daudé
0 siblings, 1 reply; 14+ messages in thread
From: Marc-André Lureau @ 2026-08-11 11:10 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: qemu-devel, qemu-s390x, Dr. David Alan Gilbert, Thomas Huth,
qemu-ppc, Corey Minyard, Markus Armbruster,
Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini,
Philippe Mathieu-Daudé
Hi
On Tue, Aug 11, 2026 at 2:55 PM Philippe Mathieu-Daudé
<philmd@oss.qualcomm.com> wrote:
>
> From: Philippe Mathieu-Daudé <philmd@linaro.org>
>
> nmi_monitor_handle() is not related to the monitor, rename
> it as nmi_trigger().
>
> Return a boolean value indicating success / failure as
> recommended by the Error API since commit e3fe3988d7
> ("error: Document Error API usage rules").
>
> The 'cpu_index' argument is not used, remove it.
>
> Document nmi_trigger() as suggested by Peter Maydell in
> https://lore.kernel.org/qemu-devel/CAFEAcA-yALySmCJLbitCmYpiZKUXJNOavGJG9RYeo8fKqz7gcw@mail.gmail.com/.
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
> ---
> include/hw/core/nmi.h | 25 ++++++++++++++++++++++++-
> hw/core/nmi.c | 9 ++++-----
> hw/ipmi/ipmi.c | 3 +--
> hw/watchdog/watchdog.c | 2 +-
> system/cpus.c | 2 +-
> 5 files changed, 31 insertions(+), 10 deletions(-)
>
> diff --git a/include/hw/core/nmi.h b/include/hw/core/nmi.h
> index 4c4ce79071d..e77c382452a 100644
> --- a/include/hw/core/nmi.h
> +++ b/include/hw/core/nmi.h
> @@ -46,6 +46,29 @@ struct NMIClass {
> void (*nmi_monitor_handler)(NMIState *ns, Error **errp);
> };
>
> -void nmi_monitor_handle(int cpu_index, Error **errp);
> +/**
> + * nmi_trigger: Trigger an NMI, in a machine-specific way
> + * @errp: pointer to error object
> + *
> + * This function triggers an NMI, in a machine-specific way. The
> + * intention is that this should typically trigger a guest kernel
> + * dump or reboot, and might happen as a result of user request
> + * from the monitor, watchdog timeouts, and similar events.
> + * (For example on the x86 PC it triggers an NMI on all CPUs,
> + * and on s390 it triggers the RESTART interrupt on the first CPU.)
> + *
> + * The NMI is triggered by looking for QOM objects which
> + * implement the TYPE_NMI interface, and calling their nmi_handler
> + * method. Usually it is the machine model class that implements
> + * this interface.
> + *
> + * Not all machines implement NMI handling; this function
> + * will return an error if used on a machine which does not
> + * implement NMIs.
> + *
> + * On success, return %true.
> + * On failure, store an error through @errp and return %false.
> + */
> +bool nmi_trigger(Error **errp);
>
> #endif /* NMI_H */
> diff --git a/hw/core/nmi.c b/hw/core/nmi.c
> index ff6454437c1..662f2051123 100644
> --- a/hw/core/nmi.c
> +++ b/hw/core/nmi.c
> @@ -22,11 +22,8 @@
> #include "qemu/osdep.h"
> #include "hw/core/nmi.h"
> #include "qapi/error.h"
> -#include "qemu/module.h"
> -#include "monitor/monitor.h"
>
> struct do_nmi_s {
> - int cpu_index;
> Error *err;
> bool handled;
> };
> @@ -54,19 +51,21 @@ static int nmi_children(Object *o, struct do_nmi_s *ns)
> return object_child_foreach_recursive(o, do_nmi, ns);
> }
>
> -void nmi_monitor_handle(int cpu_index, Error **errp)
> +bool nmi_trigger(Error **errp)
> {
> struct do_nmi_s ns = {
> - .cpu_index = cpu_index,
> .err = NULL,
> .handled = false
> };
>
> if (nmi_children(object_get_root(), &ns)) {
> error_propagate(errp, ns.err);
> + return false;
> } else if (!ns.handled) {
> error_setg(errp, "machine does not provide NMIs");
> + return false;
> }
> + return true;
> }
>
> static const TypeInfo nmi_info = {
> diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c
> index 74818ff3cea..444af726d75 100644
> --- a/hw/ipmi/ipmi.c
> +++ b/hw/ipmi/ipmi.c
> @@ -59,8 +59,7 @@ static int ipmi_do_hw_op(IPMIInterface *s, enum ipmi_op op, int checkonly)
> if (checkonly) {
> return 0;
> }
> - /* We don't care what CPU we use. */
> - nmi_monitor_handle(0, NULL);
> + nmi_trigger(NULL);
> return 0;
>
> case IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP:
> diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
> index 0842fe373ae..026768e9fb2 100644
> --- a/hw/watchdog/watchdog.c
> +++ b/hw/watchdog/watchdog.c
> @@ -81,7 +81,7 @@ void watchdog_perform_action(void)
>
> case WATCHDOG_ACTION_INJECT_NMI:
> qapi_event_send_watchdog(WATCHDOG_ACTION_INJECT_NMI);
> - nmi_monitor_handle(0, NULL);
> + nmi_trigger(NULL);
> break;
>
> default:
> diff --git a/system/cpus.c b/system/cpus.c
> index 97e5a5edee2..5c0a192c01e 100644
> --- a/system/cpus.c
> +++ b/system/cpus.c
> @@ -926,6 +926,6 @@ exit:
>
> void qmp_inject_nmi(Error **errp)
> {
> - nmi_monitor_handle(monitor_get_cpu_index(monitor_cur()), errp);
> + nmi_trigger(errp);
> }
This officially drops the current CPU for HMP command too. Just
acknowledge it in the commit message, and remove the "*cpu*"
documentation in hmp-commands.hx?
Also, can we use one word for "deliver", "trigger", "inject"? or is
there any distinction I am missing?
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 3/7] hw/nmi: Remove @cpu_index argument from NMIClass::nmi_monitor_handler()
2026-08-11 10:54 ` [PATCH v3 3/7] hw/nmi: Remove @cpu_index argument from NMIClass::nmi_monitor_handler() Philippe Mathieu-Daudé
@ 2026-08-11 13:21 ` Peter Maydell
0 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2026-08-11 13:21 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: qemu-devel, Marc-André Lureau, qemu-s390x,
Dr. David Alan Gilbert, Thomas Huth, qemu-ppc, Corey Minyard,
Markus Armbruster, Philippe Mathieu-Daudé, Richard Henderson,
Helge Deller, Paolo Bonzini, Michael S. Tsirkin, Laurent Vivier,
Mark Cave-Ayland, Nicholas Piggin, Aditya Gupta, Glenn Miles,
Harsh Prateek Bora, Ilya Leoshkevich, David Hildenbrand,
Halil Pasic, Christian Borntraeger, Eric Farman, Matthew Rosato,
Cornelia Huck
On Tue, 11 Aug 2026 at 11:56, Philippe Mathieu-Daudé
<philmd@oss.qualcomm.com> wrote:
>
> From: Philippe Mathieu-Daudé <philmd@linaro.org>
>
> Only s390x was using the 'cpu_index' argument, but since the
> previous commit it isn't anymore (it use the first cpu).
> Since this argument is now completely unused, remove it.
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
> ---
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
thanks
-- PMM
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 6/7] hw/nmi: Remove unused @errp argument from deliver_nmi()
2026-08-11 10:54 ` [PATCH v3 6/7] hw/nmi: Remove unused @errp argument from deliver_nmi() Philippe Mathieu-Daudé
@ 2026-08-11 13:24 ` Peter Maydell
0 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2026-08-11 13:24 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: qemu-devel, Marc-André Lureau, qemu-s390x,
Dr. David Alan Gilbert, Thomas Huth, qemu-ppc, Corey Minyard,
Markus Armbruster, Richard Henderson, Helge Deller,
Michael S. Tsirkin, Paolo Bonzini, Laurent Vivier,
Mark Cave-Ayland, Nicholas Piggin, Aditya Gupta, Glenn Miles,
Harsh Prateek Bora, Cornelia Huck, Eric Farman, Matthew Rosato,
Halil Pasic, Christian Borntraeger, Ilya Leoshkevich,
David Hildenbrand
On Tue, 11 Aug 2026 at 11:56, Philippe Mathieu-Daudé
<philmd@oss.qualcomm.com> wrote:
>
> Not a single handler update @errp. The single user is
> nmi_trigger() filling with "machine does not provide NMIs".
> Remove the unused argument from the deliver_nmi() callback,
> simplifying the methods in hw/core/nmi.c.
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
> ---
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
thanks
-- PMM
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 7/7] hw/nmi: Deliver NMI only once
2026-08-11 10:54 ` [PATCH v3 7/7] hw/nmi: Deliver NMI only once Philippe Mathieu-Daudé
@ 2026-08-11 13:34 ` Peter Maydell
2026-08-11 14:09 ` Philippe Mathieu-Daudé
0 siblings, 1 reply; 14+ messages in thread
From: Peter Maydell @ 2026-08-11 13:34 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: qemu-devel, Marc-André Lureau, qemu-s390x,
Dr. David Alan Gilbert, Thomas Huth, qemu-ppc, Corey Minyard,
Markus Armbruster
On Tue, 11 Aug 2026 at 11:55, Philippe Mathieu-Daudé
<philmd@oss.qualcomm.com> wrote:
>
> Use the first handler available to deliver NMI only once.
> If anothers handlers are available, no need to keep delivering.
>
> Suggested-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
> ---
> hw/core/nmi.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/hw/core/nmi.c b/hw/core/nmi.c
> index 8eea75ad530..4fe5ee75bfc 100644
> --- a/hw/core/nmi.c
> +++ b/hw/core/nmi.c
> @@ -31,6 +31,8 @@ static int do_nmi(Object *o, void *opaque)
> if (n) {
> *handled = true;
> NMI_GET_CLASS(n)->deliver_nmi(n);
> + /* We only need to deliver NMI once */
> + return 1;
> }
>
> return 0;
Looking back at my review comments on v1 of this series,
I think we could clarify the comment / commit message a bit.
Commit message:
We only expect one device in the system to implement the
TYPE_NMI interface (typically the machine, but in a few cases
for e.g. m68k and ppc this is an interrupt controller or
similar device); so we don't need to keep walking the whole
QOM tree once we've found it. As no machine type creates more
than one object implementing TYPE_NMI, this is not a behaviour
change.
and comment:
/*
* We expect only one object to implement TYPE_NMI, so once
* we've asked it to deliver the NMI we can stop looking.
*/
With that
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
thanks
-- PMM
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 4/7] hw/nmi: Remove @cpu_index argument from nmi_trigger()
2026-08-11 11:10 ` Marc-André Lureau
@ 2026-08-11 13:55 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-11 13:55 UTC (permalink / raw)
To: Marc-André Lureau
Cc: qemu-devel, qemu-s390x, Dr. David Alan Gilbert, Thomas Huth,
qemu-ppc, Corey Minyard, Markus Armbruster,
Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini,
Philippe Mathieu-Daudé
On 11/8/26 13:10, Marc-André Lureau wrote:
> Hi
>
> On Tue, Aug 11, 2026 at 2:55 PM Philippe Mathieu-Daudé
> <philmd@oss.qualcomm.com> wrote:
>>
>> From: Philippe Mathieu-Daudé <philmd@linaro.org>
>>
>> nmi_monitor_handle() is not related to the monitor, rename
>> it as nmi_trigger().
>>
>> Return a boolean value indicating success / failure as
>> recommended by the Error API since commit e3fe3988d7
>> ("error: Document Error API usage rules").
>>
>> The 'cpu_index' argument is not used, remove it.
>>
>> Document nmi_trigger() as suggested by Peter Maydell in
>> https://lore.kernel.org/qemu-devel/CAFEAcA-yALySmCJLbitCmYpiZKUXJNOavGJG9RYeo8fKqz7gcw@mail.gmail.com/.
>>
>> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
>> ---
>> include/hw/core/nmi.h | 25 ++++++++++++++++++++++++-
>> hw/core/nmi.c | 9 ++++-----
>> hw/ipmi/ipmi.c | 3 +--
>> hw/watchdog/watchdog.c | 2 +-
>> system/cpus.c | 2 +-
>> 5 files changed, 31 insertions(+), 10 deletions(-)
>> -void nmi_monitor_handle(int cpu_index, Error **errp);
>> +/**
>> + * nmi_trigger: Trigger an NMI, in a machine-specific way
>> + * @errp: pointer to error object
>> + *
>> + * This function triggers an NMI, in a machine-specific way. The
>> + * intention is that this should typically trigger a guest kernel
>> + * dump or reboot, and might happen as a result of user request
>> + * from the monitor, watchdog timeouts, and similar events.
>> + * (For example on the x86 PC it triggers an NMI on all CPUs,
>> + * and on s390 it triggers the RESTART interrupt on the first CPU.)
>> + *
>> + * The NMI is triggered by looking for QOM objects which
>> + * implement the TYPE_NMI interface, and calling their nmi_handler
>> + * method. Usually it is the machine model class that implements
>> + * this interface.
>> + *
>> + * Not all machines implement NMI handling; this function
>> + * will return an error if used on a machine which does not
>> + * implement NMIs.
>> + *
>> + * On success, return %true.
>> + * On failure, store an error through @errp and return %false.
>> + */
>> +bool nmi_trigger(Error **errp);
>> -void nmi_monitor_handle(int cpu_index, Error **errp)
>> +bool nmi_trigger(Error **errp)
>> {
>> struct do_nmi_s ns = {
>> - .cpu_index = cpu_index,
>> .err = NULL,
>> .handled = false
>> };
>>
>> if (nmi_children(object_get_root(), &ns)) {
>> error_propagate(errp, ns.err);
>> + return false;
>> } else if (!ns.handled) {
>> error_setg(errp, "machine does not provide NMIs");
>> + return false;
>> }
>> + return true;
>> }
>>
>> static const TypeInfo nmi_info = {
>> diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c
>> index 74818ff3cea..444af726d75 100644
>> --- a/hw/ipmi/ipmi.c
>> +++ b/hw/ipmi/ipmi.c
>> @@ -59,8 +59,7 @@ static int ipmi_do_hw_op(IPMIInterface *s, enum ipmi_op op, int checkonly)
>> if (checkonly) {
>> return 0;
>> }
>> - /* We don't care what CPU we use. */
>> - nmi_monitor_handle(0, NULL);
>> + nmi_trigger(NULL);
>> return 0;
>>
>> case IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP:
>> diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
>> index 0842fe373ae..026768e9fb2 100644
>> --- a/hw/watchdog/watchdog.c
>> +++ b/hw/watchdog/watchdog.c
>> @@ -81,7 +81,7 @@ void watchdog_perform_action(void)
>>
>> case WATCHDOG_ACTION_INJECT_NMI:
>> qapi_event_send_watchdog(WATCHDOG_ACTION_INJECT_NMI);
>> - nmi_monitor_handle(0, NULL);
>> + nmi_trigger(NULL);
>> break;
>>
>> default:
>> diff --git a/system/cpus.c b/system/cpus.c
>> index 97e5a5edee2..5c0a192c01e 100644
>> --- a/system/cpus.c
>> +++ b/system/cpus.c
>> @@ -926,6 +926,6 @@ exit:
>>
>> void qmp_inject_nmi(Error **errp)
>> {
>> - nmi_monitor_handle(monitor_get_cpu_index(monitor_cur()), errp);
>> + nmi_trigger(errp);
>> }
>
> This officially drops the current CPU for HMP command too. Just
> acknowledge it in the commit message, and remove the "*cpu*"
> documentation in hmp-commands.hx?
Ack.
>
> Also, can we use one word for "deliver", "trigger", "inject"? or is
> there any distinction I am missing?
Hmm indeed from the monitor perspective we "inject" a NMI.
Watchdog seems to also "inject" with WATCHDOG_ACTION_INJECT_NMI
(here my understanding is "raise", but whatever).
I suppose IPMI devices also "raise", but "inject" is acceptable.
$ git grep deliver_nmi
hw/i386/x86.c:159: apic_deliver_nmi(cpu->apic_state);
hw/intc/apic_common.c:122:void apic_deliver_nmi(APICCommonState *s)
include/hw/i386/apic.h:10:void apic_deliver_nmi(APICCommonState *s);
The NMIClass handler then "route" or "deliver" it.
I'll rename as 'nmi_inject' I suppose, better to keep in pair with
the QMP command name.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 7/7] hw/nmi: Deliver NMI only once
2026-08-11 13:34 ` Peter Maydell
@ 2026-08-11 14:09 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 14+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-11 14:09 UTC (permalink / raw)
To: Peter Maydell
Cc: qemu-devel, Marc-André Lureau, qemu-s390x,
Dr. David Alan Gilbert, Thomas Huth, qemu-ppc, Corey Minyard,
Markus Armbruster
On 11/8/26 15:34, Peter Maydell wrote:
> On Tue, 11 Aug 2026 at 11:55, Philippe Mathieu-Daudé
> <philmd@oss.qualcomm.com> wrote:
>>
>> Use the first handler available to deliver NMI only once.
>> If anothers handlers are available, no need to keep delivering.
>>
>> Suggested-by: Peter Maydell <peter.maydell@linaro.org>
>> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
>> ---
>> hw/core/nmi.c | 2 ++
>> 1 file changed, 2 insertions(+)
>>
>> diff --git a/hw/core/nmi.c b/hw/core/nmi.c
>> index 8eea75ad530..4fe5ee75bfc 100644
>> --- a/hw/core/nmi.c
>> +++ b/hw/core/nmi.c
>> @@ -31,6 +31,8 @@ static int do_nmi(Object *o, void *opaque)
>> if (n) {
>> *handled = true;
>> NMI_GET_CLASS(n)->deliver_nmi(n);
>> + /* We only need to deliver NMI once */
>> + return 1;
>> }
>>
>> return 0;
>
> Looking back at my review comments on v1 of this series,
> I think we could clarify the comment / commit message a bit.
> Commit message:
>
> We only expect one device in the system to implement the
> TYPE_NMI interface (typically the machine, but in a few cases
> for e.g. m68k and ppc this is an interrupt controller or
> similar device); so we don't need to keep walking the whole
> QOM tree once we've found it. As no machine type creates more
> than one object implementing TYPE_NMI, this is not a behaviour
> change.
>
> and comment:
>
> /*
> * We expect only one object to implement TYPE_NMI, so once
> * we've asked it to deliver the NMI we can stop looking.
> */
>
> With that
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Thanks for the wording help!
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-08-11 14:09 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-11 10:54 [PATCH v3 0/7] hw/nmi: Disconnect of vCPU and disentangle Monitor code Philippe Mathieu-Daudé
2026-08-11 10:54 ` [PATCH v3 1/7] hw/nmi: Use object_child_foreach_recursive() in nmi_children() Philippe Mathieu-Daudé
2026-08-11 10:54 ` [PATCH v3 2/7] hw/s390x/virtio-ccw: Always deliver NMI to first CPU Philippe Mathieu-Daudé
2026-08-11 10:54 ` [PATCH v3 3/7] hw/nmi: Remove @cpu_index argument from NMIClass::nmi_monitor_handler() Philippe Mathieu-Daudé
2026-08-11 13:21 ` Peter Maydell
2026-08-11 10:54 ` [PATCH v3 4/7] hw/nmi: Remove @cpu_index argument from nmi_trigger() Philippe Mathieu-Daudé
2026-08-11 11:10 ` Marc-André Lureau
2026-08-11 13:55 ` Philippe Mathieu-Daudé
2026-08-11 10:54 ` [PATCH v3 5/7] hw/nmi: Rename nmi_monitor_handler() -> deliver_nmi() Philippe Mathieu-Daudé
2026-08-11 10:54 ` [PATCH v3 6/7] hw/nmi: Remove unused @errp argument from deliver_nmi() Philippe Mathieu-Daudé
2026-08-11 13:24 ` Peter Maydell
2026-08-11 10:54 ` [PATCH v3 7/7] hw/nmi: Deliver NMI only once Philippe Mathieu-Daudé
2026-08-11 13:34 ` Peter Maydell
2026-08-11 14:09 ` Philippe Mathieu-Daudé
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.