]>
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 | */ | |
12 | #include "hw/i8259_internal.h" | |
13 | #include "hw/apic_internal.h" | |
14 | #include "kvm.h" | |
15 | ||
16 | static void kvm_pic_get(PICCommonState *s) | |
17 | { | |
18 | struct kvm_irqchip chip; | |
19 | struct kvm_pic_state *kpic; | |
20 | int ret; | |
21 | ||
22 | chip.chip_id = s->master ? KVM_IRQCHIP_PIC_MASTER : KVM_IRQCHIP_PIC_SLAVE; | |
23 | ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, &chip); | |
24 | if (ret < 0) { | |
25 | fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); | |
26 | abort(); | |
27 | } | |
28 | ||
29 | kpic = &chip.chip.pic; | |
30 | ||
31 | s->last_irr = kpic->last_irr; | |
32 | s->irr = kpic->irr; | |
33 | s->imr = kpic->imr; | |
34 | s->isr = kpic->isr; | |
35 | s->priority_add = kpic->priority_add; | |
36 | s->irq_base = kpic->irq_base; | |
37 | s->read_reg_select = kpic->read_reg_select; | |
38 | s->poll = kpic->poll; | |
39 | s->special_mask = kpic->special_mask; | |
40 | s->init_state = kpic->init_state; | |
41 | s->auto_eoi = kpic->auto_eoi; | |
42 | s->rotate_on_auto_eoi = kpic->rotate_on_auto_eoi; | |
43 | s->special_fully_nested_mode = kpic->special_fully_nested_mode; | |
44 | s->init4 = kpic->init4; | |
45 | s->elcr = kpic->elcr; | |
46 | s->elcr_mask = kpic->elcr_mask; | |
47 | } | |
48 | ||
49 | static void kvm_pic_put(PICCommonState *s) | |
50 | { | |
51 | struct kvm_irqchip chip; | |
52 | struct kvm_pic_state *kpic; | |
53 | int ret; | |
54 | ||
55 | chip.chip_id = s->master ? KVM_IRQCHIP_PIC_MASTER : KVM_IRQCHIP_PIC_SLAVE; | |
56 | ||
57 | kpic = &chip.chip.pic; | |
58 | ||
59 | kpic->last_irr = s->last_irr; | |
60 | kpic->irr = s->irr; | |
61 | kpic->imr = s->imr; | |
62 | kpic->isr = s->isr; | |
63 | kpic->priority_add = s->priority_add; | |
64 | kpic->irq_base = s->irq_base; | |
65 | kpic->read_reg_select = s->read_reg_select; | |
66 | kpic->poll = s->poll; | |
67 | kpic->special_mask = s->special_mask; | |
68 | kpic->init_state = s->init_state; | |
69 | kpic->auto_eoi = s->auto_eoi; | |
70 | kpic->rotate_on_auto_eoi = s->rotate_on_auto_eoi; | |
71 | kpic->special_fully_nested_mode = s->special_fully_nested_mode; | |
72 | kpic->init4 = s->init4; | |
73 | kpic->elcr = s->elcr; | |
74 | kpic->elcr_mask = s->elcr_mask; | |
75 | ||
76 | ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, &chip); | |
77 | if (ret < 0) { | |
78 | fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); | |
79 | abort(); | |
80 | } | |
81 | } | |
82 | ||
83 | static void kvm_pic_reset(DeviceState *dev) | |
84 | { | |
85 | PICCommonState *s = DO_UPCAST(PICCommonState, dev.qdev, dev); | |
86 | ||
87 | pic_reset_common(s); | |
88 | s->elcr = 0; | |
89 | ||
90 | kvm_pic_put(s); | |
91 | } | |
92 | ||
93 | static void kvm_pic_set_irq(void *opaque, int irq, int level) | |
94 | { | |
95 | int delivered; | |
96 | ||
97 | delivered = kvm_irqchip_set_irq(kvm_state, irq, level); | |
98 | apic_report_irq_delivered(delivered); | |
99 | } | |
100 | ||
101 | static void kvm_pic_init(PICCommonState *s) | |
102 | { | |
103 | memory_region_init_reservation(&s->base_io, "kvm-pic", 2); | |
104 | memory_region_init_reservation(&s->elcr_io, "kvm-elcr", 1); | |
105 | } | |
106 | ||
107 | qemu_irq *kvm_i8259_init(ISABus *bus) | |
108 | { | |
109 | i8259_init_chip("kvm-i8259", bus, true); | |
110 | i8259_init_chip("kvm-i8259", bus, false); | |
111 | ||
112 | return qemu_allocate_irqs(kvm_pic_set_irq, NULL, ISA_NUM_IRQS); | |
113 | } | |
114 | ||
8f04ee08 AL |
115 | static void kvm_i8259_class_init(ObjectClass *klass, void *data) |
116 | { | |
117 | PICCommonClass *k = PIC_COMMON_CLASS(klass); | |
39bffca2 | 118 | DeviceClass *dc = DEVICE_CLASS(klass); |
8f04ee08 | 119 | |
39bffca2 | 120 | dc->reset = kvm_pic_reset; |
8f04ee08 AL |
121 | k->init = kvm_pic_init; |
122 | k->pre_save = kvm_pic_get; | |
123 | k->post_load = kvm_pic_put; | |
124 | } | |
125 | ||
39bffca2 | 126 | static TypeInfo kvm_i8259_info = { |
8f04ee08 | 127 | .name = "kvm-i8259", |
39bffca2 | 128 | .parent = TYPE_PIC_COMMON, |
8f04ee08 | 129 | .class_init = kvm_i8259_class_init, |
10b61882 JK |
130 | }; |
131 | ||
132 | static void kvm_pic_register(void) | |
133 | { | |
39bffca2 | 134 | type_register_static(&kvm_i8259_info); |
10b61882 JK |
135 | } |
136 | ||
137 | device_init(kvm_pic_register) |