]> git.proxmox.com Git - qemu.git/commitdiff
Merge branch 'arm-devs.next' of git://git.linaro.org/people/pmaydell/qemu-arm
authorBlue Swirl <blauwirbel@gmail.com>
Sat, 6 Apr 2013 12:53:54 +0000 (12:53 +0000)
committerBlue Swirl <blauwirbel@gmail.com>
Sat, 6 Apr 2013 12:53:54 +0000 (12:53 +0000)
* 'arm-devs.next' of git://git.linaro.org/people/pmaydell/qemu-arm:
  hw/nand.c: Fix nand erase operation
  cadence_uart: Flush queued characters on reset
  pl330: Don't inhibit ES bits on INTEN
  pflash_cfi01: Implement migration support
  pflash_cfi01: Drop unused 'bypass' field
  hw/arm_gic_common: Use vmstate struct rather than save/load functions
  arm_gic: Fix sizes of state fields in preparation for vmstate support
  vmstate: Add support for two dimensional arrays
  hw/onenand.c: fix migration of dynamically allocated buffer "otp"
  hw/sd.c: fix migration of dynamically allocated buffer "buf"
  vmstate.h: introduce VMSTATE_BUFFER_POINTER_UNSAFE macro
  hw/arm_mptimer: Save the timer state
  pl050: Don't send always-constant is_mouse field
  hw/arm/nseries: don't print to stdout or stderr

13 files changed:
hw/arm/nseries.c
hw/arm_gic_common.c
hw/arm_gic_internal.h
hw/arm_mptimer.c
hw/armv7m_nvic.c
hw/cadence_uart.c
hw/nand.c
hw/onenand.c
hw/pflash_cfi01.c
hw/pl050.c
hw/pl330.c
hw/sd.c
include/migration/vmstate.h

index 6747c1c5472568c9d7b65e6a0c08515b472cc122..b28e7d372f1ff3bcab0219eba9def68d31f58059 100644 (file)
@@ -129,8 +129,6 @@ static void n800_mmc_cs_cb(void *opaque, int line, int level)
     /* TODO: this seems to actually be connected to the menelaus, to
      * which also both MMC slots connect.  */
     omap_mmc_enable((struct omap_mmc_s *) opaque, !level);
-
-    printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1);
 }
 
 static void n8x0_gpio_setup(struct n800_s *s)
