diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 7efa119..ab3f398 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -416,12 +416,6 @@ static void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters);
 /* Writes tally counters to specified physical memory address */
 static void RTL8139TallyCounters_physical_memory_write(target_phys_addr_t tc_addr, RTL8139TallyCounters* counters);

-/* Loads values of tally counters from VM state file */
-static void RTL8139TallyCounters_load(QEMUFile* f, RTL8139TallyCounters *tally_counters);
-
-/* Saves values of tally counters to VM state file */
-static void RTL8139TallyCounters_save(QEMUFile* f, RTL8139TallyCounters *tally_counters);
-
 typedef struct RTL8139State {
     PCIDevice dev;
     uint8_t phys[8]; /* mac address */
@@ -1349,16 +1343,6 @@ static const VMStateDescription vmstate_tally_counters = {
         VMSTATE_END_OF_LIST()
     }
 };
-static void RTL8139TallyCounters_load(QEMUFile* f, RTL8139TallyCounters *tally_counters)
-{
-    vmstate_load_state(f, &vmstate_tally_counters, tally_counters, vmstate_tally_counters.version_id);
-}
-
-/* Saves values of tally counters to VM state file */
-static void RTL8139TallyCounters_save(QEMUFile* f, RTL8139TallyCounters *tally_counters)
-{
-    vmstate_save_state(f, &vmstate_tally_counters, tally_counters);
-}

 static void rtl8139_ChipCmd_write(RTL8139State *s, uint32_t val)
 {
@@ -3112,212 +3096,97 @@ static uint32_t rtl8139_mmio_readl(void *opaque, target_phys_addr_t addr)
     return val;
 }

