diff mbox series

[v14,22/26] linux-user: Add LoongArch cpu_loop support

Message ID 20220106094200.1801206-23-gaosong@loongson.cn
State New
Headers show
Series Add LoongArch linux-user emulation support | expand

Commit Message

gaosong Jan. 6, 2022, 9:41 a.m. UTC
Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 configure                           |  3 +
 linux-user/loongarch64/cpu_loop.c   | 94 +++++++++++++++++++++++++++++
 linux-user/loongarch64/target_cpu.h | 34 +++++++++++
 3 files changed, 131 insertions(+)
 create mode 100644 linux-user/loongarch64/cpu_loop.c
 create mode 100644 linux-user/loongarch64/target_cpu.h

Comments

WANG Xuerui Jan. 9, 2022, 9:25 a.m. UTC | #1
On 1/6/22 17:41, Song Gao wrote:
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> Signed-off-by: Xiaojuan Yang<yangxiaojuan@loongson.cn>
> Reviewed-by: Richard Henderson<richard.henderson@linaro.org>
> ---
>   configure                           |  3 +
>   linux-user/loongarch64/cpu_loop.c   | 94 +++++++++++++++++++++++++++++
>   linux-user/loongarch64/target_cpu.h | 34 +++++++++++
>   3 files changed, 131 insertions(+)
>   create mode 100644 linux-user/loongarch64/cpu_loop.c
>   create mode 100644 linux-user/loongarch64/target_cpu.h
>
> diff --git a/configure b/configure
> index 030728d11e..93c4e5bd92 100755
> --- a/configure
> +++ b/configure
> @@ -659,6 +659,9 @@ case "$cpu" in
>     mips*)
>       cpu="mips" ;;
>   
> +  loongarch)
> +    cpu="loongarch64" ;;
> +
Do you really need this? Looking at the part above setting initial value 
for $cpu, you can only get here if $cpu is given on command-line, or 
returned by uname on a presumably LoongArch system not defining 
__loongarch64. Either would be unlikely though, and we really don't want 
to turn on 64-bit code for 32-bit hosts (that don't exist at the 
moment), so this case seems useless.
>     ppc)
>       CPU_CFLAGS="-m32" ;;
>     ppc64)
> diff --git a/linux-user/loongarch64/cpu_loop.c b/linux-user/loongarch64/cpu_loop.c
> new file mode 100644
> index 0000000000..6628d215ca
> --- /dev/null
> +++ b/linux-user/loongarch64/cpu_loop.c
> @@ -0,0 +1,94 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * QEMU LoongArch user cpu_loop.
> + *
> + * Copyright (c) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu.h"
> +#include "qemu-common.h"
> +#include "user-internals.h"
> +#include "cpu_loop-common.h"
> +#include "signal-common.h"
> +
> +void cpu_loop(CPULoongArchState *env)
> +{
> +    CPUState *cs = env_cpu(env);
> +    int trapnr, si_code;
> +    abi_long ret;
> +
> +    for (;;) {
> +        cpu_exec_start(cs);
> +        trapnr = cpu_exec(cs);
> +        cpu_exec_end(cs);
> +        process_queued_cpu_work(cs);
> +
> +        switch (trapnr) {
> +        case EXCP_INTERRUPT:
> +            /* just indicate that signals should be handled asap */
> +            break;
> +        case EXCP_SYSCALL:
> +            env->pc += 4;
> +            ret = do_syscall(env, env->gpr[11],
> +                             env->gpr[4], env->gpr[5],
> +                             env->gpr[6], env->gpr[7],
> +                             env->gpr[8], env->gpr[9],
> +                             -1, -1);
> +            if (ret == -QEMU_ERESTARTSYS) {
> +                env->pc -= 4;
> +                break;
> +            }
> +            if (ret == -QEMU_ESIGRETURN) {
> +                /*
> +                 * Returning from a successful sigreturn syscall.
> +                 * Avoid clobbering register state.
> +                 */
> +                break;
> +            }
> +            env->gpr[4] = ret;
> +            break;
> +        case EXCP_INE:
> +            force_sig_fault(TARGET_SIGILL, 0, env->pc);
> +            break;
> +        case EXCP_FPE:
> +            si_code = TARGET_FPE_FLTUNK;
> +            if (GET_FP_CAUSE(env->fcsr0) & FP_INVALID) {
> +                si_code = TARGET_FPE_FLTINV;
> +            } else if (GET_FP_CAUSE(env->fcsr0) & FP_DIV0) {
> +                si_code = TARGET_FPE_FLTDIV;
> +            } else if (GET_FP_CAUSE(env->fcsr0) & FP_OVERFLOW) {
> +                si_code = TARGET_FPE_FLTOVF;
> +            } else if (GET_FP_CAUSE(env->fcsr0) & FP_UNDERFLOW) {
> +                si_code = TARGET_FPE_FLTUND;
> +            } else if (GET_FP_CAUSE(env->fcsr0) & FP_INEXACT) {
> +                si_code = TARGET_FPE_FLTRES;
> +            }
> +            force_sig_fault(TARGET_SIGFPE, si_code, env->pc);
> +            break;
> +        case EXCP_DEBUG:
> +        case EXCP_BREAK:
> +            force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
> +            break;
> +        case EXCP_ATOMIC:
> +            cpu_exec_step_atomic(cs);
> +            break;
> +        default:
> +            EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n",
> +                      trapnr);
> +            exit(EXIT_FAILURE);
> +        }
> +        process_pending_signals(env);
> +    }
> +}
> +
> +void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
> +{
> +    int i;
> +
> +    for (i = 0; i < 32; i++) {
> +        env->gpr[i] = regs->regs[i];
> +    }
> +    env->pc = regs->csr.era;
> +
> +}
> diff --git a/linux-user/loongarch64/target_cpu.h b/linux-user/loongarch64/target_cpu.h
> new file mode 100644
> index 0000000000..a29af66156
> --- /dev/null
> +++ b/linux-user/loongarch64/target_cpu.h
> @@ -0,0 +1,34 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * LoongArch specific CPU ABI and functions for linux-user
> + *
> + * Copyright (c) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#ifndef LOONGARCH_TARGET_CPU_H
> +#define LOONGARCH_TARGET_CPU_H
> +
> +static inline void cpu_clone_regs_child(CPULoongArchState *env,
> +                                        target_ulong newsp, unsigned flags)
> +{
> +    if (newsp) {
> +        env->gpr[3] = newsp;
> +    }
> +    env->gpr[4] = 0;
> +}
> +
> +static inline void cpu_clone_regs_parent(CPULoongArchState *env,
> +                                         unsigned flags)
> +{
> +}
> +
> +static inline void cpu_set_tls(CPULoongArchState *env, target_ulong newtls)
> +{
> +    env->gpr[2] = newtls;
> +}
> +
> +static inline abi_ulong get_sp_from_cpustate(CPULoongArchState *state)
> +{
> +    return state->gpr[3];
> +}
> +#endif
diff mbox series