@@ -428,9 +426,6 @@ struct mipid_s {
 
 static void mipid_reset(struct mipid_s *s)
 {
-    if (!s->sleep)
-        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
-
     s->pm = 0;
     s->cmd = 0;
 
@@ -578,11 +573,9 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
 
     case 0x28: /* DISPOFF */
         s->onoff = 0;
-        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
         break;
     case 0x29: /* DISPON */
         s->onoff = 1;
-        fprintf(stderr, "%s: Display on\n", __FUNCTION__);
         break;
 
     case 0x2a: /* CASET */
@@ -669,7 +662,8 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
 
     default:
     bad_cmd:
-        fprintf(stderr, "%s: unknown command %02x\n", __FUNCTION__, s->cmd);
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: unknown command %02x\n", __func__, s->cmd);
         break;
     }
 
@@ -1347,7 +1341,6 @@ static void n8x0_init(QEMUMachineInitArgs *args,
 
     if (option_rom[0].name &&
         (args->boot_device[0] == 'n' || !args->kernel_filename)) {
-        int rom_size;
         uint8_t nolo_tags[0x10000];
         /* No, wait, better start at the ROM.  */
         s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
@@ -1361,10 +1354,9 @@ static void n8x0_init(QEMUMachineInitArgs *args,
          *
          * The code above is for loading the `zImage' file from Nokia
          * images.  */
-        rom_size = load_image_targphys(option_rom[0].name,
-                                       OMAP2_Q2_BASE + 0x400000,
-                                       sdram_size - 0x400000);
-        printf("%i bytes of image loaded\n", rom_size);
+        load_image_targphys(option_rom[0].name,
+                            OMAP2_Q2_BASE + 0x400000,
+                            sdram_size - 0x400000);
 
         n800_setup_nolo_tags(nolo_tags);
         cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000);
index f2dc8bf555a00246a75cb638550386fb822c86a4..71594f1f87e2a9ce4a5a830feafafa8cf62919e1 100644 (file)
 
 #include "hw/arm_gic_internal.h"
 
-static void gic_save(QEMUFile *f, void *opaque)
+static void gic_pre_save(void *opaque)
 {
     GICState *s = (GICState *)opaque;
     ARMGICCommonClass *c = ARM_GIC_COMMON_GET_CLASS(s);
-    int i;
-    int j;
 
     if (c->pre_save) {
         c->pre_save(s);
     }
-
-    qemu_put_be32(f, s->enabled);
-    for (i = 0; i < s->num_cpu; i++) {
-        qemu_put_be32(f, s->cpu_enabled[i]);
-        for (j = 0; j < GIC_INTERNAL; j++) {
-            qemu_put_be32(f, s->priority1[j][i]);
-        }
-        for (j = 0; j < s->num_irq; j++) {
-            qemu_put_be32(f, s->last_active[j][i]);
-        }
-        qemu_put_be32(f, s->priority_mask[i]);
-        qemu_put_be32(f, s->running_irq[i]);
-        qemu_put_be32(f, s->running_priority[i]);
-        qemu_put_be32(f, s->current_pending[i]);
-    }
-    for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
-        qemu_put_be32(f, s->priority2[i]);
-    }
-    for (i = 0; i < s->num_irq; i++) {
-        qemu_put_be32(f, s->irq_target[i]);
-        qemu_put_byte(f, s->irq_state[i].enabled);
-        qemu_put_byte(f, s->irq_state[i].pending);
-        qemu_put_byte(f, s->irq_state[i].active);
-        qemu_put_byte(f, s->irq_state[i].level);
-        qemu_put_byte(f, s->irq_state[i].model);
-        qemu_put_byte(f, s->irq_state[i].trigger);
-    }
 }
 
-static int gic_load(QEMUFile *f, void *opaque, int version_id)
+static int gic_post_load(void *opaque, int version_id)
 {
     GICState *s = (GICState *)opaque;
     ARMGICCommonClass *c = ARM_GIC_COMMON_GET_CLASS(s);
-    int i;
-    int j;
-
-    if (version_id != 3) {
-        return -EINVAL;
-    }
-
-    s->enabled = qemu_get_be32(f);
-    for (i = 0; i < s->num_cpu; i++) {
-        s->cpu_enabled[i] = qemu_get_be32(f);
-        for (j = 0; j < GIC_INTERNAL; j++) {
-            s->priority1[j][i] = qemu_get_be32(f);
-        }
-        for (j = 0; j < s->num_irq; j++) {
-            s->last_active[j][i] = qemu_get_be32(f);
-        }
-        s->priority_mask[i] = qemu_get_be32(f);
-        s->running_irq[i] = qemu_get_be32(f);
-        s->running_priority[i] = qemu_get_be32(f);
-        s->current_pending[i] = qemu_get_be32(f);
-    }
-    for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
-        s->priority2[i] = qemu_get_be32(f);
-    }
-    for (i = 0; i < s->num_irq; i++) {
-        s->irq_target[i] = qemu_get_be32(f);
-        s->irq_state[i].enabled = qemu_get_byte(f);
-        s->irq_state[i].pending = qemu_get_byte(f);
-        s->irq_state[i].active = qemu_get_byte(f);
-        s->irq_state[i].level = qemu_get_byte(f);
-        s->irq_state[i].model = qemu_get_byte(f);
-        s->irq_state[i].trigger = qemu_get_byte(f);
-    }
 
     if (c->post_load) {
         c->post_load(s);
     }
-
     return 0;
 }
 
+static const VMStateDescription vmstate_gic_irq_state = {
+    .name = "arm_gic_irq_state",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(enabled, gic_irq_state),
+        VMSTATE_UINT8(pending, gic_irq_state),
+        VMSTATE_UINT8(active, gic_irq_state),
+        VMSTATE_UINT8(level, gic_irq_state),
+        VMSTATE_BOOL(model, gic_irq_state),
+        VMSTATE_BOOL(trigger, gic_irq_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_gic = {
+    .name = "arm_gic",
+    .version_id = 4,
+    .minimum_version_id = 4,
+    .pre_save = gic_pre_save,
+    .post_load = gic_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_BOOL(enabled, GICState),
+        VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, NCPU),
+        VMSTATE_STRUCT_ARRAY(irq_state, GICState, GIC_MAXIRQ, 1,
+                             vmstate_gic_irq_state, gic_irq_state),
+        VMSTATE_UINT8_ARRAY(irq_target, GICState, GIC_MAXIRQ),
+        VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, NCPU),
+        VMSTATE_UINT8_ARRAY(priority2, GICState, GIC_MAXIRQ - GIC_INTERNAL),
+        VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, NCPU),
+        VMSTATE_UINT16_ARRAY(priority_mask, GICState, NCPU),
+        VMSTATE_UINT16_ARRAY(running_irq, GICState, NCPU),
+        VMSTATE_UINT16_ARRAY(running_priority, GICState, NCPU),
+        VMSTATE_UINT16_ARRAY(current_pending, GICState, NCPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static void arm_gic_common_realize(DeviceState *dev, Error **errp)
 {
     GICState *s = ARM_GIC_COMMON(dev);
@@ -131,8 +106,6 @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp)
                    num_irq);
         return;
     }
-
-    register_savevm(NULL, "arm_gic", -1, 3, gic_save, gic_load, s);
 }
 
 static void arm_gic_common_reset(DeviceState *dev)
@@ -149,7 +122,7 @@ static void arm_gic_common_reset(DeviceState *dev)
         s->current_pending[i] = 1023;
         s->running_irq[i] = 1023;
         s->running_priority[i] = 0x100;
-        s->cpu_enabled[i] = 0;
+        s->cpu_enabled[i] = false;
     }
     for (i = 0; i < 16; i++) {
         GIC_SET_ENABLED(i, ALL_CPU_MASK);
@@ -161,7 +134,7 @@ static void arm_gic_common_reset(DeviceState *dev)
             s->irq_target[i] = 1;
         }
     }
-    s->enabled = 0;
+    s->enabled = false;
 }
 
 static Property arm_gic_common_properties[] = {
@@ -182,6 +155,7 @@ static void arm_gic_common_class_init(ObjectClass *klass, void *data)
     dc->reset = arm_gic_common_reset;
     dc->realize = arm_gic_common_realize;
     dc->props = arm_gic_common_properties;
+    dc->vmsd = &vmstate_gic;
     dc->no_user = 1;
 }
 
index 3e1928b7ebe3e4af5558b3e42838365c0cf79788..99a3bc362b6d9e0e5474be65ba920c5c9cb86070 100644 (file)
 #define GIC_SET_ACTIVE(irq, cm) s->irq_state[irq].active |= (cm)
 #define GIC_CLEAR_ACTIVE(irq, cm) s->irq_state[irq].active &= ~(cm)
 #define GIC_TEST_ACTIVE(irq, cm) ((s->irq_state[irq].active & (cm)) != 0)
-#define GIC_SET_MODEL(irq) s->irq_state[irq].model = 1
-#define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = 0
+#define GIC_SET_MODEL(irq) s->irq_state[irq].model = true
+#define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = false
 #define GIC_TEST_MODEL(irq) s->irq_state[irq].model
 #define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level = (cm)
 #define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm)
 #define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0)
-#define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1
-#define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
+#define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = true
+#define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = false
 #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
 #define GIC_GET_PRIORITY(irq, cpu) (((irq) < GIC_INTERNAL) ?            \
                                     s->priority1[irq][cpu] :            \
 
 typedef struct gic_irq_state {
     /* The enable bits are only banked for per-cpu interrupts.  */
-    unsigned enabled:NCPU;
-    unsigned pending:NCPU;
-    unsigned active:NCPU;
-    unsigned level:NCPU;
-    unsigned model:1; /* 0 = N:N, 1 = 1:N */
-    unsigned trigger:1; /* nonzero = edge triggered.  */
+    uint8_t enabled;
+    uint8_t pending;
+    uint8_t active;
+    uint8_t level;
+    bool model; /* 0 = N:N, 1 = 1:N */
+    bool trigger; /* nonzero = edge triggered.  */
 } gic_irq_state;
 
 typedef struct GICState {
     SysBusDevice busdev;
     qemu_irq parent_irq[NCPU];
-    int enabled;
-    int cpu_enabled[NCPU];
+    bool enabled;
+    bool cpu_enabled[NCPU];
 
     gic_irq_state irq_state[GIC_MAXIRQ];
-    int irq_target[GIC_MAXIRQ];
-    int priority1[GIC_INTERNAL][NCPU];
-    int priority2[GIC_MAXIRQ - GIC_INTERNAL];
-    int last_active[GIC_MAXIRQ][NCPU];
-
-    int priority_mask[NCPU];
-    int running_irq[NCPU];
-    int running_priority[NCPU];
-    int current_pending[NCPU];
+    uint8_t irq_target[GIC_MAXIRQ];
+    uint8_t priority1[GIC_INTERNAL][NCPU];
+    uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL];
+    uint16_t last_active[GIC_MAXIRQ][NCPU];
+
+    uint16_t priority_mask[NCPU];
+    uint16_t running_irq[NCPU];
+    uint16_t running_priority[NCPU];
+    uint16_t current_pending[NCPU];
 
     uint32_t num_cpu;
 
index f59a9f11f083bf19e37a55c490c70ea10c33a757..317f5e43edc0aac9430421b66f4cc1ea7ff38fbc 100644 (file)
@@ -253,14 +253,15 @@ static int arm_mptimer_init(SysBusDevice *dev)
 
 static const VMStateDescription vmstate_timerblock = {
     .name = "arm_mptimer_timerblock",
-    .version_id = 1,
-    .minimum_version_id = 1,
+    .version_id = 2,
+    .minimum_version_id = 2,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(count, TimerBlock),
         VMSTATE_UINT32(load, TimerBlock),
         VMSTATE_UINT32(control, TimerBlock),
         VMSTATE_UINT32(status, TimerBlock),
         VMSTATE_INT64(tick, TimerBlock),
+        VMSTATE_TIMER(timer, TimerBlock),
         VMSTATE_END_OF_LIST()
     }
 };
index d198cfd96e5177b28b85b0d46d635a918aa93099..235120024f5dc491fa08d11cd2757fe555ceefb8 100644 (file)
@@ -458,10 +458,10 @@ static void armv7m_nvic_reset(DeviceState *dev)
      * as enabled by default, and with a priority mask which allows
      * all interrupts through.
      */
-    s->gic.cpu_enabled[0] = 1;
+    s->gic.cpu_enabled[0] = true;
     s->gic.priority_mask[0] = 0x100;
     /* The NVIC as a whole is always enabled. */
-    s->gic.enabled = 1;
+    s->gic.enabled = true;
     systick_reset(s);
 }
 
index 5426f1001896eecbd58ddbd167594bfd95fc9189..421ec998d69962c5ab9218f57c2f2965237f4f72 100644 (file)
@@ -157,6 +157,7 @@ static void uart_rx_reset(UartState *s)
 {
     s->rx_wpos = 0;
     s->rx_count = 0;
+    qemu_chr_accept_input(s->chr);
 
     s->r[R_SR] |= UART_SR_INTR_REMPTY;
     s->r[R_SR] &= ~UART_SR_INTR_RFUL;
index de3e502596f080de222bc055d6a042a3bea1cdeb..63620938fba0c4321c3dd94076a30cc60b6f560c 100644 (file)
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -297,6 +297,7 @@ static void nand_command(NANDFlashState *s)
         break;
 
     case NAND_CMD_BLOCKERASE2:
+        s->addr &= (1ull << s->addrlen * 8) - 1;
         if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP)
             s->addr <<= 16;
         else
index ddba366ef5ba60460499a2f285ad3660a40e55af..57a346d7da374d98a244fa9b14059fab54976097 100644 (file)
@@ -185,7 +185,8 @@ static const VMStateDescription vmstate_onenand = {
         VMSTATE_UINT8(ecc.cp, OneNANDState),
         VMSTATE_UINT16_ARRAY(ecc.lp, OneNANDState, 2),
         VMSTATE_UINT16(ecc.count, OneNANDState),
-        VMSTATE_BUFFER_UNSAFE(otp, OneNANDState, 0, ((64 + 2) << PAGE_SHIFT)),
+        VMSTATE_BUFFER_POINTER_UNSAFE(otp, OneNANDState, 0,
+            ((64 + 2) << PAGE_SHIFT)),
         VMSTATE_END_OF_LIST()
     }
 };
index 5d57babe078230b72694b470a6a45d008c075395..646dc794bf72535e09cbe6b5d991d3620c2464ad 100644 (file)
@@ -67,8 +67,7 @@ struct pflash_t {
     uint64_t sector_len;
     uint8_t width;
     uint8_t be;
-    int wcycle; /* if 0, the flash is read normally */
-    int bypass;
+    uint8_t wcycle; /* if 0, the flash is read normally */
     int ro;
     uint8_t cmd;
     uint8_t status;
@@ -78,7 +77,7 @@ struct pflash_t {
     uint16_t ident3;
     uint8_t cfi_len;
     uint8_t cfi_table[0x52];
-    hwaddr counter;
+    uint64_t counter;
     unsigned int writeblock_size;
     QEMUTimer *timer;
     MemoryRegion mem;
@@ -86,6 +85,19 @@ struct pflash_t {
     void *storage;
 };
 
+static const VMStateDescription vmstate_pflash = {
+    .name = "pflash_cfi01",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(wcycle, pflash_t),
+        VMSTATE_UINT8(cmd, pflash_t),
+        VMSTATE_UINT8(status, pflash_t),
+        VMSTATE_UINT64(counter, pflash_t),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static void pflash_timer (void *opaque)
 {
     pflash_t *pfl = opaque;
@@ -93,12 +105,8 @@ static void pflash_timer (void *opaque)
     DPRINTF("%s: command %02x done\n", __func__, pfl->cmd);
     /* Reset flash */
     pfl->status ^= 0x80;
-    if (pfl->bypass) {
-        pfl->wcycle = 2;
-    } else {
-        memory_region_rom_device_set_readable(&pfl->mem, true);
-        pfl->wcycle = 0;
-    }
+    memory_region_rom_device_set_readable(&pfl->mem, true);
+    pfl->wcycle = 0;
     pfl->cmd = 0;
 }
 
@@ -228,7 +236,7 @@ static inline void pflash_data_write(pflash_t *pfl, hwaddr offset,
     uint8_t *p = pfl->storage;
 
     DPRINTF("%s: block write offset " TARGET_FMT_plx
-            " value %x counter " TARGET_FMT_plx "\n",
+            " value %x counter %016" PRIx64 "\n",
             __func__, offset, value, pfl->counter);
     switch (width) {
     case 1:
@@ -452,7 +460,6 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
  reset_flash:
     memory_region_rom_device_set_readable(&pfl->mem, true);
 
-    pfl->bypass = 0;
     pfl->wcycle = 0;
     pfl->cmd = 0;
 }
@@ -707,6 +714,7 @@ static void pflash_cfi01_class_init(ObjectClass *klass, void *data)
 
     k->init = pflash_cfi01_init;
     dc->props = pflash_cfi01_properties;
+    dc->vmsd = &vmstate_pflash;
 }
 
 
index bc31ab688585ba1f68541ef3030e091abb14fee7..76735a0eda4976fd66c08baa174b0e1a89519cfd 100644 (file)
@@ -24,14 +24,13 @@ typedef struct {
 
 static const VMStateDescription vmstate_pl050 = {
     .name = "pl050",
-    .version_id = 1,
-    .minimum_version_id = 1,
+    .version_id = 2,
+    .minimum_version_id = 2,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(cr, pl050_state),
         VMSTATE_UINT32(clk, pl050_state),
         VMSTATE_UINT32(last, pl050_state),
         VMSTATE_INT32(pending, pl050_state),
-        VMSTATE_INT32(is_mouse, pl050_state),
         VMSTATE_END_OF_LIST()
     }
 };
index 1a04773a71c1be6ec529793195cd7ad2c9ccbc3f..60aa4a8f9f1a768efcb74a9fa2687ecd642b97f8 100644 (file)
@@ -870,9 +870,8 @@ static void pl330_dmasev(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
         ch->parent->int_status |= (1 << ev_id);
         DB_PRINT("event interrupt raised %d\n", ev_id);
         qemu_irq_raise(ch->parent->irq[ev_id]);
-    } else {
-        ch->parent->ev_status |= (1 << ev_id);
     }
+    ch->parent->ev_status |= (1 << ev_id);
 }
 
 static void pl330_dmast(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
diff --git a/hw/sd.c b/hw/sd.c
index a895123867c2d300c1330ee803c9f56f65c690cd..66c4014fbe0144bbf66dd7c234e209482cd5ffb5 100644 (file)
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -478,7 +478,7 @@ static const VMStateDescription sd_vmstate = {
         VMSTATE_UINT64(data_start, SDState),
         VMSTATE_UINT32(data_offset, SDState),
         VMSTATE_UINT8_ARRAY(data, SDState, 512),
-        VMSTATE_BUFFER_UNSAFE(buf, SDState, 1, 512),
+        VMSTATE_BUFFER_POINTER_UNSAFE(buf, SDState, 1, 512),
         VMSTATE_BOOL(enable, SDState),
         VMSTATE_END_OF_LIST()
     }
index 65918a9abe52f44893dca1f99e3fa200c0912c86..ebc4d09141828dccd658bf3f356ab37f2c6c4b03 100644 (file)
@@ -164,6 +164,7 @@ extern const VMStateInfo vmstate_info_buffer;
 extern const VMStateInfo vmstate_info_unused_buffer;
 extern const VMStateInfo vmstate_info_bitmap;
 
+#define type_check_2darray(t1,t2,n,m) ((t1(*)[n][m])0 - (t2*)0)
 #define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0)
 #define type_check_pointer(t1,t2) ((t1**)0 - (t2*)0)
 
@@ -179,6 +180,10 @@ extern const VMStateInfo vmstate_info_bitmap;
     (offsetof(_state, _field) +                                      \
      type_check_array(_type, typeof_field(_state, _field), _num))
 
+#define vmstate_offset_2darray(_state, _field, _type, _n1, _n2)      \
+    (offsetof(_state, _field) +                                      \
+     type_check_2darray(_type, typeof_field(_state, _field), _n1, _n2))
+
 #define vmstate_offset_sub_array(_state, _field, _type, _start)      \
     (offsetof(_state, _field[_start]))
 
@@ -224,6 +229,16 @@ extern const VMStateInfo vmstate_info_bitmap;
     .offset     = vmstate_offset_array(_state, _field, _type, _num), \
 }
 
+#define VMSTATE_2DARRAY(_field, _state, _n1, _n2, _version, _info, _type) { \
+    .name       = (stringify(_field)),                                      \
+    .version_id = (_version),                                               \
+    .num        = (_n1) * (_n2),                                            \
+    .info       = &(_info),                                                 \
+    .size       = sizeof(_type),                                            \
+    .flags      = VMS_ARRAY,                                                \
+    .offset     = vmstate_offset_2darray(_state, _field, _type, _n1, _n2),  \
+}
+
 #define VMSTATE_ARRAY_TEST(_field, _state, _num, _test, _info, _type) {\
     .name         = (stringify(_field)),                              \
     .field_exists = (_test),                                          \
@@ -436,6 +451,15 @@ extern const VMStateInfo vmstate_info_bitmap;
     .offset     = offsetof(_state, _field),                          \
 }
 
+#define VMSTATE_BUFFER_POINTER_UNSAFE(_field, _state, _version, _size) { \
+    .name       = (stringify(_field)),                               \
+    .version_id = (_version),                                        \
+    .size       = (_size),                                           \
+    .info       = &vmstate_info_buffer,                              \
+    .flags      = VMS_BUFFER|VMS_POINTER,                            \
+    .offset     = offsetof(_state, _field),                          \
+}
+
 #define VMSTATE_UNUSED_BUFFER(_test, _version, _size) {              \
     .name         = "unused",                                        \
     .field_exists = (_test),                                         \
@@ -583,15 +607,27 @@ extern const VMStateInfo vmstate_info_bitmap;
 #define VMSTATE_UINT16_ARRAY_V(_f, _s, _n, _v)                         \
     VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint16, uint16_t)
 
+#define VMSTATE_UINT16_2DARRAY_V(_f, _s, _n1, _n2, _v)                \
+    VMSTATE_2DARRAY(_f, _s, _n1, _n2, _v, vmstate_info_uint16, uint16_t)
+
 #define VMSTATE_UINT16_ARRAY(_f, _s, _n)                               \
     VMSTATE_UINT16_ARRAY_V(_f, _s, _n, 0)
 
+#define VMSTATE_UINT16_2DARRAY(_f, _s, _n1, _n2)                      \
+    VMSTATE_UINT16_2DARRAY_V(_f, _s, _n1, _n2, 0)
+
+#define VMSTATE_UINT8_2DARRAY_V(_f, _s, _n1, _n2, _v)                 \
+    VMSTATE_2DARRAY(_f, _s, _n1, _n2, _v, vmstate_info_uint8, uint8_t)
+
 #define VMSTATE_UINT8_ARRAY_V(_f, _s, _n, _v)                         \
     VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint8, uint8_t)
 
 #define VMSTATE_UINT8_ARRAY(_f, _s, _n)                               \
     VMSTATE_UINT8_ARRAY_V(_f, _s, _n, 0)
 
+#define VMSTATE_UINT8_2DARRAY(_f, _s, _n1, _n2)                       \
+    VMSTATE_UINT8_2DARRAY_V(_f, _s, _n1, _n2, 0)
+
 #define VMSTATE_UINT32_ARRAY_V(_f, _s, _n, _v)                        \
     VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint32, uint32_t)