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 "hw/nmi.h" 24 #include "qapi/qmp/qerror.h" 25 #include "monitor/monitor.h" 26 27 struct do_nmi_s { 28 int cpu_index; 29 Error *err; 30 bool handled; 31 }; 32 33 static void nmi_children(Object *o, struct do_nmi_s *ns); 34 35 static int do_nmi(Object *o, void *opaque) 36 { 37 struct do_nmi_s *ns = opaque; 38 NMIState *n = (NMIState *) object_dynamic_cast(o, TYPE_NMI); 39 40 if (n) { 41 NMIClass *nc = NMI_GET_CLASS(n); 42 43 ns->handled = true; 44 nc->nmi_monitor_handler(n, ns->cpu_index, &ns->err); 45 if (ns->err) { 46 return -1; 47 } 48 } 49 nmi_children(o, ns); 50 51 return 0; 52 } 53 54 static void nmi_children(Object *o, struct do_nmi_s *ns) 55 { 56 object_child_foreach(o, do_nmi, ns); 57 } 58 59 void nmi_monitor_handle(int cpu_index, Error **errp) 60 { 61 struct do_nmi_s ns = { 62 .cpu_index = cpu_index, 63 .err = NULL, 64 .handled = false 65 }; 66 67 nmi_children(object_get_root(), &ns); 68 if (ns.handled) { 69 error_propagate(errp, ns.err); 70 } else { 71 error_setg(errp, QERR_UNSUPPORTED); 72 } 73 } 74 75 void inject_nmi(void) 76 { 77 #if defined(TARGET_I386) 78 CPUState *cs; 79 80 CPU_FOREACH(cs) { 81 X86CPU *cpu = X86_CPU(cs); 82 83 if (!cpu->apic_state) { 84 cpu_interrupt(cs, CPU_INTERRUPT_NMI); 85 } else { 86 apic_deliver_nmi(cpu->apic_state); 87 } 88 } 89 #else 90 nmi_monitor_handle(0, NULL); 91 #endif 92 } 93 94 static const TypeInfo nmi_info = { 95 .name = TYPE_NMI, 96 .parent = TYPE_INTERFACE, 97 .class_size = sizeof(NMIClass), 98 }; 99 100 static void nmi_register_types(void) 101 { 102 type_register_static(&nmi_info); 103 } 104 105 type_init(nmi_register_types) 106