1 /* 2 * KVM in-kernel IOPIC support 3 * 4 * Copyright (c) 2011 Siemens AG 5 * 6 * Authors: 7 * Jan Kiszka <jan.kiszka@siemens.com> 8 * 9 * This work is licensed under the terms of the GNU GPL version 2. 10 * See the COPYING file in the top-level directory. 11 */ 12 13 #include "qemu/osdep.h" 14 #include "monitor/monitor.h" 15 #include "hw/i386/x86.h" 16 #include "hw/qdev-properties.h" 17 #include "hw/i386/ioapic_internal.h" 18 #include "hw/i386/apic_internal.h" 19 #include "sysemu/kvm.h" 20 21 /* PC Utility function */ 22 void kvm_pc_setup_irq_routing(bool pci_enabled) 23 { 24 KVMState *s = kvm_state; 25 int i; 26 27 assert(kvm_has_gsi_routing()); 28 for (i = 0; i < 8; ++i) { 29 if (i == 2) { 30 continue; 31 } 32 kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_MASTER, i); 33 } 34 for (i = 8; i < 16; ++i) { 35 kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_SLAVE, i - 8); 36 } 37 if (pci_enabled) { 38 for (i = 0; i < 24; ++i) { 39 if (i == 0) { 40 kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, 2); 41 } else if (i != 2) { 42 kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, i); 43 } 44 } 45 } 46 kvm_irqchip_commit_routes(s); 47 } 48 49 typedef struct KVMIOAPICState KVMIOAPICState; 50 51 struct KVMIOAPICState { 52 IOAPICCommonState ioapic; 53 uint32_t kvm_gsi_base; 54 }; 55 56 static void kvm_ioapic_get(IOAPICCommonState *s) 57 { 58 struct kvm_irqchip chip; 59 struct kvm_ioapic_state *kioapic; 60 int ret, i; 61 62 chip.chip_id = KVM_IRQCHIP_IOAPIC; 63 ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, &chip); 64 if (ret < 0) { 65 fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(-ret)); 66 abort(); 67 } 68 69 kioapic = &chip.chip.ioapic; 70 71 s->id = kioapic->id; 72 s->ioregsel = kioapic->ioregsel; 73 s->irr = kioapic->irr; 74 for (i = 0; i < IOAPIC_NUM_PINS; i++) { 75 s->ioredtbl[i] = kioapic->redirtbl[i].bits; 76 } 77 } 78 79 static void kvm_ioapic_put(IOAPICCommonState *s) 80 { 81 struct kvm_irqchip chip; 82 struct kvm_ioapic_state *kioapic; 83 int ret, i; 84 85 chip.chip_id = KVM_IRQCHIP_IOAPIC; 86 kioapic = &chip.chip.ioapic; 87 88 kioapic->id = s->id; 89 kioapic->ioregsel = s->ioregsel; 90 kioapic->base_address = s->busdev.mmio[0].addr; 91 kioapic->irr = s->irr; 92 for (i = 0; i < IOAPIC_NUM_PINS; i++) { 93 kioapic->redirtbl[i].bits = s->ioredtbl[i]; 94 } 95 96 ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, &chip); 97 if (ret < 0) { 98 fprintf(stderr, "KVM_SET_IRQCHIP failed: %s\n", strerror(-ret)); 99 abort(); 100 } 101 } 102 103 static void kvm_ioapic_reset(DeviceState *dev) 104 { 105 IOAPICCommonState *s = IOAPIC_COMMON(dev); 106 107 ioapic_reset_common(dev); 108 kvm_ioapic_put(s); 109 } 110 111 static void kvm_ioapic_set_irq(void *opaque, int irq, int level) 112 { 113 KVMIOAPICState *s = opaque; 114 IOAPICCommonState *common = IOAPIC_COMMON(s); 115 int delivered; 116 117 ioapic_stat_update_irq(common, irq, level); 118 delivered = kvm_set_irq(kvm_state, s->kvm_gsi_base + irq, level); 119 apic_report_irq_delivered(delivered); 120 } 121 122 static void kvm_ioapic_realize(DeviceState *dev, Error **errp) 123 { 124 IOAPICCommonState *s = IOAPIC_COMMON(dev); 125 126 memory_region_init_io(&s->io_memory, OBJECT(dev), NULL, NULL, "kvm-ioapic", 0x1000); 127 /* 128 * KVM ioapic only supports 0x11 now. This will only be used when 129 * we want to dump ioapic version. 130 */ 131 s->version = 0x11; 132 133 qdev_init_gpio_in(dev, kvm_ioapic_set_irq, IOAPIC_NUM_PINS); 134 } 135 136 static Property kvm_ioapic_properties[] = { 137 DEFINE_PROP_UINT32("gsi_base", KVMIOAPICState, kvm_gsi_base, 0), 138 DEFINE_PROP_END_OF_LIST() 139 }; 140 141 static void kvm_ioapic_class_init(ObjectClass *klass, void *data) 142 { 143 IOAPICCommonClass *k = IOAPIC_COMMON_CLASS(klass); 144 DeviceClass *dc = DEVICE_CLASS(klass); 145 146 k->realize = kvm_ioapic_realize; 147 k->pre_save = kvm_ioapic_get; 148 k->post_load = kvm_ioapic_put; 149 dc->reset = kvm_ioapic_reset; 150 device_class_set_props(dc, kvm_ioapic_properties); 151 } 152 153 static const TypeInfo kvm_ioapic_info = { 154 .name = TYPE_KVM_IOAPIC, 155 .parent = TYPE_IOAPIC_COMMON, 156 .instance_size = sizeof(KVMIOAPICState), 157 .class_init = kvm_ioapic_class_init, 158 }; 159 160 static void kvm_ioapic_register_types(void) 161 { 162 type_register_static(&kvm_ioapic_info); 163 } 164 165 type_init(kvm_ioapic_register_types) 166