diff mbox

[19/25] ahci: add migration support

Message ID ef272249acf17363d5a9e3b38f9b5896349cfd4d.1347561356.git.jbaron@redhat.com
State New
Headers show

Commit Message

Jason Baron Sept. 13, 2012, 8:12 p.m. UTC
Add support for ahci migration. This patch builds upon the patches originally
posted by Andreas Färber.

These patches have been tested by migrating Windows 7 and Fedora 16 guests on
both piix with ahci attached and on q35 (which has a built-in ahci controller).

Signed-off-by: Andreas Färber <afaerber@suse.de>
Cc: Alexander Graf <agraf@suse.de>
Cc: Jason Baron <jbaron@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: Juan Quintela <quintela@redhat.com>
Cc: Igor Mitsyanko <i.mitsyanko@samsung.com>
Signed-off-by: Jason Baron <jbaron@redhat.com>
---

v3:
    -map command list base addr and fis base addr at destination
    -drop port_no
    -make use of VMSTATE_STRUCT_VARRAY_POINTER_INT32

 hw/ide/ahci.c |   64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 hw/ide/ahci.h |   10 +++++++++
 hw/ide/ich.c  |   11 +++++++--
 3 files changed, 81 insertions(+), 4 deletions(-)

Comments

Juan Quintela Sept. 14, 2012, 8:38 a.m. UTC | #1
Jason Baron <jbaron@redhat.com> wrote:
> Add support for ahci migration. This patch builds upon the patches originally
> posted by Andreas Färber.
>
> These patches have been tested by migrating Windows 7 and Fedora 16 guests on
> both piix with ahci attached and on q35 (which has a built-in ahci controller).

> +const VMStateDescription vmstate_ahci = {
> +    .name = "ahci",
> +    .version_id = 1,
> +    .post_load = ahci_state_post_load,
> +    .fields = (VMStateField []) {

  +        VMSTATE_INT32_EQUAL(ports, AHCIState),


> +        VMSTATE_STRUCT_VARRAY_POINTER_INT32(dev, AHCIState, ports,
> +                                     vmstate_ahci_device, AHCIDevice),
> +        VMSTATE_UINT32(control_regs.cap, AHCIState),
> +        VMSTATE_UINT32(control_regs.ghc, AHCIState),
> +        VMSTATE_UINT32(control_regs.irqstatus, AHCIState),
> +        VMSTATE_UINT32(control_regs.impl, AHCIState),
> +        VMSTATE_UINT32(control_regs.version, AHCIState),
> +        VMSTATE_UINT32(idp_index, AHCIState),
> +        VMSTATE_END_OF_LIST()
> +    },
> +};
> +

Only comment that I have is if we can add that bit on the vmstate
transition.  That way we can detect when the number of ports between the
two instances are different.

You can change it to; (it checks that ports received is less ore equal
than original value):

  +        VMSTATE_INT32_LE(ports, AHCIState),

If the code will work if we transfer less ports that are active. I have
no clue which one makes more sense from the ahci point of view.

Thanks, Juan.
diff mbox

Patch

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 9561210..3d41771 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -1203,6 +1203,65 @@  void ahci_reset(AHCIState *s)
     }
 }
 
