]>
Commit | Line | Data |
---|---|---|
10b61882 JK |
1 | /* |
2 | * KVM in-kernel PIC (i8259) support | |
3 | * | |
4 | * Copyright (c) 2011 Siemens AG | |
5 | * | |
6 | * Authors: | |
7 | * Jan Kiszka <[email protected]> | |
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 | */ | |
0b8fa32f | 12 | |
b6a0aa05 | 13 | #include "qemu/osdep.h" |
0d09e41a | 14 | #include "hw/isa/i8259_internal.h" |
852c27e2 | 15 | #include "hw/intc/i8259.h" |
0b8fa32f | 16 | #include "qemu/module.h" |
0d09e41a | 17 | #include "hw/i386/apic_internal.h" |
64552b6b | 18 | #include "hw/irq.h" |
9c17d615 | 19 | #include "sysemu/kvm.h" |
db1015e9 | 20 | #include "qom/object.h" |
10b61882 | 21 | |
49fdb0c1 | 22 | #define TYPE_KVM_I8259 "kvm-i8259" |
db1015e9 | 23 | typedef struct KVMPICClass KVMPICClass; |
d2628b7d AF |
24 | #define KVM_PIC_CLASS(class) \ |
25 | OBJECT_CLASS_CHECK(KVMPICClass, (class), TYPE_KVM_I8259) | |
26 | #define KVM_PIC_GET_CLASS(obj) \ | |
27 | OBJECT_GET_CLASS(KVMPICClass, (obj), TYPE_KVM_I8259) | |
28 | ||
29 | /** | |
30 | * KVMPICClass: | |
31 | * @parent_realize: The parent's realizefn. | |
32 | */ | |
db1015e9 | 33 | struct KVMPICClass { |
d2628b7d AF |
34 | PICCommonClass parent_class; |
35 | ||
36 | DeviceRealize parent_realize; | |
db1015e9 | 37 | }; |
49fdb0c1 | 38 | |
10b61882 JK |
39 | static void kvm_pic_get(PICCommonState *s) |
40 | { | |
41 | struct kvm_irqchip chip; | |
42 | struct kvm_pic_state *kpic; | |
43 | int ret; | |
44 | ||
45 | chip.chip_id = s->master ? KVM_IRQCHIP_PIC_MASTER : KVM_IRQCHIP_PIC_SLAVE; | |
46 | ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, &chip); | |
47 | if (ret < 0) { | |
48 | fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); | |
49 | abort(); | |
50 | } | |
51 | ||
52 | kpic = &chip.chip.pic; | |
53 | ||
54 | s->last_irr = kpic->last_irr; | |
55 | s->irr = kpic->irr; | |
56 | s->imr = kpic->imr; | |
57 | s->isr = kpic->isr; | |
58 | s->priority_add = kpic->priority_add; | |
59 | s->irq_base = kpic->irq_base; | |
60 | s->read_reg_select = kpic->read_reg_select; | |
61 | s->poll = kpic->poll; | |
62 | s->special_mask = kpic->special_mask; | |
63 | s->init_state = kpic->init_state; | |
64 | s->auto_eoi = kpic->auto_eoi; | |
65 | s->rotate_on_auto_eoi = kpic->rotate_on_auto_eoi; | |
66 | s->special_fully_nested_mode = kpic->special_fully_nested_mode; | |
67 | s->init4 = kpic->init4; | |
68 | s->elcr = kpic->elcr; | |
69 | s->elcr_mask = kpic->elcr_mask; | |
70 | } | |
71 | ||
72 | static void kvm_pic_put(PICCommonState *s) | |
73 | { | |
74 | struct kvm_irqchip chip; | |
75 | struct kvm_pic_state *kpic; | |
76 | int ret; | |
77 | ||
78 | chip.chip_id = s->master ? KVM_IRQCHIP_PIC_MASTER : KVM_IRQCHIP_PIC_SLAVE; | |
79 | ||
80 | kpic = &chip.chip.pic; | |
81 | ||
82 | kpic->last_irr = s->last_irr; | |
83 | kpic->irr = s->irr; | |
84 | kpic->imr = s->imr; | |
85 | kpic->isr = s->isr; | |
86 | kpic->priority_add = s->priority_add; | |
87 | kpic->irq_base = s->irq_base; | |
88 | kpic->read_reg_select = s->read_reg_select; | |
89 | kpic->poll = s->poll; | |
90 | kpic->special_mask = s->special_mask; | |
91 | kpic->init_state = s->init_state; | |
92 | kpic->auto_eoi = s->auto_eoi; | |
93 | kpic->rotate_on_auto_eoi = s->rotate_on_auto_eoi; | |
94 | kpic->special_fully_nested_mode = s->special_fully_nested_mode; | |
95 | kpic->init4 = s->init4; | |
96 | kpic->elcr = s->elcr; | |
97 | kpic->elcr_mask = s->elcr_mask; | |
98 | ||
99 | ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, &chip); | |
100 | if (ret < 0) { | |
89284736 | 101 | fprintf(stderr, "KVM_SET_IRQCHIP failed: %s\n", strerror(ret)); |
10b61882 JK |
102 | abort(); |
103 | } | |
104 | } | |
105 | ||
106 | static void kvm_pic_reset(DeviceState *dev) | |
107 | { | |
29bb5317 | 108 | PICCommonState *s = PIC_COMMON(dev); |
10b61882 | 109 | |
10b61882 | 110 | s->elcr = 0; |
aa24822b | 111 | pic_reset_common(s); |
10b61882 JK |
112 | |
113 | kvm_pic_put(s); | |
114 | } | |
115 | ||
116 | static void kvm_pic_set_irq(void *opaque, int irq, int level) | |
117 | { | |
118 | int delivered; | |
119 | ||
e267d164 | 120 | pic_stat_update_irq(irq, level); |
3889c3fa | 121 | delivered = kvm_set_irq(kvm_state, irq, level); |
10b61882 JK |
122 | apic_report_irq_delivered(delivered); |
123 | } | |
124 | ||
d2628b7d | 125 | static void kvm_pic_realize(DeviceState *dev, Error **errp) |
10b61882 | 126 | { |
d2628b7d AF |
127 | PICCommonState *s = PIC_COMMON(dev); |
128 | KVMPICClass *kpc = KVM_PIC_GET_CLASS(dev); | |
129 | ||
257a7430 PB |
130 | memory_region_init_io(&s->base_io, OBJECT(dev), NULL, NULL, "kvm-pic", 2); |
131 | memory_region_init_io(&s->elcr_io, OBJECT(dev), NULL, NULL, "kvm-elcr", 1); | |
d2628b7d AF |
132 | |
133 | kpc->parent_realize(dev, errp); | |
10b61882 JK |
134 | } |
135 | ||
136 | qemu_irq *kvm_i8259_init(ISABus *bus) | |
137 | { | |
49fdb0c1 AF |
138 | i8259_init_chip(TYPE_KVM_I8259, bus, true); |
139 | i8259_init_chip(TYPE_KVM_I8259, bus, false); | |
10b61882 JK |
140 | |
141 | return qemu_allocate_irqs(kvm_pic_set_irq, NULL, ISA_NUM_IRQS); | |
142 | } | |
143 | ||
8f04ee08 AL |
144 | static void kvm_i8259_class_init(ObjectClass *klass, void *data) |
145 | { | |
d2628b7d | 146 | KVMPICClass *kpc = KVM_PIC_CLASS(klass); |
8f04ee08 | 147 | PICCommonClass *k = PIC_COMMON_CLASS(klass); |
39bffca2 | 148 | DeviceClass *dc = DEVICE_CLASS(klass); |
8f04ee08 | 149 | |
39bffca2 | 150 | dc->reset = kvm_pic_reset; |
bf853881 | 151 | device_class_set_parent_realize(dc, kvm_pic_realize, &kpc->parent_realize); |
8f04ee08 AL |
152 | k->pre_save = kvm_pic_get; |
153 | k->post_load = kvm_pic_put; | |
154 | } | |
155 | ||
8c43a6f0 | 156 | static const TypeInfo kvm_i8259_info = { |
49fdb0c1 | 157 | .name = TYPE_KVM_I8259, |
39bffca2 | 158 | .parent = TYPE_PIC_COMMON, |
4cafe606 | 159 | .instance_size = sizeof(PICCommonState), |
8f04ee08 | 160 | .class_init = kvm_i8259_class_init, |
d2628b7d | 161 | .class_size = sizeof(KVMPICClass), |
10b61882 JK |
162 | }; |
163 | ||
83f7d43a | 164 | static void kvm_pic_register_types(void) |
10b61882 | 165 | { |
39bffca2 | 166 | type_register_static(&kvm_i8259_info); |
10b61882 JK |
167 | } |
168 | ||
83f7d43a | 169 | type_init(kvm_pic_register_types) |