linux-user: Add LoongArch elf support

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20220624031049.1716097-4-gaosong@loongson.cn>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Song Gao 2022-06-24 11:10:39 +08:00 committed by Richard Henderson
parent 9d5cd6587a
commit 3418fe25fa
2 changed files with 103 additions and 0 deletions

View file

@ -922,6 +922,97 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *en
#endif
#ifdef TARGET_LOONGARCH64
#define ELF_START_MMAP 0x80000000
#define ELF_CLASS ELFCLASS64
#define ELF_ARCH EM_LOONGARCH
#define elf_check_arch(x) ((x) == EM_LOONGARCH)
static inline void init_thread(struct target_pt_regs *regs,
struct image_info *infop)
{
/*Set crmd PG,DA = 1,0 */
regs->csr.crmd = 2 << 3;
regs->csr.era = infop->entry;
regs->regs[3] = infop->start_stack;
}
/* See linux kernel: arch/loongarch/include/asm/elf.h */
#define ELF_NREG 45
typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
enum {
TARGET_EF_R0 = 0,
TARGET_EF_CSR_ERA = TARGET_EF_R0 + 33,
TARGET_EF_CSR_BADV = TARGET_EF_R0 + 34,
};
static void elf_core_copy_regs(target_elf_gregset_t *regs,
const CPULoongArchState *env)
{
int i;
(*regs)[TARGET_EF_R0] = 0;
for (i = 1; i < ARRAY_SIZE(env->gpr); i++) {
(*regs)[TARGET_EF_R0 + i] = tswapreg(env->gpr[i]);
}
(*regs)[TARGET_EF_CSR_ERA] = tswapreg(env->pc);
(*regs)[TARGET_EF_CSR_BADV] = tswapreg(env->CSR_BADV);
}
#define USE_ELF_CORE_DUMP
#define ELF_EXEC_PAGESIZE 4096
#define ELF_HWCAP get_elf_hwcap()
/* 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),
};
static uint32_t get_elf_hwcap(void)
{
LoongArchCPU *cpu = LOONGARCH_CPU(thread_cpu);
uint32_t 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;
}
return hwcaps;
}
#define ELF_PLATFORM "loongarch"
#endif /* TARGET_LOONGARCH64 */
#ifdef TARGET_MIPS
#define ELF_START_MMAP 0x80000000

View file

@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2021 Loongson Technology Corporation Limited
*/
#ifndef LOONGARCH_TARGET_ELF_H
#define LOONGARCH_TARGET_ELF_H
static inline const char *cpu_get_model(uint32_t eflags)
{
return "la464";
}
#endif