summary refs log tree commit diff stats
path: root/linux-user/loongarch64
diff options
context:
space:
mode:
Diffstat (limited to 'linux-user/loongarch64')
-rw-r--r--linux-user/loongarch64/cpu_loop.c11
-rw-r--r--linux-user/loongarch64/elfload.c78
-rw-r--r--linux-user/loongarch64/target_elf.h21
-rw-r--r--linux-user/loongarch64/target_ptrace.h15
-rw-r--r--linux-user/loongarch64/target_syscall.h23
5 files changed, 114 insertions, 34 deletions
diff --git a/linux-user/loongarch64/cpu_loop.c b/linux-user/loongarch64/cpu_loop.c
index ec8a06c88c..a0a4cbb7cc 100644
--- a/linux-user/loongarch64/cpu_loop.c
+++ b/linux-user/loongarch64/cpu_loop.c
@@ -120,13 +120,10 @@ void cpu_loop(CPULoongArchState *env)
     }
 }
 
-void target_cpu_copy_regs(CPUArchState *env, target_pt_regs *regs)
+void init_main_thread(CPUState *cs, struct image_info *info)
 {
-    int i;
-
-    for (i = 0; i < 32; i++) {
-        env->gpr[i] = regs->regs[i];
-    }
-    env->pc = regs->csr.era;
+    CPUArchState *env = cpu_env(cs);
 
+    env->pc = info->entry;
+    env->gpr[3] = info->start_stack;
 }
diff --git a/linux-user/loongarch64/elfload.c b/linux-user/loongarch64/elfload.c
new file mode 100644
index 0000000000..ce3bd0c607
--- /dev/null
+++ b/linux-user/loongarch64/elfload.c
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "qemu/osdep.h"
+#include "qemu.h"
+#include "loader.h"
+#include "target_elf.h"
+
+
+const char *get_elf_cpu_model(uint32_t eflags)
+{
+    return "la464";
+}
+
+/* See arch/loongarch/include/uapi/asm/hwcap.h */
+enum {
+    HWCAP_LOONGARCH_CPUCFG   = (1 << 0),
+    HWCAP_LOONGARCH_LAM      = (1 << 1),
+    HWCAP_LOONGARCH_UAL      = (1 << 2),
+    HWCAP_LOONGARCH_FPU      = (1 << 3),
+    HWCAP_LOONGARCH_LSX      = (1 << 4),
+    HWCAP_LOONGARCH_LASX     = (1 << 5),
+    HWCAP_LOONGARCH_CRC32    = (1 << 6),
+    HWCAP_LOONGARCH_COMPLEX  = (1 << 7),
+    HWCAP_LOONGARCH_CRYPTO   = (1 << 8),
+    HWCAP_LOONGARCH_LVZ      = (1 << 9),
+    HWCAP_LOONGARCH_LBT_X86  = (1 << 10),
+    HWCAP_LOONGARCH_LBT_ARM  = (1 << 11),
+    HWCAP_LOONGARCH_LBT_MIPS = (1 << 12),
+};
+
+abi_ulong get_elf_hwcap(CPUState *cs)
+{
+    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+    abi_ulong hwcaps = 0;
+
+    hwcaps |= HWCAP_LOONGARCH_CRC32;
+
+    if (FIELD_EX32(cpu->env.cpucfg[1], CPUCFG1, UAL)) {
+        hwcaps |= HWCAP_LOONGARCH_UAL;
+    }
+
+    if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, FP)) {
+        hwcaps |= HWCAP_LOONGARCH_FPU;
+    }
+
+    if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LAM)) {
+        hwcaps |= HWCAP_LOONGARCH_LAM;
+    }
+
+    if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LSX)) {
+        hwcaps |= HWCAP_LOONGARCH_LSX;
+    }
+
+    if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LASX)) {
+        hwcaps |= HWCAP_LOONGARCH_LASX;
+    }
+
+    return hwcaps;
+}
+
+const char *get_elf_platform(CPUState *cs)
+{
+    return "loongarch";
+}
+
+#define tswapreg(ptr)   tswapal(ptr)
+
+void elf_core_copy_regs(target_elf_gregset_t *r, const CPULoongArchState *env)
+{
+    r->pt.regs[0] = 0;
+
+    for (int i = 1; i < ARRAY_SIZE(env->gpr); i++) {
+        r->pt.regs[i] = tswapreg(env->gpr[i]);
+    }
+
+    r->pt.csr_era = tswapreg(env->pc);
+    r->pt.csr_badv = tswapreg(env->CSR_BADV);
+}
diff --git a/linux-user/loongarch64/target_elf.h b/linux-user/loongarch64/target_elf.h
index 95c3f05a46..3aa8c83958 100644
--- a/linux-user/loongarch64/target_elf.h
+++ b/linux-user/loongarch64/target_elf.h
@@ -5,8 +5,21 @@
 
 #ifndef LOONGARCH_TARGET_ELF_H
 #define LOONGARCH_TARGET_ELF_H
-static inline const char *cpu_get_model(uint32_t eflags)
-{
-    return "la464";
-}
+
+#include "target_ptrace.h"
+
+#define ELF_CLASS               ELFCLASS64
+#define ELF_MACHINE             EM_LOONGARCH
+#define EXSTACK_DEFAULT         true
+#define VDSO_HEADER             "vdso.c.inc"
+
+#define HAVE_ELF_HWCAP          1
+#define HAVE_ELF_PLATFORM       1
+#define HAVE_ELF_CORE_DUMP      1
+
+/* See linux kernel: arch/loongarch/include/asm/elf.h */
+typedef struct target_elf_gregset_t {
+    struct target_user_pt_regs pt;
+} target_elf_gregset_t;
+
 #endif
diff --git a/linux-user/loongarch64/target_ptrace.h b/linux-user/loongarch64/target_ptrace.h
new file mode 100644
index 0000000000..2578e09207
--- /dev/null
+++ b/linux-user/loongarch64/target_ptrace.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef LOONGARCH64_TARGET_PTRACE_H
+#define LOONGARCH64_TARGET_PTRACE_H
+
+/* See arch/loongarch/include/uapi/asm/ptrace.h. */
+struct target_user_pt_regs {
+    abi_ulong regs[32];
+    abi_ulong orig_a0;
+    abi_ulong csr_era;
+    abi_ulong csr_badv;
+    abi_ulong reserved[10];
+};
+
+#endif /* LOONGARCH64_TARGET_PTRACE_H */
diff --git a/linux-user/loongarch64/target_syscall.h b/linux-user/loongarch64/target_syscall.h
index 39f229bb9c..f7ced7b2be 100644
--- a/linux-user/loongarch64/target_syscall.h
+++ b/linux-user/loongarch64/target_syscall.h
@@ -8,29 +8,6 @@
 
 #include "qemu/units.h"
 
-/*
- * this struct defines the way the registers are stored on the
- * stack during a system call.
- */
-
-struct target_pt_regs {
-    /* Saved main processor registers. */
-    target_ulong regs[32];
-
-    /* Saved special registers. */
-    struct {
-        target_ulong era;
-        target_ulong badv;
-        target_ulong crmd;
-        target_ulong prmd;
-        target_ulong euen;
-        target_ulong ecfg;
-        target_ulong estat;
-    } csr;
-    target_ulong orig_a0;
-    target_ulong __last[0];
-};
-
 #define UNAME_MACHINE "loongarch64"
 #define UNAME_MINIMUM_RELEASE "5.19.0"