This patch adds support for AArch64 in all the small corners of linux-user and beyond.
Signed-off-by: Alexander Graf <ag...@suse.de> --- default-configs/arm64-linux-user.mak | 3 ++ linux-user/arm/syscall.h | 46 +++++++++++++++++++++++++++++---- linux-user/elfload.c | 15 +++++++++- linux-user/main.c | 9 ++++++ target-arm/cpu.h | 20 ++++++++++++--- 5 files changed, 81 insertions(+), 12 deletions(-) create mode 100644 default-configs/arm64-linux-user.mak diff --git a/default-configs/arm64-linux-user.mak b/default-configs/arm64-linux-user.mak new file mode 100644 index 0000000..46d4aa2 --- /dev/null +++ b/default-configs/arm64-linux-user.mak @@ -0,0 +1,3 @@ +# Default configuration for arm-linux-user + +CONFIG_GDBSTUB_XML=y diff --git a/linux-user/arm/syscall.h b/linux-user/arm/syscall.h index 003d424..769aac0 100644 --- a/linux-user/arm/syscall.h +++ b/linux-user/arm/syscall.h @@ -1,4 +1,36 @@ +#ifdef TARGET_ARM64 + +struct target_pt_regs { + uint64_t regs[31]; + uint64_t sp; + uint64_t pc; + uint64_t pstate; +}; + +#define ARM_cpsr uregs[16] +#define ARM_pc uregs[15] +#define ARM_lr uregs[14] +#define ARM_sp uregs[13] +#define ARM_ip uregs[12] +#define ARM_fp uregs[11] +#define ARM_r10 uregs[10] +#define ARM_r9 uregs[9] +#define ARM_r8 uregs[8] +#define ARM_r7 uregs[7] +#define ARM_r6 uregs[6] +#define ARM_r5 uregs[5] +#define ARM_r4 uregs[4] +#define ARM_r3 uregs[3] +#define ARM_r2 uregs[2] +#define ARM_r1 uregs[1] +#define ARM_r0 uregs[0] +#define ARM_ORIG_r0 uregs[17] + +#define UNAME_MACHINE "aarch64" + +#else /* TARGET_ARM64 */ + /* this struct defines the way the registers are stored on the stack during a system call. */ @@ -25,6 +57,14 @@ struct target_pt_regs { #define ARM_r0 uregs[0] #define ARM_ORIG_r0 uregs[17] +#if defined(TARGET_WORDS_BIGENDIAN) +#define UNAME_MACHINE "armv5teb" +#else +#define UNAME_MACHINE "armv5tel" +#endif + +#endif /* TARGET_ARM64 */ + #define ARM_SYSCALL_BASE 0x900000 #define ARM_THUMB_SYSCALL 0 @@ -34,9 +74,3 @@ struct target_pt_regs { #define ARM_NR_semihosting 0x123456 #define ARM_NR_thumb_semihosting 0xAB - -#if defined(TARGET_WORDS_BIGENDIAN) -#define UNAME_MACHINE "armv5teb" -#else -#define UNAME_MACHINE "armv5tel" -#endif diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 89db49c..239687d 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -260,16 +260,26 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en #define ELF_START_MMAP 0x80000000 -#define elf_check_arch(x) ( (x) == EM_ARM ) +#define elf_check_arch(x) ( (x) == ELF_MACHINE ) +#define ELF_ARCH ELF_MACHINE + +#ifdef TARGET_ARM64 +#define ELF_CLASS ELFCLASS64 +#else #define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_ARM +#endif static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) { abi_long stack = infop->start_stack; memset(regs, 0, sizeof(*regs)); + +#ifdef TARGET_ARM64 + regs->pc = infop->entry & ~0x3ULL; + regs->sp = stack; +#else regs->ARM_cpsr = 0x10; if (infop->entry & 1) regs->ARM_cpsr |= CPSR_T; @@ -283,6 +293,7 @@ static inline void init_thread(struct target_pt_regs *regs, /* For uClinux PIC binaries. */ /* XXX: Linux does this only on ARM with no MMU (do we care ?) */ regs->ARM_r10 = infop->start_data; +#endif } #define ELF_NREG 18 diff --git a/linux-user/main.c b/linux-user/main.c index d3f4b97..2e3c903 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3882,6 +3882,15 @@ int main(int argc, char **argv, char **envp) cpu_x86_load_seg(env, R_FS, 0); cpu_x86_load_seg(env, R_GS, 0); #endif +#elif defined(TARGET_ARM64) + { + int i; + for(i = 0; i < 31; i++) { + env->xregs[i] = regs->regs[i]; + } + env->pc = regs->pc; + env->sp = regs->sp; + } #elif defined(TARGET_ARM) { int i; diff --git a/target-arm/cpu.h b/target-arm/cpu.h index ec292c9..34cc00c 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -288,7 +288,11 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int rw, static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls) { - env->cp15.c13_tls2 = newtls; + if (is_a64(env)) { + env->sr.tpidr_el0 = newtls; + } else { + env->cp15.c13_tls2 = newtls; + } } #define CPSR_M (0x1f) @@ -696,9 +700,17 @@ static inline int cpu_mmu_index (CPUARMState *env) #if defined(CONFIG_USER_ONLY) static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp) { - if (newsp) - env->regs[13] = newsp; - env->regs[0] = 0; + if (is_a64(env)) { + if (newsp) { + env->sp = newsp; + } + env->xregs[0] = 0; + } else { + if (newsp) { + env->regs[13] = newsp; + } + env->regs[0] = 0; + } } #endif -- 1.6.0.2