1610626afSaliguori /* 2610626afSaliguori * ioapic.c IOAPIC emulation logic 3610626afSaliguori * 4610626afSaliguori * Copyright (c) 2004-2005 Fabrice Bellard 5610626afSaliguori * 6610626afSaliguori * Split the ioapic logic from apic.c 7610626afSaliguori * Xiantao Zhang <xiantao.zhang@intel.com> 8610626afSaliguori * 9610626afSaliguori * This library is free software; you can redistribute it and/or 10610626afSaliguori * modify it under the terms of the GNU Lesser General Public 11610626afSaliguori * License as published by the Free Software Foundation; either 12610626afSaliguori * version 2 of the License, or (at your option) any later version. 13610626afSaliguori * 14610626afSaliguori * This library is distributed in the hope that it will be useful, 15610626afSaliguori * but WITHOUT ANY WARRANTY; without even the implied warranty of 16610626afSaliguori * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17610626afSaliguori * Lesser General Public License for more details. 18610626afSaliguori * 19610626afSaliguori * You should have received a copy of the GNU Lesser General Public 208167ee88SBlue Swirl * License along with this library; if not, see <http://www.gnu.org/licenses/>. 21610626afSaliguori */ 22610626afSaliguori 23b6a0aa05SPeter Maydell #include "qemu/osdep.h" 2420fd4b7bSPeter Xu #include "qemu/error-report.h" 256bde8fd6SPavel Butsykin #include "monitor/monitor.h" 2683c9f4caSPaolo Bonzini #include "hw/hw.h" 270d09e41aSPaolo Bonzini #include "hw/i386/pc.h" 28d613f8ccSPaolo Bonzini #include "hw/i386/apic.h" 290d09e41aSPaolo Bonzini #include "hw/i386/ioapic.h" 300d09e41aSPaolo Bonzini #include "hw/i386/ioapic_internal.h" 3115eafc2eSPaolo Bonzini #include "include/hw/pci/msi.h" 3215eafc2eSPaolo Bonzini #include "sysemu/kvm.h" 33fcf5ef2aSThomas Huth #include "target/i386/cpu.h" 34cb135f59SPeter Xu #include "hw/i386/apic-msidef.h" 35e3d9c925SPeter Xu #include "hw/i386/x86-iommu.h" 36*e5074b38SPeter Xu #include "trace.h" 37610626afSaliguori 38610626afSaliguori //#define DEBUG_IOAPIC 39610626afSaliguori 409af9b330SBlue Swirl #ifdef DEBUG_IOAPIC 419af9b330SBlue Swirl #define DPRINTF(fmt, ...) \ 429af9b330SBlue Swirl do { printf("ioapic: " fmt , ## __VA_ARGS__); } while (0) 439af9b330SBlue Swirl #else 449af9b330SBlue Swirl #define DPRINTF(fmt, ...) 459af9b330SBlue Swirl #endif 469af9b330SBlue Swirl 4715eafc2eSPaolo Bonzini #define APIC_DELIVERY_MODE_SHIFT 8 4815eafc2eSPaolo Bonzini #define APIC_POLARITY_SHIFT 14 4915eafc2eSPaolo Bonzini #define APIC_TRIG_MODE_SHIFT 15 5015eafc2eSPaolo Bonzini 51244ac3afSJan Kiszka static IOAPICCommonState *ioapics[MAX_IOAPICS]; 520280b571SJan Kiszka 53db0f8888Sxiaoqiang zhao /* global variable from ioapic_common.c */ 54db0f8888Sxiaoqiang zhao extern int ioapic_no; 55db0f8888Sxiaoqiang zhao 56c15fa0beSPeter Xu struct ioapic_entry_info { 57c15fa0beSPeter Xu /* fields parsed from IOAPIC entries */ 58c15fa0beSPeter Xu uint8_t masked; 59c15fa0beSPeter Xu uint8_t trig_mode; 60c15fa0beSPeter Xu uint16_t dest_idx; 61c15fa0beSPeter Xu uint8_t dest_mode; 62c15fa0beSPeter Xu uint8_t delivery_mode; 63c15fa0beSPeter Xu uint8_t vector; 64c15fa0beSPeter Xu 65c15fa0beSPeter Xu /* MSI message generated from above parsed fields */ 66c15fa0beSPeter Xu uint32_t addr; 67c15fa0beSPeter Xu uint32_t data; 68c15fa0beSPeter Xu }; 69c15fa0beSPeter Xu 70c15fa0beSPeter Xu static void ioapic_entry_parse(uint64_t entry, struct ioapic_entry_info *info) 71c15fa0beSPeter Xu { 72c15fa0beSPeter Xu memset(info, 0, sizeof(*info)); 73c15fa0beSPeter Xu info->masked = (entry >> IOAPIC_LVT_MASKED_SHIFT) & 1; 74c15fa0beSPeter Xu info->trig_mode = (entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1; 75c15fa0beSPeter Xu /* 76c15fa0beSPeter Xu * By default, this would be dest_id[8] + reserved[8]. When IR 77c15fa0beSPeter Xu * is enabled, this would be interrupt_index[15] + 78c15fa0beSPeter Xu * interrupt_format[1]. This field never means anything, but 79c15fa0beSPeter Xu * only used to generate corresponding MSI. 80c15fa0beSPeter Xu */ 81c15fa0beSPeter Xu info->dest_idx = (entry >> IOAPIC_LVT_DEST_IDX_SHIFT) & 0xffff; 82c15fa0beSPeter Xu info->dest_mode = (entry >> IOAPIC_LVT_DEST_MODE_SHIFT) & 1; 83c15fa0beSPeter Xu info->delivery_mode = (entry >> IOAPIC_LVT_DELIV_MODE_SHIFT) \ 84c15fa0beSPeter Xu & IOAPIC_DM_MASK; 85c15fa0beSPeter Xu if (info->delivery_mode == IOAPIC_DM_EXTINT) { 86c15fa0beSPeter Xu info->vector = pic_read_irq(isa_pic); 87c15fa0beSPeter Xu } else { 88c15fa0beSPeter Xu info->vector = entry & IOAPIC_VECTOR_MASK; 89c15fa0beSPeter Xu } 90c15fa0beSPeter Xu 91c15fa0beSPeter Xu info->addr = APIC_DEFAULT_ADDRESS | \ 92c15fa0beSPeter Xu (info->dest_idx << MSI_ADDR_DEST_IDX_SHIFT) | \ 93c15fa0beSPeter Xu (info->dest_mode << MSI_ADDR_DEST_MODE_SHIFT); 94c15fa0beSPeter Xu info->data = (info->vector << MSI_DATA_VECTOR_SHIFT) | \ 95c15fa0beSPeter Xu (info->trig_mode << MSI_DATA_TRIGGER_SHIFT) | \ 96c15fa0beSPeter Xu (info->delivery_mode << MSI_DATA_DELIVERY_MODE_SHIFT); 97c15fa0beSPeter Xu } 98c15fa0beSPeter Xu 99244ac3afSJan Kiszka static void ioapic_service(IOAPICCommonState *s) 100610626afSaliguori { 101cb135f59SPeter Xu AddressSpace *ioapic_as = PC_MACHINE(qdev_get_machine())->ioapic_as; 102c15fa0beSPeter Xu struct ioapic_entry_info info; 103610626afSaliguori uint8_t i; 104610626afSaliguori uint32_t mask; 105610626afSaliguori uint64_t entry; 106610626afSaliguori 107610626afSaliguori for (i = 0; i < IOAPIC_NUM_PINS; i++) { 108610626afSaliguori mask = 1 << i; 109610626afSaliguori if (s->irr & mask) { 11015eafc2eSPaolo Bonzini int coalesce = 0; 11115eafc2eSPaolo Bonzini 112610626afSaliguori entry = s->ioredtbl[i]; 113c15fa0beSPeter Xu ioapic_entry_parse(entry, &info); 114c15fa0beSPeter Xu if (!info.masked) { 115c15fa0beSPeter Xu if (info.trig_mode == IOAPIC_TRIGGER_EDGE) { 116610626afSaliguori s->irr &= ~mask; 1170280b571SJan Kiszka } else { 11815eafc2eSPaolo Bonzini coalesce = s->ioredtbl[i] & IOAPIC_LVT_REMOTE_IRR; 119*e5074b38SPeter Xu trace_ioapic_set_remote_irr(i); 1200280b571SJan Kiszka s->ioredtbl[i] |= IOAPIC_LVT_REMOTE_IRR; 1210280b571SJan Kiszka } 122c15fa0beSPeter Xu 123f99b86b9SPeter Xu if (coalesce) { 124f99b86b9SPeter Xu /* We are level triggered interrupts, and the 125f99b86b9SPeter Xu * guest should be still working on previous one, 126f99b86b9SPeter Xu * so skip it. */ 127f99b86b9SPeter Xu continue; 128f99b86b9SPeter Xu } 129f99b86b9SPeter Xu 13015eafc2eSPaolo Bonzini #ifdef CONFIG_KVM 13115eafc2eSPaolo Bonzini if (kvm_irqchip_is_split()) { 132c15fa0beSPeter Xu if (info.trig_mode == IOAPIC_TRIGGER_EDGE) { 13315eafc2eSPaolo Bonzini kvm_set_irq(kvm_state, i, 1); 13415eafc2eSPaolo Bonzini kvm_set_irq(kvm_state, i, 0); 13515eafc2eSPaolo Bonzini } else { 13615eafc2eSPaolo Bonzini kvm_set_irq(kvm_state, i, 1); 13715eafc2eSPaolo Bonzini } 13815eafc2eSPaolo Bonzini continue; 13915eafc2eSPaolo Bonzini } 14015eafc2eSPaolo Bonzini #endif 141f99b86b9SPeter Xu 142cb135f59SPeter Xu /* No matter whether IR is enabled, we translate 143cb135f59SPeter Xu * the IOAPIC message into a MSI one, and its 144cb135f59SPeter Xu * address space will decide whether we need a 145cb135f59SPeter Xu * translation. */ 146c15fa0beSPeter Xu stl_le_phys(ioapic_as, info.addr, info.data); 147610626afSaliguori } 148610626afSaliguori } 149610626afSaliguori } 150610626afSaliguori } 151610626afSaliguori 1527d0500c4SBlue Swirl static void ioapic_set_irq(void *opaque, int vector, int level) 153610626afSaliguori { 154244ac3afSJan Kiszka IOAPICCommonState *s = opaque; 155610626afSaliguori 156610626afSaliguori /* ISA IRQs map to GSI 1-1 except for IRQ0 which maps 157610626afSaliguori * to GSI 2. GSI maps to ioapic 1-1. This is not 158610626afSaliguori * the cleanest way of doing it but it should work. */ 159610626afSaliguori 1609af9b330SBlue Swirl DPRINTF("%s: %s vec %x\n", __func__, level ? "raise" : "lower", vector); 1611f5e71a8SJan Kiszka if (vector == 0) { 162610626afSaliguori vector = 2; 1631f5e71a8SJan Kiszka } 164610626afSaliguori if (vector >= 0 && vector < IOAPIC_NUM_PINS) { 165610626afSaliguori uint32_t mask = 1 << vector; 166610626afSaliguori uint64_t entry = s->ioredtbl[vector]; 167610626afSaliguori 1681f5e71a8SJan Kiszka if (((entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1) == 1691f5e71a8SJan Kiszka IOAPIC_TRIGGER_LEVEL) { 170610626afSaliguori /* level triggered */ 171610626afSaliguori if (level) { 172610626afSaliguori s->irr |= mask; 173c5955a56SPaolo Bonzini if (!(entry & IOAPIC_LVT_REMOTE_IRR)) { 174610626afSaliguori ioapic_service(s); 175c5955a56SPaolo Bonzini } 176610626afSaliguori } else { 177610626afSaliguori s->irr &= ~mask; 178610626afSaliguori } 179610626afSaliguori } else { 18047f7be39SJan Kiszka /* According to the 82093AA manual, we must ignore edge requests 18147f7be39SJan Kiszka * if the input pin is masked. */ 18247f7be39SJan Kiszka if (level && !(entry & IOAPIC_LVT_MASKED)) { 183610626afSaliguori s->irr |= mask; 184610626afSaliguori ioapic_service(s); 185610626afSaliguori } 186610626afSaliguori } 187610626afSaliguori } 188610626afSaliguori } 189610626afSaliguori 19015eafc2eSPaolo Bonzini static void ioapic_update_kvm_routes(IOAPICCommonState *s) 19115eafc2eSPaolo Bonzini { 19215eafc2eSPaolo Bonzini #ifdef CONFIG_KVM 19315eafc2eSPaolo Bonzini int i; 19415eafc2eSPaolo Bonzini 19515eafc2eSPaolo Bonzini if (kvm_irqchip_is_split()) { 19615eafc2eSPaolo Bonzini for (i = 0; i < IOAPIC_NUM_PINS; i++) { 19715eafc2eSPaolo Bonzini MSIMessage msg; 198c15fa0beSPeter Xu struct ioapic_entry_info info; 199c15fa0beSPeter Xu ioapic_entry_parse(s->ioredtbl[i], &info); 200c15fa0beSPeter Xu msg.address = info.addr; 201c15fa0beSPeter Xu msg.data = info.data; 20215eafc2eSPaolo Bonzini kvm_irqchip_update_msi_route(kvm_state, i, msg, NULL); 20315eafc2eSPaolo Bonzini } 20415eafc2eSPaolo Bonzini kvm_irqchip_commit_routes(kvm_state); 20515eafc2eSPaolo Bonzini } 20615eafc2eSPaolo Bonzini #endif 20715eafc2eSPaolo Bonzini } 20815eafc2eSPaolo Bonzini 209e3d9c925SPeter Xu #ifdef CONFIG_KVM 210e3d9c925SPeter Xu static void ioapic_iec_notifier(void *private, bool global, 211e3d9c925SPeter Xu uint32_t index, uint32_t mask) 212e3d9c925SPeter Xu { 213e3d9c925SPeter Xu IOAPICCommonState *s = (IOAPICCommonState *)private; 214e3d9c925SPeter Xu /* For simplicity, we just update all the routes */ 215e3d9c925SPeter Xu ioapic_update_kvm_routes(s); 216e3d9c925SPeter Xu } 217e3d9c925SPeter Xu #endif 218e3d9c925SPeter Xu 2190280b571SJan Kiszka void ioapic_eoi_broadcast(int vector) 2200280b571SJan Kiszka { 221244ac3afSJan Kiszka IOAPICCommonState *s; 2220280b571SJan Kiszka uint64_t entry; 2230280b571SJan Kiszka int i, n; 2240280b571SJan Kiszka 225*e5074b38SPeter Xu trace_ioapic_eoi_broadcast(vector); 226*e5074b38SPeter Xu 2270280b571SJan Kiszka for (i = 0; i < MAX_IOAPICS; i++) { 2280280b571SJan Kiszka s = ioapics[i]; 2290280b571SJan Kiszka if (!s) { 2300280b571SJan Kiszka continue; 2310280b571SJan Kiszka } 2320280b571SJan Kiszka for (n = 0; n < IOAPIC_NUM_PINS; n++) { 2330280b571SJan Kiszka entry = s->ioredtbl[n]; 2341f5e71a8SJan Kiszka if ((entry & IOAPIC_LVT_REMOTE_IRR) 2351f5e71a8SJan Kiszka && (entry & IOAPIC_VECTOR_MASK) == vector) { 236*e5074b38SPeter Xu trace_ioapic_clear_remote_irr(n, vector); 2370280b571SJan Kiszka s->ioredtbl[n] = entry & ~IOAPIC_LVT_REMOTE_IRR; 2380280b571SJan Kiszka if (!(entry & IOAPIC_LVT_MASKED) && (s->irr & (1 << n))) { 2390280b571SJan Kiszka ioapic_service(s); 2400280b571SJan Kiszka } 2410280b571SJan Kiszka } 2420280b571SJan Kiszka } 2430280b571SJan Kiszka } 2440280b571SJan Kiszka } 2450280b571SJan Kiszka 2466bde8fd6SPavel Butsykin void ioapic_dump_state(Monitor *mon, const QDict *qdict) 2476bde8fd6SPavel Butsykin { 2486bde8fd6SPavel Butsykin int i; 2496bde8fd6SPavel Butsykin 2506bde8fd6SPavel Butsykin for (i = 0; i < MAX_IOAPICS; i++) { 2516bde8fd6SPavel Butsykin if (ioapics[i] != 0) { 2526bde8fd6SPavel Butsykin ioapic_print_redtbl(mon, ioapics[i]); 2536bde8fd6SPavel Butsykin } 2546bde8fd6SPavel Butsykin } 2556bde8fd6SPavel Butsykin } 2566bde8fd6SPavel Butsykin 2574d5bf5f6SJan Kiszka static uint64_t 258a8170e5eSAvi Kivity ioapic_mem_read(void *opaque, hwaddr addr, unsigned int size) 259610626afSaliguori { 260244ac3afSJan Kiszka IOAPICCommonState *s = opaque; 261610626afSaliguori int index; 262610626afSaliguori uint32_t val = 0; 263610626afSaliguori 264*e5074b38SPeter Xu addr &= 0xff; 265*e5074b38SPeter Xu 266*e5074b38SPeter Xu switch (addr) { 2671f5e71a8SJan Kiszka case IOAPIC_IOREGSEL: 268610626afSaliguori val = s->ioregsel; 2691f5e71a8SJan Kiszka break; 2701f5e71a8SJan Kiszka case IOAPIC_IOWIN: 2711a440963SJan Kiszka if (size != 4) { 2721a440963SJan Kiszka break; 2731a440963SJan Kiszka } 274610626afSaliguori switch (s->ioregsel) { 2751f5e71a8SJan Kiszka case IOAPIC_REG_ID: 2762f5a3b12SPaolo Bonzini case IOAPIC_REG_ARB: 2771f5e71a8SJan Kiszka val = s->id << IOAPIC_ID_SHIFT; 278610626afSaliguori break; 2791f5e71a8SJan Kiszka case IOAPIC_REG_VER: 28020fd4b7bSPeter Xu val = s->version | 2811f5e71a8SJan Kiszka ((IOAPIC_NUM_PINS - 1) << IOAPIC_VER_ENTRIES_SHIFT); 282610626afSaliguori break; 283610626afSaliguori default: 2841f5e71a8SJan Kiszka index = (s->ioregsel - IOAPIC_REG_REDTBL_BASE) >> 1; 285610626afSaliguori if (index >= 0 && index < IOAPIC_NUM_PINS) { 2861f5e71a8SJan Kiszka if (s->ioregsel & 1) { 287610626afSaliguori val = s->ioredtbl[index] >> 32; 2881f5e71a8SJan Kiszka } else { 289610626afSaliguori val = s->ioredtbl[index] & 0xffffffff; 290610626afSaliguori } 291610626afSaliguori } 2921f5e71a8SJan Kiszka } 2939af9b330SBlue Swirl DPRINTF("read: %08x = %08x\n", s->ioregsel, val); 2941f5e71a8SJan Kiszka break; 295610626afSaliguori } 296*e5074b38SPeter Xu 297*e5074b38SPeter Xu trace_ioapic_mem_read(addr, size, val); 298*e5074b38SPeter Xu 299610626afSaliguori return val; 300610626afSaliguori } 301610626afSaliguori 302ed1263c3SPeter Xu /* 303ed1263c3SPeter Xu * This is to satisfy the hack in Linux kernel. One hack of it is to 304ed1263c3SPeter Xu * simulate clearing the Remote IRR bit of IOAPIC entry using the 305ed1263c3SPeter Xu * following: 306ed1263c3SPeter Xu * 307ed1263c3SPeter Xu * "For IO-APIC's with EOI register, we use that to do an explicit EOI. 308ed1263c3SPeter Xu * Otherwise, we simulate the EOI message manually by changing the trigger 309ed1263c3SPeter Xu * mode to edge and then back to level, with RTE being masked during 310ed1263c3SPeter Xu * this." 311ed1263c3SPeter Xu * 312ed1263c3SPeter Xu * (See linux kernel __eoi_ioapic_pin() comment in commit c0205701) 313ed1263c3SPeter Xu * 314ed1263c3SPeter Xu * This is based on the assumption that, Remote IRR bit will be 315ed1263c3SPeter Xu * cleared by IOAPIC hardware when configured as edge-triggered 316ed1263c3SPeter Xu * interrupts. 317ed1263c3SPeter Xu * 318ed1263c3SPeter Xu * Without this, level-triggered interrupts in IR mode might fail to 319ed1263c3SPeter Xu * work correctly. 320ed1263c3SPeter Xu */ 321ed1263c3SPeter Xu static inline void 322ed1263c3SPeter Xu ioapic_fix_edge_remote_irr(uint64_t *entry) 323ed1263c3SPeter Xu { 324ed1263c3SPeter Xu if (!(*entry & IOAPIC_LVT_TRIGGER_MODE)) { 325ed1263c3SPeter Xu /* Edge-triggered interrupts, make sure remote IRR is zero */ 326ed1263c3SPeter Xu *entry &= ~((uint64_t)IOAPIC_LVT_REMOTE_IRR); 327ed1263c3SPeter Xu } 328ed1263c3SPeter Xu } 329ed1263c3SPeter Xu 3301f5e71a8SJan Kiszka static void 331a8170e5eSAvi Kivity ioapic_mem_write(void *opaque, hwaddr addr, uint64_t val, 3324d5bf5f6SJan Kiszka unsigned int size) 333610626afSaliguori { 334244ac3afSJan Kiszka IOAPICCommonState *s = opaque; 335610626afSaliguori int index; 336610626afSaliguori 337*e5074b38SPeter Xu addr &= 0xff; 338*e5074b38SPeter Xu trace_ioapic_mem_write(addr, size, val); 339*e5074b38SPeter Xu 340*e5074b38SPeter Xu switch (addr) { 3411f5e71a8SJan Kiszka case IOAPIC_IOREGSEL: 342610626afSaliguori s->ioregsel = val; 3431f5e71a8SJan Kiszka break; 3441f5e71a8SJan Kiszka case IOAPIC_IOWIN: 3451a440963SJan Kiszka if (size != 4) { 3461a440963SJan Kiszka break; 3471a440963SJan Kiszka } 3480c1f781bSJason Wang DPRINTF("write: %08x = %08" PRIx64 "\n", s->ioregsel, val); 349610626afSaliguori switch (s->ioregsel) { 3501f5e71a8SJan Kiszka case IOAPIC_REG_ID: 3511f5e71a8SJan Kiszka s->id = (val >> IOAPIC_ID_SHIFT) & IOAPIC_ID_MASK; 3521f5e71a8SJan Kiszka break; 3531f5e71a8SJan Kiszka case IOAPIC_REG_VER: 3541f5e71a8SJan Kiszka case IOAPIC_REG_ARB: 3551f5e71a8SJan Kiszka break; 356610626afSaliguori default: 3571f5e71a8SJan Kiszka index = (s->ioregsel - IOAPIC_REG_REDTBL_BASE) >> 1; 358610626afSaliguori if (index >= 0 && index < IOAPIC_NUM_PINS) { 359479c2a1cSPeter Xu uint64_t ro_bits = s->ioredtbl[index] & IOAPIC_RO_BITS; 360610626afSaliguori if (s->ioregsel & 1) { 361610626afSaliguori s->ioredtbl[index] &= 0xffffffff; 362610626afSaliguori s->ioredtbl[index] |= (uint64_t)val << 32; 363610626afSaliguori } else { 364610626afSaliguori s->ioredtbl[index] &= ~0xffffffffULL; 365610626afSaliguori s->ioredtbl[index] |= val; 366610626afSaliguori } 367479c2a1cSPeter Xu /* restore RO bits */ 368479c2a1cSPeter Xu s->ioredtbl[index] &= IOAPIC_RW_BITS; 369479c2a1cSPeter Xu s->ioredtbl[index] |= ro_bits; 370ed1263c3SPeter Xu ioapic_fix_edge_remote_irr(&s->ioredtbl[index]); 371610626afSaliguori ioapic_service(s); 372610626afSaliguori } 373610626afSaliguori } 3741f5e71a8SJan Kiszka break; 37520fd4b7bSPeter Xu case IOAPIC_EOI: 37620fd4b7bSPeter Xu /* Explicit EOI is only supported for IOAPIC version 0x20 */ 37720fd4b7bSPeter Xu if (size != 4 || s->version != 0x20) { 37820fd4b7bSPeter Xu break; 37920fd4b7bSPeter Xu } 38020fd4b7bSPeter Xu ioapic_eoi_broadcast(val); 38120fd4b7bSPeter Xu break; 382610626afSaliguori } 38315eafc2eSPaolo Bonzini 38415eafc2eSPaolo Bonzini ioapic_update_kvm_routes(s); 385610626afSaliguori } 386610626afSaliguori 3874d5bf5f6SJan Kiszka static const MemoryRegionOps ioapic_io_ops = { 3884d5bf5f6SJan Kiszka .read = ioapic_mem_read, 3894d5bf5f6SJan Kiszka .write = ioapic_mem_write, 3904d5bf5f6SJan Kiszka .endianness = DEVICE_NATIVE_ENDIAN, 391610626afSaliguori }; 392610626afSaliguori 393e3d9c925SPeter Xu static void ioapic_machine_done_notify(Notifier *notifier, void *data) 394e3d9c925SPeter Xu { 395e3d9c925SPeter Xu #ifdef CONFIG_KVM 396e3d9c925SPeter Xu IOAPICCommonState *s = container_of(notifier, IOAPICCommonState, 397e3d9c925SPeter Xu machine_done); 398e3d9c925SPeter Xu 399e3d9c925SPeter Xu if (kvm_irqchip_is_split()) { 400e3d9c925SPeter Xu X86IOMMUState *iommu = x86_iommu_get_default(); 401e3d9c925SPeter Xu if (iommu) { 402e3d9c925SPeter Xu /* Register this IOAPIC with IOMMU IEC notifier, so that 403e3d9c925SPeter Xu * when there are IR invalidates, we can be notified to 404e3d9c925SPeter Xu * update kernel IR cache. */ 405e3d9c925SPeter Xu x86_iommu_iec_register_notifier(iommu, ioapic_iec_notifier, s); 406e3d9c925SPeter Xu } 407e3d9c925SPeter Xu } 408e3d9c925SPeter Xu #endif 409e3d9c925SPeter Xu } 410e3d9c925SPeter Xu 411db0f8888Sxiaoqiang zhao static void ioapic_realize(DeviceState *dev, Error **errp) 412610626afSaliguori { 413db0f8888Sxiaoqiang zhao IOAPICCommonState *s = IOAPIC_COMMON(dev); 414f9771858Sxiaoqiang zhao 41520fd4b7bSPeter Xu if (s->version != 0x11 && s->version != 0x20) { 41620fd4b7bSPeter Xu error_report("IOAPIC only supports version 0x11 or 0x20 " 41720fd4b7bSPeter Xu "(default: 0x11)."); 41820fd4b7bSPeter Xu exit(1); 41920fd4b7bSPeter Xu } 42020fd4b7bSPeter Xu 4211437c94bSPaolo Bonzini memory_region_init_io(&s->io_memory, OBJECT(s), &ioapic_io_ops, s, 4221437c94bSPaolo Bonzini "ioapic", 0x1000); 423610626afSaliguori 424f9771858Sxiaoqiang zhao qdev_init_gpio_in(dev, ioapic_set_irq, IOAPIC_NUM_PINS); 425610626afSaliguori 426db0f8888Sxiaoqiang zhao ioapics[ioapic_no] = s; 427e3d9c925SPeter Xu s->machine_done.notify = ioapic_machine_done_notify; 428e3d9c925SPeter Xu qemu_add_machine_init_done_notifier(&s->machine_done); 429610626afSaliguori } 43096051119SBlue Swirl 43120fd4b7bSPeter Xu static Property ioapic_properties[] = { 432048a2e88SPeter Xu DEFINE_PROP_UINT8("version", IOAPICCommonState, version, 0x20), 43320fd4b7bSPeter Xu DEFINE_PROP_END_OF_LIST(), 43420fd4b7bSPeter Xu }; 43520fd4b7bSPeter Xu 436999e12bbSAnthony Liguori static void ioapic_class_init(ObjectClass *klass, void *data) 437999e12bbSAnthony Liguori { 438999e12bbSAnthony Liguori IOAPICCommonClass *k = IOAPIC_COMMON_CLASS(klass); 43939bffca2SAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 440999e12bbSAnthony Liguori 441db0f8888Sxiaoqiang zhao k->realize = ioapic_realize; 44239bffca2SAnthony Liguori dc->reset = ioapic_reset_common; 44320fd4b7bSPeter Xu dc->props = ioapic_properties; 444999e12bbSAnthony Liguori } 445999e12bbSAnthony Liguori 4468c43a6f0SAndreas Färber static const TypeInfo ioapic_info = { 447999e12bbSAnthony Liguori .name = "ioapic", 44839bffca2SAnthony Liguori .parent = TYPE_IOAPIC_COMMON, 44939bffca2SAnthony Liguori .instance_size = sizeof(IOAPICCommonState), 450999e12bbSAnthony Liguori .class_init = ioapic_class_init, 45196051119SBlue Swirl }; 45296051119SBlue Swirl 45383f7d43aSAndreas Färber static void ioapic_register_types(void) 45496051119SBlue Swirl { 45539bffca2SAnthony Liguori type_register_static(&ioapic_info); 45696051119SBlue Swirl } 45796051119SBlue Swirl 45883f7d43aSAndreas Färber type_init(ioapic_register_types) 459