diff options
author | Paul Brook <paul@codesourcery.com> | 2009-11-11 18:07:53 +0000 |
---|---|---|
committer | Paul Brook <paul@codesourcery.com> | 2009-11-11 18:07:53 +0000 |
commit | f2d74978764f62d832d61ac17bb5d934ade58816 (patch) | |
tree | 93c836769cf2da4b27d73e1bbf2accda18dee31a /hw | |
parent | 715a664ac4ca3b9e44ffbc0ca41ecd91fbe96656 (diff) |
Fix ARM system emulation
Since 45a50b1 load_image_targphys should only be called once.
ARM boards incorrectly call it every time the system is reset.
Signed-off-by: Paul Brook <paul@codesourcery.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/arm-misc.h | 4 | ||||
-rw-r--r-- | hw/arm_boot.c | 65 |
2 files changed, 41 insertions, 28 deletions
diff --git a/hw/arm-misc.h b/hw/arm-misc.h index 367dd25c0b..e584073cb2 100644 --- a/hw/arm-misc.h +++ b/hw/arm-misc.h @@ -31,6 +31,10 @@ struct arm_boot_info { int nb_cpus; int board_id; int (*atag_board)(struct arm_boot_info *info, void *p); + /* Used internally by arm_boot.c */ + int is_linux; + target_phys_addr_t initrd_size; + target_phys_addr_t entry; }; void arm_load_kernel(CPUState *env, struct arm_boot_info *info); diff --git a/hw/arm_boot.c b/hw/arm_boot.c index a8a38c5a36..28e9dbd607 100644 --- a/hw/arm_boot.c +++ b/hw/arm_boot.c @@ -44,17 +44,6 @@ static uint32_t smpboot[] = { 0xe12fff11 /* bx r1 */ }; -static void main_cpu_reset(void *opaque) -{ - CPUState *env = opaque; - - cpu_reset(env); - if (env->boot_info) - arm_load_kernel(env, env->boot_info); - - /* TODO: Reset secondary CPUs. */ -} - #define WRITE_WORD(p, value) do { \ stl_phys_notdirty(p, value); \ p += 4; \ @@ -186,6 +175,29 @@ static void set_kernel_args_old(struct arm_boot_info *info, } } +static void main_cpu_reset(void *opaque) +{ + CPUState *env = opaque; + struct arm_boot_info *info = env->boot_info; + + cpu_reset(env); + if (info) { + if (!info->is_linux) { + /* Jump to the entry point. */ + env->regs[15] = info->entry & 0xfffffffe; + env->thumb = info->entry & 1; + } else { + if (old_param) { + set_kernel_args_old(info, info->initrd_size, + info->loader_start); + } else { + set_kernel_args(info, info->initrd_size, info->loader_start); + } + } + } + /* TODO: Reset secondary CPUs. */ +} + void arm_load_kernel(CPUState *env, struct arm_boot_info *info) { int kernel_size; @@ -202,12 +214,9 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info) exit(1); } - if (!env->boot_info) { - if (info->nb_cpus == 0) - info->nb_cpus = 1; - env->boot_info = info; - qemu_register_reset(main_cpu_reset, env); - } + if (info->nb_cpus == 0) + info->nb_cpus = 1; + env->boot_info = info; #ifdef TARGET_WORDS_BIGENDIAN big_endian = 1; @@ -234,11 +243,8 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info) info->kernel_filename); exit(1); } - if (!is_linux) { - /* Jump to the entry point. */ - env->regs[15] = entry & 0xfffffffe; - env->thumb = entry & 1; - } else { + info->entry = entry; + if (is_linux) { if (info->initrd_filename) { initrd_size = load_image_targphys(info->initrd_filename, info->loader_start @@ -257,16 +263,19 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info) bootloader[5] = info->loader_start + KERNEL_ARGS_ADDR; bootloader[6] = entry; for (n = 0; n < sizeof(bootloader) / 4; n++) { - stl_phys_notdirty(info->loader_start + (n * 4), bootloader[n]); + bootloader[n] = tswap32(bootloader[n]); } + rom_add_blob_fixed("bootloader", bootloader, sizeof(bootloader), + info->loader_start); if (info->nb_cpus > 1) { for (n = 0; n < sizeof(smpboot) / 4; n++) { - stl_phys_notdirty(info->smp_loader_start + (n * 4), smpboot[n]); + smpboot[n] = tswap32(smpboot[n]); } + rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), + info->smp_loader_start); } - if (old_param) - set_kernel_args_old(info, initrd_size, info->loader_start); - else - set_kernel_args(info, initrd_size, info->loader_start); + info->initrd_size = initrd_size; } + info->is_linux = is_linux; + qemu_register_reset(main_cpu_reset, env); } |