This implements an NMI interface for i386 PC machines. This removes #ifdef I386 branch in qmp_inject_nmi so new i386's nmi() callback is going to be used for NMI.
This changes code to inject NMI on the current CPU instead of injecting it on every CPU. However that does not seem to be an issue. Since kvm_apic_external_nmi() takes care of preforming operations in the specific CPU thread so no extra measure is required here. Signed-off-by: Alexey Kardashevskiy <a...@ozlabs.ru> Reviewed-by: Alexander Graf <ag...@suse.de> --- Changes: v6: * make use of NMI interface v5: * make use of NMI interface v4: * s/\<nmi\>/nmi_monitor_handler/ v3: * now contains both old code removal and new code insertion, easier to track changes * fixed compile for linux-user --- cpus.c | 14 -------------- hw/i386/pc_piix.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/cpus.c b/cpus.c index eb1ac85..f57fe5f 100644 --- a/cpus.c +++ b/cpus.c @@ -1525,21 +1525,7 @@ exit: void qmp_inject_nmi(Error **errp) { -#if defined(TARGET_I386) - CPUState *cs; - - CPU_FOREACH(cs) { - X86CPU *cpu = X86_CPU(cs); - - if (!cpu->apic_state) { - cpu_interrupt(cs, CPU_INTERRUPT_NMI); - } else { - apic_deliver_nmi(cpu->apic_state); - } - } -#else nmi_monitor_handle(monitor_get_cpu_index(), errp); -#endif } void dump_drift_info(FILE *f, fprintf_function cpu_fprintf) diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 4f22be8..125e609 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -49,11 +49,13 @@ #include "hw/acpi/acpi.h" #include "cpu.h" #include "qemu/error-report.h" +#include "hw/nmi.h" #ifdef CONFIG_XEN # include <xen/hvm/hvm_info_table.h> #endif #define MAX_IDE_BUS 2 +#define TYPE_NMI_X86 "x86-nmi" static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 }; static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 }; @@ -297,6 +299,9 @@ static void pc_init1(MachineState *machine, if (pci_enabled) { pc_pci_device_init(pci_bus); } + + object_property_add_child(OBJECT(machine), "nmi", + object_new(TYPE_NMI_X86), NULL); } static void pc_init_pci(MachineState *machine) @@ -926,3 +931,40 @@ static void pc_machine_init(void) } machine_init(pc_machine_init); + +static void x86_nmi(NMIState *n, int cpu_index, Error **errp) +{ + CPUState *cs = qemu_get_cpu(cpu_index); + X86CPU *cpu = X86_CPU(cs); + + if (!cpu->apic_state) { + cpu_interrupt(cs, CPU_INTERRUPT_NMI); +#ifndef CONFIG_USER_ONLY + } else { + apic_deliver_nmi(cpu->apic_state); +#endif + } +} + +static void x86_nmi_class_init(ObjectClass *oc, void *data) +{ + NMIClass *nc = NMI_CLASS(oc); + nc->nmi_monitor_handler = x86_nmi; +} + +static const TypeInfo x86_nmi_info = { + .name = TYPE_NMI_X86, + .parent = TYPE_OBJECT, + .class_init = x86_nmi_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_NMI }, + { } + }, +}; + +static void x86_nmi_register_types(void) +{ + type_register_static(&x86_nmi_info); +} + +type_init(x86_nmi_register_types) -- 2.0.0