@@ -365,6 +365,17 @@ extern const VMStateInfo vmstate_info_buffer;
+ type_check_array(_type,typeof_field(_state, _field),_num) \
}
+#define VMSTATE_ARRAY_POINTER(_field, _state, _num, _version, _info, _type) {\
+ .name = (stringify(_field)), \
+ .version_id = (_version), \
+ .num = (_num), \
+ .info = &(_info), \
+ .size = sizeof(_type), \
+ .flags = VMS_ARRAY|VMS_POINTER, \
+ .offset = offsetof(_state, _field) \
+ + type_check_pointer(_type,typeof_field(_state, _field)) \
+}
+
#define VMSTATE_VARRAY(_field, _state, _field_num, _version, _info, _type) {\
.name = (stringify(_field)), \
.version_id = (_version), \
@@ -532,6 +543,15 @@ extern const VMStateDescription vmstate_pcie_device;
#define VMSTATE_UINT64_ARRAY(_f, _s, _n) \
VMSTATE_UINT64_ARRAY_V(_f, _s, _n, 0)
+#define VMSTATE_UINT64_ARRAY_POINTER(_f, _s, _n) \
+ VMSTATE_ARRAY_POINTER(_f, _s, _n, 0, vmstate_info_uint64, uint64_t)
+
+#define VMSTATE_UINT64_VARRAY_V(_f, _s, _f_n, _v) \
+ VMSTATE_VARRAY(_f, _s, _f_n, _v, vmstate_info_uint64, uint64_t)
+
+#define VMSTATE_UINT64_VARRAY(_f, _s, _f_n) \
+ VMSTATE_UINT64_VARRAY_V(_f, _s, _f_n, 0)
+
#define VMSTATE_INT32_ARRAY_V(_f, _s, _n, _v) \
VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_int32, int32_t)
@@ -32,7 +32,7 @@
# define IOAPIC_DPRINTF(format, ...) do { } while (0)
#endif
-#define IOAPIC_NUM_PINS 0x18
+#define IOAPIC_NUM_PINS_DEFAULT 0x18
#define IOAPIC_LVT_MASKED (1<<16)
#define IOAPIC_TRIGGER_EDGE 0
@@ -48,11 +48,12 @@
#define IOAPIC_DM_EXTINT 0x7
struct IOAPICState {
+ int32_t num_pins; /* MRE: maximum redirection entries */
uint8_t id;
uint8_t ioregsel;
uint32_t irr;
- uint64_t ioredtbl[IOAPIC_NUM_PINS];
+ uint64_t *ioredtbl;
ioapic_update_fn update_fn;
void *opaque;
};
@@ -75,7 +76,7 @@ static void ioapic_service(IOAPICState *s)
uint8_t dest_mode;
uint8_t polarity;
- for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+ for (i = 0; i < s->num_pins; i++) {
mask = 1 << i;
if (s->irr & mask) {
entry = s->ioredtbl[i];
@@ -110,7 +111,7 @@ static void ioapic_set_irq(void *opaque, int vector, int level)
if (vector == 0)
vector = 2;
- if (vector >= 0 && vector < IOAPIC_NUM_PINS) {
+ if (vector >= 0 && vector < s->num_pins) {
uint32_t mask = 1 << vector;
uint64_t entry = s->ioredtbl[vector];
@@ -147,14 +148,14 @@ static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
val = s->id << 24;
break;
case 0x01:
- val = 0x11 | ((IOAPIC_NUM_PINS - 1) << 16); /* version 0x11 */
+ val = 0x11 | ((s->num_pins - 1) << 16); /* version 0x11 */
break;
case 0x02:
val = 0;
break;
default:
index = (s->ioregsel - 0x10) >> 1;
- if (index >= 0 && index < IOAPIC_NUM_PINS) {
+ if (index >= 0 && index < s->num_pins) {
if (s->ioregsel & 1)
val = s->ioredtbl[index] >> 32;
else
@@ -186,7 +187,7 @@ static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t va
return;
default:
index = (s->ioregsel - 0x10) >> 1;
- if (index >= 0 && index < IOAPIC_NUM_PINS) {
+ if (index >= 0 && index < s->num_pins) {
if (s->ioregsel & 1) {
s->ioredtbl[index] &= 0xffffffff;
s->ioredtbl[index] |= (uint64_t)val << 32;
@@ -209,7 +210,22 @@ static const VMStateDescription vmstate_ioapic = {
.fields = (VMStateField []) {
VMSTATE_UINT8(id, IOAPICState),
VMSTATE_UINT8(ioregsel, IOAPICState),
- VMSTATE_UINT64_ARRAY(ioredtbl, IOAPICState, IOAPIC_NUM_PINS),
+ VMSTATE_UINT64_ARRAY_POINTER(ioredtbl, IOAPICState,
+ IOAPIC_NUM_PINS_DEFAULT),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_ioapic_with_mre = {
+ .name = "ioapic",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_INT32(num_pins, IOAPICState),
+ VMSTATE_UINT8(id, IOAPICState),
+ VMSTATE_UINT8(ioregsel, IOAPICState),
+ VMSTATE_UINT64_VARRAY(ioredtbl, IOAPICState, num_pins),
VMSTATE_END_OF_LIST()
}
};
@@ -221,8 +237,10 @@ static void ioapic_reset(void *opaque)
ioapic_callback(s, 1);
- memset(s, 0, sizeof(*s));
- for(i = 0; i < IOAPIC_NUM_PINS; i++)
+ s->id = 0;
+ s->ioregsel = 0;
+ s->irr = 0;
+ for(i = 0; i < s->num_pins; i++)
s->ioredtbl[i] = 1 << 16; /* mask LVT */
}
@@ -238,13 +256,18 @@ static CPUWriteMemoryFunc * const ioapic_mem_write[3] = {
ioapic_mem_writel,
};
-qemu_irq *ioapic_init_with_arg(ioapic_update_fn update_fn, void *opaque)
+static void ioapic_init_with_arg(uint8_t num_pins,
+ ioapic_update_fn update_fn, void *opaque,
+ IOAPICState **sp, qemu_irq **irq)
{
IOAPICState *s;
- qemu_irq *irq;
int io_memory;
- s = qemu_mallocz(sizeof(IOAPICState));
+ s = qemu_mallocz(sizeof(*s));
+ *sp = s;
+
+ s->ioredtbl = qemu_mallocz(sizeof(s->ioredtbl[0]) * num_pins);
+ s->num_pins = num_pins;
s->update_fn = update_fn;
s->opaque = opaque;
ioapic_reset(s);
@@ -253,14 +276,25 @@ qemu_irq *ioapic_init_with_arg(ioapic_update_fn update_fn, void *opaque)
ioapic_mem_write, s);
cpu_register_physical_memory(0xfec00000, 0x1000, io_memory);
- vmstate_register(0, &vmstate_ioapic, s);
qemu_register_reset(ioapic_reset, s);
- irq = qemu_allocate_irqs(ioapic_set_irq, s, IOAPIC_NUM_PINS);
+ *irq = qemu_allocate_irqs(ioapic_set_irq, s, num_pins);
+}
+qemu_irq *ioapic_init_with_mre(uint8_t num_pins,
+ ioapic_update_fn update_fn, void *opaque)
+{
+ IOAPICState *s;
+ qemu_irq *irq;
+ ioapic_init_with_arg(num_pins, update_fn, opaque, &s, &irq);
+ vmstate_register(0, &vmstate_ioapic_with_mre, s);
return irq;
}
qemu_irq *ioapic_init(void)
{
- return ioapic_init_with_arg(NULL, NULL);
+ IOAPICState *s;
+ qemu_irq *irq;
+ ioapic_init_with_arg(IOAPIC_NUM_PINS_DEFAULT, NULL, NULL, &s, &irq);
+ vmstate_register(0, &vmstate_ioapic, s);
+ return irq;
}
@@ -53,7 +53,8 @@ void apic_deliver_pic_intr(CPUState *env, int level);
int apic_get_interrupt(CPUState *env);
qemu_irq *ioapic_init(void);
typedef void (*ioapic_update_fn)(void *opaque, int reset);
-qemu_irq *ioapic_init_with_arg(ioapic_update_fn update_fn, void *opaque);
+qemu_irq *ioapic_init_with_mre(uint8_t num_pins,
+ ioapic_update_fn update_fn, void *opaque);
void apic_reset_irq_delivered(void);
int apic_get_irq_delivered(void);
make the number of pins configurable. Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> --- hw/hw.h | 20 +++++++++++++++++ hw/ioapic.c | 66 ++++++++++++++++++++++++++++++++++++++++++++-------------- hw/pc.h | 3 +- 3 files changed, 72 insertions(+), 17 deletions(-)