diff --git a/hw/arm_boot.c b/hw/arm_boot.c index c313a9f9af..dfc00db28a 100644 --- a/hw/arm_boot.c +++ b/hw/arm_boot.c @@ -24,6 +24,17 @@ static uint32_t bootloader[] = { 0 /* Kernel entry point. Set by integratorcp_init. */ }; +static void main_cpu_reset(void *opaque) +{ + CPUState *env = opaque; + + cpu_reset(env); + if (env->kernel_filename) + arm_load_kernel(env, env->ram_size, env->kernel_filename, + env->kernel_cmdline, env->initrd_filename, + env->board_id); +} + static void set_kernel_args(uint32_t ram_size, int initrd_size, const char *kernel_cmdline) { @@ -81,6 +92,14 @@ void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename, exit(1); } + if (!env->kernel_filename) { + env->ram_size = ram_size; + env->kernel_filename = kernel_filename; + env->kernel_cmdline = kernel_cmdline; + env->initrd_filename = initrd_filename; + env->board_id = board_id; + qemu_register_reset(main_cpu_reset, env); + } /* Assume that raw images are linux kernels, and ELF images are not. */ kernel_size = load_elf(kernel_filename, 0, &elf_entry); entry = elf_entry; diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c index e9de998a2a..90ea76e714 100644 --- a/hw/arm_sysctl.c +++ b/hw/arm_sysctl.c @@ -149,7 +149,7 @@ static void arm_sysctl_write(void *opaque, target_phys_addr_t offset, if (s->lockval == LOCK_VALUE) { s->resetlevel = val; if (val & 0x100) - cpu_abort(cpu_single_env, "Board reset\n"); + qemu_system_reset_request (); } break; case 0x44: /* PCICTL */ diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 891616ecbe..68bf3fd0f4 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -122,6 +122,12 @@ typedef struct CPUARMState { CPU_COMMON + /* These fields after the common ones so thes are preserved on reset. */ + int ram_size; + const char *kernel_filename; + const char *kernel_cmdline; + const char *initrd_filename; + int board_id; } CPUARMState; CPUARMState *cpu_arm_init(void); diff --git a/target-arm/helper.c b/target-arm/helper.c index 36f5fe073f..242dd28f7b 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -5,8 +5,37 @@ #include "cpu.h" #include "exec-all.h" +static inline void set_feature(CPUARMState *env, int feature) +{ + env->features |= 1u << feature; +} + +static void cpu_reset_model_id(CPUARMState *env, uint32_t id) +{ + env->cp15.c0_cpuid = id; + switch (id) { + case ARM_CPUID_ARM926: + set_feature(env, ARM_FEATURE_VFP); + env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090; + break; + case ARM_CPUID_ARM1026: + set_feature(env, ARM_FEATURE_VFP); + set_feature(env, ARM_FEATURE_AUXCR); + env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0; + break; + default: + cpu_abort(env, "Bad CPU ID: %x\n", id); + break; + } +} + void cpu_reset(CPUARMState *env) { + uint32_t id; + id = env->cp15.c0_cpuid; + memset(env, 0, offsetof(CPUARMState, breakpoints)); + if (id) + cpu_reset_model_id(env, id); #if defined (CONFIG_USER_ONLY) env->uncached_cpsr = ARM_CPU_MODE_USR; env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30; @@ -16,6 +45,7 @@ void cpu_reset(CPUARMState *env) env->vfp.xregs[ARM_VFP_FPEXC] = 0; #endif env->regs[15] = 0; + tlb_flush(env, 1); } CPUARMState *cpu_arm_init(void) @@ -27,15 +57,9 @@ CPUARMState *cpu_arm_init(void) return NULL; cpu_exec_init(env); cpu_reset(env); - tlb_flush(env, 1); return env; } -static inline void set_feature(CPUARMState *env, int feature) -{ - env->features |= 1u << feature; -} - struct arm_cpu_t { uint32_t id; const char *name; @@ -74,22 +98,7 @@ void cpu_arm_set_model(CPUARMState *env, const char *name) cpu_abort(env, "Unknown CPU '%s'", name); return; } - - env->cp15.c0_cpuid = id; - switch (id) { - case ARM_CPUID_ARM926: - set_feature(env, ARM_FEATURE_VFP); - env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090; - break; - case ARM_CPUID_ARM1026: - set_feature(env, ARM_FEATURE_VFP); - set_feature(env, ARM_FEATURE_AUXCR); - env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0; - break; - default: - cpu_abort(env, "Bad CPU ID: %x\n", id); - break; - } + cpu_reset_model_id(env, id); } void cpu_arm_close(CPUARMState *env)