1a39c1d47SJan Kiszka /* 2a39c1d47SJan Kiszka * KVM in-kernel IOPIC support 3a39c1d47SJan Kiszka * 4a39c1d47SJan Kiszka * Copyright (c) 2011 Siemens AG 5a39c1d47SJan Kiszka * 6a39c1d47SJan Kiszka * Authors: 7a39c1d47SJan Kiszka * Jan Kiszka <jan.kiszka@siemens.com> 8a39c1d47SJan Kiszka * 9a39c1d47SJan Kiszka * This work is licensed under the terms of the GNU GPL version 2. 10a39c1d47SJan Kiszka * See the COPYING file in the top-level directory. 11a39c1d47SJan Kiszka */ 12a39c1d47SJan Kiszka 13b6a0aa05SPeter Maydell #include "qemu/osdep.h" 14d665d696SPavel Butsykin #include "monitor/monitor.h" 15*89a289c7SPaolo Bonzini #include "hw/i386/x86.h" 1664552b6bSMarkus Armbruster #include "hw/irq.h" 17a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 180d09e41aSPaolo Bonzini #include "hw/i386/ioapic_internal.h" 190d09e41aSPaolo Bonzini #include "hw/i386/apic_internal.h" 209c17d615SPaolo Bonzini #include "sysemu/kvm.h" 21a39c1d47SJan Kiszka 22d8ee0384SJason Baron /* PC Utility function */ 23d8ee0384SJason Baron void kvm_pc_setup_irq_routing(bool pci_enabled) 24d8ee0384SJason Baron { 25d8ee0384SJason Baron KVMState *s = kvm_state; 26d8ee0384SJason Baron int i; 27d8ee0384SJason Baron 28d8ee0384SJason Baron if (kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) { 29d8ee0384SJason Baron for (i = 0; i < 8; ++i) { 30d8ee0384SJason Baron if (i == 2) { 31d8ee0384SJason Baron continue; 32d8ee0384SJason Baron } 33d8ee0384SJason Baron kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_MASTER, i); 34d8ee0384SJason Baron } 35d8ee0384SJason Baron for (i = 8; i < 16; ++i) { 36d8ee0384SJason Baron kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_SLAVE, i - 8); 37d8ee0384SJason Baron } 38d8ee0384SJason Baron if (pci_enabled) { 39d8ee0384SJason Baron for (i = 0; i < 24; ++i) { 40d8ee0384SJason Baron if (i == 0) { 41d8ee0384SJason Baron kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, 2); 42d8ee0384SJason Baron } else if (i != 2) { 43d8ee0384SJason Baron kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, i); 44d8ee0384SJason Baron } 45d8ee0384SJason Baron } 46d8ee0384SJason Baron } 47cb925cf9SAlexander Graf kvm_irqchip_commit_routes(s); 48d8ee0384SJason Baron } 49d8ee0384SJason Baron } 50d8ee0384SJason Baron 51d8ee0384SJason Baron void kvm_pc_gsi_handler(void *opaque, int n, int level) 52d8ee0384SJason Baron { 53d8ee0384SJason Baron GSIState *s = opaque; 54d8ee0384SJason Baron 55d8ee0384SJason Baron if (n < ISA_NUM_IRQS) { 56d8ee0384SJason Baron /* Kernel will forward to both PIC and IOAPIC */ 57d8ee0384SJason Baron qemu_set_irq(s->i8259_irq[n], level); 58d8ee0384SJason Baron } else { 59d8ee0384SJason Baron qemu_set_irq(s->ioapic_irq[n], level); 60d8ee0384SJason Baron } 61d8ee0384SJason Baron } 62d8ee0384SJason Baron 63a39c1d47SJan Kiszka typedef struct KVMIOAPICState KVMIOAPICState; 64a39c1d47SJan Kiszka 65a39c1d47SJan Kiszka struct KVMIOAPICState { 66a39c1d47SJan Kiszka IOAPICCommonState ioapic; 67a39c1d47SJan Kiszka uint32_t kvm_gsi_base; 68a39c1d47SJan Kiszka }; 69a39c1d47SJan Kiszka 70a39c1d47SJan Kiszka static void kvm_ioapic_get(IOAPICCommonState *s) 71a39c1d47SJan Kiszka { 72a39c1d47SJan Kiszka struct kvm_irqchip chip; 73a39c1d47SJan Kiszka struct kvm_ioapic_state *kioapic; 74a39c1d47SJan Kiszka int ret, i; 75a39c1d47SJan Kiszka 76a39c1d47SJan Kiszka chip.chip_id = KVM_IRQCHIP_IOAPIC; 77a39c1d47SJan Kiszka ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, &chip); 78a39c1d47SJan Kiszka if (ret < 0) { 79a39c1d47SJan Kiszka fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); 80a39c1d47SJan Kiszka abort(); 81a39c1d47SJan Kiszka } 82a39c1d47SJan Kiszka 83a39c1d47SJan Kiszka kioapic = &chip.chip.ioapic; 84a39c1d47SJan Kiszka 85a39c1d47SJan Kiszka s->id = kioapic->id; 86a39c1d47SJan Kiszka s->ioregsel = kioapic->ioregsel; 87a39c1d47SJan Kiszka s->irr = kioapic->irr; 88a39c1d47SJan Kiszka for (i = 0; i < IOAPIC_NUM_PINS; i++) { 89a39c1d47SJan Kiszka s->ioredtbl[i] = kioapic->redirtbl[i].bits; 90a39c1d47SJan Kiszka } 91a39c1d47SJan Kiszka } 92a39c1d47SJan Kiszka 93a39c1d47SJan Kiszka static void kvm_ioapic_put(IOAPICCommonState *s) 94a39c1d47SJan Kiszka { 95a39c1d47SJan Kiszka struct kvm_irqchip chip; 96a39c1d47SJan Kiszka struct kvm_ioapic_state *kioapic; 97a39c1d47SJan Kiszka int ret, i; 98a39c1d47SJan Kiszka 99a39c1d47SJan Kiszka chip.chip_id = KVM_IRQCHIP_IOAPIC; 100a39c1d47SJan Kiszka kioapic = &chip.chip.ioapic; 101a39c1d47SJan Kiszka 102a39c1d47SJan Kiszka kioapic->id = s->id; 103a39c1d47SJan Kiszka kioapic->ioregsel = s->ioregsel; 104a39c1d47SJan Kiszka kioapic->base_address = s->busdev.mmio[0].addr; 105a39c1d47SJan Kiszka kioapic->irr = s->irr; 106a39c1d47SJan Kiszka for (i = 0; i < IOAPIC_NUM_PINS; i++) { 107a39c1d47SJan Kiszka kioapic->redirtbl[i].bits = s->ioredtbl[i]; 108a39c1d47SJan Kiszka } 109a39c1d47SJan Kiszka 110a39c1d47SJan Kiszka ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, &chip); 111a39c1d47SJan Kiszka if (ret < 0) { 112a39c1d47SJan Kiszka fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); 113a39c1d47SJan Kiszka abort(); 114a39c1d47SJan Kiszka } 115a39c1d47SJan Kiszka } 116a39c1d47SJan Kiszka 117a39c1d47SJan Kiszka static void kvm_ioapic_reset(DeviceState *dev) 118a39c1d47SJan Kiszka { 119b3119631SAndreas Färber IOAPICCommonState *s = IOAPIC_COMMON(dev); 120a39c1d47SJan Kiszka 121a39c1d47SJan Kiszka ioapic_reset_common(dev); 122a39c1d47SJan Kiszka kvm_ioapic_put(s); 123a39c1d47SJan Kiszka } 124a39c1d47SJan Kiszka 125a39c1d47SJan Kiszka static void kvm_ioapic_set_irq(void *opaque, int irq, int level) 126a39c1d47SJan Kiszka { 127a39c1d47SJan Kiszka KVMIOAPICState *s = opaque; 128cce5405eSPeter Xu IOAPICCommonState *common = IOAPIC_COMMON(s); 129a39c1d47SJan Kiszka int delivered; 130a39c1d47SJan Kiszka 131cce5405eSPeter Xu ioapic_stat_update_irq(common, irq, level); 1323889c3faSPeter Maydell delivered = kvm_set_irq(kvm_state, s->kvm_gsi_base + irq, level); 133a39c1d47SJan Kiszka apic_report_irq_delivered(delivered); 134a39c1d47SJan Kiszka } 135a39c1d47SJan Kiszka 136db0f8888Sxiaoqiang zhao static void kvm_ioapic_realize(DeviceState *dev, Error **errp) 137a39c1d47SJan Kiszka { 138db0f8888Sxiaoqiang zhao IOAPICCommonState *s = IOAPIC_COMMON(dev); 139f9771858Sxiaoqiang zhao 140257a7430SPaolo Bonzini memory_region_init_io(&s->io_memory, OBJECT(dev), NULL, NULL, "kvm-ioapic", 0x1000); 141b7a4104bSPeter Xu /* 142b7a4104bSPeter Xu * KVM ioapic only supports 0x11 now. This will only be used when 143b7a4104bSPeter Xu * we want to dump ioapic version. 144b7a4104bSPeter Xu */ 145b7a4104bSPeter Xu s->version = 0x11; 146a39c1d47SJan Kiszka 147f9771858Sxiaoqiang zhao qdev_init_gpio_in(dev, kvm_ioapic_set_irq, IOAPIC_NUM_PINS); 148a39c1d47SJan Kiszka } 149a39c1d47SJan Kiszka 15039bffca2SAnthony Liguori static Property kvm_ioapic_properties[] = { 15139bffca2SAnthony Liguori DEFINE_PROP_UINT32("gsi_base", KVMIOAPICState, kvm_gsi_base, 0), 15239bffca2SAnthony Liguori DEFINE_PROP_END_OF_LIST() 15339bffca2SAnthony Liguori }; 15439bffca2SAnthony Liguori 155999e12bbSAnthony Liguori static void kvm_ioapic_class_init(ObjectClass *klass, void *data) 156999e12bbSAnthony Liguori { 157999e12bbSAnthony Liguori IOAPICCommonClass *k = IOAPIC_COMMON_CLASS(klass); 15839bffca2SAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 159999e12bbSAnthony Liguori 160db0f8888Sxiaoqiang zhao k->realize = kvm_ioapic_realize; 161999e12bbSAnthony Liguori k->pre_save = kvm_ioapic_get; 162999e12bbSAnthony Liguori k->post_load = kvm_ioapic_put; 16339bffca2SAnthony Liguori dc->reset = kvm_ioapic_reset; 16439bffca2SAnthony Liguori dc->props = kvm_ioapic_properties; 165999e12bbSAnthony Liguori } 166999e12bbSAnthony Liguori 1678c43a6f0SAndreas Färber static const TypeInfo kvm_ioapic_info = { 16834bec7a8SLi Qiang .name = TYPE_KVM_IOAPIC, 16939bffca2SAnthony Liguori .parent = TYPE_IOAPIC_COMMON, 17039bffca2SAnthony Liguori .instance_size = sizeof(KVMIOAPICState), 171999e12bbSAnthony Liguori .class_init = kvm_ioapic_class_init, 172a39c1d47SJan Kiszka }; 173a39c1d47SJan Kiszka 17483f7d43aSAndreas Färber static void kvm_ioapic_register_types(void) 175a39c1d47SJan Kiszka { 17639bffca2SAnthony Liguori type_register_static(&kvm_ioapic_info); 177a39c1d47SJan Kiszka } 178a39c1d47SJan Kiszka 17983f7d43aSAndreas Färber type_init(kvm_ioapic_register_types) 180