Commit 3964f535 authored by Anthony Liguori's avatar Anthony Liguori
Browse files

Merge remote-tracking branch 'mst/for_anthony' into staging

parents a69fb350 5300f1a5
......@@ -34,10 +34,21 @@ typedef unsigned long ram_addr_t;
typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset,
ram_addr_t region_offset);
void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset,
ram_addr_t region_offset,
bool log_dirty);
static inline void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset,
ram_addr_t region_offset)
{
cpu_register_physical_memory_log(start_addr, size, phys_offset,
region_offset, false);
}
static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset)
......@@ -91,7 +102,8 @@ struct CPUPhysMemoryClient {
void (*set_memory)(struct CPUPhysMemoryClient *client,
target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset);
ram_addr_t phys_offset,
bool log_dirty);
int (*sync_dirty_bitmap)(struct CPUPhysMemoryClient *client,
target_phys_addr_t start_addr,
target_phys_addr_t end_addr);
......
......@@ -1718,11 +1718,12 @@ static QLIST_HEAD(memory_client_list, CPUPhysMemoryClient) memory_client_list
static void cpu_notify_set_memory(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset)
ram_addr_t phys_offset,
bool log_dirty)
{
CPUPhysMemoryClient *client;
QLIST_FOREACH(client, &memory_client_list, list) {
client->set_memory(client, start_addr, size, phys_offset);
client->set_memory(client, start_addr, size, phys_offset, log_dirty);
}
}
......@@ -1749,8 +1750,14 @@ static int cpu_notify_migration_log(int enable)
return 0;
}
/* The l1_phys_map provides the upper P_L1_BITs of the guest physical
* address. Each intermediate table provides the next L2_BITs of guest
* physical address space. The number of levels vary based on host and
* guest configuration, making it efficient to build the final guest
* physical address by seeding the L1 offset and shifting and adding in
* each L2 offset as we recurse through them. */
static void phys_page_for_each_1(CPUPhysMemoryClient *client,
int level, void **lp)
int level, void **lp, target_phys_addr_t addr)
{
int i;
......@@ -1759,16 +1766,18 @@ static void phys_page_for_each_1(CPUPhysMemoryClient *client,
}
if (level == 0) {
PhysPageDesc *pd = *lp;
addr <<= L2_BITS + TARGET_PAGE_BITS;
for (i = 0; i < L2_SIZE; ++i) {
if (pd[i].phys_offset != IO_MEM_UNASSIGNED) {
client->set_memory(client, pd[i].region_offset,
TARGET_PAGE_SIZE, pd[i].phys_offset);
client->set_memory(client, addr | i << TARGET_PAGE_BITS,
TARGET_PAGE_SIZE, pd[i].phys_offset, false);
}
}
} else {
void **pp = *lp;
for (i = 0; i < L2_SIZE; ++i) {
phys_page_for_each_1(client, level - 1, pp + i);
phys_page_for_each_1(client, level - 1, pp + i,
(addr << L2_BITS) | i);
}
}
}
......@@ -1778,7 +1787,7 @@ static void phys_page_for_each(CPUPhysMemoryClient *client)
int i;
for (i = 0; i < P_L1_SIZE; ++i) {
phys_page_for_each_1(client, P_L1_SHIFT / L2_BITS - 1,
l1_phys_map + 1);
l1_phys_map + i, i);
}
}
......@@ -2607,10 +2616,11 @@ static subpage_t *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
start_addr and region_offset are rounded down to a page boundary
before calculating this offset. This should not be a problem unless
the low bits of start_addr and region_offset differ. */
void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset,
ram_addr_t region_offset)
ram_addr_t region_offset,
bool log_dirty)
{
target_phys_addr_t addr, end_addr;
PhysPageDesc *p;
......@@ -2619,7 +2629,7 @@ void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
subpage_t *subpage;
assert(size);
cpu_notify_set_memory(start_addr, size, phys_offset);
cpu_notify_set_memory(start_addr, size, phys_offset, log_dirty);
if (phys_offset == IO_MEM_UNASSIGNED) {
region_offset = start_addr;
......
......@@ -2489,7 +2489,9 @@ static void map_linear_vram(CirrusVGAState *s)
if (!s->vga.map_addr && s->vga.lfb_addr && s->vga.lfb_end) {
s->vga.map_addr = s->vga.lfb_addr;
s->vga.map_end = s->vga.lfb_end;
cpu_register_physical_memory(s->vga.map_addr, s->vga.map_end - s->vga.map_addr, s->vga.vram_offset);
cpu_register_physical_memory_log(s->vga.map_addr,
s->vga.map_end - s->vga.map_addr,
s->vga.vram_offset, 0, true);
}
if (!s->vga.map_addr)
......@@ -2502,10 +2504,14 @@ static void map_linear_vram(CirrusVGAState *s)
&& !((s->vga.gr[0x0B] & 0x14) == 0x14)
&& !(s->vga.gr[0x0B] & 0x02)) {
cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x8000,
(s->vga.vram_offset + s->cirrus_bank_base[0]) | IO_MEM_RAM);
cpu_register_physical_memory(isa_mem_base + 0xa8000, 0x8000,
(s->vga.vram_offset + s->cirrus_bank_base[1]) | IO_MEM_RAM);
cpu_register_physical_memory_log(isa_mem_base + 0xa0000, 0x8000,
(s->vga.vram_offset +
s->cirrus_bank_base[0]) |
IO_MEM_RAM, 0, true);
cpu_register_physical_memory_log(isa_mem_base + 0xa8000, 0x8000,
(s->vga.vram_offset +
s->cirrus_bank_base[1]) |
IO_MEM_RAM, 0, true);
s->vga.lfb_vram_mapped = 1;
}
......@@ -3024,7 +3030,6 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
s->vga.cursor_draw_line = cirrus_cursor_draw_line;
qemu_register_reset(cirrus_reset, s);
cirrus_reset(s);
}
/***************************************
......@@ -3076,15 +3081,6 @@ static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
vga_dirty_log_start(&s->vga);
}
static void cirrus_pci_mmio_map(PCIDevice *d, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
CirrusVGAState *s = &DO_UPCAST(PCICirrusVGAState, dev, d)->cirrus_vga;
cpu_register_physical_memory(addr, CIRRUS_PNPMMIO_SIZE,
s->cirrus_mmio_io_addr);
}
static void pci_cirrus_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len)
{
......@@ -3123,8 +3119,8 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
pci_register_bar(&d->dev, 0, 0x2000000,
PCI_BASE_ADDRESS_MEM_PREFETCH, cirrus_pci_lfb_map);
if (device_id == CIRRUS_ID_CLGD5446) {
pci_register_bar(&d->dev, 1, CIRRUS_PNPMMIO_SIZE,
PCI_BASE_ADDRESS_SPACE_MEMORY, cirrus_pci_mmio_map);
pci_register_bar_simple(&d->dev, 1, CIRRUS_PNPMMIO_SIZE, 0,
s->cirrus_mmio_io_addr);
}
return 0;
}
......
This diff is collapsed.
......@@ -1129,15 +1129,6 @@ void ahci_uninit(AHCIState *s)
qemu_free(s->dev);
}
void ahci_pci_map(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
struct AHCIPCIState *d = (struct AHCIPCIState *)pci_dev;
AHCIState *s = &d->ahci;
cpu_register_physical_memory(addr, size, s->mem);
}
void ahci_reset(void *opaque)
{
struct AHCIPCIState *d = opaque;
......
......@@ -325,9 +325,6 @@ typedef struct NCQFrame {
void ahci_init(AHCIState *s, DeviceState *qdev, int ports);
void ahci_uninit(AHCIState *s);
void ahci_pci_map(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type);
void ahci_reset(void *opaque);
#endif /* HW_IDE_AHCI_H */
......@@ -94,8 +94,7 @@ static int pci_ich9_ahci_init(PCIDevice *dev)
qemu_register_reset(ahci_reset, d);
/* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
pci_register_bar(&d->card, 5, 0x1000, PCI_BASE_ADDRESS_SPACE_MEMORY,
ahci_pci_map);
pci_register_bar_simple(&d->card, 5, 0x1000, 0, d->ahci.mem);
msi_init(dev, 0x50, 1, true, false);
......@@ -110,10 +109,7 @@ static int pci_ich9_uninit(PCIDevice *dev)
struct AHCIPCIState *d;
d = DO_UPCAST(struct AHCIPCIState, card, dev);
if (msi_enabled(dev)) {
msi_uninit(dev);
}
msi_uninit(dev);
qemu_unregister_reset(ahci_reset, d);
ahci_uninit(&d->ahci);
......
......@@ -1109,14 +1109,6 @@ static CPUWriteMemoryFunc * const intel_hda_mmio_write[3] = {
intel_hda_mmio_writel,
};
static void intel_hda_map(PCIDevice *pci, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci);
cpu_register_physical_memory(addr, 0x4000, d->mmio_addr);
}
/* --------------------------------------------------------------------- */
static void intel_hda_reset(DeviceState *dev)
......@@ -1158,8 +1150,7 @@ static int intel_hda_init(PCIDevice *pci)
d->mmio_addr = cpu_register_io_memory(intel_hda_mmio_read,
intel_hda_mmio_write, d,
DEVICE_NATIVE_ENDIAN);
pci_register_bar(&d->pci, 0, 0x4000, PCI_BASE_ADDRESS_SPACE_MEMORY,
intel_hda_map);
pci_register_bar_simple(&d->pci, 0, 0x4000, 0, d->mmio_addr);
if (d->msi) {
msi_init(&d->pci, 0x50, 1, true, false);
}
......@@ -1174,9 +1165,7 @@ static int intel_hda_exit(PCIDevice *pci)
{
IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci);
if (d->msi) {
msi_uninit(&d->pci);
}
msi_uninit(&d->pci);
cpu_unregister_io_memory(d->mmio_addr);
return 0;
}
......
......@@ -2094,15 +2094,6 @@ static void lsi_ram_mapfunc(PCIDevice *pci_dev, int region_num,
cpu_register_physical_memory(addr + 0, 0x2000, s->ram_io_addr);
}
static void lsi_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
LSIState *s = DO_UPCAST(LSIState, dev, pci_dev);
DPRINTF("Mapping registers at %08"FMT_PCIBUS"\n", addr);
cpu_register_physical_memory(addr + 0, 0x400, s->mmio_io_addr);
}
static void lsi_scsi_reset(DeviceState *dev)
{
LSIState *s = DO_UPCAST(LSIState, dev.qdev, dev);
......@@ -2245,8 +2236,7 @@ static int lsi_scsi_init(PCIDevice *dev)
pci_register_bar(&s->dev, 0, 256,
PCI_BASE_ADDRESS_SPACE_IO, lsi_io_mapfunc);
pci_register_bar(&s->dev, 1, 0x400,
PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_mmio_mapfunc);
pci_register_bar_simple(&s->dev, 1, 0x400, 0, s->mmio_io_addr);
pci_register_bar(&s->dev, 2, 0x2000,
PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_ram_mapfunc);
QTAILQ_INIT(&s->queue);
......
......@@ -164,9 +164,17 @@ int msi_init(struct PCIDevice *dev, uint8_t offset,
void msi_uninit(struct PCIDevice *dev)
{
uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
uint8_t cap_size = msi_cap_sizeof(flags);
uint16_t flags;
uint8_t cap_size;
if (!(dev->cap_present & QEMU_PCI_CAP_MSI)) {
return;
}
flags = pci_get_word(dev->config + msi_flags_off(dev));
cap_size = msi_cap_sizeof(flags);
pci_del_capability(dev, PCI_CAP_ID_MSIX, cap_size);
dev->cap_present &= ~QEMU_PCI_CAP_MSI;
MSI_DEV_PRINTF(dev, "uninit\n");
}
......
......@@ -126,6 +126,13 @@ static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change)
bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
}
int pci_bus_get_irq_level(PCIBus *bus, int irq_num)
{
assert(irq_num >= 0);
assert(irq_num < bus->nirq);
return !!bus->irq_count[irq_num];
}
/* Update interrupt status bit in config space on interrupt
* state change. */
static void pci_update_irq_status(PCIDevice *dev)
......@@ -859,6 +866,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
r->filtered_size = size;
r->type = type;
r->map_func = map_func;
r->ram_addr = IO_MEM_UNASSIGNED;
wmask = ~(size - 1);
addr = pci_bar(pci_dev, region_num);
......@@ -877,6 +885,22 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
}
}
static void pci_simple_bar_mapfunc(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
cpu_register_physical_memory(addr, size,
pci_dev->io_regions[region_num].ram_addr);
}
void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
pcibus_t size, uint8_t attr, ram_addr_t ram_addr)
{
pci_register_bar(pci_dev, region_num, size,
PCI_BASE_ADDRESS_SPACE_MEMORY | attr,
pci_simple_bar_mapfunc);
pci_dev->io_regions[region_num].ram_addr = ram_addr;
}
static void pci_bridge_filter(PCIDevice *d, pcibus_t *addr, pcibus_t *size,
uint8_t type)
{
......@@ -1145,6 +1169,7 @@ static const pci_class_desc pci_class_descriptions[] =
{ 0x0400, "Video controller", "video"},
{ 0x0401, "Audio controller", "sound"},
{ 0x0402, "Phone"},
{ 0x0403, "Audio controller", "sound"},
{ 0x0480, "Multimedia controller"},
{ 0x0500, "RAM controller", "memory"},
{ 0x0501, "Flash controller", "flash"},
......
......@@ -92,6 +92,7 @@ typedef struct PCIIORegion {
pcibus_t filtered_size;
uint8_t type;
PCIMapIORegionFunc *map_func;
ram_addr_t ram_addr;
} PCIIORegion;
#define PCI_ROM_SLOT 6
......@@ -200,6 +201,8 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
void pci_register_bar(PCIDevice *pci_dev, int region_num,
pcibus_t size, uint8_t type,
PCIMapIORegionFunc *map_func);
void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
pcibus_t size, uint8_t attr, ram_addr_t ram_addr);
int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
uint8_t offset, uint8_t size);
......@@ -234,6 +237,7 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min);
void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void *irq_opaque, int nirq);
int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
PCIBus *pci_register_bus(DeviceState *parent, const char *name,
pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
......
......@@ -214,19 +214,6 @@ static CPUReadMemoryFunc * const pcnet_mmio_read[] = {
&pcnet_mmio_readl
};
static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
#ifdef PCNET_DEBUG_IO
printf("pcnet_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n",
addr, size);
#endif
cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->state.mmio_index);
}
static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr,
uint8_t *buf, int len, int do_bswap)
{
......@@ -300,8 +287,7 @@ static int pci_pcnet_init(PCIDevice *pci_dev)
pci_register_bar(pci_dev, 0, PCNET_IOPORT_SIZE,
PCI_BASE_ADDRESS_SPACE_IO, pcnet_ioport_map);
pci_register_bar(pci_dev, 1, PCNET_PNPMMIO_SIZE,
PCI_BASE_ADDRESS_SPACE_MEMORY, pcnet_mmio_map);
pci_register_bar_simple(pci_dev, 1, PCNET_PNPMMIO_SIZE, 0, s->mmio_index);
s->irq = pci_dev->irq[0];
s->phys_mem_read = pci_physical_memory_read;
......
......@@ -37,10 +37,31 @@
typedef PCIHostState I440FXState;
#define PIIX_NUM_PIC_IRQS 16 /* i8259 * 2 */
#define PIIX_NUM_PIRQS 4ULL /* PIRQ[A-D] */
#define PIIX_PIRQC 0x60
typedef struct PIIX3State {
PCIDevice dev;
int pci_irq_levels[4];
/*
* bitmap to track pic levels.
* The pic level is the logical OR of all the PCI irqs mapped to it
* So one PIC level is tracked by PIIX_NUM_PIRQS bits.
*
* PIRQ is mapped to PIC pins, we track it by
* PIIX_NUM_PIRQS * PIIX_NUM_PIC_IRQS = 64 bits with
* pic_irq * PIIX_NUM_PIRQS + pirq
*/
#if PIIX_NUM_PIC_IRQS * PIIX_NUM_PIRQS > 64
#error "unable to encode pic state in 64bit in pic_levels."
#endif
uint64_t pic_levels;
qemu_irq *pic;
/* This member isn't used. Just for save/load compatibility */
int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
} PIIX3State;
struct PCII440FXState {
......@@ -55,16 +76,16 @@ struct PCII440FXState {
#define I440FX_PAM_SIZE 7
#define I440FX_SMRAM 0x72
static void piix3_set_irq(void *opaque, int irq_num, int level);
static void piix3_set_irq(void *opaque, int pirq, int level);
/* return the global irq number corresponding to a given device irq
pin. We could also use the bus number to have a more precise
mapping. */
static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
static int pci_slot_get_pirq(PCIDevice *pci_dev, int pci_intx)
{
int slot_addend;
slot_addend = (pci_dev->devfn >> 3) - 1;
return (irq_num + slot_addend) & 3;
return (pci_intx + slot_addend) & 3;
}
static void update_pam(PCII440FXState *d, uint32_t start, uint32_t end, int r)
......@@ -162,9 +183,11 @@ static int i440fx_load_old(QEMUFile* f, void *opaque, int version_id)
i440fx_update_memory_mappings(d);
qemu_get_8s(f, &d->smm_enabled);
if (version_id == 2)
for (i = 0; i < 4; i++)
d->piix3->pci_irq_levels[i] = qemu_get_be32(f);
if (version_id == 2) {
for (i = 0; i < PIIX_NUM_PIRQS; i++) {
qemu_get_be32(f); /* dummy load for compatibility */
}
}
return 0;
}
......@@ -236,7 +259,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *
piix3 = DO_UPCAST(PIIX3State, dev,
pci_create_simple_multifunction(b, -1, true, "PIIX3"));
piix3->pic = pic;
pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3, 4);
pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3, PIIX_NUM_PIRQS);
(*pi440fx_state)->piix3 = piix3;
*piix3_devfn = piix3->dev.devfn;
......@@ -250,26 +273,60 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *
}
/* PIIX3 PCI to ISA bridge */
static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
{
qemu_set_irq(piix3->pic[pic_irq],
!!(piix3->pic_levels &
(((1UL << PIIX_NUM_PIRQS) - 1) <<
(pic_irq * PIIX_NUM_PIRQS))));
}
static void piix3_set_irq_level(PIIX3State *piix3, int pirq, int level)
{
int pic_irq;
uint64_t mask;
pic_irq = piix3->dev.config[PIIX_PIRQC + pirq];
if (pic_irq >= PIIX_NUM_PIC_IRQS) {
return;
}
static void piix3_set_irq(void *opaque, int irq_num, int level)
mask = 1ULL << ((pic_irq * PIIX_NUM_PIRQS) + pirq);
piix3->pic_levels &= ~mask;
piix3->pic_levels |= mask * !!level;
piix3_set_irq_pic(piix3, pic_irq);
}
static void piix3_set_irq(void *opaque, int pirq, int level)
{
int i, pic_irq, pic_level;
PIIX3State *piix3 = opaque;
piix3_set_irq_level(piix3, pirq, level);
}
/* irq routing is changed. so rebuild bitmap */
static void piix3_update_irq_levels(PIIX3State *piix3)
{
int pirq;
piix3->pci_irq_levels[irq_num] = level;
/* now we change the pic irq level according to the piix irq mappings */
/* XXX: optimize */
pic_irq = piix3->dev.config[0x60 + irq_num];
if (pic_irq < 16) {
/* The pic level is the logical OR of all the PCI irqs mapped
to it */
pic_level = 0;
for (i = 0; i < 4; i++) {
if (pic_irq == piix3->dev.config[0x60 + i])
pic_level |= piix3->pci_irq_levels[i];
piix3->pic_levels = 0;
for (pirq = 0; pirq < PIIX_NUM_PIRQS; pirq++) {
piix3_set_irq_level(piix3, pirq,
pci_bus_get_irq_level(piix3->dev.bus, pirq));
}
}
static void piix3_write_config(PCIDevice *dev,
uint32_t address, uint32_t val, int len)
{
pci_default_write_config(dev, address, val, len);
if (ranges_overlap(address, len, PIIX_PIRQC, 4)) {
PIIX3State *piix3 = DO_UPCAST(PIIX3State, dev, dev);
int pic_irq;
piix3_update_irq_levels(piix3);
for (pic_irq = 0; pic_irq < PIIX_NUM_PIC_IRQS; pic_irq++) {
piix3_set_irq_pic(piix3, pic_irq);
}
qemu_set_irq(piix3->pic[pic_irq], pic_level);
}
}
......@@ -310,7 +367,25 @@ static void piix3_reset(void *opaque)
pci_conf[0xac] = 0x00;
pci_conf[0xae] = 0x00;
memset(d->pci_irq_levels, 0, sizeof(d->pci_irq_levels));
d->pic_levels = 0;
}
static int piix3_post_load(void *opaque, int version_id)
{
PIIX3State *piix3 = opaque;
piix3_update_irq_levels(piix3);
return 0;
}
static void piix3_pre_save(void *opaque)
{
int i;
PIIX3State *piix3 = opaque;
for (i = 0; i < ARRAY_SIZE(piix3->pci_irq_levels_vmstate); i++) {
piix3->pci_irq_levels_vmstate[i] =
pci_bus_get_irq_level(piix3->dev.bus, i);
}
}
static const VMStateDescription vmstate_piix3 = {
......@@ -318,9 +393,12 @@ static const VMStateDescription vmstate_piix3 = {
.version_id = 3,
.minimum_version_id = 2,
.minimum_version_id_old = 2,
.post_load = piix3_post_load,
.pre_save = piix3_pre_save,
.fields = (VMStateField []) {
VMSTATE_PCI_DEVICE(dev, PIIX3State),
VMSTATE_INT32_ARRAY_V(pci_irq_levels, PIIX3State, 4, 3),
VMSTATE_INT32_ARRAY_V(pci_irq_levels_vmstate, PIIX3State,
PIIX_NUM_PIRQS, 3),
VMSTATE_END_OF_LIST()
}
};
......@@ -359,6 +437,7 @@ static PCIDeviceInfo i440fx_info[] = {
.qdev.no_user = 1,
.no_hotplug = 1,