1244ac3afSJan Kiszka /* 2244ac3afSJan Kiszka * IOAPIC emulation logic - common bits of emulated and KVM kernel model 3244ac3afSJan Kiszka * 4244ac3afSJan Kiszka * Copyright (c) 2004-2005 Fabrice Bellard 5244ac3afSJan Kiszka * Copyright (c) 2009 Xiantao Zhang, Intel 6244ac3afSJan Kiszka * Copyright (c) 2011 Jan Kiszka, Siemens AG 7244ac3afSJan Kiszka * 8244ac3afSJan Kiszka * This library is free software; you can redistribute it and/or 9244ac3afSJan Kiszka * modify it under the terms of the GNU Lesser General Public 10244ac3afSJan Kiszka * License as published by the Free Software Foundation; either 11244ac3afSJan Kiszka * version 2 of the License, or (at your option) any later version. 12244ac3afSJan Kiszka * 13244ac3afSJan Kiszka * This library is distributed in the hope that it will be useful, 14244ac3afSJan Kiszka * but WITHOUT ANY WARRANTY; without even the implied warranty of 15244ac3afSJan Kiszka * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16244ac3afSJan Kiszka * Lesser General Public License for more details. 17244ac3afSJan Kiszka * 18244ac3afSJan Kiszka * You should have received a copy of the GNU Lesser General Public 19244ac3afSJan Kiszka * License along with this library; if not, see <http://www.gnu.org/licenses/>. 20244ac3afSJan Kiszka */ 21244ac3afSJan Kiszka 22b6a0aa05SPeter Maydell #include "qemu/osdep.h" 23da34e65cSMarkus Armbruster #include "qapi/error.h" 24d665d696SPavel Butsykin #include "monitor/monitor.h" 250d09e41aSPaolo Bonzini #include "hw/i386/ioapic.h" 260d09e41aSPaolo Bonzini #include "hw/i386/ioapic_internal.h" 274a499ad2SPeter Xu #include "hw/intc/intc.h" 2883c9f4caSPaolo Bonzini #include "hw/sysbus.h" 29244ac3afSJan Kiszka 30db0f8888Sxiaoqiang zhao /* ioapic_no count start from 0 to MAX_IOAPICS, 31db0f8888Sxiaoqiang zhao * remove as static variable from ioapic_common_init. 32db0f8888Sxiaoqiang zhao * now as a global variable, let child to increase the counter 33db0f8888Sxiaoqiang zhao * then we can drop the 'instance_no' argument 34db0f8888Sxiaoqiang zhao * and convert to our QOM's realize function 35db0f8888Sxiaoqiang zhao */ 36db0f8888Sxiaoqiang zhao int ioapic_no; 37db0f8888Sxiaoqiang zhao 38d665d696SPavel Butsykin static void ioapic_irr_dump(Monitor *mon, const char *name, uint32_t bitmap) 39d665d696SPavel Butsykin { 40d665d696SPavel Butsykin int i; 41d665d696SPavel Butsykin 42d665d696SPavel Butsykin monitor_printf(mon, "%-10s ", name); 43d665d696SPavel Butsykin if (bitmap == 0) { 44d665d696SPavel Butsykin monitor_printf(mon, "(none)\n"); 45d665d696SPavel Butsykin return; 46d665d696SPavel Butsykin } 47d665d696SPavel Butsykin for (i = 0; i < IOAPIC_NUM_PINS; i++) { 48d665d696SPavel Butsykin if (bitmap & (1 << i)) { 49d665d696SPavel Butsykin monitor_printf(mon, "%-2u ", i); 50d665d696SPavel Butsykin } 51d665d696SPavel Butsykin } 52d665d696SPavel Butsykin monitor_printf(mon, "\n"); 53d665d696SPavel Butsykin } 54d665d696SPavel Butsykin 55d665d696SPavel Butsykin void ioapic_print_redtbl(Monitor *mon, IOAPICCommonState *s) 56d665d696SPavel Butsykin { 57d665d696SPavel Butsykin static const char *delm_str[] = { 58d665d696SPavel Butsykin "fixed", "lowest", "SMI", "...", "NMI", "INIT", "...", "extINT"}; 59d665d696SPavel Butsykin uint32_t remote_irr = 0; 60d665d696SPavel Butsykin int i; 61d665d696SPavel Butsykin 62*6a218b03SPeter Xu monitor_printf(mon, "ioapic0: ver=0x%x id=0x%02x sel=0x%02x", 638b77709cSPeter Xu s->version, s->id, s->ioregsel); 64d665d696SPavel Butsykin if (s->ioregsel) { 65d665d696SPavel Butsykin monitor_printf(mon, " (redir[%u])\n", 66d665d696SPavel Butsykin (s->ioregsel - IOAPIC_REG_REDTBL_BASE) >> 1); 67d665d696SPavel Butsykin } else { 68d665d696SPavel Butsykin monitor_printf(mon, "\n"); 69d665d696SPavel Butsykin } 70d665d696SPavel Butsykin for (i = 0; i < IOAPIC_NUM_PINS; i++) { 71d665d696SPavel Butsykin uint64_t entry = s->ioredtbl[i]; 72d665d696SPavel Butsykin uint32_t delm = (uint32_t)((entry & IOAPIC_LVT_DELIV_MODE) >> 73d665d696SPavel Butsykin IOAPIC_LVT_DELIV_MODE_SHIFT); 74d665d696SPavel Butsykin monitor_printf(mon, " pin %-2u 0x%016"PRIx64" dest=%"PRIx64 75d665d696SPavel Butsykin " vec=%-3"PRIu64" %s %-5s %-6s %-6s %s\n", 76d665d696SPavel Butsykin i, entry, 77d665d696SPavel Butsykin (entry >> IOAPIC_LVT_DEST_SHIFT) & 78d665d696SPavel Butsykin (entry & IOAPIC_LVT_DEST_MODE ? 0xff : 0xf), 79d665d696SPavel Butsykin entry & IOAPIC_VECTOR_MASK, 80d665d696SPavel Butsykin entry & IOAPIC_LVT_POLARITY ? "active-lo" : "active-hi", 81d665d696SPavel Butsykin entry & IOAPIC_LVT_TRIGGER_MODE ? "level" : "edge", 82d665d696SPavel Butsykin entry & IOAPIC_LVT_MASKED ? "masked" : "", 83d665d696SPavel Butsykin delm_str[delm], 84d665d696SPavel Butsykin entry & IOAPIC_LVT_DEST_MODE ? "logical" : "physical"); 85d665d696SPavel Butsykin 86d665d696SPavel Butsykin remote_irr |= entry & IOAPIC_LVT_TRIGGER_MODE ? 87d665d696SPavel Butsykin (entry & IOAPIC_LVT_REMOTE_IRR ? (1 << i) : 0) : 0; 88d665d696SPavel Butsykin } 89d665d696SPavel Butsykin ioapic_irr_dump(mon, " IRR", s->irr); 90d665d696SPavel Butsykin ioapic_irr_dump(mon, " Remote IRR", remote_irr); 91d665d696SPavel Butsykin } 92d665d696SPavel Butsykin 93244ac3afSJan Kiszka void ioapic_reset_common(DeviceState *dev) 94244ac3afSJan Kiszka { 95999e12bbSAnthony Liguori IOAPICCommonState *s = IOAPIC_COMMON(dev); 96244ac3afSJan Kiszka int i; 97244ac3afSJan Kiszka 98244ac3afSJan Kiszka s->id = 0; 99244ac3afSJan Kiszka s->ioregsel = 0; 100244ac3afSJan Kiszka s->irr = 0; 101244ac3afSJan Kiszka for (i = 0; i < IOAPIC_NUM_PINS; i++) { 102244ac3afSJan Kiszka s->ioredtbl[i] = 1 << IOAPIC_LVT_MASKED_SHIFT; 103244ac3afSJan Kiszka } 104244ac3afSJan Kiszka } 105244ac3afSJan Kiszka 10644b1ff31SDr. David Alan Gilbert static int ioapic_dispatch_pre_save(void *opaque) 107244ac3afSJan Kiszka { 108999e12bbSAnthony Liguori IOAPICCommonState *s = IOAPIC_COMMON(opaque); 109999e12bbSAnthony Liguori IOAPICCommonClass *info = IOAPIC_COMMON_GET_CLASS(s); 110244ac3afSJan Kiszka 111244ac3afSJan Kiszka if (info->pre_save) { 112244ac3afSJan Kiszka info->pre_save(s); 113244ac3afSJan Kiszka } 11444b1ff31SDr. David Alan Gilbert 11544b1ff31SDr. David Alan Gilbert return 0; 116244ac3afSJan Kiszka } 117244ac3afSJan Kiszka 118244ac3afSJan Kiszka static int ioapic_dispatch_post_load(void *opaque, int version_id) 119244ac3afSJan Kiszka { 120999e12bbSAnthony Liguori IOAPICCommonState *s = IOAPIC_COMMON(opaque); 121999e12bbSAnthony Liguori IOAPICCommonClass *info = IOAPIC_COMMON_GET_CLASS(s); 122244ac3afSJan Kiszka 123244ac3afSJan Kiszka if (info->post_load) { 124244ac3afSJan Kiszka info->post_load(s); 125244ac3afSJan Kiszka } 126244ac3afSJan Kiszka return 0; 127244ac3afSJan Kiszka } 128244ac3afSJan Kiszka 129f5ba7523SHu Tao static void ioapic_common_realize(DeviceState *dev, Error **errp) 130244ac3afSJan Kiszka { 131f16a69f7SIgor Mammedov IOAPICCommonState *s = IOAPIC_COMMON(dev); 132999e12bbSAnthony Liguori IOAPICCommonClass *info; 133244ac3afSJan Kiszka 134244ac3afSJan Kiszka if (ioapic_no >= MAX_IOAPICS) { 135f5ba7523SHu Tao error_setg(errp, "Only %d ioapics allowed", MAX_IOAPICS); 136f5ba7523SHu Tao return; 137244ac3afSJan Kiszka } 138244ac3afSJan Kiszka 139999e12bbSAnthony Liguori info = IOAPIC_COMMON_GET_CLASS(s); 140db0f8888Sxiaoqiang zhao info->realize(dev, errp); 141244ac3afSJan Kiszka 142f5ba7523SHu Tao sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->io_memory); 143244ac3afSJan Kiszka ioapic_no++; 144244ac3afSJan Kiszka } 145244ac3afSJan Kiszka 1464a499ad2SPeter Xu static void ioapic_print_info(InterruptStatsProvider *obj, 1474a499ad2SPeter Xu Monitor *mon) 1484a499ad2SPeter Xu { 1494a499ad2SPeter Xu IOAPICCommonState *s = IOAPIC_COMMON(obj); 1504a499ad2SPeter Xu 1514a499ad2SPeter Xu ioapic_dispatch_pre_save(s); 1524a499ad2SPeter Xu ioapic_print_redtbl(mon, s); 1534a499ad2SPeter Xu } 1544a499ad2SPeter Xu 155244ac3afSJan Kiszka static const VMStateDescription vmstate_ioapic_common = { 156244ac3afSJan Kiszka .name = "ioapic", 157244ac3afSJan Kiszka .version_id = 3, 158244ac3afSJan Kiszka .minimum_version_id = 1, 159244ac3afSJan Kiszka .pre_save = ioapic_dispatch_pre_save, 160244ac3afSJan Kiszka .post_load = ioapic_dispatch_post_load, 161244ac3afSJan Kiszka .fields = (VMStateField[]) { 162244ac3afSJan Kiszka VMSTATE_UINT8(id, IOAPICCommonState), 163244ac3afSJan Kiszka VMSTATE_UINT8(ioregsel, IOAPICCommonState), 164244ac3afSJan Kiszka VMSTATE_UNUSED_V(2, 8), /* to account for qemu-kvm's v2 format */ 165244ac3afSJan Kiszka VMSTATE_UINT32_V(irr, IOAPICCommonState, 2), 166244ac3afSJan Kiszka VMSTATE_UINT64_ARRAY(ioredtbl, IOAPICCommonState, IOAPIC_NUM_PINS), 167244ac3afSJan Kiszka VMSTATE_END_OF_LIST() 168244ac3afSJan Kiszka } 169244ac3afSJan Kiszka }; 170244ac3afSJan Kiszka 171999e12bbSAnthony Liguori static void ioapic_common_class_init(ObjectClass *klass, void *data) 172244ac3afSJan Kiszka { 17339bffca2SAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 1744a499ad2SPeter Xu InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(klass); 175999e12bbSAnthony Liguori 176f5ba7523SHu Tao dc->realize = ioapic_common_realize; 17739bffca2SAnthony Liguori dc->vmsd = &vmstate_ioapic_common; 1784a499ad2SPeter Xu ic->print_info = ioapic_print_info; 179244ac3afSJan Kiszka } 180999e12bbSAnthony Liguori 1818c43a6f0SAndreas Färber static const TypeInfo ioapic_common_type = { 182999e12bbSAnthony Liguori .name = TYPE_IOAPIC_COMMON, 183999e12bbSAnthony Liguori .parent = TYPE_SYS_BUS_DEVICE, 184999e12bbSAnthony Liguori .instance_size = sizeof(IOAPICCommonState), 185999e12bbSAnthony Liguori .class_size = sizeof(IOAPICCommonClass), 186999e12bbSAnthony Liguori .class_init = ioapic_common_class_init, 187999e12bbSAnthony Liguori .abstract = true, 1884a499ad2SPeter Xu .interfaces = (InterfaceInfo[]) { 1894a499ad2SPeter Xu { TYPE_INTERRUPT_STATS_PROVIDER }, 1904a499ad2SPeter Xu { } 1914a499ad2SPeter Xu }, 192999e12bbSAnthony Liguori }; 193999e12bbSAnthony Liguori 194f9771858Sxiaoqiang zhao static void ioapic_common_register_types(void) 195999e12bbSAnthony Liguori { 196999e12bbSAnthony Liguori type_register_static(&ioapic_common_type); 197999e12bbSAnthony Liguori } 198999e12bbSAnthony Liguori 199f9771858Sxiaoqiang zhao type_init(ioapic_common_register_types) 200