2 * IOAPIC emulation logic - common bits of emulated and KVM kernel model
4 * Copyright (c) 2004-2005 Fabrice Bellard
5 * Copyright (c) 2009 Xiantao Zhang, Intel
6 * Copyright (c) 2011 Jan Kiszka, Siemens AG
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 #include "qemu/osdep.h"
23 #include "qapi/error.h"
24 #include "qemu/module.h"
25 #include "migration/vmstate.h"
26 #include "hw/intc/intc.h"
27 #include "hw/intc/ioapic.h"
28 #include "hw/intc/ioapic_internal.h"
29 #include "hw/sysbus.h"
31 /* ioapic_no count start from 0 to MAX_IOAPICS,
32 * remove as static variable from ioapic_common_init.
33 * now as a global variable, let child to increase the counter
34 * then we can drop the 'instance_no' argument
35 * and convert to our QOM's realize function
39 void ioapic_stat_update_irq(IOAPICCommonState
*s
, int irq
, int level
)
41 if (level
!= s
->irq_level
[irq
]) {
42 s
->irq_level
[irq
] = level
;
49 static bool ioapic_get_statistics(InterruptStatsProvider
*obj
,
50 uint64_t **irq_counts
,
51 unsigned int *nb_irqs
)
53 IOAPICCommonState
*s
= IOAPIC_COMMON(obj
);
55 *irq_counts
= s
->irq_count
;
56 *nb_irqs
= IOAPIC_NUM_PINS
;
61 static void ioapic_irr_dump(GString
*buf
, const char *name
, uint32_t bitmap
)
65 g_string_append_printf(buf
, "%-10s ", name
);
67 g_string_append_printf(buf
, "(none)\n");
70 for (i
= 0; i
< IOAPIC_NUM_PINS
; i
++) {
71 if (bitmap
& (1 << i
)) {
72 g_string_append_printf(buf
, "%-2u ", i
);
75 g_string_append_c(buf
, '\n');
78 static void ioapic_print_redtbl(GString
*buf
, IOAPICCommonState
*s
)
80 static const char *delm_str
[] = {
81 "fixed", "lowest", "SMI", "...", "NMI", "INIT", "...", "extINT"};
82 uint32_t remote_irr
= 0;
85 g_string_append_printf(buf
, "ioapic0: ver=0x%x id=0x%02x sel=0x%02x",
86 s
->version
, s
->id
, s
->ioregsel
);
88 g_string_append_printf(buf
, " (redir[%u])\n",
89 (s
->ioregsel
- IOAPIC_REG_REDTBL_BASE
) >> 1);
91 g_string_append_c(buf
, '\n');
93 for (i
= 0; i
< IOAPIC_NUM_PINS
; i
++) {
94 uint64_t entry
= s
->ioredtbl
[i
];
95 uint32_t delm
= (uint32_t)((entry
& IOAPIC_LVT_DELIV_MODE
) >>
96 IOAPIC_LVT_DELIV_MODE_SHIFT
);
97 g_string_append_printf(buf
, " pin %-2u 0x%016"PRIx64
" dest=%"PRIx64
98 " vec=%-3"PRIu64
" %s %-5s %-6s %-6s %s\n",
100 (entry
>> IOAPIC_LVT_DEST_SHIFT
) &
101 (entry
& IOAPIC_LVT_DEST_MODE
? 0xff : 0xf),
102 entry
& IOAPIC_VECTOR_MASK
,
103 entry
& IOAPIC_LVT_POLARITY
104 ? "active-lo" : "active-hi",
105 entry
& IOAPIC_LVT_TRIGGER_MODE
107 entry
& IOAPIC_LVT_MASKED
? "masked" : "",
109 entry
& IOAPIC_LVT_DEST_MODE
110 ? "logical" : "physical");
112 remote_irr
|= entry
& IOAPIC_LVT_TRIGGER_MODE
?
113 (entry
& IOAPIC_LVT_REMOTE_IRR
? (1 << i
) : 0) : 0;
115 ioapic_irr_dump(buf
, " IRR", s
->irr
);
116 ioapic_irr_dump(buf
, " Remote IRR", remote_irr
);
119 void ioapic_reset_common(DeviceState
*dev
)
121 IOAPICCommonState
*s
= IOAPIC_COMMON(dev
);
127 for (i
= 0; i
< IOAPIC_NUM_PINS
; i
++) {
128 s
->ioredtbl
[i
] = 1 << IOAPIC_LVT_MASKED_SHIFT
;
132 static int ioapic_dispatch_pre_save(void *opaque
)
134 IOAPICCommonState
*s
= IOAPIC_COMMON(opaque
);
135 IOAPICCommonClass
*info
= IOAPIC_COMMON_GET_CLASS(s
);
137 if (info
->pre_save
) {
144 static int ioapic_dispatch_post_load(void *opaque
, int version_id
)
146 IOAPICCommonState
*s
= IOAPIC_COMMON(opaque
);
147 IOAPICCommonClass
*info
= IOAPIC_COMMON_GET_CLASS(s
);
149 if (info
->post_load
) {
155 static void ioapic_common_realize(DeviceState
*dev
, Error
**errp
)
158 IOAPICCommonState
*s
= IOAPIC_COMMON(dev
);
159 IOAPICCommonClass
*info
;
161 if (ioapic_no
>= MAX_IOAPICS
) {
162 error_setg(errp
, "Only %d ioapics allowed", MAX_IOAPICS
);
166 info
= IOAPIC_COMMON_GET_CLASS(s
);
167 info
->realize(dev
, errp
);
172 sysbus_init_mmio(SYS_BUS_DEVICE(s
), &s
->io_memory
);
176 static void ioapic_print_info(InterruptStatsProvider
*obj
, GString
*buf
)
178 IOAPICCommonState
*s
= IOAPIC_COMMON(obj
);
180 ioapic_dispatch_pre_save(s
);
181 ioapic_print_redtbl(buf
, s
);
184 static const VMStateDescription vmstate_ioapic_common
= {
187 .minimum_version_id
= 1,
188 .pre_save
= ioapic_dispatch_pre_save
,
189 .post_load
= ioapic_dispatch_post_load
,
190 .fields
= (const VMStateField
[]) {
191 VMSTATE_UINT8(id
, IOAPICCommonState
),
192 VMSTATE_UINT8(ioregsel
, IOAPICCommonState
),
193 VMSTATE_UNUSED_V(2, 8), /* to account for qemu-kvm's v2 format */
194 VMSTATE_UINT32_V(irr
, IOAPICCommonState
, 2),
195 VMSTATE_UINT64_ARRAY(ioredtbl
, IOAPICCommonState
, IOAPIC_NUM_PINS
),
196 VMSTATE_END_OF_LIST()
200 static void ioapic_common_class_init(ObjectClass
*klass
, void *data
)
202 DeviceClass
*dc
= DEVICE_CLASS(klass
);
203 InterruptStatsProviderClass
*ic
= INTERRUPT_STATS_PROVIDER_CLASS(klass
);
205 dc
->realize
= ioapic_common_realize
;
206 dc
->vmsd
= &vmstate_ioapic_common
;
207 ic
->print_info
= ioapic_print_info
;
208 ic
->get_statistics
= ioapic_get_statistics
;
211 static const TypeInfo ioapic_common_type
= {
212 .name
= TYPE_IOAPIC_COMMON
,
213 .parent
= TYPE_SYS_BUS_DEVICE
,
214 .instance_size
= sizeof(IOAPICCommonState
),
215 .class_size
= sizeof(IOAPICCommonClass
),
216 .class_init
= ioapic_common_class_init
,
218 .interfaces
= (InterfaceInfo
[]) {
219 { TYPE_INTERRUPT_STATS_PROVIDER
},
224 static void ioapic_common_register_types(void)
226 type_register_static(&ioapic_common_type
);
229 type_init(ioapic_common_register_types
)