root / hw / kvm / i8259.c @ 10b61882
History | View | Annotate | Download (3.3 kB)
1 |
/*
|
---|---|
2 |
* KVM in-kernel PIC (i8259) 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 |
#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 |
|
115 |
static PICCommonInfo kvm_i8259_info = {
|
116 |
.isadev.qdev.name = "kvm-i8259",
|
117 |
.isadev.qdev.reset = kvm_pic_reset, |
118 |
.init = kvm_pic_init, |
119 |
.pre_save = kvm_pic_get, |
120 |
.post_load = kvm_pic_put, |
121 |
}; |
122 |
|
123 |
static void kvm_pic_register(void) |
124 |
{ |
125 |
pic_qdev_register(&kvm_i8259_info); |
126 |
} |
127 |
|
128 |
device_init(kvm_pic_register) |