summary refs log tree commit diff stats
path: root/linux-user/arm/cpu_loop.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2025-07-28 10:43:26 -1000
committerRichard Henderson <richard.henderson@linaro.org>2025-08-28 06:39:25 +1000
commitea8683d2b3777fcb934a075df8b63d45642097d6 (patch)
treec6fbe600feffe0a70233248858734058a8112761 /linux-user/arm/cpu_loop.c
parent8d4020dd025dc37d9003c6a514e758d8c6ef99b9 (diff)
downloadfocaccia-qemu-ea8683d2b3777fcb934a075df8b63d45642097d6.tar.gz
focaccia-qemu-ea8683d2b3777fcb934a075df8b63d45642097d6.zip
linux-user/arm: Create init_main_thread
Merge init_thread and target_cpu_copy_regs.
There's no point going through a target_pt_regs intermediate.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'linux-user/arm/cpu_loop.c')
-rw-r--r--linux-user/arm/cpu_loop.c53
1 files changed, 43 insertions, 10 deletions
diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
index 9d54422736..739e1607e3 100644
--- a/linux-user/arm/cpu_loop.c
+++ b/linux-user/arm/cpu_loop.c
@@ -480,17 +480,50 @@ void cpu_loop(CPUARMState *env)
     }
 }
 
-void target_cpu_copy_regs(CPUArchState *env, target_pt_regs *regs)
+void init_main_thread(CPUState *cs, struct image_info *info)
 {
-    CPUState *cpu = env_cpu(env);
-    TaskState *ts = get_task_state(cpu);
-    struct image_info *info = ts->info;
-    int i;
-
-    cpsr_write(env, regs->uregs[16], CPSR_USER | CPSR_EXEC,
-               CPSRWriteByInstr);
-    for(i = 0; i < 16; i++) {
-        env->regs[i] = regs->uregs[i];
+    CPUARMState *env = cpu_env(cs);
+    abi_ptr stack = info->start_stack;
+    abi_ptr entry = info->entry;
+
+    cpsr_write(env, ARM_CPU_MODE_USR | (entry & 1 ? CPSR_T : 0),
+               CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
+
+    env->regs[15] = entry & 0xfffffffe;
+    env->regs[13] = stack;
+
+    /* FIXME - what to for failure of get_user()? */
+    get_user_ual(env->regs[2], stack + 8); /* envp */
+    get_user_ual(env->regs[1], stack + 4); /* envp */
+
+    /*
+     * Per the SVR4 ABI, r0 contains a pointer to a function to be
+     * registered with atexit.  A value of 0 means we have no such handler.
+     */
+    env->regs[0] = 0;
+
+    /* For uClinux PIC binaries.  */
+    /* XXX: Linux does this only on ARM with no MMU (do we care?) */
+    env->regs[10] = info->start_data;
+
+    /* Support ARM FDPIC.  */
+    if (info_is_fdpic(info)) {
+        /*
+         * As described in the ABI document, r7 points to the loadmap info
+         * prepared by the kernel. If an interpreter is needed, r8 points
+         * to the interpreter loadmap and r9 points to the interpreter
+         * PT_DYNAMIC info. If no interpreter is needed, r8 is zero, and
+         * r9 points to the main program PT_DYNAMIC info.
+         */
+        env->regs[7] = info->loadmap_addr;
+        if (info->interpreter_loadmap_addr) {
+            /* Executable is dynamically loaded.  */
+            env->regs[8] = info->interpreter_loadmap_addr;
+            env->regs[9] = info->interpreter_pt_dynamic_addr;
+        } else {
+            env->regs[8] = 0;
+            env->regs[9] = info->pt_dynamic_addr;
+        }
     }
 
     if (TARGET_BIG_ENDIAN) {