-/* */
-
-static void rtl8139_save(QEMUFile* f,void* opaque)
-{
-    RTL8139State* s = opaque;
-    unsigned int i;
-
-    pci_device_save(&s->dev, f);
-
-    qemu_put_buffer(f, s->phys, 6);
-    qemu_put_buffer(f, s->mult, 8);
-
-    for (i=0; i<4; ++i)
-    {
-        qemu_put_be32s(f, &s->TxStatus[i]); /* TxStatus0 */
-    }
-    for (i=0; i<4; ++i)
-    {
-        qemu_put_be32s(f, &s->TxAddr[i]); /* TxAddr0 */
-    }
-
-    qemu_put_be32s(f, &s->RxBuf); /* Receive buffer */
-    qemu_put_be32s(f, &s->RxBufferSize);/* internal variable, receive ring buffer size in C mode */
-    qemu_put_be32s(f, &s->RxBufPtr);
-    qemu_put_be32s(f, &s->RxBufAddr);
-
-    qemu_put_be16s(f, &s->IntrStatus);
-    qemu_put_be16s(f, &s->IntrMask);
-
-    qemu_put_be32s(f, &s->TxConfig);
-    qemu_put_be32s(f, &s->RxConfig);
-    qemu_put_be32s(f, &s->RxMissed);
-    qemu_put_be16s(f, &s->CSCR);
-
-    qemu_put_8s(f, &s->Cfg9346);
-    qemu_put_8s(f, &s->Config0);
-    qemu_put_8s(f, &s->Config1);
-    qemu_put_8s(f, &s->Config3);
-    qemu_put_8s(f, &s->Config4);
-    qemu_put_8s(f, &s->Config5);
-
-    qemu_put_8s(f, &s->clock_enabled);
-    qemu_put_8s(f, &s->bChipCmdState);
-
-    qemu_put_be16s(f, &s->MultiIntr);
-
-    qemu_put_be16s(f, &s->BasicModeCtrl);
-    qemu_put_be16s(f, &s->BasicModeStatus);
-    qemu_put_be16s(f, &s->NWayAdvert);
-    qemu_put_be16s(f, &s->NWayLPAR);
-    qemu_put_be16s(f, &s->NWayExpansion);
-
-    qemu_put_be16s(f, &s->CpCmd);
-    qemu_put_8s(f, &s->TxThresh);
-
-    i = 0;
-    qemu_put_be32s(f, &i); /* unused.  */
-    qemu_put_buffer(f, s->macaddr, 6);
-    qemu_put_be32(f, s->rtl8139_mmio_io_addr);
-
-    qemu_put_be32s(f, &s->currTxDesc);
-    qemu_put_be32s(f, &s->currCPlusRxDesc);
-    qemu_put_be32s(f, &s->currCPlusTxDesc);
-    qemu_put_be32s(f, &s->RxRingAddrLO);
-    qemu_put_be32s(f, &s->RxRingAddrHI);
-
-    for (i=0; i<EEPROM_9346_SIZE; ++i)
-    {
-        qemu_put_be16s(f, &s->eeprom.contents[i]);
-    }
-    qemu_put_be32(f, s->eeprom.mode);
-    qemu_put_be32s(f, &s->eeprom.tick);
-    qemu_put_8s(f, &s->eeprom.address);
-    qemu_put_be16s(f, &s->eeprom.input);
-    qemu_put_be16s(f, &s->eeprom.output);
-
-    qemu_put_8s(f, &s->eeprom.eecs);
-    qemu_put_8s(f, &s->eeprom.eesk);
-    qemu_put_8s(f, &s->eeprom.eedi);
-    qemu_put_8s(f, &s->eeprom.eedo);
-
-    qemu_put_be32s(f, &s->TCTR);
-    qemu_put_be32s(f, &s->TimerInt);
-    qemu_put_be64(f, s->TCTR_base);
-
-    RTL8139TallyCounters_save(f, &s->tally_counters);
-
-    qemu_put_be32s(f, &s->cplus_enabled);
-}
-
-static int rtl8139_load(QEMUFile* f,void* opaque,int version_id)
+static int rtl8139_post_load(void *opaque, int version_id)
 {
     RTL8139State* s = opaque;
-    unsigned int i;
-    int ret;
-
-    /* just 2 versions for now */
-    if (version_id > 4)
-            return -EINVAL;
-
-    if (version_id >= 3) {
-        ret = pci_device_load(&s->dev, f);
-        if (ret < 0)
-            return ret;
-    }
-
-    /* saved since version 1 */
-    qemu_get_buffer(f, s->phys, 6);
-    qemu_get_buffer(f, s->mult, 8);
-
-    for (i=0; i<4; ++i)
-    {
-        qemu_get_be32s(f, &s->TxStatus[i]); /* TxStatus0 */
-    }
-    for (i=0; i<4; ++i)
-    {
-        qemu_get_be32s(f, &s->TxAddr[i]); /* TxAddr0 */
-    }
-
-    qemu_get_be32s(f, &s->RxBuf); /* Receive buffer */
-    qemu_get_be32s(f, &s->RxBufferSize);/* internal variable, receive ring buffer size in C mode */
-    qemu_get_be32s(f, &s->RxBufPtr);
-    qemu_get_be32s(f, &s->RxBufAddr);
-
-    qemu_get_be16s(f, &s->IntrStatus);
-    qemu_get_be16s(f, &s->IntrMask);
-
-    qemu_get_be32s(f, &s->TxConfig);
-    qemu_get_be32s(f, &s->RxConfig);
-    qemu_get_be32s(f, &s->RxMissed);
-    qemu_get_be16s(f, &s->CSCR);
-
-    qemu_get_8s(f, &s->Cfg9346);
-    qemu_get_8s(f, &s->Config0);
-    qemu_get_8s(f, &s->Config1);
-    qemu_get_8s(f, &s->Config3);
-    qemu_get_8s(f, &s->Config4);
-    qemu_get_8s(f, &s->Config5);
-
-    qemu_get_8s(f, &s->clock_enabled);
-    qemu_get_8s(f, &s->bChipCmdState);
-
-    qemu_get_be16s(f, &s->MultiIntr);
-
-    qemu_get_be16s(f, &s->BasicModeCtrl);
-    qemu_get_be16s(f, &s->BasicModeStatus);
-    qemu_get_be16s(f, &s->NWayAdvert);
-    qemu_get_be16s(f, &s->NWayLPAR);
-    qemu_get_be16s(f, &s->NWayExpansion);
-
-    qemu_get_be16s(f, &s->CpCmd);
-    qemu_get_8s(f, &s->TxThresh);
-
-    qemu_get_be32s(f, &i); /* unused.  */
-    qemu_get_buffer(f, s->macaddr, 6);
-    s->rtl8139_mmio_io_addr=qemu_get_be32(f);
-
-    qemu_get_be32s(f, &s->currTxDesc);
-    qemu_get_be32s(f, &s->currCPlusRxDesc);
-    qemu_get_be32s(f, &s->currCPlusTxDesc);
-    qemu_get_be32s(f, &s->RxRingAddrLO);
-    qemu_get_be32s(f, &s->RxRingAddrHI);
-
-    for (i=0; i<EEPROM_9346_SIZE; ++i)
-    {
-        qemu_get_be16s(f, &s->eeprom.contents[i]);
-    }
-    s->eeprom.mode=qemu_get_be32(f);
-    qemu_get_be32s(f, &s->eeprom.tick);
-    qemu_get_8s(f, &s->eeprom.address);
-    qemu_get_be16s(f, &s->eeprom.input);
-    qemu_get_be16s(f, &s->eeprom.output);
-
-    qemu_get_8s(f, &s->eeprom.eecs);
-    qemu_get_8s(f, &s->eeprom.eesk);
-    qemu_get_8s(f, &s->eeprom.eedi);
-    qemu_get_8s(f, &s->eeprom.eedo);
-
-    /* saved since version 2 */
-    if (version_id >= 2)
-    {
-        qemu_get_be32s(f, &s->TCTR);
-        qemu_get_be32s(f, &s->TimerInt);
-        s->TCTR_base=qemu_get_be64(f);
-
-        RTL8139TallyCounters_load(f, &s->tally_counters);
-    }
-    else
-    {
-        /* not saved, use default */
-        s->TCTR = 0;
-        s->TimerInt = 0;
-        s->TCTR_base = 0;
-
-        RTL8139TallyCounters_clear(&s->tally_counters);
-    }
-
-    if (version_id >= 4) {
-        qemu_get_be32s(f, &s->cplus_enabled);
-    } else {
+    if (version_id < 4) {
         s->cplus_enabled = s->CpCmd != 0;
     }

     return 0;
 }

+static const VMStateDescription vmstate_rtl8139 = {
+    .name = "rtl8139",
+    .version_id = 4,
+    .minimum_version_id = 3,
+    .minimum_version_id_old = 3,
+    .post_load = rtl8139_post_load,
+    .fields      = (VMStateField []) {
+        VMSTATE_PCI_DEVICE(dev, RTL8139State),
+        VMSTATE_PARTIAL_BUFFER(phys, RTL8139State, 6),
+        VMSTATE_BUFFER(mult, RTL8139State),
+        VMSTATE_UINT32_ARRAY(TxStatus, RTL8139State, 4),
+        VMSTATE_UINT32_ARRAY(TxAddr, RTL8139State, 4),
+
+        VMSTATE_UINT32(RxBuf, RTL8139State),
+        VMSTATE_UINT32(RxBufferSize, RTL8139State),
+        VMSTATE_UINT32(RxBufPtr, RTL8139State),
+        VMSTATE_UINT32(RxBufAddr, RTL8139State),
+
+        VMSTATE_UINT16(IntrStatus, RTL8139State),
+        VMSTATE_UINT16(IntrMask, RTL8139State),
+
+        VMSTATE_UINT32(TxConfig, RTL8139State),
+        VMSTATE_UINT32(RxConfig, RTL8139State),
+        VMSTATE_UINT32(RxMissed, RTL8139State),
+        VMSTATE_UINT16(CSCR, RTL8139State),
+
+        VMSTATE_UINT8(Cfg9346, RTL8139State),
+        VMSTATE_UINT8(Config0, RTL8139State),
+        VMSTATE_UINT8(Config1, RTL8139State),
+        VMSTATE_UINT8(Config3, RTL8139State),
+        VMSTATE_UINT8(Config4, RTL8139State),
+        VMSTATE_UINT8(Config5, RTL8139State),
+
+        VMSTATE_UINT8(clock_enabled, RTL8139State),
+        VMSTATE_UINT8(bChipCmdState, RTL8139State),
+
+        VMSTATE_UINT16(MultiIntr, RTL8139State),
+
+        VMSTATE_UINT16(BasicModeCtrl, RTL8139State),
+        VMSTATE_UINT16(BasicModeStatus, RTL8139State),
+        VMSTATE_UINT16(NWayAdvert, RTL8139State),
+        VMSTATE_UINT16(NWayLPAR, RTL8139State),
+        VMSTATE_UINT16(NWayExpansion, RTL8139State),
+
+        VMSTATE_UINT16(CpCmd, RTL8139State),
+        VMSTATE_UINT8(TxThresh, RTL8139State),
+
+        VMSTATE_UNUSED(4),
+        VMSTATE_BUFFER(macaddr, RTL8139State),
+        VMSTATE_INT32(rtl8139_mmio_io_addr, RTL8139State),
+
+        VMSTATE_UINT32(currTxDesc, RTL8139State),
+        VMSTATE_UINT32(currCPlusRxDesc, RTL8139State),
+        VMSTATE_UINT32(currCPlusTxDesc, RTL8139State),
+        VMSTATE_UINT32(RxRingAddrLO, RTL8139State),
+        VMSTATE_UINT32(RxRingAddrHI, RTL8139State),
+
+        VMSTATE_UINT16_ARRAY(eeprom.contents, RTL8139State, EEPROM_9346_SIZE),
+        VMSTATE_INT32(eeprom.mode, RTL8139State),
+        VMSTATE_UINT32(eeprom.tick, RTL8139State),
+        VMSTATE_UINT8(eeprom.address, RTL8139State),
+        VMSTATE_UINT16(eeprom.input, RTL8139State),
+        VMSTATE_UINT16(eeprom.output, RTL8139State),
+
+        VMSTATE_UINT8(eeprom.eecs, RTL8139State),
+        VMSTATE_UINT8(eeprom.eesk, RTL8139State),
+        VMSTATE_UINT8(eeprom.eedi, RTL8139State),
+        VMSTATE_UINT8(eeprom.eedo, RTL8139State),
+
+        VMSTATE_UINT32(TCTR, RTL8139State),
+        VMSTATE_UINT32(TimerInt, RTL8139State),
+        VMSTATE_INT64(TCTR_base, RTL8139State),
+
+        VMSTATE_STRUCT(tally_counters, RTL8139State, 0,
+                       vmstate_tally_counters, RTL8139TallyCounters),
+
+        VMSTATE_UINT32_V(cplus_enabled, RTL8139State, 4),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 /***********************************************************/
 /* PCI RTL8139 definitions */

@@ -3424,7 +3293,7 @@ static void rtl8139_cleanup(VLANClientState *vc)
     qemu_free_timer(s->timer);
 #endif

-    unregister_savevm("rtl8139", s);
+    vmstate_unregister(&vmstate_rtl8139, s);
 }

 static int pci_rtl8139_uninit(PCIDevice *dev)
@@ -3473,7 +3342,7 @@ static int pci_rtl8139_init(PCIDevice *dev)
     s->cplus_txbuffer_len = 0;
     s->cplus_txbuffer_offset = 0;

-    register_savevm("rtl8139", -1, 4, rtl8139_save, rtl8139_load, s);
+    vmstate_register(-1, &vmstate_rtl8139, s);

 #ifdef RTL8139_ONBOARD_TIMER
     s->timer = qemu_new_timer(vm_clock, rtl8139_timer, s);