+static const VMStateDescription vmstate_ahci_device = {
+    .name = "ahci port",
+    .version_id = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_IDE_BUS(port, AHCIDevice),
+        VMSTATE_UINT32(port_state, AHCIDevice),
+        VMSTATE_UINT32(finished, AHCIDevice),
+        VMSTATE_UINT32(port_regs.lst_addr, AHCIDevice),
+        VMSTATE_UINT32(port_regs.lst_addr_hi, AHCIDevice),
+        VMSTATE_UINT32(port_regs.fis_addr, AHCIDevice),
+        VMSTATE_UINT32(port_regs.fis_addr_hi, AHCIDevice),
+        VMSTATE_UINT32(port_regs.irq_stat, AHCIDevice),
+        VMSTATE_UINT32(port_regs.irq_mask, AHCIDevice),
+        VMSTATE_UINT32(port_regs.cmd, AHCIDevice),
+        VMSTATE_UINT32(port_regs.tfdata, AHCIDevice),
+        VMSTATE_UINT32(port_regs.sig, AHCIDevice),
+        VMSTATE_UINT32(port_regs.scr_stat, AHCIDevice),
+        VMSTATE_UINT32(port_regs.scr_ctl, AHCIDevice),
+        VMSTATE_UINT32(port_regs.scr_err, AHCIDevice),
+        VMSTATE_UINT32(port_regs.scr_act, AHCIDevice),
+        VMSTATE_UINT32(port_regs.cmd_issue, AHCIDevice),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static int ahci_state_post_load(void *opaque, int version_id)
+{
+    int i;
+    AHCIState *s = opaque;
+
+    for (i = 0; i < s->ports; i++) {
+        AHCIPortRegs *pr = &s->dev[i].port_regs;
+
+        map_page(&s->dev[i].lst,
+                 ((uint64_t)pr->lst_addr_hi << 32) | pr->lst_addr, 1024);
+        map_page(&s->dev[i].res_fis,
+                 ((uint64_t)pr->fis_addr_hi << 32) | pr->fis_addr, 256);
+    }
+
+    return 0;
+}
+
+const VMStateDescription vmstate_ahci = {
+    .name = "ahci",
+    .version_id = 1,
+    .post_load = ahci_state_post_load,
+    .fields = (VMStateField []) {
+        VMSTATE_STRUCT_VARRAY_POINTER_INT32(dev, AHCIState, ports,
+                                     vmstate_ahci_device, AHCIDevice),
+        VMSTATE_UINT32(control_regs.cap, AHCIState),
+        VMSTATE_UINT32(control_regs.ghc, AHCIState),
+        VMSTATE_UINT32(control_regs.irqstatus, AHCIState),
+        VMSTATE_UINT32(control_regs.impl, AHCIState),
+        VMSTATE_UINT32(control_regs.version, AHCIState),
+        VMSTATE_UINT32(idp_index, AHCIState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
 typedef struct SysbusAHCIState {
     SysBusDevice busdev;
     AHCIState ahci;
@@ -1211,7 +1270,10 @@  typedef struct SysbusAHCIState {
 
 static const VMStateDescription vmstate_sysbus_ahci = {
     .name = "sysbus-ahci",
-    .unmigratable = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_AHCI(ahci, AHCIPCIState),
+        VMSTATE_END_OF_LIST()
+    },
 };
 
 static void sysbus_ahci_reset(DeviceState *dev)
diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
index 1200a56..7719dbf 100644
--- a/hw/ide/ahci.h
+++ b/hw/ide/ahci.h
@@ -307,6 +307,16 @@  typedef struct AHCIPCIState {
     AHCIState ahci;
 } AHCIPCIState;
 
+extern const VMStateDescription vmstate_ahci;
+
+#define VMSTATE_AHCI(_field, _state) {                               \
+    .name       = (stringify(_field)),                               \
+    .size       = sizeof(AHCIState),                                 \
+    .vmsd       = &vmstate_ahci,                                     \
+    .flags      = VMS_STRUCT,                                        \
+    .offset     = vmstate_offset_value(_state, _field, AHCIState),   \
+}
+
 typedef struct NCQFrame {
     uint8_t fis_type;
     uint8_t c;
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index 272b773..ae6f56f 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -79,9 +79,14 @@ 
 #define ICH9_IDP_INDEX          0x10
 #define ICH9_IDP_INDEX_LOG2     0x04
 
-static const VMStateDescription vmstate_ahci = {
+static const VMStateDescription vmstate_ich9_ahci = {
     .name = "ahci",
-    .unmigratable = 1,
+    .version_id = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_PCI_DEVICE(card, AHCIPCIState),
+        VMSTATE_AHCI(ahci, AHCIPCIState),
+        VMSTATE_END_OF_LIST()
+    },
 };
 
 static void pci_ich9_reset(DeviceState *dev)
@@ -152,7 +157,7 @@  static void ich_ahci_class_init(ObjectClass *klass, void *data)
     k->device_id = PCI_DEVICE_ID_INTEL_82801IR;
     k->revision = 0x02;
     k->class_id = PCI_CLASS_STORAGE_SATA;
-    dc->vmsd = &vmstate_ahci;
+    dc->vmsd = &vmstate_ich9_ahci;
     dc->reset = pci_ich9_reset;
 }