1 /* 2 * NMI monitor handler class and helpers. 3 * 4 * Copyright IBM Corp., 2014 5 * 6 * Author: Alexey Kardashevskiy <aik@ozlabs.ru> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, 11 * or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 #include "qemu/osdep.h" 23 #include "qom/cpu.h" 24 #include "hw/nmi.h" 25 #include "qapi/error.h" 26 #include "qapi/qmp/qerror.h" 27 #include "monitor/monitor.h" 28 29 #if defined(TARGET_I386) 30 #include "cpu.h" 31 #endif 32 33 struct do_nmi_s { 34 int cpu_index; 35 Error *err; 36 bool handled; 37 }; 38 39 static void nmi_children(Object *o, struct do_nmi_s *ns); 40 41 static int do_nmi(Object *o, void *opaque) 42 { 43 struct do_nmi_s *ns = opaque; 44 NMIState *n = (NMIState *) object_dynamic_cast(o, TYPE_NMI); 45 46 if (n) { 47 NMIClass *nc = NMI_GET_CLASS(n); 48 49 ns->handled = true; 50 nc->nmi_monitor_handler(n, ns->cpu_index, &ns->err); 51 if (ns->err) { 52 return -1; 53 } 54 } 55 nmi_children(o, ns); 56 57 return 0; 58 } 59 60 static void nmi_children(Object *o, struct do_nmi_s *ns) 61 { 62 object_child_foreach(o, do_nmi, ns); 63 } 64 65 void nmi_monitor_handle(int cpu_index, Error **errp) 66 { 67 struct do_nmi_s ns = { 68 .cpu_index = cpu_index, 69 .err = NULL, 70 .handled = false 71 }; 72 73 nmi_children(object_get_root(), &ns); 74 if (ns.handled) { 75 error_propagate(errp, ns.err); 76 } else { 77 error_setg(errp, QERR_UNSUPPORTED); 78 } 79 } 80 81 void inject_nmi(void) 82 { 83 #if defined(TARGET_I386) 84 CPUState *cs; 85 86 CPU_FOREACH(cs) { 87 X86CPU *cpu = X86_CPU(cs); 88 89 if (!cpu->apic_state) { 90 cpu_interrupt(cs, CPU_INTERRUPT_NMI); 91 } else { 92 apic_deliver_nmi(cpu->apic_state); 93 } 94 } 95 #else 96 nmi_monitor_handle(0, NULL); 97 #endif 98 } 99 100 static const TypeInfo nmi_info = { 101 .name = TYPE_NMI, 102 .parent = TYPE_INTERFACE, 103 .class_size = sizeof(NMIClass), 104 }; 105 106 static void nmi_register_types(void) 107 { 108 type_register_static(&nmi_info); 109 } 110 111 type_init(nmi_register_types) 112