aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2013-08-09 14:19:03 +0100
committerPeter Maydell <peter.maydell@linaro.org>2013-09-03 19:40:01 +0100
commit7b8c3251bffc778c878206f204fa206335e6be18 (patch)
tree6223d37df8b42adbac93d5dcb5c7e4ca89f53eba
parent3938ae588c6c6e561e2d35c2b4ce3d618548879f (diff)
downloadqemu-arm-7b8c3251bffc778c878206f204fa206335e6be18.tar.gz
linux-user: Add AArch64 support
This patch adds support for AArch64 in all the small corners of linux-user (primarily in image loading and startup code). Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: John Rigby <john.rigby@linaro.org> Message-id: 1368505980-17151-11-git-send-email-john.rigby@linaro.org [PMM: * removed some unnecessary #defines from syscall.h * catch attempts to use a 32 bit only cpu with aarch64-linux-user * termios stuff moved into its own patch * we specify our minimum uname version here now ] Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--linux-user/aarch64/syscall.h9
-rw-r--r--linux-user/elfload.c15
-rw-r--r--linux-user/main.c16
3 files changed, 38 insertions, 2 deletions
diff --git a/linux-user/aarch64/syscall.h b/linux-user/aarch64/syscall.h
new file mode 100644
index 0000000000..aef419efeb
--- /dev/null
+++ b/linux-user/aarch64/syscall.h
@@ -0,0 +1,9 @@
+struct target_pt_regs {
+ uint64_t regs[31];
+ uint64_t sp;
+ uint64_t pc;
+ uint64_t pstate;
+};
+
+#define UNAME_MACHINE "aarch64"
+#define UNAME_MINIMUM_RELEASE "3.8.0"
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 7ce2eab1bb..e2f40b9860 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -269,16 +269,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_AARCH64
+#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_AARCH64
+ regs->pc = infop->entry & ~0x3ULL;
+ regs->sp = stack;
+#else
regs->ARM_cpsr = 0x10;
if (infop->entry & 1)
regs->ARM_cpsr |= CPSR_T;
@@ -292,6 +302,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 d530f01f87..e213085805 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3964,6 +3964,22 @@ 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_AARCH64)
+ {
+ int i;
+
+ if (!(arm_feature(env, ARM_FEATURE_AARCH64))) {
+ fprintf(stderr,
+ "The selected ARM CPU does not support 64 bit mode\n");
+ exit(1);
+ }
+
+ for (i = 0; i < 31; i++) {
+ env->xregs[i] = regs->regs[i];
+ }
+ env->pc = regs->pc;
+ env->xregs[31] = regs->sp;
+ }
#elif defined(TARGET_ARM)
{
int i;