Commit 52fc1d83bc50b0b6fc6861cfecc5763edbad7e60

Authored by balrog
1 parent b26177d7

Save/load PCI-device, PCI-bus and PIIX3 irq-related state (patches by Uri Lublin.

Note that other PCI bridges are not fixed here.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3793 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 63 additions and 7 deletions
hw/pci.c
... ... @@ -42,6 +42,7 @@ struct PCIBus {
42 42 PCIBus *next;
43 43 /* The bus IRQ state is the logical OR of the connected devices.
44 44 Keep a count of the number of devices with raised IRQs. */
  45 + int nirq;
45 46 int irq_count[];
46 47 };
47 48  
... ... @@ -52,16 +53,51 @@ target_phys_addr_t pci_mem_base;
52 53 static int pci_irq_index;
53 54 static PCIBus *first_bus;
54 55  
  56 +static void pcibus_save(QEMUFile *f, void *opaque)
  57 +{
  58 + PCIBus *bus = (PCIBus *)opaque;
  59 + int i;
  60 +
  61 + qemu_put_be32(f, bus->nirq);
  62 + for (i = 0; i < bus->nirq; i++)
  63 + qemu_put_be32(f, bus->irq_count[i]);
  64 +}
  65 +
  66 +static int pcibus_load(QEMUFile *f, void *opaque, int version_id)
  67 +{
  68 + PCIBus *bus = (PCIBus *)opaque;
  69 + int i, nirq;
  70 +
  71 + if (version_id != 1)
  72 + return -EINVAL;
  73 +
  74 + nirq = qemu_get_be32(f);
  75 + if (bus->nirq != nirq) {
  76 + fprintf(stderr, "pcibus_load: nirq mismatch: src=%d dst=%d\n",
  77 + nirq, bus->nirq);
  78 + return -EINVAL;
  79 + }
  80 +
  81 + for (i = 0; i < nirq; i++)
  82 + bus->irq_count[i] = qemu_get_be32(f);
  83 +
  84 + return 0;
  85 +}
  86 +
55 87 PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
56 88 qemu_irq *pic, int devfn_min, int nirq)
57 89 {
58 90 PCIBus *bus;
  91 + static int nbus = 0;
  92 +
59 93 bus = qemu_mallocz(sizeof(PCIBus) + (nirq * sizeof(int)));
60 94 bus->set_irq = set_irq;
61 95 bus->map_irq = map_irq;
62 96 bus->irq_opaque = pic;
63 97 bus->devfn_min = devfn_min;
  98 + bus->nirq = nirq;
64 99 first_bus = bus;
  100 + register_savevm("PCIBUS", nbus++, 1, pcibus_save, pcibus_load, bus);
65 101 return bus;
66 102 }
67 103  
... ... @@ -83,18 +119,29 @@ int pci_bus_num(PCIBus *s)
83 119  
84 120 void pci_device_save(PCIDevice *s, QEMUFile *f)
85 121 {
86   - qemu_put_be32(f, 1); /* PCI device version */
  122 + int i;
  123 +
  124 + qemu_put_be32(f, 2); /* PCI device version */
87 125 qemu_put_buffer(f, s->config, 256);
  126 + for (i = 0; i < 4; i++)
  127 + qemu_put_be32(f, s->irq_state[i]);
88 128 }
89 129  
90 130 int pci_device_load(PCIDevice *s, QEMUFile *f)
91 131 {
92 132 uint32_t version_id;
  133 + int i;
  134 +
93 135 version_id = qemu_get_be32(f);
94   - if (version_id != 1)
  136 + if (version_id > 2)
95 137 return -EINVAL;
96 138 qemu_get_buffer(f, s->config, 256);
97 139 pci_update_mappings(s);
  140 +
  141 + if (version_id >= 2)
  142 + for (i = 0; i < 4; i ++)
  143 + s->irq_state[i] = qemu_get_be32(f);
  144 +
98 145 return 0;
99 146 }
100 147  
... ...
hw/piix_pci.c
... ... @@ -57,6 +57,7 @@ static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
57 57  
58 58 static uint32_t isa_page_descs[384 / 4];
59 59 static uint8_t smm_enabled;
  60 +static int pci_irq_levels[4];
60 61  
61 62 static void update_pam(PCIDevice *d, uint32_t start, uint32_t end, int r)
62 63 {
... ... @@ -139,22 +140,32 @@ static void i440fx_write_config(PCIDevice *d,
139 140 static void i440fx_save(QEMUFile* f, void *opaque)
140 141 {
141 142 PCIDevice *d = opaque;
  143 + int i;
  144 +
142 145 pci_device_save(d, f);
143 146 qemu_put_8s(f, &smm_enabled);
  147 +
  148 + for (i = 0; i < 4; i++)
  149 + qemu_put_be32(f, pci_irq_levels[i]);
144 150 }
145 151  
146 152 static int i440fx_load(QEMUFile* f, void *opaque, int version_id)
147 153 {
148 154 PCIDevice *d = opaque;
149   - int ret;
  155 + int ret, i;
150 156  
151   - if (version_id != 1)
  157 + if (version_id > 2)
152 158 return -EINVAL;
153 159 ret = pci_device_load(d, f);
154 160 if (ret < 0)
155 161 return ret;
156 162 i440fx_update_memory_mappings(d);
157 163 qemu_get_8s(f, &smm_enabled);
  164 +
  165 + if (version_id >= 2)
  166 + for (i = 0; i < 4; i++)
  167 + pci_irq_levels[i] = qemu_get_be32(f);
  168 +
158 169 return 0;
159 170 }
160 171  
... ... @@ -192,7 +203,7 @@ PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic)
192 203  
193 204 d->config[0x72] = 0x02; /* SMRAM */
194 205  
195   - register_savevm("I440FX", 0, 1, i440fx_save, i440fx_load, d);
  206 + register_savevm("I440FX", 0, 2, i440fx_save, i440fx_load, d);
196 207 *pi440fx_state = d;
197 208 return b;
198 209 }
... ... @@ -205,8 +216,6 @@ PCIDevice *piix4_dev;
205 216 /* just used for simpler irq handling. */
206 217 #define PCI_IRQ_WORDS ((PCI_DEVICES_MAX + 31) / 32)
207 218  
208   -static int pci_irq_levels[4];
209   -
210 219 static void piix3_set_irq(qemu_irq *pic, int irq_num, int level)
211 220 {
212 221 int i, pic_irq, pic_level;
... ...