19cb805fdSAlexey Kardashevskiy /* 29cb805fdSAlexey Kardashevskiy * NMI monitor handler class and helpers. 39cb805fdSAlexey Kardashevskiy * 49cb805fdSAlexey Kardashevskiy * Copyright IBM Corp., 2014 59cb805fdSAlexey Kardashevskiy * 69cb805fdSAlexey Kardashevskiy * Author: Alexey Kardashevskiy <aik@ozlabs.ru> 79cb805fdSAlexey Kardashevskiy * 89cb805fdSAlexey Kardashevskiy * This program is free software; you can redistribute it and/or modify 99cb805fdSAlexey Kardashevskiy * it under the terms of the GNU General Public License as published by 109cb805fdSAlexey Kardashevskiy * the Free Software Foundation; either version 2 of the License, 119cb805fdSAlexey Kardashevskiy * or (at your option) any later version. 129cb805fdSAlexey Kardashevskiy * 139cb805fdSAlexey Kardashevskiy * This program is distributed in the hope that it will be useful, 149cb805fdSAlexey Kardashevskiy * but WITHOUT ANY WARRANTY; without even the implied warranty of 159cb805fdSAlexey Kardashevskiy * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 169cb805fdSAlexey Kardashevskiy * GNU General Public License for more details. 179cb805fdSAlexey Kardashevskiy * 189cb805fdSAlexey Kardashevskiy * You should have received a copy of the GNU General Public License 199cb805fdSAlexey Kardashevskiy * along with this program; if not, see <http://www.gnu.org/licenses/>. 209cb805fdSAlexey Kardashevskiy */ 219cb805fdSAlexey Kardashevskiy 2218c86e2bSPeter Maydell #include "qemu/osdep.h" 239cb805fdSAlexey Kardashevskiy #include "hw/nmi.h" 24*da34e65cSMarkus Armbruster #include "qapi/error.h" 259cb805fdSAlexey Kardashevskiy #include "qapi/qmp/qerror.h" 26f9a535e0SXu Wang #include "monitor/monitor.h" 279cb805fdSAlexey Kardashevskiy 289cb805fdSAlexey Kardashevskiy struct do_nmi_s { 299cb805fdSAlexey Kardashevskiy int cpu_index; 30533fdaedSMarkus Armbruster Error *err; 319cb805fdSAlexey Kardashevskiy bool handled; 329cb805fdSAlexey Kardashevskiy }; 339cb805fdSAlexey Kardashevskiy 349cb805fdSAlexey Kardashevskiy static void nmi_children(Object *o, struct do_nmi_s *ns); 359cb805fdSAlexey Kardashevskiy 369cb805fdSAlexey Kardashevskiy static int do_nmi(Object *o, void *opaque) 379cb805fdSAlexey Kardashevskiy { 389cb805fdSAlexey Kardashevskiy struct do_nmi_s *ns = opaque; 399cb805fdSAlexey Kardashevskiy NMIState *n = (NMIState *) object_dynamic_cast(o, TYPE_NMI); 409cb805fdSAlexey Kardashevskiy 419cb805fdSAlexey Kardashevskiy if (n) { 429cb805fdSAlexey Kardashevskiy NMIClass *nc = NMI_GET_CLASS(n); 439cb805fdSAlexey Kardashevskiy 449cb805fdSAlexey Kardashevskiy ns->handled = true; 45533fdaedSMarkus Armbruster nc->nmi_monitor_handler(n, ns->cpu_index, &ns->err); 46533fdaedSMarkus Armbruster if (ns->err) { 479cb805fdSAlexey Kardashevskiy return -1; 489cb805fdSAlexey Kardashevskiy } 499cb805fdSAlexey Kardashevskiy } 509cb805fdSAlexey Kardashevskiy nmi_children(o, ns); 519cb805fdSAlexey Kardashevskiy 529cb805fdSAlexey Kardashevskiy return 0; 539cb805fdSAlexey Kardashevskiy } 549cb805fdSAlexey Kardashevskiy 559cb805fdSAlexey Kardashevskiy static void nmi_children(Object *o, struct do_nmi_s *ns) 569cb805fdSAlexey Kardashevskiy { 579cb805fdSAlexey Kardashevskiy object_child_foreach(o, do_nmi, ns); 589cb805fdSAlexey Kardashevskiy } 599cb805fdSAlexey Kardashevskiy 609cb805fdSAlexey Kardashevskiy void nmi_monitor_handle(int cpu_index, Error **errp) 619cb805fdSAlexey Kardashevskiy { 629cb805fdSAlexey Kardashevskiy struct do_nmi_s ns = { 639cb805fdSAlexey Kardashevskiy .cpu_index = cpu_index, 64533fdaedSMarkus Armbruster .err = NULL, 659cb805fdSAlexey Kardashevskiy .handled = false 669cb805fdSAlexey Kardashevskiy }; 679cb805fdSAlexey Kardashevskiy 689cb805fdSAlexey Kardashevskiy nmi_children(object_get_root(), &ns); 699cb805fdSAlexey Kardashevskiy if (ns.handled) { 70533fdaedSMarkus Armbruster error_propagate(errp, ns.err); 719cb805fdSAlexey Kardashevskiy } else { 72c6bd8c70SMarkus Armbruster error_setg(errp, QERR_UNSUPPORTED); 739cb805fdSAlexey Kardashevskiy } 749cb805fdSAlexey Kardashevskiy } 759cb805fdSAlexey Kardashevskiy 76f9a535e0SXu Wang void inject_nmi(void) 77f9a535e0SXu Wang { 78f9a535e0SXu Wang #if defined(TARGET_I386) 79f9a535e0SXu Wang CPUState *cs; 80f9a535e0SXu Wang 81f9a535e0SXu Wang CPU_FOREACH(cs) { 82f9a535e0SXu Wang X86CPU *cpu = X86_CPU(cs); 83f9a535e0SXu Wang 84f9a535e0SXu Wang if (!cpu->apic_state) { 85f9a535e0SXu Wang cpu_interrupt(cs, CPU_INTERRUPT_NMI); 86f9a535e0SXu Wang } else { 87f9a535e0SXu Wang apic_deliver_nmi(cpu->apic_state); 88f9a535e0SXu Wang } 89f9a535e0SXu Wang } 90f9a535e0SXu Wang #else 91f9a535e0SXu Wang nmi_monitor_handle(0, NULL); 92f9a535e0SXu Wang #endif 93f9a535e0SXu Wang } 94f9a535e0SXu Wang 959cb805fdSAlexey Kardashevskiy static const TypeInfo nmi_info = { 969cb805fdSAlexey Kardashevskiy .name = TYPE_NMI, 979cb805fdSAlexey Kardashevskiy .parent = TYPE_INTERFACE, 989cb805fdSAlexey Kardashevskiy .class_size = sizeof(NMIClass), 999cb805fdSAlexey Kardashevskiy }; 1009cb805fdSAlexey Kardashevskiy 1019cb805fdSAlexey Kardashevskiy static void nmi_register_types(void) 1029cb805fdSAlexey Kardashevskiy { 1039cb805fdSAlexey Kardashevskiy type_register_static(&nmi_info); 1049cb805fdSAlexey Kardashevskiy } 1059cb805fdSAlexey Kardashevskiy 1069cb805fdSAlexey Kardashevskiy type_init(nmi_register_types) 107