Patch

diff --git a/configure b/configure
index 030728d11e..93c4e5bd92 100755
--- a/configure
+++ b/configure
@@ -659,6 +659,9 @@  case "$cpu" in
   mips*)
     cpu="mips" ;;
 
+  loongarch)
+    cpu="loongarch64" ;;
+
   ppc)
     CPU_CFLAGS="-m32" ;;
   ppc64)
diff --git a/linux-user/loongarch64/cpu_loop.c b/linux-user/loongarch64/cpu_loop.c
new file mode 100644
index 0000000000..6628d215ca
--- /dev/null
+++ b/linux-user/loongarch64/cpu_loop.c
@@ -0,0 +1,94 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch user cpu_loop.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu.h"
+#include "qemu-common.h"
+#include "user-internals.h"
+#include "cpu_loop-common.h"
+#include "signal-common.h"
+
+void cpu_loop(CPULoongArchState *env)
+{
+    CPUState *cs = env_cpu(env);
+    int trapnr, si_code;
+    abi_long ret;
+
+    for (;;) {
+        cpu_exec_start(cs);
+        trapnr = cpu_exec(cs);
+        cpu_exec_end(cs);
+        process_queued_cpu_work(cs);
+
+        switch (trapnr) {
+        case EXCP_INTERRUPT:
+            /* just indicate that signals should be handled asap */
+            break;
+        case EXCP_SYSCALL:
+            env->pc += 4;
+            ret = do_syscall(env, env->gpr[11],
+                             env->gpr[4], env->gpr[5],
+                             env->gpr[6], env->gpr[7],
+                             env->gpr[8], env->gpr[9],
+                             -1, -1);
+            if (ret == -QEMU_ERESTARTSYS) {
+                env->pc -= 4;
+                break;
+            }
+            if (ret == -QEMU_ESIGRETURN) {
+                /*
+                 * Returning from a successful sigreturn syscall.
+                 * Avoid clobbering register state.
+                 */
+                break;
+            }
+            env->gpr[4] = ret;
+            break;
+        case EXCP_INE:
+            force_sig_fault(TARGET_SIGILL, 0, env->pc);
+            break;
+        case EXCP_FPE:
+            si_code = TARGET_FPE_FLTUNK;
+            if (GET_FP_CAUSE(env->fcsr0) & FP_INVALID) {
+                si_code = TARGET_FPE_FLTINV;
+            } else if (GET_FP_CAUSE(env->fcsr0) & FP_DIV0) {
+                si_code = TARGET_FPE_FLTDIV;
+            } else if (GET_FP_CAUSE(env->fcsr0) & FP_OVERFLOW) {
+                si_code = TARGET_FPE_FLTOVF;
+            } else if (GET_FP_CAUSE(env->fcsr0) & FP_UNDERFLOW) {
+                si_code = TARGET_FPE_FLTUND;
+            } else if (GET_FP_CAUSE(env->fcsr0) & FP_INEXACT) {
+                si_code = TARGET_FPE_FLTRES;
+            }
+            force_sig_fault(TARGET_SIGFPE, si_code, env->pc);
+            break;
+        case EXCP_DEBUG:
+        case EXCP_BREAK:
+            force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
+            break;
+        case EXCP_ATOMIC:
+            cpu_exec_step_atomic(cs);
+            break;
+        default:
+            EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n",
+                      trapnr);
+            exit(EXIT_FAILURE);
+        }
+        process_pending_signals(env);
+    }
+}
+
+void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
+{
+    int i;
+
+    for (i = 0; i < 32; i++) {
+        env->gpr[i] = regs->regs[i];
+    }
+    env->pc = regs->csr.era;
+
+}
diff --git a/linux-user/loongarch64/target_cpu.h b/linux-user/loongarch64/target_cpu.h
new file mode 100644
index 0000000000..a29af66156
--- /dev/null
+++ b/linux-user/loongarch64/target_cpu.h
@@ -0,0 +1,34 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_TARGET_CPU_H
+#define LOONGARCH_TARGET_CPU_H
+
+static inline void cpu_clone_regs_child(CPULoongArchState *env,
+                                        target_ulong newsp, unsigned flags)
+{
+    if (newsp) {
+        env->gpr[3] = newsp;
+    }
+    env->gpr[4] = 0;
+}
+
+static inline void cpu_clone_regs_parent(CPULoongArchState *env,
+                                         unsigned flags)
+{
+}
+
+static inline void cpu_set_tls(CPULoongArchState *env, target_ulong newtls)
+{
+    env->gpr[2] = newtls;
+}
+
+static inline abi_ulong get_sp_from_cpustate(CPULoongArchState *state)
+{
+    return state->gpr[3];
+}
+#endif