summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorJuan Quintela <quintela@redhat.com>2009-08-20 19:42:39 +0200
committerAnthony Liguori <aliguori@us.ibm.com>2009-08-27 20:30:22 -0500
commit73534f2f682f2957fabb25e3890481098cc5dcee (patch)
tree16dc4aa473ce9f024409689a77e3ff775a8f6c66 /hw
parentf16c4abfadf9ae63bd22fb793484912542be0da7 (diff)
downloadqemu-73534f2f682f2957fabb25e3890481098cc5dcee.tar.gz
Port PCIDevice state to VMState
This uses a variant of buffer, with extra checks. Also uses the new support for cheking that a read value is less or equal than a field. Signed-off-by: Juan Quintela <quintela@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/hw.h12
-rw-r--r--hw/pci.c65
2 files changed, 55 insertions, 22 deletions
diff --git a/hw/hw.h b/hw/hw.h
index f7b0a14793..73f2f43281 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -402,6 +402,18 @@ extern const VMStateInfo vmstate_info_buffer;
+ type_check_array(uint8_t,typeof_field(_state, _field),sizeof(typeof_field(_state,_field))) \
}
+extern const VMStateDescription vmstate_pci_device;
+
+#define VMSTATE_PCI_DEVICE(_field, _state) { \
+ .name = (stringify(_field)), \
+ .version_id = 2, \
+ .size = sizeof(PCIDevice), \
+ .vmsd = &vmstate_pci_device, \
+ .flags = VMS_STRUCT, \
+ .offset = offsetof(_state, _field) \
+ + type_check(PCIDevice,typeof_field(_state, _field)) \
+}
+
/* _f : field name
_f_n : num of elements field_name
_n : num of elements
diff --git a/hw/pci.c b/hw/pci.c
index 7644dee90e..2266e23c11 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -140,39 +140,60 @@ int pci_bus_num(PCIBus *s)
return s->bus_num;
}
-void pci_device_save(PCIDevice *s, QEMUFile *f)
-{
- int i;
-
- qemu_put_be32(f, s->version_id); /* PCI device version */
- qemu_put_buffer(f, s->config, 256);
- for (i = 0; i < 4; i++)
- qemu_put_be32(f, s->irq_state[i]);
-}
-
-int pci_device_load(PCIDevice *s, QEMUFile *f)
+static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
{
- uint8_t config[PCI_CONFIG_SPACE_SIZE];
- uint32_t version_id;
+ PCIDevice *s = container_of(pv, PCIDevice, config);
+ uint8_t config[size];
int i;
- version_id = qemu_get_be32(f);
- if (version_id > 2)
- return -EINVAL;
- qemu_get_buffer(f, config, sizeof config);
- for (i = 0; i < sizeof config; ++i)
+ qemu_get_buffer(f, config, size);
+ for (i = 0; i < size; ++i)
if ((config[i] ^ s->config[i]) & s->cmask[i] & ~s->wmask[i])
return -EINVAL;
- memcpy(s->config, config, sizeof config);
+ memcpy(s->config, config, size);
pci_update_mappings(s);
- if (version_id >= 2)
- for (i = 0; i < 4; i ++)
- s->irq_state[i] = qemu_get_be32(f);
return 0;
}
+/* just put buffer */
+static void put_pci_config_device(QEMUFile *f, const void *pv, size_t size)
+{
+ const uint8_t *v = pv;
+ qemu_put_buffer(f, v, size);
+}
+
+static VMStateInfo vmstate_info_pci_config = {
+ .name = "pci config",
+ .get = get_pci_config_device,
+ .put = put_pci_config_device,
+};
+
+const VMStateDescription vmstate_pci_device = {
+ .name = "PCIDevice",
+ .version_id = 2,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_INT32_LE(version_id, PCIDevice),
+ VMSTATE_SINGLE(config, PCIDevice, 0, vmstate_info_pci_config,
+ typeof_field(PCIDevice,config)),
+ VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, 4, 2),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+void pci_device_save(PCIDevice *s, QEMUFile *f)
+{
+ vmstate_save_state(f, &vmstate_pci_device, s);
+}
+
+int pci_device_load(PCIDevice *s, QEMUFile *f)
+{
+ return vmstate_load_state(f, &vmstate_pci_device, s, s->version_id);
+}
+
static int pci_set_default_subsystem_id(PCIDevice *pci_dev)
{
uint16_t *id;