summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurelien Jarno <aurelien@aurel32.net>2012-11-01 16:42:29 +0100
committerAurelien Jarno <aurelien@aurel32.net>2012-11-01 16:42:29 +0100
commit735c1eeb85450acd551c5990952f7ed8512d8547 (patch)
treee9973aefc432339548d281814a0724b512fc6788
parent286d52ebfc0d0d53c2a878e454292fea14bad41b (diff)
parent50a5be6c3d50c7684a417da4eb5f9587dace0a44 (diff)
downloadqemu-735c1eeb85450acd551c5990952f7ed8512d8547.tar.gz
Merge branch 'arm-devs.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm
* 'arm-devs.for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm: (28 commits) hw/sd.c: add SD card save/load support vmstate: Add support for saving/loading bitmaps hw/sd.c: Fix erase for high capacity cards pflash_cfi01: Fix debug mode printfery pflash_cfi0x: QOMified pflash_cfi01: remove unused total_len field pflash_cfi0x: remove unused base field hw/versatile_i2c: Use LOG_GUEST_ERROR hw/arm_l2x0: Use LOG_GUEST_ERROR hw/arm_sysctl: Use LOG_GUEST_ERROR hw/armv7m_nvic: Use LOG_GUEST_ERROR and LOG_UNIMP hw/arm_timer: Use LOG_GUEST_ERROR and LOG_UNIMP hw/arm_gic: Use LOG_GUEST_ERROR hw/arm11mpcore: Use LOG_GUEST_ERROR rather than hw_error() hw/pl190: Use LOG_UNIMP rather than hw_error() hw/pl110: Use LOG_GUEST_ERROR rather than hw_error() hw/pl080: Use LOG_GUEST_ERROR and LOG_UNIMP hw/pl061: Use LOG_GUEST_ERROR hw/pl050: Use LOG_GUEST_ERROR hw/exynos4_boards: Don't prematurely explode QEMUMachineInitArgs ...
-rw-r--r--hw/arm11mpcore.c7
-rw-r--r--hw/arm_gic.c12
-rw-r--r--hw/arm_l2x0.c6
-rw-r--r--hw/arm_sysctl.c8
-rw-r--r--hw/arm_timer.c19
-rw-r--r--hw/armv7m_nvic.c87
-rw-r--r--hw/exynos4_boards.c32
-rw-r--r--hw/mainstone.c21
-rw-r--r--hw/nseries.c39
-rw-r--r--hw/omap_sx1.c36
-rw-r--r--hw/pflash_cfi01.c148
-rw-r--r--hw/pflash_cfi02.c162
-rw-r--r--hw/pl050.c6
-rw-r--r--hw/pl061.c6
-rw-r--r--hw/pl080.c11
-rw-r--r--hw/pl110.c6
-rw-r--r--hw/pl190.c2
-rw-r--r--hw/realview.c68
-rw-r--r--hw/sd.c106
-rw-r--r--hw/sd.h1
-rw-r--r--hw/spitz.c45
-rw-r--r--hw/versatile_i2c.c6
-rw-r--r--hw/versatilepb.c44
-rw-r--r--hw/vexpress.c38
-rw-r--r--savevm.c41
-rw-r--r--vmstate.h13
26 files changed, 541 insertions, 429 deletions
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index 105f158fd4..640ed20a61 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -44,7 +44,9 @@ static uint64_t mpcore_scu_read(void *opaque, hwaddr offset,
case 0x0c: /* Invalidate all. */
return 0;
default:
- hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "mpcore_priv_read: Bad offset %x\n", (int)offset);
+ return 0;
}
}
@@ -61,7 +63,8 @@ static void mpcore_scu_write(void *opaque, hwaddr offset,
/* This is a no-op as cache is not emulated. */
break;
default:
- hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "mpcore_priv_read: Bad offset %x\n", (int)offset);
}
}
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index ce16e8367f..f9e423f152 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -324,7 +324,8 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset)
}
return res;
bad_reg:
- hw_error("gic_dist_readb: Bad offset %x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "gic_dist_readb: Bad offset %x\n", (int)offset);
return 0;
}
@@ -487,7 +488,8 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
gic_update(s);
return;
bad_reg:
- hw_error("gic_dist_writeb: Bad offset %x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "gic_dist_writeb: Bad offset %x\n", (int)offset);
}
static void gic_dist_writew(void *opaque, hwaddr offset,
@@ -556,7 +558,8 @@ static uint32_t gic_cpu_read(GICState *s, int cpu, int offset)
case 0x18: /* Highest Pending Interrupt */
return s->current_pending[cpu];
default:
- hw_error("gic_cpu_read: Bad offset %x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "gic_cpu_read: Bad offset %x\n", (int)offset);
return 0;
}
}
@@ -577,7 +580,8 @@ static void gic_cpu_write(GICState *s, int cpu, int offset, uint32_t value)
case 0x10: /* End Of Interrupt */
return gic_complete_irq(s, cpu, value & 0x3ff);
default:
- hw_error("gic_cpu_write: Bad offset %x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "gic_cpu_write: Bad offset %x\n", (int)offset);
return;
}
gic_update(s);
diff --git a/hw/arm_l2x0.c b/hw/arm_l2x0.c
index 8f5921c3a6..6abf0ee160 100644
--- a/hw/arm_l2x0.c
+++ b/hw/arm_l2x0.c
@@ -87,7 +87,8 @@ static uint64_t l2x0_priv_read(void *opaque, hwaddr offset,
case 0xF80:
return 0;
default:
- fprintf(stderr, "l2x0_priv_read: Bad offset %x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "l2x0_priv_read: Bad offset %x\n", (int)offset);
break;
}
return 0;
@@ -128,7 +129,8 @@ static void l2x0_priv_write(void *opaque, hwaddr offset,
case 0xF80:
return;
default:
- fprintf(stderr, "l2x0_priv_write: Bad offset %x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "l2x0_priv_write: Bad offset %x\n", (int)offset);
break;
}
}
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index 26318e14d5..58eb98216d 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -184,7 +184,9 @@ static uint64_t arm_sysctl_read(void *opaque, hwaddr offset,
return s->sys_cfgstat;
default:
bad_reg:
- printf ("arm_sysctl_read: Bad register offset 0x%x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "arm_sysctl_read: Bad register offset 0x%x\n",
+ (int)offset);
return 0;
}
}
@@ -339,7 +341,9 @@ static void arm_sysctl_write(void *opaque, hwaddr offset,
return;
default:
bad_reg:
- printf ("arm_sysctl_write: Bad register offset 0x%x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "arm_sysctl_write: Bad register offset 0x%x\n",
+ (int)offset);
return;
}
}
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 2e136216c6..af339d3d19 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -64,7 +64,8 @@ static uint32_t arm_timer_read(void *opaque, hwaddr offset)
return 0;
return s->int_level;
default:
- hw_error("%s: Bad offset %x\n", __func__, (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad offset %x\n", __func__, (int)offset);
return 0;
}
}
@@ -131,7 +132,8 @@ static void arm_timer_write(void *opaque, hwaddr offset,
arm_timer_recalibrate(s, 0);
break;
default:
- hw_error("%s: Bad offset %x\n", __func__, (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad offset %x\n", __func__, (int)offset);
}
arm_timer_update(s);
}
@@ -223,10 +225,14 @@ static uint64_t sp804_read(void *opaque, hwaddr offset,
/* Integration Test control registers, which we won't support */
case 0xf00: /* TimerITCR */
case 0xf04: /* TimerITOP (strictly write only but..) */
+ qemu_log_mask(LOG_UNIMP,
+ "%s: integration test registers unimplemented\n",
+ __func__);
return 0;
}
- hw_error("%s: Bad offset %x\n", __func__, (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad offset %x\n", __func__, (int)offset);
return 0;
}
@@ -246,7 +252,8 @@ static void sp804_write(void *opaque, hwaddr offset,
}
/* Technically we could be writing to the Test Registers, but not likely */
- hw_error("%s: Bad offset %x\n", __func__, (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %x\n",
+ __func__, (int)offset);
}
static const MemoryRegionOps sp804_ops = {
@@ -300,7 +307,7 @@ static uint64_t icp_pit_read(void *opaque, hwaddr offset,
/* ??? Don't know the PrimeCell ID for this device. */
n = offset >> 8;
if (n > 2) {
- hw_error("%s: Bad timer %d\n", __func__, n);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad timer %d\n", __func__, n);
}
return arm_timer_read(s->timer[n], offset & 0xff);
@@ -314,7 +321,7 @@ static void icp_pit_write(void *opaque, hwaddr offset,
n = offset >> 8;
if (n > 2) {
- hw_error("%s: Bad timer %d\n", __func__, n);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad timer %d\n", __func__, n);
}
arm_timer_write(s->timer[n], offset & 0xff, value);
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index 35c1aa67e2..f0a2e7b5d2 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -138,9 +138,8 @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
gic_complete_irq(&s->gic, 0, irq);
}
-static uint32_t nvic_readl(void *opaque, uint32_t offset)
+static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
{
- nvic_state *s = (nvic_state *)opaque;
uint32_t val;
int irq;
@@ -216,14 +215,6 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
case 0xd14: /* Configuration Control. */
/* TODO: Implement Configuration Control bits. */
return 0;
- case 0xd18: case 0xd1c: case 0xd20: /* System Handler Priority. */
- irq = offset - 0xd14;
- val = 0;
- val |= s->gic.priority1[irq++][0];
- val |= s->gic.priority1[irq++][0] << 8;
- val |= s->gic.priority1[irq++][0] << 16;
- val |= s->gic.priority1[irq][0] << 24;
- return val;
case 0xd24: /* System Handler Status. */
val = 0;
if (s->gic.irq_state[ARMV7M_EXCP_MEM].active) val |= (1 << 0);
@@ -243,7 +234,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
return val;
case 0xd28: /* Configurable Fault Status. */
/* TODO: Implement Fault Status. */
- hw_error("Not implemented: Configurable Fault Status.");
+ qemu_log_mask(LOG_UNIMP, "Configurable Fault Status unimplemented\n");
return 0;
case 0xd2c: /* Hard Fault Status. */
case 0xd30: /* Debug Fault Status. */
@@ -251,7 +242,8 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
case 0xd38: /* Bus Fault Address. */
case 0xd3c: /* Aux Fault Status. */
/* TODO: Implement fault status registers. */
- goto bad_reg;
+ qemu_log_mask(LOG_UNIMP, "Fault status registers unimplemented\n");
+ return 0;
case 0xd40: /* PFR0. */
return 0x00000030;
case 0xd44: /* PRF1. */
@@ -280,14 +272,13 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
return 0x01310102;
/* TODO: Implement debug registers. */
default:
- bad_reg:
- hw_error("NVIC: Bad read offset 0x%x\n", offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset);
+ return 0;
}
}
-static void nvic_writel(void *opaque, uint32_t offset, uint32_t value)
+static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
{
- nvic_state *s = (nvic_state *)opaque;
uint32_t oldval;
switch (offset) {
case 0x10: /* SysTick Control and Status. */
@@ -345,27 +336,17 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value)
case 0xd0c: /* Application Interrupt/Reset Control. */
if ((value >> 16) == 0x05fa) {
if (value & 2) {
- hw_error("VECTCLRACTIVE not implemented");
+ qemu_log_mask(LOG_UNIMP, "VECTCLRACTIVE unimplemented\n");
}
if (value & 5) {
- hw_error("System reset");
+ qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
}
}
break;
case 0xd10: /* System Control. */
case 0xd14: /* Configuration Control. */
/* TODO: Implement control registers. */
- goto bad_reg;
- case 0xd18: case 0xd1c: case 0xd20: /* System Handler Priority. */
- {
- int irq;
- irq = offset - 0xd14;
- s->gic.priority1[irq++][0] = value & 0xff;
- s->gic.priority1[irq++][0] = (value >> 8) & 0xff;
- s->gic.priority1[irq++][0] = (value >> 16) & 0xff;
- s->gic.priority1[irq][0] = (value >> 24) & 0xff;
- gic_update(&s->gic);
- }
+ qemu_log_mask(LOG_UNIMP, "NVIC: SCR and CCR unimplemented\n");
break;
case 0xd24: /* System Handler Control. */
/* TODO: Real hardware allows you to set/clear the active bits
@@ -380,47 +361,71 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value)
case 0xd34: /* Mem Manage Address. */
case 0xd38: /* Bus Fault Address. */
case 0xd3c: /* Aux Fault Status. */
- goto bad_reg;
+ qemu_log_mask(LOG_UNIMP,
+ "NVIC: fault status registers unimplemented\n");
+ break;
case 0xf00: /* Software Triggered Interrupt Register */
if ((value & 0x1ff) < s->num_irq) {
gic_set_pending_private(&s->gic, 0, value & 0x1ff);
}
break;
default:
- bad_reg:
- hw_error("NVIC: Bad write offset 0x%x\n", offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "NVIC: Bad write offset 0x%x\n", offset);
}
}
static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
unsigned size)
{
- /* At the moment we only support the ID registers for byte/word access.
- * This is not strictly correct as a few of the other registers also
- * allow byte access.
- */
+ nvic_state *s = (nvic_state *)opaque;
uint32_t offset = addr;
- if (offset >= 0xfe0) {
+ int i;
+ uint32_t val;
+
+ switch (offset) {
+ case 0xd18 ... 0xd23: /* System Handler Priority. */
+ val = 0;
+ for (i = 0; i < size; i++) {
+ val |= s->gic.priority1[(offset - 0xd14) + i][0] << (i * 8);
+ }
+ return val;
+ case 0xfe0 ... 0xfff: /* ID. */
if (offset & 3) {
return 0;
}
return nvic_id[(offset - 0xfe0) >> 2];
}
if (size == 4) {
- return nvic_readl(opaque, offset);
+ return nvic_readl(s, offset);
}
- hw_error("NVIC: Bad read of size %d at offset 0x%x\n", size, offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "NVIC: Bad read of size %d at offset 0x%x\n", size, offset);
+ return 0;
}
static void nvic_sysreg_write(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
+ nvic_state *s = (nvic_state *)opaque;
uint32_t offset = addr;
+ int i;
+
+ switch (offset) {
+ case 0xd18 ... 0xd23: /* System Handler Priority. */
+ for (i = 0; i < size; i++) {
+ s->gic.priority1[(offset - 0xd14) + i][0] =
+ (value >> (i * 8)) & 0xff;
+ }
+ gic_update(&s->gic);
+ return;
+ }
if (size == 4) {
- nvic_writel(opaque, offset, value);
+ nvic_writel(s, offset, value);
return;
}
- hw_error("NVIC: Bad write of size %d at offset 0x%x\n", size, offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "NVIC: Bad write of size %d at offset 0x%x\n", size, offset);
}
static const MemoryRegionOps nvic_sysreg_ops = {
diff --git a/hw/exynos4_boards.c b/hw/exynos4_boards.c
index 4951064c3f..bc815bbae3 100644
--- a/hw/exynos4_boards.c
+++ b/hw/exynos4_boards.c
@@ -93,11 +93,8 @@ static void lan9215_init(uint32_t base, qemu_irq irq)
}
}
-static Exynos4210State *exynos4_boards_init_common(
- const char *kernel_filename,
- const char *kernel_cmdline,
- const char *initrd_filename,
- Exynos4BoardType board_type)
+static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args,
+ Exynos4BoardType board_type)
{
if (smp_cpus != EXYNOS4210_NCPUS) {
fprintf(stderr, "%s board supports only %d CPU cores. Ignoring smp_cpus"
@@ -110,9 +107,9 @@ static Exynos4210State *exynos4_boards_init_common(
exynos4_board_binfo.board_id = exynos4_board_id[board_type];
exynos4_board_binfo.smp_bootreg_addr =
exynos4_board_smp_bootreg_addr[board_type];
- exynos4_board_binfo.kernel_filename = kernel_filename;
- exynos4_board_binfo.initrd_filename = initrd_filename;
- exynos4_board_binfo.kernel_cmdline = kernel_cmdline;
+ exynos4_board_binfo.kernel_filename = args->kernel_filename;
+ exynos4_board_binfo.initrd_filename = args->initrd_filename;
+ exynos4_board_binfo.kernel_cmdline = args->kernel_cmdline;
exynos4_board_binfo.gic_cpu_if_addr =
EXYNOS4210_SMP_PRIVATE_BASE_ADDR + 0x100;
@@ -122,9 +119,9 @@ static Exynos4210State *exynos4_boards_init_common(
" initrd_filename: %s\n",
exynos4_board_ram_size[board_type] / 1048576,
exynos4_board_ram_size[board_type],
- kernel_filename,
- kernel_cmdline,
- initrd_filename);
+ args->kernel_filename,
+ args->kernel_cmdline,
+ args->initrd_filename);
return exynos4210_init(get_system_memory(),
exynos4_board_ram_size[board_type]);
@@ -132,22 +129,15 @@ static Exynos4210State *exynos4_boards_init_common(
static void nuri_init(QEMUMachineInitArgs *args)
{
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- exynos4_boards_init_common(kernel_filename, kernel_cmdline,
- initrd_filename, EXYNOS4_BOARD_NURI);
+ exynos4_boards_init_common(args, EXYNOS4_BOARD_NURI);
arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo);
}
static void smdkc210_init(QEMUMachineInitArgs *args)
{
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- Exynos4210State *s = exynos4_boards_init_common(kernel_filename,
- kernel_cmdline, initrd_filename, EXYNOS4_BOARD_SMDKC210);
+ Exynos4210State *s = exynos4_boards_init_common(args,
+ EXYNOS4_BOARD_SMDKC210);
lan9215_init(SMDK_LAN9118_BASE_ADDR,
qemu_irq_invert(s->irq_table[exynos4210_get_irq(37, 1)]));
diff --git a/hw/mainstone.c b/hw/mainstone.c
index 3266946954..5bbecb7304 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -95,10 +95,8 @@ static struct arm_boot_info mainstone_binfo = {
};
static void mainstone_common_init(MemoryRegion *address_space_mem,
- ram_addr_t ram_size,
- const char *kernel_filename,
- const char *kernel_cmdline, const char *initrd_filename,
- const char *cpu_model, enum mainstone_model_e model, int arm_id)
+ QEMUMachineInitArgs *args,
+ enum mainstone_model_e model, int arm_id)
{
uint32_t sector_len = 256 * 1024;
hwaddr mainstone_flash_base[] = { MST_FLASH_0, MST_FLASH_1 };
@@ -108,6 +106,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
int i;
int be;
MemoryRegion *rom = g_new(MemoryRegion, 1);
+ const char *cpu_model = args->cpu_model;
if (!cpu_model)
cpu_model = "pxa270-c5";
@@ -164,22 +163,16 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
smc91c111_init(&nd_table[0], MST_ETH_PHYS,
qdev_get_gpio_in(mst_irq, ETHERNET_IRQ));
- mainstone_binfo.kernel_filename = kernel_filename;
- mainstone_binfo.kernel_cmdline = kernel_cmdline;
- mainstone_binfo.initrd_filename = initrd_filename;
+ mainstone_binfo.kernel_filename = args->kernel_filename;
+ mainstone_binfo.kernel_cmdline = args->kernel_cmdline;
+ mainstone_binfo.initrd_filename = args->initrd_filename;
mainstone_binfo.board_id = arm_id;
arm_load_kernel(mpu->cpu, &mainstone_binfo);
}
static void mainstone_init(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- mainstone_common_init(get_system_memory(), ram_size, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model, mainstone, 0x196);
+ mainstone_common_init(get_system_memory(), args, mainstone, 0x196);
}
static QEMUMachine mainstone2_machine = {
diff --git a/hw/nseries.c b/hw/nseries.c
index 9306aa15a7..652d9da333 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -1284,17 +1284,15 @@ static int n810_atag_setup(const struct arm_boot_info *info, void *p)
return n8x0_atag_setup(p, 810);
}
-static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
- const char *kernel_filename,
- const char *kernel_cmdline, const char *initrd_filename,
- const char *cpu_model, struct arm_boot_info *binfo, int model)
+static void n8x0_init(QEMUMachineInitArgs *args,
+ struct arm_boot_info *binfo, int model)
{
MemoryRegion *sysmem = get_system_memory();
struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s));
int sdram_size = binfo->ram_size;
DisplayState *ds;
- s->mpu = omap2420_mpu_init(sysmem, sdram_size, cpu_model);
+ s->mpu = omap2420_mpu_init(sysmem, sdram_size, args->cpu_model);
/* Setup peripherals
*
@@ -1338,17 +1336,18 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
n8x0_usb_setup(s);
}
- if (kernel_filename) {
+ if (args->kernel_filename) {
/* Or at the linux loader. */
- binfo->kernel_filename = kernel_filename;
- binfo->kernel_cmdline = kernel_cmdline;
- binfo->initrd_filename = initrd_filename;
+ binfo->kernel_filename = args->kernel_filename;
+ binfo->kernel_cmdline = args->kernel_cmdline;
+ binfo->initrd_filename = args->initrd_filename;
arm_load_kernel(s->mpu->cpu, binfo);
qemu_register_reset(n8x0_boot_init, s);
}
- if (option_rom[0].name && (boot_device[0] == 'n' || !kernel_filename)) {
+ 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. */
@@ -1400,28 +1399,12 @@ static struct arm_boot_info n810_binfo = {
static void n800_init(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- return n8x0_init(ram_size, boot_device,
- kernel_filename, kernel_cmdline, initrd_filename,
- cpu_model, &n800_binfo, 800);
+ return n8x0_init(args, &n800_binfo, 800);
}
static void n810_init(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- return n8x0_init(ram_size, boot_device,
- kernel_filename, kernel_cmdline, initrd_filename,
- cpu_model, &n810_binfo, 810);
+ return n8x0_init(args, &n810_binfo, 810);
}
static QEMUMachine n800_machine = {
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index eb2bf0569c..21a5bbb006 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -97,11 +97,7 @@ static struct arm_boot_info sx1_binfo = {
.board_id = 0x265,
};
-static void sx1_init(ram_addr_t ram_size,
- const char *boot_device,
- const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename, const char *cpu_model,
- const int version)
+static void sx1_init(QEMUMachineInitArgs *args, const int version)
{
struct omap_mpu_state_s *mpu;
MemoryRegion *address_space = get_system_memory();
@@ -121,7 +117,7 @@ static void sx1_init(ram_addr_t ram_size,
flash_size = flash2_size;
}
- mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, cpu_model);
+ mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, args->cpu_model);
/* External Flash (EMIFS) */
memory_region_init_ram(flash, "omap_sx1.flash0-0", flash_size);
@@ -192,16 +188,16 @@ static void sx1_init(ram_addr_t ram_size,
OMAP_CS1_BASE, &cs[1]);
}
- if (!kernel_filename && !fl_idx) {
+ if (!args->kernel_filename && !fl_idx) {
fprintf(stderr, "Kernel or Flash image must be specified\n");
exit(1);
}
/* Load the kernel. */
- if (kernel_filename) {
- sx1_binfo.kernel_filename = kernel_filename;
- sx1_binfo.kernel_cmdline = kernel_cmdline;
- sx1_binfo.initrd_filename = initrd_filename;
+ if (args->kernel_filename) {
+ sx1_binfo.kernel_filename = args->kernel_filename;
+ sx1_binfo.kernel_cmdline = args->kernel_cmdline;
+ sx1_binfo.initrd_filename = args->initrd_filename;
arm_load_kernel(mpu->cpu, &sx1_binfo);
}
@@ -211,26 +207,12 @@ static void sx1_init(ram_addr_t ram_size,
static void sx1_init_v1(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- sx1_init(ram_size, boot_device, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model, 1);
+ sx1_init(args, 1);
}
static void sx1_init_v2(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- sx1_init(ram_size, boot_device, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model, 2);
+ sx1_init(args, 2);
}
static QEMUMachine sx1_machine_v2 = {
diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index 5e3a409c2b..7d040b508a 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -42,6 +42,7 @@
#include "qemu-timer.h"
#include "exec-memory.h"
#include "host-utils.h"
+#include "sysbus.h"
#define PFLASH_BUG(fmt, ...) \
do { \
@@ -60,23 +61,28 @@ do { \
#endif
struct pflash_t {
+ SysBusDevice busdev;
BlockDriverState *bs;
- hwaddr base;
- hwaddr sector_len;
- hwaddr total_len;
- int width;
+ uint32_t nb_blocs;
+ uint64_t sector_len;
+ 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;
- uint16_t ident[4];
+ uint16_t ident0;
+ uint16_t ident1;
+ uint16_t ident2;
+ uint16_t ident3;
uint8_t cfi_len;
uint8_t cfi_table[0x52];
hwaddr counter;
unsigned int writeblock_size;
QEMUTimer *timer;
MemoryRegion mem;
+ char *name;
void *storage;
};
@@ -168,15 +174,16 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
case 0x90:
switch (boff) {
case 0:
- ret = pfl->ident[0] << 8 | pfl->ident[1];
+ ret = pfl->ident0 << 8 | pfl->ident1;
DPRINTF("%s: Manufacturer Code %04x\n", __func__, ret);
break;
case 1:
- ret = pfl->ident[2] << 8 | pfl->ident[3];
+ ret = pfl->ident2 << 8 | pfl->ident3;
DPRINTF("%s: Device ID Code %04x\n", __func__, ret);
break;
default:
- DPRINTF("%s: Read Device Information boff=%x\n", __func__, boff);
+ DPRINTF("%s: Read Device Information boff=%x\n", __func__,
+ (unsigned)boff);
ret = 0;
break;
}
@@ -279,9 +286,8 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
p = pfl->storage;
offset &= ~(pfl->sector_len - 1);
- DPRINTF("%s: block erase at " TARGET_FMT_plx " bytes "
- TARGET_FMT_plx "\n",
- __func__, offset, pfl->sector_len);
+ DPRINTF("%s: block erase at " TARGET_FMT_plx " bytes %x\n",
+ __func__, offset, (unsigned)pfl->sector_len);
if (!pfl->ro) {
memset(p + offset, 0xff, pfl->sector_len);
@@ -543,19 +549,13 @@ static const MemoryRegionOps pflash_cfi01_ops_le = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-pflash_t *pflash_cfi01_register(hwaddr base,
- DeviceState *qdev, const char *name,
- hwaddr size,
- BlockDriverState *bs, uint32_t sector_len,
- int nb_blocs, int width,
- uint16_t id0, uint16_t id1,
- uint16_t id2, uint16_t id3, int be)
+static int pflash_cfi01_init(SysBusDevice *dev)
{
- pflash_t *pfl;
- hwaddr total_len;
+ pflash_t *pfl = FROM_SYSBUS(typeof(*pfl), dev);
+ uint64_t total_len;
int ret;
- total_len = sector_len * nb_blocs;
+ total_len = pfl->sector_len * pfl->nb_blocs;
/* XXX: to be fixed */
#if 0
@@ -564,27 +564,22 @@ pflash_t *pflash_cfi01_register(hwaddr base,
return NULL;
#endif
- pfl = g_malloc0(sizeof(pflash_t));
-
memory_region_init_rom_device(
- &pfl->mem, be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl,
- name, size);
- vmstate_register_ram(&pfl->mem, qdev);
+ &pfl->mem, pfl->be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl,
+ pfl->name, total_len);
+ vmstate_register_ram(&pfl->mem, DEVICE(pfl));
pfl->storage = memory_region_get_ram_ptr(&pfl->mem);
- memory_region_add_subregion(get_system_memory(), base, &pfl->mem);
+ sysbus_init_mmio(dev, &pfl->mem);
- pfl->bs = bs;
if (pfl->bs) {
/* read the initial flash content */
ret = bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9);
+
if (ret < 0) {
- memory_region_del_subregion(get_system_memory(), &pfl->mem);
- vmstate_unregister_ram(&pfl->mem, qdev);
+ vmstate_unregister_ram(&pfl->mem, DEVICE(pfl));
memory_region_destroy(&pfl->mem);
- g_free(pfl);
- return NULL;
+ return 1;
}
- bdrv_attach_dev_nofail(pfl->bs, pfl);
}
if (pfl->bs) {
@@ -594,17 +589,9 @@ pflash_t *pflash_cfi01_register(hwaddr base,
}
pfl->timer = qemu_new_timer_ns(vm_clock, pflash_timer, pfl);
- pfl->base = base;
- pfl->sector_len = sector_len;
- pfl->total_len = total_len;
- pfl->width = width;
pfl->wcycle = 0;
pfl->cmd = 0;
pfl->status = 0;
- pfl->ident[0] = id0;
- pfl->ident[1] = id1;
- pfl->ident[2] = id2;
- pfl->ident[3] = id3;
/* Hardcoded CFI table */
pfl->cfi_len = 0x52;
/* Standard "QRY" string */
@@ -653,7 +640,7 @@ pflash_t *pflash_cfi01_register(hwaddr base,
pfl->cfi_table[0x28] = 0x02;
pfl->cfi_table[0x29] = 0x00;
/* Max number of bytes in multi-bytes write */
- if (width == 1) {
+ if (pfl->width == 1) {
pfl->cfi_table[0x2A] = 0x08;
} else {
pfl->cfi_table[0x2A] = 0x0B;
@@ -664,10 +651,10 @@ pflash_t *pflash_cfi01_register(hwaddr base,
/* Number of erase block regions (uniform) */
pfl->cfi_table[0x2C] = 0x01;
/* Erase block region 1 */
- pfl->cfi_table[0x2D] = nb_blocs - 1;
- pfl->cfi_table[0x2E] = (nb_blocs - 1) >> 8;
- pfl->cfi_table[0x2F] = sector_len >> 8;
- pfl->cfi_table[0x30] = sector_len >> 16;
+ pfl->cfi_table[0x2D] = pfl->nb_blocs - 1;
+ pfl->cfi_table[0x2E] = (pfl->nb_blocs - 1) >> 8;
+ pfl->cfi_table[0x2F] = pfl->sector_len >> 8;
+ pfl->cfi_table[0x30] = pfl->sector_len >> 16;
/* Extended */
pfl->cfi_table[0x31] = 'P';
@@ -689,6 +676,75 @@ pflash_t *pflash_cfi01_register(hwaddr base,
pfl->cfi_table[0x3f] = 0x01; /* Number of protection fields */
+ return 0;
+}
+
+static Property pflash_cfi01_properties[] = {
+ DEFINE_PROP_DRIVE("drive", struct pflash_t, bs),
+ DEFINE_PROP_UINT32("num-blocks", struct pflash_t, nb_blocs, 0),
+ DEFINE_PROP_UINT64("sector-length", struct pflash_t, sector_len, 0),
+ DEFINE_PROP_UINT8("width", struct pflash_t, width, 0),
+ DEFINE_PROP_UINT8("big-endian", struct pflash_t, be, 0),
+ DEFINE_PROP_UINT16("id0", struct pflash_t, ident0, 0),
+ DEFINE_PROP_UINT16("id1", struct pflash_t, ident1, 0),
+ DEFINE_PROP_UINT16("id2", struct pflash_t, ident2, 0),
+ DEFINE_PROP_UINT16("id3", struct pflash_t, ident3, 0),
+ DEFINE_PROP_STRING("name", struct pflash_t, name),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pflash_cfi01_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pflash_cfi01_init;
+ dc->props = pflash_cfi01_properties;
+}
+
+
+static const TypeInfo pflash_cfi01_info = {
+ .name = "cfi.pflash01",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(struct pflash_t),
+ .class_init = pflash_cfi01_class_init,
+};
+
+static void pflash_cfi01_register_types(void)
+{
+ type_register_static(&pflash_cfi01_info);
+}
+
+type_init(pflash_cfi01_register_types)
+
+pflash_t *pflash_cfi01_register(hwaddr base,
+ DeviceState *qdev, const char *name,
+ hwaddr size,
+ BlockDriverState *bs,
+ uint32_t sector_len, int nb_blocs, int width,
+ uint16_t id0, uint16_t id1,
+ uint16_t id2, uint16_t id3, int be)
+{
+ DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
+ SysBusDevice *busdev = sysbus_from_qdev(dev);
+ pflash_t *pfl = (pflash_t *)object_dynamic_cast(OBJECT(dev),
+ "cfi.pflash01");
+
+ if (bs && qdev_prop_set_drive(dev, "drive", bs)) {
+ abort();
+ }
+ qdev_prop_set_uint32(dev, "num-blocks", nb_blocs);
+ qdev_prop_set_uint64(dev, "sector-length", sector_len);
+ qdev_prop_set_uint8(dev, "width", width);
+ qdev_prop_set_uint8(dev, "big-endian", !!be);
+ qdev_prop_set_uint16(dev, "id0", id0);
+ qdev_prop_set_uint16(dev, "id1", id1);
+ qdev_prop_set_uint16(dev, "id2", id2);
+ qdev_prop_set_uint16(dev, "id3", id3);
+ qdev_prop_set_string(dev, "name", name);
+ qdev_init_nofail(dev);
+
+ sysbus_mmio_map(busdev, 0, base);
return pfl;
}
diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c
index 9f94c0623d..f918e36580 100644
--- a/hw/pflash_cfi02.c
+++ b/hw/pflash_cfi02.c
@@ -41,6 +41,7 @@
#include "block.h"
#include "exec-memory.h"
#include "host-utils.h"
+#include "sysbus.h"
//#define PFLASH_DEBUG
#ifdef PFLASH_DEBUG
@@ -55,19 +56,26 @@ do { \
#define PFLASH_LAZY_ROMD_THRESHOLD 42
struct pflash_t {
+ SysBusDevice busdev;
BlockDriverState *bs;
- hwaddr base;
uint32_t sector_len;
+ uint32_t nb_blocs;
uint32_t chip_len;
- int mappings;
- int width;
+ uint8_t mappings;
+ 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;
- uint16_t ident[4];
- uint16_t unlock_addr[2];
+ /* FIXME: implement array device properties */
+ uint16_t ident0;
+ uint16_t ident1;
+ uint16_t ident2;
+ uint16_t ident3;
+ uint16_t unlock_addr0;
+ uint16_t unlock_addr1;
uint8_t cfi_len;
uint8_t cfi_table[0x52];
QEMUTimer *timer;
@@ -80,6 +88,7 @@ struct pflash_t {
MemoryRegion orig_mem;
int rom_mode;
int read_counter; /* used for lazy switch-back to rom mode */
+ char *name;
void *storage;
};
@@ -190,16 +199,17 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
switch (boff) {
case 0x00:
case 0x01:
- ret = pfl->ident[boff & 0x01];
+ ret = boff & 0x01 ? pfl->ident1 : pfl->ident0;
break;
case 0x02:
ret = 0x00; /* Pretend all sectors are unprotected */
break;
case 0x0E:
case 0x0F:
- if (pfl->ident[2 + (boff & 0x01)] == (uint8_t)-1)
+ ret = boff & 0x01 ? pfl->ident3 : pfl->ident2;
+ if (ret == (uint8_t)-1) {
goto flash_read;
- ret = pfl->ident[2 + (boff & 0x01)];
+ }
break;
default:
goto flash_read;
@@ -283,9 +293,9 @@ static void pflash_write (pflash_t *pfl, hwaddr offset,
pfl->cmd = 0x98;
return;
}
- if (boff != pfl->unlock_addr[0] || cmd != 0xAA) {
+ if (boff != pfl->unlock_addr0 || cmd != 0xAA) {
DPRINTF("%s: unlock0 failed " TARGET_FMT_plx " %02x %04x\n",
- __func__, boff, cmd, pfl->unlock_addr[0]);
+ __func__, boff, cmd, pfl->unlock_addr0);
goto reset_flash;
}
DPRINTF("%s: unlock sequence started\n", __func__);
@@ -293,7 +303,7 @@ static void pflash_write (pflash_t *pfl, hwaddr offset,
case 1:
/* We started an unlock sequence */
check_unlock1:
- if (boff != pfl->unlock_addr[1] || cmd != 0x55) {
+ if (boff != pfl->unlock_addr1 || cmd != 0x55) {
DPRINTF("%s: unlock1 failed " TARGET_FMT_plx " %02x\n", __func__,
boff, cmd);
goto reset_flash;
@@ -302,7 +312,7 @@ static void pflash_write (pflash_t *pfl, hwaddr offset,
break;
case 2:
/* We finished an unlock sequence */
- if (!pfl->bypass && boff != pfl->unlock_addr[0]) {
+ if (!pfl->bypass && boff != pfl->unlock_addr0) {
DPRINTF("%s: command failed " TARGET_FMT_plx " %02x\n", __func__,
boff, cmd);
goto reset_flash;
@@ -400,7 +410,7 @@ static void pflash_write (pflash_t *pfl, hwaddr offset,
case 5:
switch (cmd) {
case 0x10:
- if (boff != pfl->unlock_addr[0]) {
+ if (boff != pfl->unlock_addr0) {
DPRINTF("%s: chip erase: invalid address " TARGET_FMT_plx "\n",
__func__, offset);
goto reset_flash;
@@ -575,50 +585,38 @@ static const MemoryRegionOps pflash_cfi02_ops_le = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-pflash_t *pflash_cfi02_register(hwaddr base,
- DeviceState *qdev, const char *name,
- hwaddr size,
- BlockDriverState *bs, uint32_t sector_len,
- int nb_blocs, int nb_mappings, int width,
- uint16_t id0, uint16_t id1,
- uint16_t id2, uint16_t id3,
- uint16_t unlock_addr0, uint16_t unlock_addr1,
- int be)
+static int pflash_cfi02_init(SysBusDevice *dev)
{
- pflash_t *pfl;
- int32_t chip_len;
+ pflash_t *pfl = FROM_SYSBUS(typeof(*pfl), dev);
+ uint32_t chip_len;
int ret;
- chip_len = sector_len * nb_blocs;
+ chip_len = pfl->sector_len * pfl->nb_blocs;
/* XXX: to be fixed */
#if 0
if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) &&
total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024))
return NULL;
#endif
- pfl = g_malloc0(sizeof(pflash_t));
- memory_region_init_rom_device(
- &pfl->orig_mem, be ? &pflash_cfi02_ops_be : &pflash_cfi02_ops_le, pfl,
- name, size);
- vmstate_register_ram(&pfl->orig_mem, qdev);
+
+ memory_region_init_rom_device(&pfl->orig_mem, pfl->be ?
+ &pflash_cfi02_ops_be : &pflash_cfi02_ops_le,
+ pfl, pfl->name, chip_len);
+ vmstate_register_ram(&pfl->orig_mem, DEVICE(pfl));
pfl->storage = memory_region_get_ram_ptr(&pfl->orig_mem);
- pfl->base = base;
pfl->chip_len = chip_len;
- pfl->mappings = nb_mappings;
- pfl->bs = bs;
if (pfl->bs) {
/* read the initial flash content */
ret = bdrv_read(pfl->bs, 0, pfl->storage, chip_len >> 9);
if (ret < 0) {
g_free(pfl);
- return NULL;
+ return 1;
}
- bdrv_attach_dev_nofail(pfl->bs, pfl);
}
pflash_setup_mappings(pfl);
pfl->rom_mode = 1;
- memory_region_add_subregion(get_system_memory(), pfl->base, &pfl->mem);
+ sysbus_init_mmio(dev, &pfl->mem);
if (pfl->bs) {
pfl->ro = bdrv_is_read_only(pfl->bs);
@@ -627,17 +625,9 @@ pflash_t *pflash_cfi02_register(hwaddr base,
}
pfl->timer = qemu_new_timer_ns(vm_clock, pflash_timer, pfl);
- pfl->sector_len = sector_len;
- pfl->width = width;
pfl->wcycle = 0;
pfl->cmd = 0;
pfl->status = 0;
- pfl->ident[0] = id0;
- pfl->ident[1] = id1;
- pfl->ident[2] = id2;
- pfl->ident[3] = id3;
- pfl->unlock_addr[0] = unlock_addr0;
- pfl->unlock_addr[1] = unlock_addr1;
/* Hardcoded CFI table (mostly from SG29 Spansion flash) */
pfl->cfi_len = 0x52;
/* Standard "QRY" string */
@@ -693,10 +683,10 @@ pflash_t *pflash_cfi02_register(hwaddr base,
/* Number of erase block regions (uniform) */
pfl->cfi_table[0x2C] = 0x01;
/* Erase block region 1 */
- pfl->cfi_table[0x2D] = nb_blocs - 1;
- pfl->cfi_table[0x2E] = (nb_blocs - 1) >> 8;
- pfl->cfi_table[0x2F] = sector_len >> 8;
- pfl->cfi_table[0x30] = sector_len >> 16;
+ pfl->cfi_table[0x2D] = pfl->nb_blocs - 1;
+ pfl->cfi_table[0x2E] = (pfl->nb_blocs - 1) >> 8;
+ pfl->cfi_table[0x2F] = pfl->sector_len >> 8;
+ pfl->cfi_table[0x30] = pfl->sector_len >> 16;
/* Extended */
pfl->cfi_table[0x31] = 'P';
@@ -716,5 +706,81 @@ pflash_t *pflash_cfi02_register(hwaddr base,
pfl->cfi_table[0x3b] = 0x00;
pfl->cfi_table[0x3c] = 0x00;
+ return 0;
+}
+
+static Property pflash_cfi02_properties[] = {
+ DEFINE_PROP_DRIVE("drive", struct pflash_t, bs),
+ DEFINE_PROP_UINT32("num-blocks", struct pflash_t, nb_blocs, 0),
+ DEFINE_PROP_UINT32("sector-length", struct pflash_t, sector_len, 0),
+ DEFINE_PROP_UINT8("width", struct pflash_t, width, 0),
+ DEFINE_PROP_UINT8("mappings", struct pflash_t, mappings, 0),
+ DEFINE_PROP_UINT8("big-endian", struct pflash_t, be, 0),
+ DEFINE_PROP_UINT16("id0", struct pflash_t, ident0, 0),
+ DEFINE_PROP_UINT16("id1", struct pflash_t, ident1, 0),
+ DEFINE_PROP_UINT16("id2", struct pflash_t, ident2, 0),
+ DEFINE_PROP_UINT16("id3", struct pflash_t, ident3, 0),
+ DEFINE_PROP_UINT16("unlock-addr0", struct pflash_t, unlock_addr0, 0),
+ DEFINE_PROP_UINT16("unlock-addr1", struct pflash_t, unlock_addr1, 0),
+ DEFINE_PROP_STRING("name", struct pflash_t, name),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pflash_cfi02_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pflash_cfi02_init;
+ dc->props = pflash_cfi02_properties;
+}
+
+static const TypeInfo pflash_cfi02_info = {
+ .name = "cfi.pflash02",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(struct pflash_t),
+ .class_init = pflash_cfi02_class_init,
+};
+
+static void pflash_cfi02_register_types(void)
+{
+ type_register_static(&pflash_cfi02_info);
+}
+
+type_init(pflash_cfi02_register_types)
+
+pflash_t *pflash_cfi02_register(hwaddr base,
+ DeviceState *qdev, const char *name,
+ hwaddr size,
+ BlockDriverState *bs, uint32_t sector_len,
+ int nb_blocs, int nb_mappings, int width,
+ uint16_t id0, uint16_t id1,
+ uint16_t id2, uint16_t id3,
+ uint16_t unlock_addr0, uint16_t unlock_addr1,
+ int be)
+{
+ DeviceState *dev = qdev_create(NULL, "cfi.pflash02");
+ SysBusDevice *busdev = sysbus_from_qdev(dev);
+ pflash_t *pfl = (pflash_t *)object_dynamic_cast(OBJECT(dev),
+ "cfi.pflash02");
+
+ if (bs && qdev_prop_set_drive(dev, "drive", bs)) {
+ abort();
+ }
+ qdev_prop_set_uint32(dev, "num-blocks", nb_blocs);
+ qdev_prop_set_uint32(dev, "sector-length", sector_len);
+ qdev_prop_set_uint8(dev, "width", width);
+ qdev_prop_set_uint8(dev, "mappings", nb_mappings);
+ qdev_prop_set_uint8(dev, "big-endian", !!be);
+ qdev_prop_set_uint16(dev, "id0", id0);
+ qdev_prop_set_uint16(dev, "id1", id1);
+ qdev_prop_set_uint16(dev, "id2", id2);
+ qdev_prop_set_uint16(dev, "id3", id3);
+ qdev_prop_set_uint16(dev, "unlock-addr0", unlock_addr0);
+ qdev_prop_set_uint16(dev, "unlock-addr1", unlock_addr1);
+ qdev_prop_set_string(dev, "name", name);
+ qdev_init_nofail(dev);
+
+ sysbus_mmio_map(busdev, 0, base);
return pfl;
}
diff --git a/hw/pl050.c b/hw/pl050.c
index 470572eabb..47032f1260 100644
--- a/hw/pl050.c
+++ b/hw/pl050.c
@@ -95,7 +95,8 @@ static uint64_t pl050_read(void *opaque, hwaddr offset,
case 4: /* KMIIR */
return s->pending | 2;
default:
- hw_error("pl050_read: Bad offset %x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "pl050_read: Bad offset %x\n", (int)offset);
return 0;
}
}
@@ -123,7 +124,8 @@ static void pl050_write(void *opaque, hwaddr offset,
s->clk = value;
return;
default:
- hw_error("pl050_write: Bad offset %x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "pl050_write: Bad offset %x\n", (int)offset);
}
}
static const MemoryRegionOps pl050_ops = {
diff --git a/hw/pl061.c b/hw/pl061.c
index 7d182e7cdf..f1ed5ced1d 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -164,7 +164,8 @@ static uint64_t pl061_read(void *opaque, hwaddr offset,
case 0x528: /* Analog mode select */
return s->amsel;
default:
- hw_error("pl061_read: Bad offset %x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "pl061_read: Bad offset %x\n", (int)offset);
return 0;
}
}
@@ -239,7 +240,8 @@ static void pl061_write(void *opaque, hwaddr offset,
s->amsel = value & 0xff;
break;
default:
- hw_error("pl061_write: Bad offset %x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "pl061_write: Bad offset %x\n", (int)offset);
}
pl061_update(s);
}
diff --git a/hw/pl080.c b/hw/pl080.c
index 6abe52857e..26150af757 100644
--- a/hw/pl080.c
+++ b/hw/pl080.c
@@ -281,7 +281,8 @@ static uint64_t pl080_read(void *opaque, hwaddr offset,
return s->sync;
default:
bad_offset:
- hw_error("pl080_read: Bad offset %x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "pl080_read: Bad offset %x\n", (int)offset);
return 0;
}
}
@@ -327,12 +328,13 @@ static void pl080_write(void *opaque, hwaddr offset,
case 10: /* SoftLBReq */
case 11: /* SoftLSReq */
/* ??? Implement these. */
- hw_error("pl080_write: Soft DMA not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "pl080_write: Soft DMA not implemented\n");
break;
case 12: /* Configuration */
s->conf = value;
if (s->conf & (PL080_CONF_M1 | PL080_CONF_M1)) {
- hw_error("pl080_write: Big-endian DMA not implemented\n");
+ qemu_log_mask(LOG_UNIMP,
+ "pl080_write: Big-endian DMA not implemented\n");
}
pl080_run(s);
break;
@@ -341,7 +343,8 @@ static void pl080_write(void *opaque, hwaddr offset,
break;
default:
bad_offset:
- hw_error("pl080_write: Bad offset %x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "pl080_write: Bad offset %x\n", (int)offset);
}
pl080_update(s);
}
diff --git a/hw/pl110.c b/hw/pl110.c
index 82486b0c14..d5472f4cce 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -349,7 +349,8 @@ static uint64_t pl110_read(void *opaque, hwaddr offset,
case 12: /* LCDLPCURR */
return s->lpbase;
default:
- hw_error("pl110_read: Bad offset %x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "pl110_read: Bad offset %x\n", (int)offset);
return 0;
}
}
@@ -417,7 +418,8 @@ static void pl110_write(void *opaque, hwaddr offset,
pl110_update(s);
break;
default:
- hw_error("pl110_write: Bad offset %x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "pl110_write: Bad offset %x\n", (int)offset);
}
}
diff --git a/hw/pl190.c b/hw/pl190.c
index 213229b566..40199302a9 100644
--- a/hw/pl190.c
+++ b/hw/pl190.c
@@ -199,7 +199,7 @@ static void pl190_write(void *opaque, hwaddr offset,
break;
case 0xc0: /* ITCR */
if (val) {
- hw_error("pl190: Test mode not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "pl190: Test mode not implemented\n");
}
break;
default:
diff --git a/hw/realview.c b/hw/realview.c
index b5cb08cb84..e789c159a9 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -44,11 +44,8 @@ static const int realview_board_id[] = {
0x76d
};
-static void realview_init(ram_addr_t ram_size,
- const char *boot_device,
- const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename, const char *cpu_model,
- enum realview_board_type board_type)
+static void realview_init(QEMUMachineInitArgs *args,
+ enum realview_board_type board_type)
{
ARMCPU *cpu = NULL;
CPUARMState *env;
@@ -73,6 +70,7 @@ static void realview_init(ram_addr_t ram_size,
uint32_t proc_id = 0;
uint32_t sys_id;
ram_addr_t low_ram_size;
+ ram_addr_t ram_size = args->ram_size;
switch (board_type) {
case BOARD_EB:
@@ -89,7 +87,7 @@ static void realview_init(ram_addr_t ram_size,
break;
}
for (n = 0; n < smp_cpus; n++) {
- cpu = cpu_arm_init(cpu_model);
+ cpu = cpu_arm_init(args->cpu_model);
if (!cpu) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
@@ -321,9 +319,9 @@ static void realview_init(ram_addr_t ram_size,
memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack);
realview_binfo.ram_size = ram_size;
- realview_binfo.kernel_filename = kernel_filename;
- realview_binfo.kernel_cmdline = kernel_cmdline;
- realview_binfo.initrd_filename = initrd_filename;
+ realview_binfo.kernel_filename = args->kernel_filename;
+ realview_binfo.kernel_cmdline = args->kernel_cmdline;
+ realview_binfo.initrd_filename = args->initrd_filename;
realview_binfo.nb_cpus = smp_cpus;
realview_binfo.board_id = realview_board_id[board_type];
realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0);
@@ -332,62 +330,34 @@ static void realview_init(ram_addr_t ram_size,
static void realview_eb_init(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- if (!cpu_model) {
- cpu_model = "arm926";
+ if (!args->cpu_model) {
+ args->cpu_model = "arm926";
}
- realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
- initrd_filename, cpu_model, BOARD_EB);
+ realview_init(args, BOARD_EB);
}
static void realview_eb_mpcore_init(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- if (!cpu_model) {
- cpu_model = "arm11mpcore";
+ if (!args->cpu_model) {
+ args->cpu_model = "arm11mpcore";
}
- realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
- initrd_filename, cpu_model, BOARD_EB_MPCORE);
+ realview_init(args, BOARD_EB_MPCORE);
}
static void realview_pb_a8_init(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- if (!cpu_model) {
- cpu_model = "cortex-a8";
+ if (!args->cpu_model) {
+ args->cpu_model = "cortex-a8";
}
- realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
- initrd_filename, cpu_model, BOARD_PB_A8);
+ realview_init(args, BOARD_PB_A8);
}
static void realview_pbx_a9_init(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- if (!cpu_model) {
- cpu_model = "cortex-a9";
+ if (!args->cpu_model) {
+ args->cpu_model = "cortex-a9";
}
- realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
- initrd_filename, cpu_model, BOARD_PBX_A9);
+ realview_init(args, BOARD_PBX_A9);
}
static QEMUMachine realview_eb_machine = {
diff --git a/hw/sd.c b/hw/sd.c
index 297580aabe..3c34d43ad4 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -55,24 +55,28 @@ typedef enum {
sd_illegal = -2,
} sd_rsp_type_t;
+enum SDCardModes {
+ sd_inactive,
+ sd_card_identification_mode,
+ sd_data_transfer_mode,
+};
+
+enum SDCardStates {
+ sd_inactive_state = -1,
+ sd_idle_state = 0,
+ sd_ready_state,
+ sd_identification_state,
+ sd_standby_state,
+ sd_transfer_state,
+ sd_sendingdata_state,
+ sd_receivingdata_state,
+ sd_programming_state,
+ sd_disconnect_state,
+};
+
struct SDState {
- enum {
- sd_inactive,
- sd_card_identification_mode,
- sd_data_transfer_mode,
- } mode;
- enum {
- sd_inactive_state = -1,
- sd_idle_state = 0,
- sd_ready_state,
- sd_identification_state,
- sd_standby_state,
- sd_transfer_state,
- sd_sendingdata_state,
- sd_receivingdata_state,
- sd_programming_state,
- sd_disconnect_state,
- } state;
+ uint32_t mode; /* current card mode, one of SDCardModes */
+ int32_t state; /* current card state, one of SDCardStates */
uint32_t ocr;
uint8_t scr[8];
uint8_t cid[16];
@@ -83,21 +87,22 @@ struct SDState {
uint32_t vhs;
bool wp_switch;
unsigned long *wp_groups;
+ int32_t wpgrps_size;
uint64_t size;
- int blk_len;
+ uint32_t blk_len;
uint32_t erase_start;
uint32_t erase_end;
uint8_t pwd[16];
- int pwd_len;
- int function_group[6];
+ uint32_t pwd_len;
+ uint8_t function_group[6];
bool spi;
- int current_cmd;
+ uint8_t current_cmd;
/* True if we will handle the next command as an ACMD. Note that this does
* *not* track the APP_CMD status bit!
*/
bool expecting_acmd;
- int blk_written;
+ uint32_t blk_written;
uint64_t data_start;
uint32_t data_offset;
uint8_t data[512];
@@ -421,8 +426,9 @@ static void sd_reset(SDState *sd, BlockDriverState *bdrv)
if (sd->wp_groups)
g_free(sd->wp_groups);
sd->wp_switch = bdrv ? bdrv_is_read_only(bdrv) : false;
- sd->wp_groups = bitmap_new(sect);
- memset(sd->function_group, 0, sizeof(int) * 6);
+ sd->wpgrps_size = sect;
+ sd->wp_groups = bitmap_new(sd->wpgrps_size);
+ memset(sd->function_group, 0, sizeof(sd->function_group));
sd->erase_start = 0;
sd->erase_end = 0;
sd->size = size;
@@ -446,6 +452,38 @@ static const BlockDevOps sd_block_ops = {
.change_media_cb = sd_cardchange,
};
+static const VMStateDescription sd_vmstate = {
+ .name = "sd-card",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(mode, SDState),
+ VMSTATE_INT32(state, SDState),
+ VMSTATE_UINT8_ARRAY(cid, SDState, 16),
+ VMSTATE_UINT8_ARRAY(csd, SDState, 16),
+ VMSTATE_UINT16(rca, SDState),
+ VMSTATE_UINT32(card_status, SDState),
+ VMSTATE_PARTIAL_BUFFER(sd_status, SDState, 1),
+ VMSTATE_UINT32(vhs, SDState),
+ VMSTATE_BITMAP(wp_groups, SDState, 0, wpgrps_size),
+ VMSTATE_UINT32(blk_len, SDState),
+ VMSTATE_UINT32(erase_start, SDState),
+ VMSTATE_UINT32(erase_end, SDState),
+ VMSTATE_UINT8_ARRAY(pwd, SDState, 16),
+ VMSTATE_UINT32(pwd_len, SDState),
+ VMSTATE_UINT8_ARRAY(function_group, SDState, 6),
+ VMSTATE_UINT8(current_cmd, SDState),
+ VMSTATE_BOOL(expecting_acmd, SDState),
+ VMSTATE_UINT32(blk_written, SDState),
+ VMSTATE_UINT64(data_start, SDState),
+ VMSTATE_UINT32(data_offset, SDState),
+ VMSTATE_UINT8_ARRAY(data, SDState, 512),
+ VMSTATE_BUFFER_UNSAFE(buf, SDState, 1, 512),
+ VMSTATE_BOOL(enable, SDState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
/* We do not model the chip select pin, so allow the board to select
whether card should be in SSI or MMC/SD mode. It is also up to the
board to ensure that ssi transfers only occur when the chip select
@@ -463,6 +501,7 @@ SDState *sd_init(BlockDriverState *bs, bool is_spi)
bdrv_attach_dev_nofail(sd->bdrv, sd);
bdrv_set_dev_ops(sd->bdrv, &sd_block_ops, sd);
}
+ vmstate_register(NULL, -1, &sd_vmstate, sd);
return sd;
}
@@ -476,19 +515,28 @@ void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert)
static void sd_erase(SDState *sd)
{
- int i, start, end;
+ int i;
+ uint64_t erase_start = sd->erase_start;
+ uint64_t erase_end = sd->erase_end;
+
if (!sd->erase_start || !sd->erase_end) {
sd->card_status |= ERASE_SEQ_ERROR;
return;
}
- start = sd_addr_to_wpnum(sd->erase_start);
- end = sd_addr_to_wpnum(sd->erase_end);
+ if (extract32(sd->ocr, OCR_CCS_BITN, 1)) {
+ /* High capacity memory card: erase units are 512 byte blocks */
+ erase_start *= 512;
+ erase_end *= 512;
+ }
+
+ erase_start = sd_addr_to_wpnum(erase_start);
+ erase_end = sd_addr_to_wpnum(erase_end);
sd->erase_start = 0;
sd->erase_end = 0;
sd->csd[14] |= 0x40;
- for (i = start; i <= end; i++) {
+ for (i = erase_start; i <= erase_end; i++) {
if (test_bit(i, sd->wp_groups)) {
sd->card_status |= WP_ERASE_SKIP;
}
@@ -567,7 +615,7 @@ static void sd_lock_command(SDState *sd)
sd->card_status |= LOCK_UNLOCK_FAILED;
return;
}
- bitmap_zero(sd->wp_groups, sd_addr_to_wpnum(sd->size) + 1);
+ bitmap_zero(sd->wp_groups, sd->wpgrps_size);
sd->csd[14] &= ~0x10;
sd->card_status &= ~CARD_IS_LOCKED;
sd->pwd_len = 0;
diff --git a/hw/sd.h b/hw/sd.h
index 4eb9679acd..d9b97e4466 100644
--- a/hw/sd.h
+++ b/hw/sd.h
@@ -50,6 +50,7 @@
#define READY_FOR_DATA (1 << 8)
#define APP_CMD (1 << 5)
#define AKE_SEQ_ERROR (1 << 3)
+#define OCR_CCS_BITN 30
typedef enum {
sd_none = -1,
diff --git a/hw/spitz.c b/hw/spitz.c
index 944c274a82..12e2815221 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -879,15 +879,14 @@ static struct arm_boot_info spitz_binfo = {
.ram_size = 0x04000000,
};
-static void spitz_common_init(ram_addr_t ram_size,
- const char *kernel_filename,
- const char *kernel_cmdline, const char *initrd_filename,
- const char *cpu_model, enum spitz_model_e model, int arm_id)
+static void spitz_common_init(QEMUMachineInitArgs *args,
+ enum spitz_model_e model, int arm_id)
{
PXA2xxState *mpu;
DeviceState *scp0, *scp1 = NULL;
MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *rom = g_new(MemoryRegion, 1);
+ const char *cpu_model = args->cpu_model;
if (!cpu_model)
cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0";
@@ -928,9 +927,9 @@ static void spitz_common_init(ram_addr_t ram_size,
/* A 4.0 GB microdrive is permanently sitting in CF slot 0. */
spitz_microdrive_attach(mpu, 0);
- spitz_binfo.kernel_filename = kernel_filename;
- spitz_binfo.kernel_cmdline = kernel_cmdline;
- spitz_binfo.initrd_filename = initrd_filename;
+ spitz_binfo.kernel_filename = args->kernel_filename;
+ spitz_binfo.kernel_cmdline = args->kernel_cmdline;
+ spitz_binfo.initrd_filename = args->initrd_filename;
spitz_binfo.board_id = arm_id;
arm_load_kernel(mpu->cpu, &spitz_binfo);
sl_bootparam_write(SL_PXA_PARAM_BASE);
@@ -938,46 +937,22 @@ static void spitz_common_init(ram_addr_t ram_size,
static void spitz_init(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- spitz_common_init(ram_size, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model, spitz, 0x2c9);
+ spitz_common_init(args, spitz, 0x2c9);
}
static void borzoi_init(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- spitz_common_init(ram_size, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model, borzoi, 0x33f);
+ spitz_common_init(args, borzoi, 0x33f);
}
static void akita_init(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- spitz_common_init(ram_size, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model, akita, 0x2e8);
+ spitz_common_init(args, akita, 0x2e8);
}
static void terrier_init(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- spitz_common_init(ram_size, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model, terrier, 0x33f);
+ spitz_common_init(args, terrier, 0x33f);
}
static QEMUMachine akitapda_machine = {
diff --git a/hw/versatile_i2c.c b/hw/versatile_i2c.c
index 44e7e40f2f..ad71e9d92d 100644
--- a/hw/versatile_i2c.c
+++ b/hw/versatile_i2c.c
@@ -40,7 +40,8 @@ static uint64_t versatile_i2c_read(void *opaque, hwaddr offset,
if (offset == 0) {
return (s->out & 1) | (s->in << 1);
} else {
- hw_error("%s: Bad offset 0x%x\n", __func__, (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad offset 0x%x\n", __func__, (int)offset);
return -1;
}
}
@@ -58,7 +59,8 @@ static void versatile_i2c_write(void *opaque, hwaddr offset,
s->out &= ~value;
break;
default:
- hw_error("%s: Bad offset 0x%x\n", __func__, (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad offset 0x%x\n", __func__, (int)offset);
}
bitbang_i2c_set(s->bitbang, BITBANG_I2C_SCL, (s->out & 1) != 0);
s->in = bitbang_i2c_set(s->bitbang, BITBANG_I2C_SDA, (s->out & 2) != 0);
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index e85f982897..25e652b1aa 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -167,11 +167,7 @@ static int vpb_sic_init(SysBusDevice *dev)
static struct arm_boot_info versatile_binfo;
-static void versatile_init(ram_addr_t ram_size,
- const char *boot_device,
- const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename, const char *cpu_model,
- int board_id)
+static void versatile_init(QEMUMachineInitArgs *args, int board_id)
{
ARMCPU *cpu;
MemoryRegion *sysmem = get_system_memory();
@@ -189,15 +185,15 @@ static void versatile_init(ram_addr_t ram_size,
int done_smc = 0;
DriveInfo *dinfo;
- if (!cpu_model) {
- cpu_model = "arm926";
+ if (!args->cpu_model) {
+ args->cpu_model = "arm926";
}
- cpu = cpu_arm_init(cpu_model);
+ cpu = cpu_arm_init(args->cpu_model);
if (!cpu) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
- memory_region_init_ram(ram, "versatile.ram", ram_size);
+ memory_region_init_ram(ram, "versatile.ram", args->ram_size);
vmstate_register_ram_global(ram);
/* ??? RAM should repeat to fill physical memory space. */
/* SDRAM at address zero. */
@@ -340,40 +336,22 @@ static void versatile_init(ram_addr_t ram_size,
fprintf(stderr, "qemu: Error registering flash memory.\n");
}
- versatile_binfo.ram_size = ram_size;
- versatile_binfo.kernel_filename = kernel_filename;
- versatile_binfo.kernel_cmdline = kernel_cmdline;
- versatile_binfo.initrd_filename = initrd_filename;
+ versatile_binfo.ram_size = args->ram_size;
+ versatile_binfo.kernel_filename = args->kernel_filename;
+ versatile_binfo.kernel_cmdline = args->kernel_cmdline;
+ versatile_binfo.initrd_filename = args->initrd_filename;
versatile_binfo.board_id = board_id;
arm_load_kernel(cpu, &versatile_binfo);
}
static void vpb_init(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- versatile_init(ram_size,
- boot_device,
- kernel_filename, kernel_cmdline,
- initrd_filename, cpu_model, 0x183);
+ versatile_init(args, 0x183);
}
static void vab_init(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- versatile_init(ram_size,
- boot_device,
- kernel_filename, kernel_cmdline,
- initrd_filename, cpu_model, 0x25e);
+ versatile_init(args, 0x25e);
}
static QEMUMachine versatilepb_machine = {
diff --git a/hw/vexpress.c b/hw/vexpress.c
index 3f7cb66a6b..d93f057bff 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -348,12 +348,7 @@ static const VEDBoardInfo a15_daughterboard = {
};
static void vexpress_common_init(const VEDBoardInfo *daughterboard,
- ram_addr_t ram_size,
- const char *boot_device,
- const char *kernel_filename,
- const char *kernel_cmdline,
- const char *initrd_filename,
- const char *cpu_model)
+ QEMUMachineInitArgs *args)
{
DeviceState *dev, *sysctl, *pl041;
qemu_irq pic[64];
@@ -366,7 +361,8 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
MemoryRegion *sram = g_new(MemoryRegion, 1);
const hwaddr *map = daughterboard->motherboard_map;
- daughterboard->init(daughterboard, ram_size, cpu_model, pic, &proc_id);
+ daughterboard->init(daughterboard, args->ram_size, args->cpu_model,
+ pic, &proc_id);
/* Motherboard peripherals: the wiring is the same but the
* addresses vary between the legacy and A-Series memory maps.
@@ -454,10 +450,10 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
/* VE_DAPROM: not modelled */
- vexpress_binfo.ram_size = ram_size;
- vexpress_binfo.kernel_filename = kernel_filename;
- vexpress_binfo.kernel_cmdline = kernel_cmdline;
- vexpress_binfo.initrd_filename = initrd_filename;
+ vexpress_binfo.ram_size = args->ram_size;
+ vexpress_binfo.kernel_filename = args->kernel_filename;
+ vexpress_binfo.kernel_cmdline = args->kernel_cmdline;
+ vexpress_binfo.initrd_filename = args->initrd_filename;
vexpress_binfo.nb_cpus = smp_cpus;
vexpress_binfo.board_id = VEXPRESS_BOARD_ID;
vexpress_binfo.loader_start = daughterboard->loader_start;
@@ -469,28 +465,12 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
static void vexpress_a9_init(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- vexpress_common_init(&a9_daughterboard,
- ram_size, boot_device, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model);
+ vexpress_common_init(&a9_daughterboard, args);
}
static void vexpress_a15_init(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- vexpress_common_init(&a15_daughterboard,
- ram_size, boot_device, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model);
+ vexpress_common_init(&a15_daughterboard, args);
}
static QEMUMachine vexpress_a9_machine = {
diff --git a/savevm.c b/savevm.c
index b080d37258..43d3d1bbeb 100644
--- a/savevm.c
+++ b/savevm.c
@@ -86,6 +86,7 @@
#include "memory.h"
#include "qmp-commands.h"
#include "trace.h"
+#include "bitops.h"
#define SELF_ANNOUNCE_ROUNDS 5
@@ -1132,6 +1133,46 @@ const VMStateInfo vmstate_info_unused_buffer = {
.put = put_unused_buffer,
};
+/* bitmaps (as defined by bitmap.h). Note that size here is the size
+ * of the bitmap in bits. The on-the-wire format of a bitmap is 64
+ * bit words with the bits in big endian order. The in-memory format
+ * is an array of 'unsigned long', which may be either 32 or 64 bits.
+ */
+/* This is the number of 64 bit words sent over the wire */
+#define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64)
+static int get_bitmap(QEMUFile *f, void *pv, size_t size)
+{
+ unsigned long *bmp = pv;
+ int i, idx = 0;
+ for (i = 0; i < BITS_TO_U64S(size); i++) {
+ uint64_t w = qemu_get_be64(f);
+ bmp[idx++] = w;
+ if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {
+ bmp[idx++] = w >> 32;
+ }
+ }
+ return 0;
+}
+
+static void put_bitmap(QEMUFile *f, void *pv, size_t size)
+{
+ unsigned long *bmp = pv;
+ int i, idx = 0;
+ for (i = 0; i < BITS_TO_U64S(size); i++) {
+ uint64_t w = bmp[idx++];
+ if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {
+ w |= ((uint64_t)bmp[idx++]) << 32;
+ }
+ qemu_put_be64(f, w);
+ }
+}
+
+const VMStateInfo vmstate_info_bitmap = {
+ .name = "bitmap",
+ .get = get_bitmap,
+ .put = put_bitmap,
+};
+
typedef struct CompatEntry {
char idstr[256];
int instance_id;
diff --git a/vmstate.h b/vmstate.h
index c9c320e62e..623af0a29a 100644
--- a/vmstate.h
+++ b/vmstate.h
@@ -139,6 +139,7 @@ extern const VMStateInfo vmstate_info_uint64;
extern const VMStateInfo vmstate_info_timer;
extern const VMStateInfo vmstate_info_buffer;
extern const VMStateInfo vmstate_info_unused_buffer;
+extern const VMStateInfo vmstate_info_bitmap;
#define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0)
#define type_check_pointer(t1,t2) ((t1**)0 - (t2*)0)
@@ -411,6 +412,18 @@ extern const VMStateInfo vmstate_info_unused_buffer;
.flags = VMS_BUFFER, \
}
+/* _field_size should be a int32_t field in the _state struct giving the
+ * size of the bitmap _field in bits.
+ */
+#define VMSTATE_BITMAP(_field, _state, _version, _field_size) { \
+ .name = (stringify(_field)), \
+ .version_id = (_version), \
+ .size_offset = vmstate_offset_value(_state, _field_size, int32_t),\
+ .info = &vmstate_info_bitmap, \
+ .flags = VMS_VBUFFER|VMS_POINTER, \
+ .offset = offsetof(_state, _field), \
+}
+
/* _f : field name
_f_n : num of elements field_name
_n : num of elements