1 /* 2 * IOAPIC emulation logic - common bits of emulated and KVM kernel model 3 * 4 * Copyright (c) 2004-2005 Fabrice Bellard 5 * Copyright (c) 2009 Xiantao Zhang, Intel 6 * Copyright (c) 2011 Jan Kiszka, Siemens AG 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library 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 GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 #include "monitor/monitor.h" 23 #include "hw/i386/ioapic.h" 24 #include "hw/i386/ioapic_internal.h" 25 #include "hw/sysbus.h" 26 27 /* ioapic_no count start from 0 to MAX_IOAPICS, 28 * remove as static variable from ioapic_common_init. 29 * now as a global variable, let child to increase the counter 30 * then we can drop the 'instance_no' argument 31 * and convert to our QOM's realize function 32 */ 33 int ioapic_no; 34 35 static void ioapic_irr_dump(Monitor *mon, const char *name, uint32_t bitmap) 36 { 37 int i; 38 39 monitor_printf(mon, "%-10s ", name); 40 if (bitmap == 0) { 41 monitor_printf(mon, "(none)\n"); 42 return; 43 } 44 for (i = 0; i < IOAPIC_NUM_PINS; i++) { 45 if (bitmap & (1 << i)) { 46 monitor_printf(mon, "%-2u ", i); 47 } 48 } 49 monitor_printf(mon, "\n"); 50 } 51 52 void ioapic_print_redtbl(Monitor *mon, IOAPICCommonState *s) 53 { 54 static const char *delm_str[] = { 55 "fixed", "lowest", "SMI", "...", "NMI", "INIT", "...", "extINT"}; 56 uint32_t remote_irr = 0; 57 int i; 58 59 monitor_printf(mon, "ioapic id=0x%02x sel=0x%02x", s->id, s->ioregsel); 60 if (s->ioregsel) { 61 monitor_printf(mon, " (redir[%u])\n", 62 (s->ioregsel - IOAPIC_REG_REDTBL_BASE) >> 1); 63 } else { 64 monitor_printf(mon, "\n"); 65 } 66 for (i = 0; i < IOAPIC_NUM_PINS; i++) { 67 uint64_t entry = s->ioredtbl[i]; 68 uint32_t delm = (uint32_t)((entry & IOAPIC_LVT_DELIV_MODE) >> 69 IOAPIC_LVT_DELIV_MODE_SHIFT); 70 monitor_printf(mon, "pin %-2u 0x%016"PRIx64" dest=%"PRIx64 71 " vec=%-3"PRIu64" %s %-5s %-6s %-6s %s\n", 72 i, entry, 73 (entry >> IOAPIC_LVT_DEST_SHIFT) & 74 (entry & IOAPIC_LVT_DEST_MODE ? 0xff : 0xf), 75 entry & IOAPIC_VECTOR_MASK, 76 entry & IOAPIC_LVT_POLARITY ? "active-lo" : "active-hi", 77 entry & IOAPIC_LVT_TRIGGER_MODE ? "level" : "edge", 78 entry & IOAPIC_LVT_MASKED ? "masked" : "", 79 delm_str[delm], 80 entry & IOAPIC_LVT_DEST_MODE ? "logical" : "physical"); 81 82 remote_irr |= entry & IOAPIC_LVT_TRIGGER_MODE ? 83 (entry & IOAPIC_LVT_REMOTE_IRR ? (1 << i) : 0) : 0; 84 } 85 ioapic_irr_dump(mon, "IRR", s->irr); 86 ioapic_irr_dump(mon, "Remote IRR", remote_irr); 87 } 88 89 void ioapic_reset_common(DeviceState *dev) 90 { 91 IOAPICCommonState *s = IOAPIC_COMMON(dev); 92 int i; 93 94 s->id = 0; 95 s->ioregsel = 0; 96 s->irr = 0; 97 for (i = 0; i < IOAPIC_NUM_PINS; i++) { 98 s->ioredtbl[i] = 1 << IOAPIC_LVT_MASKED_SHIFT; 99 } 100 } 101 102 static void ioapic_dispatch_pre_save(void *opaque) 103 { 104 IOAPICCommonState *s = IOAPIC_COMMON(opaque); 105 IOAPICCommonClass *info = IOAPIC_COMMON_GET_CLASS(s); 106 107 if (info->pre_save) { 108 info->pre_save(s); 109 } 110 } 111 112 static int ioapic_dispatch_post_load(void *opaque, int version_id) 113 { 114 IOAPICCommonState *s = IOAPIC_COMMON(opaque); 115 IOAPICCommonClass *info = IOAPIC_COMMON_GET_CLASS(s); 116 117 if (info->post_load) { 118 info->post_load(s); 119 } 120 return 0; 121 } 122 123 static void ioapic_common_realize(DeviceState *dev, Error **errp) 124 { 125 IOAPICCommonState *s = IOAPIC_COMMON(dev); 126 IOAPICCommonClass *info; 127 128 if (ioapic_no >= MAX_IOAPICS) { 129 error_setg(errp, "Only %d ioapics allowed", MAX_IOAPICS); 130 return; 131 } 132 133 info = IOAPIC_COMMON_GET_CLASS(s); 134 info->realize(dev, errp); 135 136 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->io_memory); 137 ioapic_no++; 138 } 139 140 static const VMStateDescription vmstate_ioapic_common = { 141 .name = "ioapic", 142 .version_id = 3, 143 .minimum_version_id = 1, 144 .pre_save = ioapic_dispatch_pre_save, 145 .post_load = ioapic_dispatch_post_load, 146 .fields = (VMStateField[]) { 147 VMSTATE_UINT8(id, IOAPICCommonState), 148 VMSTATE_UINT8(ioregsel, IOAPICCommonState), 149 VMSTATE_UNUSED_V(2, 8), /* to account for qemu-kvm's v2 format */ 150 VMSTATE_UINT32_V(irr, IOAPICCommonState, 2), 151 VMSTATE_UINT64_ARRAY(ioredtbl, IOAPICCommonState, IOAPIC_NUM_PINS), 152 VMSTATE_END_OF_LIST() 153 } 154 }; 155 156 static void ioapic_common_class_init(ObjectClass *klass, void *data) 157 { 158 DeviceClass *dc = DEVICE_CLASS(klass); 159 160 dc->realize = ioapic_common_realize; 161 dc->vmsd = &vmstate_ioapic_common; 162 } 163 164 static const TypeInfo ioapic_common_type = { 165 .name = TYPE_IOAPIC_COMMON, 166 .parent = TYPE_SYS_BUS_DEVICE, 167 .instance_size = sizeof(IOAPICCommonState), 168 .class_size = sizeof(IOAPICCommonClass), 169 .class_init = ioapic_common_class_init, 170 .abstract = true, 171 }; 172 173 static void ioapic_common_register_types(void) 174 { 175 type_register_static(&ioapic_common_type); 176 } 177 178 type_init(ioapic_common_register_types) 179