From 591f73f642a5f3c822c3efaae8d83a174371a4f5 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 5 Apr 2013 16:17:58 +0100 Subject: [PATCH 01/14] hw/arm/nseries: don't print to stdout or stderr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove various bits of printing to stdout or stderr from the nseries code, replacing it with a qemu log message where there's an appropriate log category, and just dropping the output for some of the more debug-like printing. In particular, this will get rid of the 'mipid_reset' message you currently get from 'make check'. Signed-off-by: Peter Maydell Reviewed-by: Andreas Färber Message-id: 1363368565-24546-1-git-send-email-peter.maydell@linaro.org --- hw/arm/nseries.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c index 6747c1c547..b28e7d372f 100644 --- a/hw/arm/nseries.c +++ b/hw/arm/nseries.c @@ -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); From e8945b4f2a65fc2872cc31a5141e136fd27d0af8 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 5 Apr 2013 16:17:58 +0100 Subject: [PATCH 02/14] pl050: Don't send always-constant is_mouse field The is_mouse field of the pl050 state structure is constant (it tracks whether this is a 'pl050_keyboard' or 'pl050_mouse'), so there's no need to include it in the VMState structure. Signed-off-by: Peter Maydell Message-id: 1363628480-29306-1-git-send-email-peter.maydell@linaro.org --- hw/pl050.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/pl050.c b/hw/pl050.c index bc31ab6885..76735a0eda 100644 --- a/hw/pl050.c +++ b/hw/pl050.c @@ -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() } }; From 28092a23e6e2cb8298c1381f4f046842ffd376eb Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 5 Apr 2013 16:17:58 +0100 Subject: [PATCH 03/14] hw/arm_mptimer: Save the timer state Add a missing VMSTATE_TIMER() entry to the arm_mptimer vmstate description; this omission meant that we would probably hang on reload when the timer failed to fire. Signed-off-by: Peter Maydell Reviewed-by: Peter Crosthwaite Message-id: 1363967348-3044-1-git-send-email-peter.maydell@linaro.org --- hw/arm_mptimer.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/arm_mptimer.c b/hw/arm_mptimer.c index f59a9f11f0..317f5e43ed 100644 --- a/hw/arm_mptimer.c +++ b/hw/arm_mptimer.c @@ -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() } }; From 8070568b9aa8d93b3729ab7e9ca0ef8a6351d2bd Mon Sep 17 00:00:00 2001 From: Igor Mitsyanko Date: Fri, 5 Apr 2013 16:17:58 +0100 Subject: [PATCH 04/14] vmstate.h: introduce VMSTATE_BUFFER_POINTER_UNSAFE macro Macro could be used to migrate a dynamically allocated buffer of known size. Signed-off-by: Igor Mitsyanko Reviewed-by: Peter Maydell Message-id: 1362923278-4080-2-git-send-email-i.mitsyanko@gmail.com Signed-off-by: Peter Maydell --- include/migration/vmstate.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index 65918a9abe..8184123448 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -436,6 +436,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), \ From 5f00679ee98b1643ff652bbf982dffe1b432596e Mon Sep 17 00:00:00 2001 From: Igor Mitsyanko Date: Fri, 5 Apr 2013 16:17:59 +0100 Subject: [PATCH 05/14] hw/sd.c: fix migration of dynamically allocated buffer "buf" VMSTATE_BUFFER_UNSAFE should be used for buffers inlined in device state, not for buffers allocated dynamically. Change to VMSTATE_BUFFER_POINTER_UNSAFE macro, which will do migration right. Signed-off-by: Igor Mitsyanko Reviewed-by: Peter Maydell Tested-by: Michael Walle Message-id: 1362923278-4080-3-git-send-email-i.mitsyanko@gmail.com Signed-off-by: Peter Maydell --- hw/sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/sd.c b/hw/sd.c index a895123867..66c4014fbe 100644 --- 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() } From b79269b78d0182fa7f4e23b779010145d0b4eaea Mon Sep 17 00:00:00 2001 From: Igor Mitsyanko Date: Fri, 5 Apr 2013 16:17:59 +0100 Subject: [PATCH 06/14] hw/onenand.c: fix migration of dynamically allocated buffer "otp" VMSTATE_BUFFER_UNSAFE should be used for buffers inlined in device state, not for buffers allocated dynamically. Change to VMSTATE_BUFFER_POINTER_UNSAFE macro, which will do migration right. Signed-off-by: Igor Mitsyanko Reviewed-by: Peter Maydell Message-id: 1362923278-4080-4-git-send-email-i.mitsyanko@gmail.com Signed-off-by: Peter Maydell --- hw/onenand.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/onenand.c b/hw/onenand.c index ddba366ef5..57a346d7da 100644 --- a/hw/onenand.c +++ b/hw/onenand.c @@ -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() } }; From bd7f92e59e7f40ddaeda40e55f7818c8121ecf1a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 5 Apr 2013 16:17:59 +0100 Subject: [PATCH 07/14] vmstate: Add support for two dimensional arrays Add support for migrating two dimensional arrays, by defining a set of new macros VMSTATE_*_2DARRAY paralleling the existing VMSTATE_*_ARRAY macros. 2D arrays are handled the same for actual state serialization; the only difference is that the type check has to change for a 2D array. Signed-off-by: Peter Maydell Reviewed-by: Igor Mitsyanko Message-id: 1363975375-3166-2-git-send-email-peter.maydell@linaro.org --- include/migration/vmstate.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index 8184123448..ebc4d09141 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -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), \ @@ -592,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) From c3037774be5329e584d4d709b9df7e1799bba215 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 5 Apr 2013 16:17:59 +0100 Subject: [PATCH 08/14] arm_gic: Fix sizes of state fields in preparation for vmstate support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for switching to vmstate for migration support, fix the sizes of various GIC state fields. In particular, we replace all the bitfields (which VMState can't deal with) with straightforward uint8_t values which we do bit operations on. (The bitfields made more sense when NCPU was set differently in different situations, but we now always model at the architectural limit of 8.) Signed-off-by: Peter Maydell Reviewed-by: Igor Mitsyanko Reviewed-by: Andreas Färber Message-id: 1363975375-3166-3-git-send-email-peter.maydell@linaro.org --- hw/arm_gic_common.c | 4 ++-- hw/arm_gic_internal.h | 40 ++++++++++++++++++++-------------------- hw/armv7m_nvic.c | 4 ++-- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/hw/arm_gic_common.c b/hw/arm_gic_common.c index f2dc8bf555..f95bec3650 100644 --- a/hw/arm_gic_common.c +++ b/hw/arm_gic_common.c @@ -149,7 +149,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 +161,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[] = { diff --git a/hw/arm_gic_internal.h b/hw/arm_gic_internal.h index 3e1928b7eb..99a3bc362b 100644 --- a/hw/arm_gic_internal.h +++ b/hw/arm_gic_internal.h @@ -45,14 +45,14 @@ #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] : \ @@ -61,30 +61,30 @@ 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]; + 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]; - int priority_mask[NCPU]; - int running_irq[NCPU]; - int running_priority[NCPU]; - int current_pending[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; diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c index d198cfd96e..235120024f 100644 --- a/hw/armv7m_nvic.c +++ b/hw/armv7m_nvic.c @@ -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); } From 2e19a7035a8e721f32610c8d22223ab748c4232f Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 5 Apr 2013 16:18:00 +0100 Subject: [PATCH 09/14] hw/arm_gic_common: Use vmstate struct rather than save/load functions Update the GIC save/restore to use vmstate rather than hand-rolled save/load functions. Signed-off-by: Peter Maydell Reviewed-by: Igor Mitsyanko Message-id: 1363975375-3166-4-git-send-email-peter.maydell@linaro.org --- hw/arm_gic_common.c | 108 +++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 67 deletions(-) diff --git a/hw/arm_gic_common.c b/hw/arm_gic_common.c index f95bec3650..71594f1f87 100644 --- a/hw/arm_gic_common.c +++ b/hw/arm_gic_common.c @@ -20,90 +20,65 @@ #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) @@ -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; } From 5d79b80b335c5f65f148d1bb1672d9d534ace73b Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 5 Apr 2013 16:18:00 +0100 Subject: [PATCH 10/14] pflash_cfi01: Drop unused 'bypass' field For pflash_cfi01 the 'bypass' field is set to zero and never changes, so remove it (it is a leftover from pflash_cfi02, where bypass is implemented). Signed-off-by: Peter Maydell Message-id: 1363717469-30980-2-git-send-email-peter.maydell@linaro.org --- hw/pflash_cfi01.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index 5d57babe07..20d10b3b13 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -68,7 +68,6 @@ struct pflash_t { uint8_t width; uint8_t be; int wcycle; /* if 0, the flash is read normally */ - int bypass; int ro; uint8_t cmd; uint8_t status; @@ -93,12 +92,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; } @@ -452,7 +447,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; } From d8d24fb78cf21205bf672d85231712dc1f0bbb39 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 5 Apr 2013 16:18:00 +0100 Subject: [PATCH 11/14] pflash_cfi01: Implement migration support Add a vmstate to pflash_cfi01, so that it can be live migrated. Signed-off-by: Peter Maydell Message-id: 1363717469-30980-3-git-send-email-peter.maydell@linaro.org --- hw/pflash_cfi01.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index 20d10b3b13..646dc794bf 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -67,7 +67,7 @@ struct pflash_t { uint64_t sector_len; uint8_t width; uint8_t be; - int wcycle; /* if 0, the flash is read normally */ + uint8_t wcycle; /* if 0, the flash is read normally */ int ro; uint8_t cmd; uint8_t status; @@ -77,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; @@ -85,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; @@ -223,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: @@ -701,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; } From fd7f8a99f3b08640a7fe2b2f3c3e6b68068b4983 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 2 Apr 2013 17:59:29 +0000 Subject: [PATCH 12/14] pl330: Don't inhibit ES bits on INTEN This if-else logic inhibits setting of the event status (ES) bits when interrupts are enabled. This is incorrect. ES should be set regardless on INTEN state. INTEN only inhibits the signalling of events to PL330 threads, not setting of the ES register. Signed-off-by: Peter Crosthwaite Signed-off-by: Peter Maydell --- hw/pl330.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/pl330.c b/hw/pl330.c index 1a04773a71..60aa4a8f9f 100644 --- a/hw/pl330.c +++ b/hw/pl330.c @@ -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) From 1db8b5efe0c2b5000e50691eea61264a615f43de Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Wed, 3 Apr 2013 14:52:21 +1000 Subject: [PATCH 13/14] cadence_uart: Flush queued characters on reset Reset can be used to empty the rx-fifo. As the fifo full condition is used to return false from can_receive, queued rx data should be flushed on reset accordingly. Cc: Wendy Liang Cc: Jason Wu Signed-off-by: Peter Crosthwaite Reported-by: Jason Wu Message-id: 494c1e005e225c915d295ddfd75d992ad2dabc3c.1364964526.git.peter.crosthwaite@xilinx.com Signed-off-by: Peter Maydell --- hw/cadence_uart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c index 5426f10018..421ec998d6 100644 --- a/hw/cadence_uart.c +++ b/hw/cadence_uart.c @@ -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; From 32aea752f47f30c00878dcc323ac4debf0c9e645 Mon Sep 17 00:00:00 2001 From: Wendy Liang Date: Wed, 3 Apr 2013 15:33:08 +1000 Subject: [PATCH 14/14] hw/nand.c: Fix nand erase operation Usually, nand erase operation has only 2 or 3 address cycles. We need to mask s->addr to zero unset stale high-order bytes in the nand address before using it as the erase address. This fixes the NAND erase operation in Linux. [PC: Generalised to work for any number of address cycles rather than just 3] Signed-off-by: Wendy Liang Signed-off-by: Peter Crosthwaite Message-id: 1364967188-26711-1-git-send-email-peter.crosthwaite@xilinx.com Signed-off-by: Peter Maydell --- hw/nand.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/nand.c b/hw/nand.c index de3e502596..63620938fb 100644 --- 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