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,6 +42,7 @@ struct PCIBus {
42 PCIBus *next; 42 PCIBus *next;
43 /* The bus IRQ state is the logical OR of the connected devices. 43 /* The bus IRQ state is the logical OR of the connected devices.
44 Keep a count of the number of devices with raised IRQs. */ 44 Keep a count of the number of devices with raised IRQs. */
  45 + int nirq;
45 int irq_count[]; 46 int irq_count[];
46 }; 47 };
47 48
@@ -52,16 +53,51 @@ target_phys_addr_t pci_mem_base; @@ -52,16 +53,51 @@ target_phys_addr_t pci_mem_base;
52 static int pci_irq_index; 53 static int pci_irq_index;
53 static PCIBus *first_bus; 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 PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, 87 PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
56 qemu_irq *pic, int devfn_min, int nirq) 88 qemu_irq *pic, int devfn_min, int nirq)
57 { 89 {
58 PCIBus *bus; 90 PCIBus *bus;
  91 + static int nbus = 0;
  92 +
59 bus = qemu_mallocz(sizeof(PCIBus) + (nirq * sizeof(int))); 93 bus = qemu_mallocz(sizeof(PCIBus) + (nirq * sizeof(int)));
60 bus->set_irq = set_irq; 94 bus->set_irq = set_irq;
61 bus->map_irq = map_irq; 95 bus->map_irq = map_irq;
62 bus->irq_opaque = pic; 96 bus->irq_opaque = pic;
63 bus->devfn_min = devfn_min; 97 bus->devfn_min = devfn_min;
  98 + bus->nirq = nirq;
64 first_bus = bus; 99 first_bus = bus;
  100 + register_savevm("PCIBUS", nbus++, 1, pcibus_save, pcibus_load, bus);
65 return bus; 101 return bus;
66 } 102 }
67 103
@@ -83,18 +119,29 @@ int pci_bus_num(PCIBus *s) @@ -83,18 +119,29 @@ int pci_bus_num(PCIBus *s)
83 119
84 void pci_device_save(PCIDevice *s, QEMUFile *f) 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 qemu_put_buffer(f, s->config, 256); 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 int pci_device_load(PCIDevice *s, QEMUFile *f) 130 int pci_device_load(PCIDevice *s, QEMUFile *f)
91 { 131 {
92 uint32_t version_id; 132 uint32_t version_id;
  133 + int i;
  134 +
93 version_id = qemu_get_be32(f); 135 version_id = qemu_get_be32(f);
94 - if (version_id != 1) 136 + if (version_id > 2)
95 return -EINVAL; 137 return -EINVAL;
96 qemu_get_buffer(f, s->config, 256); 138 qemu_get_buffer(f, s->config, 256);
97 pci_update_mappings(s); 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 return 0; 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,6 +57,7 @@ static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
57 57
58 static uint32_t isa_page_descs[384 / 4]; 58 static uint32_t isa_page_descs[384 / 4];
59 static uint8_t smm_enabled; 59 static uint8_t smm_enabled;
  60 +static int pci_irq_levels[4];
60 61
61 static void update_pam(PCIDevice *d, uint32_t start, uint32_t end, int r) 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,22 +140,32 @@ static void i440fx_write_config(PCIDevice *d,
139 static void i440fx_save(QEMUFile* f, void *opaque) 140 static void i440fx_save(QEMUFile* f, void *opaque)
140 { 141 {
141 PCIDevice *d = opaque; 142 PCIDevice *d = opaque;
  143 + int i;
  144 +
142 pci_device_save(d, f); 145 pci_device_save(d, f);
143 qemu_put_8s(f, &smm_enabled); 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 static int i440fx_load(QEMUFile* f, void *opaque, int version_id) 152 static int i440fx_load(QEMUFile* f, void *opaque, int version_id)
147 { 153 {
148 PCIDevice *d = opaque; 154 PCIDevice *d = opaque;
149 - int ret; 155 + int ret, i;
150 156
151 - if (version_id != 1) 157 + if (version_id > 2)
152 return -EINVAL; 158 return -EINVAL;
153 ret = pci_device_load(d, f); 159 ret = pci_device_load(d, f);
154 if (ret < 0) 160 if (ret < 0)
155 return ret; 161 return ret;
156 i440fx_update_memory_mappings(d); 162 i440fx_update_memory_mappings(d);
157 qemu_get_8s(f, &smm_enabled); 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 return 0; 169 return 0;
159 } 170 }
160 171
@@ -192,7 +203,7 @@ PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic) @@ -192,7 +203,7 @@ PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic)
192 203
193 d->config[0x72] = 0x02; /* SMRAM */ 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 *pi440fx_state = d; 207 *pi440fx_state = d;
197 return b; 208 return b;
198 } 209 }
@@ -205,8 +216,6 @@ PCIDevice *piix4_dev; @@ -205,8 +216,6 @@ PCIDevice *piix4_dev;
205 /* just used for simpler irq handling. */ 216 /* just used for simpler irq handling. */
206 #define PCI_IRQ_WORDS ((PCI_DEVICES_MAX + 31) / 32) 217 #define PCI_IRQ_WORDS ((PCI_DEVICES_MAX + 31) / 32)
207 218
208 -static int pci_irq_levels[4];  
209 -  
210 static void piix3_set_irq(qemu_irq *pic, int irq_num, int level) 219 static void piix3_set_irq(qemu_irq *pic, int irq_num, int level)
211 { 220 {
212 int i, pic_irq, pic_level; 221 int i, pic_irq, pic_level;