qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/12] AArch64 preparation patch set
@ 2013-03-06  2:01 Alexander Graf
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 01/12] ARM: Extract the disas struct to a header file Alexander Graf
                   ` (11 more replies)
  0 siblings, 12 replies; 22+ messages in thread
From: Alexander Graf @ 2013-03-06  2:01 UTC (permalink / raw)
  To: qemu-devel qemu-devel; +Cc: Peter Maydell, Riku Voipio

There is some work ongoing at different places to add AArch64 (ARM64) support
to QEMU. Most of that work is currently happening behind closed doors that
won't open during the next few days.

But we should at least try and get the bits that are uncontroversial into QEMU,
so that everyone can base off the same base.

This patch set adds bits that are all based on publicly available information.


Alex

Alexander Graf (11):
  ARM: Extract the disas struct to a header file
  ARM: Export cpu_env
  ARM: Prepare translation for AArch64 code
  ARM: Add AArch64 translation stub
  AArch64: Add gdb stub
  linux-user: Don't treat aarch64 cpu names specially
  linux-user: AArch64 requires at least 3.8.0
  linux-user: Add syscall handling for AArch64
  linux-user: Fix up AArch64 syscall handlers
  linux-user: Add AArch64 support
  ARM: Add arm64 target to configure

Andreas Schwab (1):
  linux-user: Add signal handling for AArch64

 configure                            |    9 +
 default-configs/arm64-linux-user.mak |    3 +
 gdb-xml/aarch64-core.xml             |   46 +++++
 gdb-xml/aarch64-fpu.xml              |   86 +++++++++
 gdbstub.c                            |   53 ++++++
 include/elf.h                        |    2 +
 linux-user/Makefile.objs             |    1 +
 linux-user/arm/syscall.h             |   46 ++++-
 linux-user/arm/syscall_nr.h          |  326 ++++++++++++++++++++++++++++++++++
 linux-user/arm/target_signal.h       |    4 +
 linux-user/cpu-uname.c               |    3 +-
 linux-user/elfload.c                 |   15 ++-
 linux-user/main.c                    |   24 +++
 linux-user/signal.c                  |  263 +++++++++++++++++++++++++++
 linux-user/syscall.c                 |   10 +-
 linux-user/syscall_defs.h            |   28 +++-
 target-arm/Makefile.objs             |    1 +
 target-arm/cpu.h                     |  123 ++++++++++---
 target-arm/translate-a64.c           |  139 +++++++++++++++
 target-arm/translate.c               |   83 +++++-----
 target-arm/translate.h               |   35 ++++
 21 files changed, 1215 insertions(+), 85 deletions(-)
 create mode 100644 default-configs/arm64-linux-user.mak
 create mode 100644 gdb-xml/aarch64-core.xml
 create mode 100644 gdb-xml/aarch64-fpu.xml
 create mode 100644 target-arm/translate-a64.c
 create mode 100644 target-arm/translate.h

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH 01/12] ARM: Extract the disas struct to a header file
  2013-03-06  2:01 [Qemu-devel] [PATCH 00/12] AArch64 preparation patch set Alexander Graf
@ 2013-03-06  2:01 ` Alexander Graf
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 02/12] ARM: Export cpu_env Alexander Graf
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Alexander Graf @ 2013-03-06  2:01 UTC (permalink / raw)
  To: qemu-devel qemu-devel; +Cc: Peter Maydell, Riku Voipio

We will need to share the disassembly status struct between AArch32 and
AArch64 modes. So put it into a header file that both sides can use.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 target-arm/translate.c |   24 +-----------------------
 target-arm/translate.h |   27 +++++++++++++++++++++++++++
 2 files changed, 28 insertions(+), 23 deletions(-)
 create mode 100644 target-arm/translate.h

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 35a21be..7dbf781 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -45,29 +45,7 @@
 
 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
 
-/* internal defines */
-typedef struct DisasContext {
-    target_ulong pc;
-    int is_jmp;
-    /* Nonzero if this instruction has been conditionally skipped.  */
-    int condjmp;
-    /* The label that will be jumped to when the instruction is skipped.  */
-    int condlabel;
-    /* Thumb-2 conditional execution bits.  */
-    int condexec_mask;
-    int condexec_cond;
-    struct TranslationBlock *tb;
-    int singlestep_enabled;
-    int thumb;
-    int bswap_code;
-#if !defined(CONFIG_USER_ONLY)
-    int user;
-#endif
-    int vfp_enabled;
-    int vec_len;
-    int vec_stride;
-} DisasContext;
-
+#include "translate.h"
 static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
 
 #if defined(CONFIG_USER_ONLY)
diff --git a/target-arm/translate.h b/target-arm/translate.h
new file mode 100644
index 0000000..e727bc6
--- /dev/null
+++ b/target-arm/translate.h
@@ -0,0 +1,27 @@
+#ifndef TARGET_ARM_TRANSLATE_H
+#define TARGET_ARM_TRANSLATE_H
+
+/* internal defines */
+typedef struct DisasContext {
+    target_ulong pc;
+    int is_jmp;
+    /* Nonzero if this instruction has been conditionally skipped.  */
+    int condjmp;
+    /* The label that will be jumped to when the instruction is skipped.  */
+    int condlabel;
+    /* Thumb-2 conditional execution bits.  */
+    int condexec_mask;
+    int condexec_cond;
+    struct TranslationBlock *tb;
+    int singlestep_enabled;
+    int thumb;
+    int bswap_code;
+#if !defined(CONFIG_USER_ONLY)
+    int user;
+#endif
+    int vfp_enabled;
+    int vec_len;
+    int vec_stride;
+} DisasContext;
+
+#endif /* TARGET_ARM_TRANSLATE_H */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH 02/12] ARM: Export cpu_env
  2013-03-06  2:01 [Qemu-devel] [PATCH 00/12] AArch64 preparation patch set Alexander Graf
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 01/12] ARM: Extract the disas struct to a header file Alexander Graf
@ 2013-03-06  2:01 ` Alexander Graf
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 03/12] ARM: Prepare translation for AArch64 code Alexander Graf
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Alexander Graf @ 2013-03-06  2:01 UTC (permalink / raw)
  To: qemu-devel qemu-devel; +Cc: Peter Maydell, Riku Voipio

The cpu_env tcg variable will be used by both the AArch32 and AArch64
handling code. Unstaticify it, so that both sides can make use of it.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 target-arm/translate.c |    2 +-
 target-arm/translate.h |    2 ++
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 7dbf781..f8838f3 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -59,7 +59,7 @@ static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
 #define DISAS_WFI 4
 #define DISAS_SWI 5
 
-static TCGv_ptr cpu_env;
+TCGv_ptr cpu_env;
 /* We reuse the same 64-bit temporaries for efficiency.  */
 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
 static TCGv_i32 cpu_R[16];
diff --git a/target-arm/translate.h b/target-arm/translate.h
index e727bc6..8ba1433 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -24,4 +24,6 @@ typedef struct DisasContext {
     int vec_stride;
 } DisasContext;
 
+extern TCGv_ptr cpu_env;
+
 #endif /* TARGET_ARM_TRANSLATE_H */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH 03/12] ARM: Prepare translation for AArch64 code
  2013-03-06  2:01 [Qemu-devel] [PATCH 00/12] AArch64 preparation patch set Alexander Graf
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 01/12] ARM: Extract the disas struct to a header file Alexander Graf
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 02/12] ARM: Export cpu_env Alexander Graf
@ 2013-03-06  2:01 ` Alexander Graf
  2013-03-06  7:11   ` Laurent Desnogues
  2013-03-08  2:27   ` Peter Maydell
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 04/12] ARM: Add AArch64 translation stub Alexander Graf
                   ` (8 subsequent siblings)
  11 siblings, 2 replies; 22+ messages in thread
From: Alexander Graf @ 2013-03-06  2:01 UTC (permalink / raw)
  To: qemu-devel qemu-devel; +Cc: Peter Maydell, Riku Voipio

This patch adds all the prerequisites for AArch64 support that didn't
fit into split up patches. It extends important bits in the core cpu
headers to also take AArch64 mode into account.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 include/elf.h          |    2 +
 target-arm/cpu.h       |  103 ++++++++++++++++++++++++++++++++++++------------
 target-arm/translate.c |   42 +++++++++++--------
 3 files changed, 103 insertions(+), 44 deletions(-)

diff --git a/include/elf.h b/include/elf.h
index a21ea53..0ff0ea6 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -109,6 +109,8 @@ typedef int64_t  Elf64_Sxword;
 #define EM_OPENRISC     92        /* OpenCores OpenRISC */
 
 #define EM_UNICORE32    110     /* UniCore32 */
+#define EM_AARCH64      183     /* ARM 64-bit architecture */
+
 
 /*
  * This is an interim value that we will use until the committee comes
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index c28a0d9..ec292c9 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -19,13 +19,19 @@
 #ifndef CPU_ARM_H
 #define CPU_ARM_H
 
-#define TARGET_LONG_BITS 32
+#include "config.h"
 
-#define ELF_MACHINE	EM_ARM
+#if defined (TARGET_ARM64)
+  /* AArch64 definitions */
+#  define TARGET_LONG_BITS 64
+#  define ELF_MACHINE	EM_AARCH64
+#else
+#  define TARGET_LONG_BITS 32
+#  define ELF_MACHINE	EM_ARM
+#endif
 
 #define CPUArchState struct CPUARMState
 
-#include "config.h"
 #include "qemu-common.h"
 #include "exec/cpu-defs.h"
 
@@ -79,6 +85,13 @@ struct arm_boot_info;
 typedef struct CPUARMState {
     /* Regs for current mode.  */
     uint32_t regs[16];
+
+    /* Regs for A64 mode.  */
+    uint64_t xregs[32];
+    uint64_t pc;
+    uint64_t sp;
+    uint32_t pstate;
+
     /* Frequently accessed CPSR bits are stored separately for efficiency.
        This contains all the other bits.  Use cpsr_{read,write} to access
        the whole CPSR.  */
@@ -154,6 +167,11 @@ typedef struct CPUARMState {
         uint32_t c15_power_control; /* power control */
     } cp15;
 
+    /* System registers (AArch64) */
+    struct {
+        uint64_t tpidr_el0;
+    } sr;
+
     struct {
         uint32_t other_sp;
         uint32_t vecbase;
@@ -170,7 +188,7 @@ typedef struct CPUARMState {
 
     /* VFP coprocessor state.  */
     struct {
-        float64 regs[32];
+        float64 regs[64];
 
         uint32_t xregs[16];
         /* We store these fpcsr fields separately for convenience.  */
@@ -241,6 +259,24 @@ int bank_number(int mode);
 void switch_mode(CPUARMState *, int);
 uint32_t do_arm_semihosting(CPUARMState *env);
 
+static inline bool is_a64(CPUARMState *env)
+{
+#ifdef TARGET_ARM64
+    return true;
+#else
+    return false;
+#endif
+}
+
+#define PSTATE_N_SHIFT 3
+#define PSTATE_N  (1 << PSTATE_N_SHIFT)
+#define PSTATE_Z_SHIFT 2
+#define PSTATE_Z  (1 << PSTATE_Z_SHIFT)
+#define PSTATE_C_SHIFT 1
+#define PSTATE_C  (1 << PSTATE_C_SHIFT)
+#define PSTATE_V_SHIFT 0
+#define PSTATE_V  (1 << PSTATE_V_SHIFT)
+
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
    is returned if the signal was handled by the virtual CPU.  */
@@ -624,8 +660,13 @@ static inline bool cp_access_ok(CPUARMState *env,
 #define TARGET_PAGE_BITS 10
 #endif
 
-#define TARGET_PHYS_ADDR_SPACE_BITS 40
-#define TARGET_VIRT_ADDR_SPACE_BITS 32
+#if defined (TARGET_ARM64)
+#  define TARGET_PHYS_ADDR_SPACE_BITS 64
+#  define TARGET_VIRT_ADDR_SPACE_BITS 64
+#else
+#  define TARGET_PHYS_ADDR_SPACE_BITS 40
+#  define TARGET_VIRT_ADDR_SPACE_BITS 32
+#endif
 
 static inline CPUARMState *cpu_init(const char *cpu_model)
 {
@@ -699,25 +740,31 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
 static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
-    int privmode;
-    *pc = env->regs[15];
-    *cs_base = 0;
-    *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
-        | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
-        | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
-        | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
-        | (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT);
-    if (arm_feature(env, ARM_FEATURE_M)) {
-        privmode = !((env->v7m.exception == 0) && (env->v7m.control & 1));
+    if (is_a64(env)) {
+        *pc = env->pc;
+        *flags = 0;
     } else {
-        privmode = (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR;
-    }
-    if (privmode) {
-        *flags |= ARM_TBFLAG_PRIV_MASK;
-    }
-    if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
-        *flags |= ARM_TBFLAG_VFPEN_MASK;
+        int privmode;
+        *pc = env->regs[15];
+        *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
+            | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
+            | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
+            | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
+            | (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT);
+        if (arm_feature(env, ARM_FEATURE_M)) {
+            privmode = !((env->v7m.exception == 0) && (env->v7m.control & 1));
+        } else {
+            privmode = (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR;
+        }
+        if (privmode) {
+            *flags |= ARM_TBFLAG_PRIV_MASK;
+        }
+        if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
+            *flags |= ARM_TBFLAG_VFPEN_MASK;
+        }
     }
+
+    *cs_base = 0;
 }
 
 static inline bool cpu_has_work(CPUState *cpu)
@@ -732,11 +779,15 @@ static inline bool cpu_has_work(CPUState *cpu)
 
 static inline void cpu_pc_from_tb(CPUARMState *env, TranslationBlock *tb)
 {
-    env->regs[15] = tb->pc;
+    if (is_a64(env)) {
+        env->pc = tb->pc;
+    } else {
+        env->regs[15] = tb->pc;
+    }
 }
 
 /* Load an instruction and return it in the standard little-endian order */
-static inline uint32_t arm_ldl_code(CPUARMState *env, uint32_t addr,
+static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
                                     bool do_swap)
 {
     uint32_t insn = cpu_ldl_code(env, addr);
@@ -747,7 +798,7 @@ static inline uint32_t arm_ldl_code(CPUARMState *env, uint32_t addr,
 }
 
 /* Ditto, for a halfword (Thumb) instruction */
-static inline uint16_t arm_lduw_code(CPUARMState *env, uint32_t addr,
+static inline uint16_t arm_lduw_code(CPUARMState *env, target_ulong addr,
                                      bool do_swap)
 {
     uint16_t insn = cpu_lduw_code(env, addr);
diff --git a/target-arm/translate.c b/target-arm/translate.c
index f8838f3..de04a0c 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9749,7 +9749,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
     uint16_t *gen_opc_end;
     int j, lj;
     target_ulong pc_start;
-    uint32_t next_page_start;
+    target_ulong next_page_start;
     int num_insns;
     int max_insns;
 
@@ -9833,24 +9833,26 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
         store_cpu_field(tmp, condexec_bits);
       }
     do {
+        if (!is_a64(env)) {
 #ifdef CONFIG_USER_ONLY
-        /* Intercept jump to the magic kernel page.  */
-        if (dc->pc >= 0xffff0000) {
-            /* We always get here via a jump, so know we are not in a
-               conditional execution block.  */
-            gen_exception(EXCP_KERNEL_TRAP);
-            dc->is_jmp = DISAS_UPDATE;
-            break;
-        }
+            /* Intercept jump to the magic kernel page.  */
+            if (dc->pc >= 0xffff0000) {
+                /* We always get here via a jump, so know we are not in a
+                   conditional execution block.  */
+                gen_exception(EXCP_KERNEL_TRAP);
+                dc->is_jmp = DISAS_UPDATE;
+                break;
+            }
 #else
-        if (dc->pc >= 0xfffffff0 && IS_M(env)) {
-            /* We always get here via a jump, so know we are not in a
-               conditional execution block.  */
-            gen_exception(EXCP_EXCEPTION_EXIT);
-            dc->is_jmp = DISAS_UPDATE;
-            break;
-        }
+            if (dc->pc >= 0xfffffff0 && IS_M(env)) {
+                /* We always get here via a jump, so know we are not in a
+                   conditional execution block.  */
+                gen_exception(EXCP_EXCEPTION_EXIT);
+                dc->is_jmp = DISAS_UPDATE;
+                break;
+            }
 #endif
+        }
 
         if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
             QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
@@ -9904,7 +9906,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
         }
 
         if (tcg_check_temp_count()) {
-            fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc);
+            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n", dc->pc);
         }
 
         /* Translation stops when a conditional branch is encountered.
@@ -10074,6 +10076,10 @@ void cpu_dump_state(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf,
 
 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
 {
-    env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
+    if (is_a64(env)) {
+        env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+    } else {
+        env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
+    }
     env->condexec_bits = gen_opc_condexec_bits[pc_pos];
 }
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH 04/12] ARM: Add AArch64 translation stub
  2013-03-06  2:01 [Qemu-devel] [PATCH 00/12] AArch64 preparation patch set Alexander Graf
                   ` (2 preceding siblings ...)
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 03/12] ARM: Prepare translation for AArch64 code Alexander Graf
@ 2013-03-06  2:01 ` Alexander Graf
  2013-03-06  7:06   ` Laurent Desnogues
  2013-03-08  2:31   ` Peter Maydell
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 05/12] AArch64: Add gdb stub Alexander Graf
                   ` (7 subsequent siblings)
  11 siblings, 2 replies; 22+ messages in thread
From: Alexander Graf @ 2013-03-06  2:01 UTC (permalink / raw)
  To: qemu-devel qemu-devel; +Cc: Peter Maydell, Riku Voipio

We should translate AArch64 mode separately from AArch32 mode. In AArch64 mode,
registers look vastly different, instruction encoding is completely different,
basically the system turns into a different machine.

So let's do a simple if() in translate.c to decide whether we can handle the
current code in the legacy AArch32 code or in the new AArch64 code.

So far, the translation always complains about unallocated instructions. There
is no emulator functionality in this patch!

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 target-arm/Makefile.objs   |    1 +
 target-arm/translate-a64.c |  139 ++++++++++++++++++++++++++++++++++++++++++++
 target-arm/translate.c     |   15 +++++
 target-arm/translate.h     |    6 ++
 4 files changed, 161 insertions(+), 0 deletions(-)
 create mode 100644 target-arm/translate-a64.c

diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
index d89b57c..f9f0de4 100644
--- a/target-arm/Makefile.objs
+++ b/target-arm/Makefile.objs
@@ -3,3 +3,4 @@ obj-$(CONFIG_SOFTMMU) += machine.o
 obj-$(CONFIG_KVM) += kvm.o
 obj-y += translate.o op_helper.o helper.o cpu.o
 obj-y += neon_helper.o iwmmxt_helper.o
+obj-$(TARGET_ARM64) += translate-a64.o
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
new file mode 100644
index 0000000..f354d08
--- /dev/null
+++ b/target-arm/translate-a64.c
@@ -0,0 +1,139 @@
+/*
+ *  AArch64 translation
+ *
+ *  Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "cpu.h"
+#include "tcg-op.h"
+#include "qemu/log.h"
+#include "translate.h"
+#include "qemu/host-utils.h"
+
+#include "helper.h"
+#define GEN_HELPER 1
+#include "helper.h"
+
+static TCGv_i64 cpu_X[32];
+static TCGv_i64 cpu_pc;
+static TCGv_i64 cpu_sp;
+static TCGv_i32 pstate;
+
+static const char *regnames[] =
+    { "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
+      "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
+      "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
+      "x24", "x25", "x26", "x27", "x28", "x29", "lr", "xzr" };
+
+/* initialize TCG globals.  */
+void a64_translate_init(void)
+{
+    int i;
+
+    cpu_pc = tcg_global_mem_new_i64(TCG_AREG0,
+                                    offsetof(CPUARMState, pc),
+                                    "pc");
+    cpu_sp = tcg_global_mem_new_i64(TCG_AREG0,
+                                    offsetof(CPUARMState, sp),
+                                    "sp");
+    for (i = 0; i < 32; i++) {
+        cpu_X[i] = tcg_global_mem_new_i64(TCG_AREG0,
+                                          offsetof(CPUARMState, xregs[i]),
+                                          regnames[i]);
+    }
+
+    pstate = tcg_global_mem_new_i32(TCG_AREG0,
+                                    offsetof(CPUARMState, pstate),
+                                    "pstate");
+}
+
+void cpu_dump_state_a64(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf,
+                        int flags)
+{
+    int i;
+
+    cpu_fprintf(f, "PC=%016"PRIx64"  SP=%016"PRIx64"\n", env->pc, env->sp);
+    for(i = 0; i < 31; i++) {
+        cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]);
+        if ((i % 4) == 3)
+            cpu_fprintf(f, "\n");
+        else
+            cpu_fprintf(f, " ");
+    }
+    cpu_fprintf(f, "XZR=%016"PRIx64"\n", env->xregs[31]);
+    cpu_fprintf(f, "PSTATE=%c%c%c%c\n",
+        env->pstate & PSTATE_N ? 'n' : '.',
+        env->pstate & PSTATE_Z ? 'z' : '.',
+        env->pstate & PSTATE_C ? 'c' : '.',
+        env->pstate & PSTATE_V ? 'v' : '.');
+    cpu_fprintf(f, "\n");
+}
+
+void gen_a64_set_pc_im(uint64_t val)
+{
+    tcg_gen_movi_i64(cpu_pc, val);
+}
+
+static void gen_exception(int excp)
+{
+    TCGv_i32 tmp = tcg_temp_new_i32();
+    tcg_gen_movi_i32(tmp, excp);
+    gen_helper_exception(cpu_env, tmp);
+    tcg_temp_free_i32(tmp);
+}
+
+static void gen_exception_insn(DisasContext *s, int offset, int excp)
+{
+    gen_a64_set_pc_im(s->pc - offset);
+    gen_exception(excp);
+    s->is_jmp = DISAS_JUMP;
+}
+
+static void real_unallocated_encoding(DisasContext *s)
+{
+    fprintf(stderr, "Unknown instruction: %#x\n",
+            arm_ldl_code(cpu_single_env, s->pc - 4, s->bswap_code));
+    gen_exception_insn(s, 4, EXCP_UDEF);
+}
+
+#define unallocated_encoding(s) do { \
+    fprintf(stderr, "unallocated encoding at line: %d\n", __LINE__); \
+    real_unallocated_encoding(s); \
+    } while(0)
+
+void disas_a64_insn(CPUARMState *env, DisasContext *s)
+{
+    uint32_t insn;
+
+    insn = arm_ldl_code(env, s->pc, s->bswap_code);
+    s->pc += 4;
+
+    switch ((insn >> 24) & 0x1f) {
+    default:
+        unallocated_encoding(s);
+        break;
+    }
+
+    if (unlikely(s->singlestep_enabled) && (s->is_jmp == DISAS_TB_JUMP)) {
+        /* go through the main loop for single step */
+        s->is_jmp = DISAS_JUMP;
+    }
+}
diff --git a/target-arm/translate.c b/target-arm/translate.c
index de04a0c..a3cb5ee 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -112,6 +112,10 @@ void arm_translate_init(void)
         offsetof(CPUARMState, exclusive_info), "exclusive_info");
 #endif
 
+#ifdef TARGET_ARM64
+    a64_translate_init();
+#endif
+
 #define GEN_HELPER 2
 #include "helper.h"
 }
@@ -9944,6 +9948,9 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
             gen_set_label(dc->condlabel);
         }
         if (dc->condjmp || !dc->is_jmp) {
+            if (is_a64(env)) {
+                gen_a64_set_pc_im(dc->pc);
+            }
             gen_set_pc_im(dc->pc);
             dc->condjmp = 0;
         }
@@ -9967,6 +9974,9 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
         gen_set_condexec(dc);
         switch(dc->is_jmp) {
         case DISAS_NEXT:
+            if (is_a64(env)) {
+                gen_a64_set_pc_im(dc->pc);
+            }
             gen_goto_tb(dc, 1, dc->pc);
             break;
         default:
@@ -10038,6 +10048,11 @@ void cpu_dump_state(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf,
     int i;
     uint32_t psr;
 
+    if (is_a64(env)) {
+        cpu_dump_state_a64(env, f, cpu_fprintf, flags);
+        return;
+    }
+
     for(i=0;i<16;i++) {
         cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
         if ((i % 4) == 3)
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 8ba1433..9086e43 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -26,4 +26,10 @@ typedef struct DisasContext {
 
 extern TCGv_ptr cpu_env;
 
+void a64_translate_init(void);
+void cpu_dump_state_a64(CPUARMState *env, FILE *f,
+        fprintf_function cpu_fprintf, int flags);
+void disas_a64_insn(CPUARMState *env, DisasContext *s);
+void gen_a64_set_pc_im(uint64_t val);
+
 #endif /* TARGET_ARM_TRANSLATE_H */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH 05/12] AArch64: Add gdb stub
  2013-03-06  2:01 [Qemu-devel] [PATCH 00/12] AArch64 preparation patch set Alexander Graf
                   ` (3 preceding siblings ...)
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 04/12] ARM: Add AArch64 translation stub Alexander Graf
@ 2013-03-06  2:01 ` Alexander Graf
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 06/12] linux-user: Don't treat aarch64 cpu names specially Alexander Graf
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Alexander Graf @ 2013-03-06  2:01 UTC (permalink / raw)
  To: qemu-devel qemu-devel; +Cc: Peter Maydell, Riku Voipio

We want to be able to debug AArch64 guests. So let's add the respective gdb
stub functions and xml descriptions that allow us to do so.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 gdb-xml/aarch64-core.xml |   46 ++++++++++++++++++++++++
 gdb-xml/aarch64-fpu.xml  |   86 ++++++++++++++++++++++++++++++++++++++++++++++
 gdbstub.c                |   53 ++++++++++++++++++++++++++++
 3 files changed, 185 insertions(+), 0 deletions(-)
 create mode 100644 gdb-xml/aarch64-core.xml
 create mode 100644 gdb-xml/aarch64-fpu.xml

diff --git a/gdb-xml/aarch64-core.xml b/gdb-xml/aarch64-core.xml
new file mode 100644
index 0000000..e1e9dc3
--- /dev/null
+++ b/gdb-xml/aarch64-core.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2009-2012 Free Software Foundation, Inc.
+     Contributed by ARM Ltd.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.aarch64.core">
+  <reg name="x0" bitsize="64"/>
+  <reg name="x1" bitsize="64"/>
+  <reg name="x2" bitsize="64"/>
+  <reg name="x3" bitsize="64"/>
+  <reg name="x4" bitsize="64"/>
+  <reg name="x5" bitsize="64"/>
+  <reg name="x6" bitsize="64"/>
+  <reg name="x7" bitsize="64"/>
+  <reg name="x8" bitsize="64"/>
+  <reg name="x9" bitsize="64"/>
+  <reg name="x10" bitsize="64"/>
+  <reg name="x11" bitsize="64"/>
+  <reg name="x12" bitsize="64"/>
+  <reg name="x13" bitsize="64"/>
+  <reg name="x14" bitsize="64"/>
+  <reg name="x15" bitsize="64"/>
+  <reg name="x16" bitsize="64"/>
+  <reg name="x17" bitsize="64"/>
+  <reg name="x18" bitsize="64"/>
+  <reg name="x19" bitsize="64"/>
+  <reg name="x20" bitsize="64"/>
+  <reg name="x21" bitsize="64"/>
+  <reg name="x22" bitsize="64"/>
+  <reg name="x23" bitsize="64"/>
+  <reg name="x24" bitsize="64"/>
+  <reg name="x25" bitsize="64"/>
+  <reg name="x26" bitsize="64"/>
+  <reg name="x27" bitsize="64"/>
+  <reg name="x28" bitsize="64"/>
+  <reg name="x29" bitsize="64"/>
+  <reg name="x30" bitsize="64"/>
+  <reg name="sp" bitsize="64" type="data_ptr"/>
+
+  <reg name="pc" bitsize="64" type="code_ptr"/>
+  <reg name="cpsr" bitsize="32"/>
+</feature>
diff --git a/gdb-xml/aarch64-fpu.xml b/gdb-xml/aarch64-fpu.xml
new file mode 100644
index 0000000..997197e
--- /dev/null
+++ b/gdb-xml/aarch64-fpu.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2009-2012 Free Software Foundation, Inc.
+     Contributed by ARM Ltd.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.aarch64.fpu">
+  <vector id="v2d" type="ieee_double" count="2"/>
+  <vector id="v2u" type="uint64" count="2"/>
+  <vector id="v2i" type="int64" count="2"/>
+  <vector id="v4f" type="ieee_single" count="4"/>
+  <vector id="v4u" type="uint32" count="4"/>
+  <vector id="v4i" type="int32" count="4"/>
+  <vector id="v8u" type="uint16" count="8"/>
+  <vector id="v8i" type="int16" count="8"/>
+  <vector id="v16u" type="uint8" count="16"/>
+  <vector id="v16i" type="int8" count="16"/>
+  <vector id="v1u" type="uint128" count="1"/>
+  <vector id="v1i" type="int128" count="1"/>
+  <union id="vnd">
+    <field name="f" type="v2d"/>
+    <field name="u" type="v2u"/>
+    <field name="s" type="v2i"/>
+  </union>
+  <union id="vns">
+    <field name="f" type="v4f"/>
+    <field name="u" type="v4u"/>
+    <field name="s" type="v4i"/>
+  </union>
+  <union id="vnh">
+    <field name="u" type="v8u"/>
+    <field name="s" type="v8i"/>
+  </union>
+  <union id="vnb">
+    <field name="u" type="v16u"/>
+    <field name="s" type="v16i"/>
+  </union>
+  <union id="vnq">
+    <field name="u" type="v1u"/>
+    <field name="s" type="v1i"/>
+  </union>
+  <union id="aarch64v">
+    <field name="d" type="vnd"/>
+    <field name="s" type="vns"/>
+    <field name="h" type="vnh"/>
+    <field name="b" type="vnb"/>
+    <field name="q" type="vnq"/>
+  </union>
+  <reg name="v0" bitsize="128" type="aarch64v" regnum="34"/>
+  <reg name="v1" bitsize="128" type="aarch64v" />
+  <reg name="v2" bitsize="128" type="aarch64v" />
+  <reg name="v3" bitsize="128" type="aarch64v" />
+  <reg name="v4" bitsize="128" type="aarch64v" />
+  <reg name="v5" bitsize="128" type="aarch64v" />
+  <reg name="v6" bitsize="128" type="aarch64v" />
+  <reg name="v7" bitsize="128" type="aarch64v" />
+  <reg name="v8" bitsize="128" type="aarch64v" />
+  <reg name="v9" bitsize="128" type="aarch64v" />
+  <reg name="v10" bitsize="128" type="aarch64v"/>
+  <reg name="v11" bitsize="128" type="aarch64v"/>
+  <reg name="v12" bitsize="128" type="aarch64v"/>
+  <reg name="v13" bitsize="128" type="aarch64v"/>
+  <reg name="v14" bitsize="128" type="aarch64v"/>
+  <reg name="v15" bitsize="128" type="aarch64v"/>
+  <reg name="v16" bitsize="128" type="aarch64v"/>
+  <reg name="v17" bitsize="128" type="aarch64v"/>
+  <reg name="v18" bitsize="128" type="aarch64v"/>
+  <reg name="v19" bitsize="128" type="aarch64v"/>
+  <reg name="v20" bitsize="128" type="aarch64v"/>
+  <reg name="v21" bitsize="128" type="aarch64v"/>
+  <reg name="v22" bitsize="128" type="aarch64v"/>
+  <reg name="v23" bitsize="128" type="aarch64v"/>
+  <reg name="v24" bitsize="128" type="aarch64v"/>
+  <reg name="v25" bitsize="128" type="aarch64v"/>
+  <reg name="v26" bitsize="128" type="aarch64v"/>
+  <reg name="v27" bitsize="128" type="aarch64v"/>
+  <reg name="v28" bitsize="128" type="aarch64v"/>
+  <reg name="v29" bitsize="128" type="aarch64v"/>
+  <reg name="v30" bitsize="128" type="aarch64v"/>
+  <reg name="v31" bitsize="128" type="aarch64v"/>
+  <reg name="fpsr" bitsize="32"/>
+  <reg name="fpcr" bitsize="32"/>
+</feature>
diff --git a/gdbstub.c b/gdbstub.c
index e414ad9..db3ac45 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -934,6 +934,59 @@ static int cpu_gdb_write_register(CPUSPARCState *env, uint8_t *mem_buf, int n)
     return 8;
 #endif
 }
+#elif defined (TARGET_ARM64)
+
+#define NUM_CORE_REGS 34
+#define GDB_CORE_XML "aarch64-core.xml"
+
+static int cpu_gdb_read_register(CPUARMState *env, uint8_t *mem_buf, int n)
+{
+    if (n < 31) {
+        /* Core integer register.  */
+        GET_REG64(env->xregs[n]);
+    }
+    switch (n) {
+    case 31:
+        GET_REG64(env->sp);
+        break;
+    case 32:
+        GET_REG64(env->pc);
+        break;
+    case 33:
+        GET_REG32(env->pstate);
+        break;
+    }
+    /* Unknown register.  */
+    return 0;
+}
+
+static int cpu_gdb_write_register(CPUARMState *env, uint8_t *mem_buf, int n)
+{
+    uint64_t tmp;
+
+    tmp = ldq_p(mem_buf);
+
+    if (n < 31) {
+        /* Core integer register.  */
+        env->xregs[n] = tmp;
+        return 8;
+    }
+    switch (n) {
+    case 31:
+        env->sp = tmp;
+        return 8;
+    case 32:
+        env->pc = tmp;
+        return 8;
+    case 33:
+        /* CPSR */
+        env->pstate = tmp;
+        return 4;
+    }
+    /* Unknown register.  */
+    return 0;
+}
+
 #elif defined (TARGET_ARM)
 
 /* Old gdb always expect FPA registers.  Newer (xml-aware) gdb only expect
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH 06/12] linux-user: Don't treat aarch64 cpu names specially
  2013-03-06  2:01 [Qemu-devel] [PATCH 00/12] AArch64 preparation patch set Alexander Graf
                   ` (4 preceding siblings ...)
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 05/12] AArch64: Add gdb stub Alexander Graf
@ 2013-03-06  2:01 ` Alexander Graf
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 07/12] linux-user: AArch64 requires at least 3.8.0 Alexander Graf
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Alexander Graf @ 2013-03-06  2:01 UTC (permalink / raw)
  To: qemu-devel qemu-devel; +Cc: Peter Maydell, Riku Voipio

32-bit ARM has a lot of different names for different types of CPUs it supports.
On AArch64, we don't have this, so we really don't want to execute the 32-bit
logic. Stub it out for AArch64 linux-user guests.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 linux-user/cpu-uname.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/linux-user/cpu-uname.c b/linux-user/cpu-uname.c
index 59cd647..50231c1 100644
--- a/linux-user/cpu-uname.c
+++ b/linux-user/cpu-uname.c
@@ -30,7 +30,8 @@
  * return here */
 const char *cpu_to_uname_machine(void *cpu_env)
 {
-#ifdef TARGET_ARM
+#if defined(TARGET_ARM) && !defined(TARGET_ARM64)
+
     /* utsname machine name on linux arm is CPU arch name + endianness, e.g.
      * armv7l; to get a list of CPU arch names from the linux source, use:
      *     grep arch_name: -A1 linux/arch/arm/mm/proc-*.S
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH 07/12] linux-user: AArch64 requires at least 3.8.0
  2013-03-06  2:01 [Qemu-devel] [PATCH 00/12] AArch64 preparation patch set Alexander Graf
                   ` (5 preceding siblings ...)
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 06/12] linux-user: Don't treat aarch64 cpu names specially Alexander Graf
@ 2013-03-06  2:01 ` Alexander Graf
  2013-03-06  7:04   ` Riku Voipio
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 08/12] linux-user: Add syscall handling for AArch64 Alexander Graf
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 22+ messages in thread
From: Alexander Graf @ 2013-03-06  2:01 UTC (permalink / raw)
  To: qemu-devel qemu-devel; +Cc: Peter Maydell, Riku Voipio

Glibc 1.17 checks for the host kernel version on startup. Unfortunately,
it also checks whether the host kernel version is recent enough for the
target to run at all.

Since AArch64 support only got introduced in 3.8.0, that means that glibc
refuses to run on any older kernel version than that.

To allow for execution of linux-user guests even on older host kernels,
let's always fake the kernel version to 3.8.0 on AArch64 guests.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 linux-user/syscall.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 19630ea..38c0711 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -313,7 +313,12 @@ static int sys_uname(struct new_utsname *buf)
   memset(buf, 0, sizeof(*buf));
   COPY_UTSNAME_FIELD(buf->sysname, uts_buf.sysname);
   COPY_UTSNAME_FIELD(buf->nodename, uts_buf.nodename);
+#ifdef TARGET_ARM64
+  /* glibc refuses to run on older kernels */
+  COPY_UTSNAME_FIELD(buf->release, "3.8.0");
+#else
   COPY_UTSNAME_FIELD(buf->release, uts_buf.release);
+#endif
   COPY_UTSNAME_FIELD(buf->version, uts_buf.version);
   COPY_UTSNAME_FIELD(buf->machine, uts_buf.machine);
 #ifdef _GNU_SOURCE
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH 08/12] linux-user: Add syscall handling for AArch64
  2013-03-06  2:01 [Qemu-devel] [PATCH 00/12] AArch64 preparation patch set Alexander Graf
                   ` (6 preceding siblings ...)
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 07/12] linux-user: AArch64 requires at least 3.8.0 Alexander Graf
@ 2013-03-06  2:01 ` Alexander Graf
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 09/12] linux-user: Fix up AArch64 syscall handlers Alexander Graf
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Alexander Graf @ 2013-03-06  2:01 UTC (permalink / raw)
  To: qemu-devel qemu-devel; +Cc: Peter Maydell, Riku Voipio

The AArch64 syscall definitions are all publicly available in the Linux
kernel. Let's add them to our linux-user emulation target, so that we
can easily handle AArch64 syscalls.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 linux-user/arm/syscall_nr.h |  326 +++++++++++++++++++++++++++++++++++++++++++
 linux-user/main.c           |   15 ++
 2 files changed, 341 insertions(+), 0 deletions(-)

diff --git a/linux-user/arm/syscall_nr.h b/linux-user/arm/syscall_nr.h
index 42d6855..203476f 100644
--- a/linux-user/arm/syscall_nr.h
+++ b/linux-user/arm/syscall_nr.h
@@ -2,6 +2,8 @@
  * This file contains the system call numbers.
  */
 
+#ifndef TARGET_ARM64
+
 #define TARGET_NR_restart_syscall		(  0)
 #define TARGET_NR_exit			(  1)
 #define TARGET_NR_fork			(  2)
@@ -378,3 +380,327 @@
 #define TARGET_NR_open_by_handle_at            (371)
 #define TARGET_NR_clock_adjtime                (372)
 #define TARGET_NR_syncfs                       (373)
+
+#else /* !TARGET_ARM64 */
+
+#define TARGET_NR_io_setup 0
+#define TARGET_NR_io_destroy 1
+#define TARGET_NR_io_submit 2
+#define TARGET_NR_io_cancel 3
+#define TARGET_NR_io_getevents 4
+#define TARGET_NR_setxattr 5
+#define TARGET_NR_lsetxattr 6
+#define TARGET_NR_fsetxattr 7
+#define TARGET_NR_getxattr 8
+#define TARGET_NR_lgetxattr 9
+#define TARGET_NR_fgetxattr 10
+#define TARGET_NR_listxattr 11
+#define TARGET_NR_llistxattr 12
+#define TARGET_NR_flistxattr 13
+#define TARGET_NR_removexattr 14
+#define TARGET_NR_lremovexattr 15
+#define TARGET_NR_fremovexattr 16
+#define TARGET_NR_getcwd 17
+#define TARGET_NR_lookup_dcookie 18
+#define TARGET_NR_eventfd2 19
+#define TARGET_NR_epoll_create1 20
+#define TARGET_NR_epoll_ctl 21
+#define TARGET_NR_epoll_pwait 22
+#define TARGET_NR_dup 23
+#define TARGET_NR_dup3 24
+#define TARGET_NR_fcntl 25
+#define TARGET_NR_inotify_init1 26
+#define TARGET_NR_inotify_add_watch 27
+#define TARGET_NR_inotify_rm_watch 28
+#define TARGET_NR_ioctl 29
+#define TARGET_NR_ioprio_set 30
+#define TARGET_NR_ioprio_get 31
+#define TARGET_NR_flock 32
+#define TARGET_NR_mknodat 33
+#define TARGET_NR_mkdirat 34
+#define TARGET_NR_unlinkat 35
+#define TARGET_NR_symlinkat 36
+#define TARGET_NR_linkat 37
+#define TARGET_NR_renameat 38
+#define TARGET_NR_umount2 39
+#define TARGET_NR_mount 40
+#define TARGET_NR_pivot_root 41
+#define TARGET_NR_nfsservctl 42
+#define TARGET_NR_statfs 43
+#define TARGET_NR_fstatfs 44
+#define TARGET_NR_truncate 45
+#define TARGET_NR_ftruncate 46
+#define TARGET_NR_fallocate 47
+#define TARGET_NR_faccessat 48
+#define TARGET_NR_chdir 49
+#define TARGET_NR_fchdir 50
+#define TARGET_NR_chroot 51
+#define TARGET_NR_fchmod 52
+#define TARGET_NR_fchmodat 53
+#define TARGET_NR_fchownat 54
+#define TARGET_NR_fchown 55
+#define TARGET_NR_openat 56
+#define TARGET_NR_close 57
+#define TARGET_NR_vhangup 58
+#define TARGET_NR_pipe2 59
+#define TARGET_NR_quotactl 60
+#define TARGET_NR_getdents64 61
+#define TARGET_NR_lseek 62
+#define TARGET_NR_read 63
+#define TARGET_NR_write 64
+#define TARGET_NR_readv 65
+#define TARGET_NR_writev 66
+#define TARGET_NR_pread64 67
+#define TARGET_NR_pwrite64 68
+#define TARGET_NR_preadv 69
+#define TARGET_NR_pwritev 70
+#define TARGET_NR_sendfile 71
+#define TARGET_NR_pselect6 72
+#define TARGET_NR_ppoll 73
+#define TARGET_NR_signalfd4 74
+#define TARGET_NR_vmsplice 75
+#define TARGET_NR_splice 76
+#define TARGET_NR_tee 77
+#define TARGET_NR_readlinkat 78
+#define TARGET_NR_fstatat64 79
+#define TARGET_NR_fstat 80
+#define TARGET_NR_sync 81
+#define TARGET_NR_fsync 82
+#define TARGET_NR_fdatasync 83
+#define TARGET_NR_sync_file_range2 84
+/* #define TARGET_NR_sync_file_range 84 */
+#define TARGET_NR_timerfd_create 85
+#define TARGET_NR_timerfd_settime 86
+#define TARGET_NR_timerfd_gettime 87
+#define TARGET_NR_utimensat 88
+#define TARGET_NR_acct 89
+#define TARGET_NR_capget 90
+#define TARGET_NR_capset 91
+#define TARGET_NR_personality 92
+#define TARGET_NR_exit 93
+#define TARGET_NR_exit_group 94
+#define TARGET_NR_waitid 95
+#define TARGET_NR_set_tid_address 96
+#define TARGET_NR_unshare 97
+#define TARGET_NR_futex 98
+#define TARGET_NR_set_robust_list 99
+#define TARGET_NR_get_robust_list 100
+#define TARGET_NR_nanosleep 101
+#define TARGET_NR_getitimer 102
+#define TARGET_NR_setitimer 103
+#define TARGET_NR_kexec_load 104
+#define TARGET_NR_init_module 105
+#define TARGET_NR_delete_module 106
+#define TARGET_NR_timer_create 107
+#define TARGET_NR_timer_gettime 108
+#define TARGET_NR_timer_getoverrun 109
+#define TARGET_NR_timer_settime 110
+#define TARGET_NR_timer_delete 111
+#define TARGET_NR_clock_settime 112
+#define TARGET_NR_clock_gettime 113
+#define TARGET_NR_clock_getres 114
+#define TARGET_NR_clock_nanosleep 115
+#define TARGET_NR_syslog 116
+#define TARGET_NR_ptrace 117
+#define TARGET_NR_sched_setparam 118
+#define TARGET_NR_sched_setscheduler 119
+#define TARGET_NR_sched_getscheduler 120
+#define TARGET_NR_sched_getparam 121
+#define TARGET_NR_sched_setaffinity 122
+#define TARGET_NR_sched_getaffinity 123
+#define TARGET_NR_sched_yield 124
+#define TARGET_NR_sched_get_priority_max 125
+#define TARGET_NR_sched_get_priority_min 126
+#define TARGET_NR_sched_rr_get_interval 127
+#define TARGET_NR_restart_syscall 128
+#define TARGET_NR_kill 129
+#define TARGET_NR_tkill 130
+#define TARGET_NR_tgkill 131
+#define TARGET_NR_sigaltstack 132
+#define TARGET_NR_rt_sigsuspend 133
+#define TARGET_NR_rt_sigaction 134
+#define TARGET_NR_rt_sigprocmask 135
+#define TARGET_NR_rt_sigpending 136
+#define TARGET_NR_rt_sigtimedwait 137
+#define TARGET_NR_rt_sigqueueinfo 138
+#define TARGET_NR_rt_sigreturn 139
+#define TARGET_NR_setpriority 140
+#define TARGET_NR_getpriority 141
+#define TARGET_NR_reboot 142
+#define TARGET_NR_setregid 143
+#define TARGET_NR_setgid 144
+#define TARGET_NR_setreuid 145
+#define TARGET_NR_setuid 146
+#define TARGET_NR_setresuid 147
+#define TARGET_NR_getresuid 148
+#define TARGET_NR_setresgid 149
+#define TARGET_NR_getresgid 150
+#define TARGET_NR_setfsuid 151
+#define TARGET_NR_setfsgid 152
+#define TARGET_NR_times 153
+#define TARGET_NR_setpgid 154
+#define TARGET_NR_getpgid 155
+#define TARGET_NR_getsid 156
+#define TARGET_NR_setsid 157
+#define TARGET_NR_getgroups 158
+#define TARGET_NR_setgroups 159
+#define TARGET_NR_uname 160
+#define TARGET_NR_sethostname 161
+#define TARGET_NR_setdomainname 162
+#define TARGET_NR_getrlimit 163
+#define TARGET_NR_setrlimit 164
+#define TARGET_NR_getrusage 165
+#define TARGET_NR_umask 166
+#define TARGET_NR_prctl 167
+#define TARGET_NR_getcpu 168
+#define TARGET_NR_gettimeofday 169
+#define TARGET_NR_settimeofday 170
+#define TARGET_NR_adjtimex 171
+#define TARGET_NR_getpid 172
+#define TARGET_NR_getppid 173
+#define TARGET_NR_getuid 174
+#define TARGET_NR_geteuid 175
+#define TARGET_NR_getgid 176
+#define TARGET_NR_getegid 177
+#define TARGET_NR_gettid 178
+#define TARGET_NR_sysinfo 179
+#define TARGET_NR_mq_open 180
+#define TARGET_NR_mq_unlink 181
+#define TARGET_NR_mq_timedsend 182
+#define TARGET_NR_mq_timedreceive 183
+#define TARGET_NR_mq_notify 184
+#define TARGET_NR_mq_getsetattr 185
+#define TARGET_NR_msgget 186
+#define TARGET_NR_msgctl 187
+#define TARGET_NR_msgrcv 188
+#define TARGET_NR_msgsnd 189
+#define TARGET_NR_semget 190
+#define TARGET_NR_semctl 191
+#define TARGET_NR_semtimedop 192
+#define TARGET_NR_semop 193
+#define TARGET_NR_shmget 194
+#define TARGET_NR_shmctl 195
+#define TARGET_NR_shmat 196
+#define TARGET_NR_shmdt 197
+#define TARGET_NR_socket 198
+#define TARGET_NR_socketpair 199
+#define TARGET_NR_bind 200
+#define TARGET_NR_listen 201
+#define TARGET_NR_accept 202
+#define TARGET_NR_connect 203
+#define TARGET_NR_getsockname 204
+#define TARGET_NR_getpeername 205
+#define TARGET_NR_sendto 206
+#define TARGET_NR_recvfrom 207
+#define TARGET_NR_setsockopt 208
+#define TARGET_NR_getsockopt 209
+#define TARGET_NR_shutdown 210
+#define TARGET_NR_sendmsg 211
+#define TARGET_NR_recvmsg 212
+#define TARGET_NR_readahead 213
+#define TARGET_NR_brk 214
+#define TARGET_NR_munmap 215
+#define TARGET_NR_mremap 216
+#define TARGET_NR_add_key 217
+#define TARGET_NR_request_key 218
+#define TARGET_NR_keyctl 219
+#define TARGET_NR_clone 220
+#define TARGET_NR_execve 221
+#define TARGET_NR_mmap 222
+#define TARGET_NR_fadvise64 223
+#define TARGET_NR_swapon 224
+#define TARGET_NR_swapoff 225
+#define TARGET_NR_mprotect 226
+#define TARGET_NR_msync 227
+#define TARGET_NR_mlock 228
+#define TARGET_NR_munlock 229
+#define TARGET_NR_mlockall 230
+#define TARGET_NR_munlockall 231
+#define TARGET_NR_mincore 232
+#define TARGET_NR_madvise 233
+#define TARGET_NR_remap_file_pages 234
+#define TARGET_NR_mbind 235
+#define TARGET_NR_get_mempolicy 236
+#define TARGET_NR_set_mempolicy 237
+#define TARGET_NR_migrate_pages 238
+#define TARGET_NR_move_pages 239
+#define TARGET_NR_rt_tgsigqueueinfo 240
+#define TARGET_NR_perf_event_open 241
+#define TARGET_NR_accept4 242
+#define TARGET_NR_recvmmsg 243
+#define TARGET_NR_arch_specific_syscall 244
+#define TARGET_NR_wait4 260
+#define TARGET_NR_prlimit64 261
+#define TARGET_NR_fanotify_init 262
+#define TARGET_NR_fanotify_mark 263
+#define TARGET_NR_name_to_handle_at         264
+#define TARGET_NR_open_by_handle_at         265
+#define TARGET_NR_clock_adjtime 266
+#define TARGET_NR_syncfs 267
+#define TARGET_NR_setns 268
+#define TARGET_NR_sendmmsg 269
+#define TARGET_NR_process_vm_readv 270
+#define TARGET_NR_process_vm_writev 271
+#define TARGET_NR_kcmp 272
+#define TARGET_NR_finit_module 273
+#define TARGET_NR_open 1024
+#define TARGET_NR_link 1025
+#define TARGET_NR_unlink 1026
+#define TARGET_NR_mknod 1027
+#define TARGET_NR_chmod 1028
+#define TARGET_NR_chown 1029
+#define TARGET_NR_mkdir 1030
+#define TARGET_NR_rmdir 1031
+#define TARGET_NR_lchown 1032
+#define TARGET_NR_access 1033
+#define TARGET_NR_rename 1034
+#define TARGET_NR_readlink 1035
+#define TARGET_NR_symlink 1036
+#define TARGET_NR_utimes 1037
+#define TARGET_NR_stat 1038
+#define TARGET_NR_lstat 1039
+#define TARGET_NR_pipe 1040
+#define TARGET_NR_dup2 1041
+#define TARGET_NR_epoll_create 1042
+#define TARGET_NR_inotify_init 1043
+#define TARGET_NR_eventfd 1044
+#define TARGET_NR_signalfd 1045
+#define TARGET_NR_sendfile64 1046
+#define TARGET_NR_ftruncate64 1047
+#define TARGET_NR_truncate64 1048
+#define TARGET_NR_stat64 1049
+#define TARGET_NR_lstat64 1050
+#define TARGET_NR_fstat64 1051
+#define TARGET_NR_fcntl64 1052
+/* #define TARGET_NR_fadvise64 1053 */
+#define TARGET_NR_newfstatat 1054
+#define TARGET_NR_fstatfs64 1055
+#define TARGET_NR_statfs64 1056
+#define TARGET_NR_lseek64 1057
+#define TARGET_NR_mmap64 1058
+#define TARGET_NR_alarm 1059
+#define TARGET_NR_getpgrp 1060
+#define TARGET_NR_pause 1061
+#define TARGET_NR_time 1062
+#define TARGET_NR_utime 1063
+#define TARGET_NR_creat 1064
+#define TARGET_NR_getdents 1065
+#define TARGET_NR_futimesat 1066
+#define TARGET_NR_select 1067
+#define TARGET_NR_poll 1068
+#define TARGET_NR_epoll_wait 1069
+#define TARGET_NR_ustat 1070
+#define TARGET_NR_vfork 1071
+#define TARGET_NR_oldwait4 1072
+#define TARGET_NR_recv 1073
+#define TARGET_NR_send 1074
+#define TARGET_NR_bdflush 1075
+#define TARGET_NR_umount 1076
+#define TARGET_NR_uselib 1077
+#define TARGET_NR__sysctl 1078
+#define TARGET_NR_fork 1079
+#define TARGET_NR_syscalls (__NR_fork+1)
+
+#define TARGET_NR_sigreturn 1999
+
+#endif
diff --git a/linux-user/main.c b/linux-user/main.c
index d8b0cd6..d3f4b97 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -700,7 +700,9 @@ void cpu_loop(CPUARMState *env)
 {
     CPUState *cs = CPU(arm_env_get_cpu(env));
     int trapnr;
+#ifndef TARGET_ARM64
     unsigned int n, insn;
+#endif
     target_siginfo_t info;
     uint32_t addr;
 
@@ -783,6 +785,18 @@ void cpu_loop(CPUARMState *env)
         case EXCP_SWI:
         case EXCP_BKPT:
             {
+#ifdef TARGET_ARM64
+                env->xregs[0] = do_syscall(env,
+                                           env->xregs[8],
+                                           env->xregs[0],
+                                           env->xregs[1],
+                                           env->xregs[2],
+                                           env->xregs[3],
+                                           env->xregs[4],
+                                           env->xregs[5],
+                                           0, 0);
+#else
+
                 env->eabi = 1;
                 /* system call */
                 if (trapnr == EXCP_BKPT) {
@@ -853,6 +867,7 @@ void cpu_loop(CPUARMState *env)
                 } else {
                     goto error;
                 }
+#endif
             }
             break;
         case EXCP_INTERRUPT:
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH 09/12] linux-user: Fix up AArch64 syscall handlers
  2013-03-06  2:01 [Qemu-devel] [PATCH 00/12] AArch64 preparation patch set Alexander Graf
                   ` (7 preceding siblings ...)
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 08/12] linux-user: Add syscall handling for AArch64 Alexander Graf
@ 2013-03-06  2:01 ` Alexander Graf
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 10/12] linux-user: Add signal handling for AArch64 Alexander Graf
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Alexander Graf @ 2013-03-06  2:01 UTC (permalink / raw)
  To: qemu-devel qemu-devel; +Cc: Peter Maydell, Riku Voipio

Some syscall handlers have special code for ARM enabled that we don't
need on AArch64. Exclude AArch64 in those cases. In other places we
can share struct definitions with other targets or have to provide our
own.

With this patch applied, most syscall definitions in linux-user should
be sound for AArch64.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 linux-user/syscall.c      |    5 +++--
 linux-user/syscall_defs.h |   28 ++++++++++++++++++++++++++--
 2 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 38c0711..eb1e39d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4846,7 +4846,7 @@ static inline abi_long host_to_target_stat64(void *cpu_env,
                                              abi_ulong target_addr,
                                              struct stat *host_st)
 {
-#ifdef TARGET_ARM
+#if defined(TARGET_ARM) && defined(TARGET_ABI32)
     if (((CPUARMState *)cpu_env)->eabi) {
         struct target_eabi_stat64 *target_st;
 
@@ -6477,7 +6477,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif
 #ifdef TARGET_NR_mmap
     case TARGET_NR_mmap:
-#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || \
+#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
+    (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
     defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
     || defined(TARGET_S390X)
         {
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 92c01a9..d82af5f 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -1137,7 +1137,8 @@ struct target_winsize {
 #define TARGET_MAP_UNINITIALIZED 0x4000000	/* for anonymous mmap, memory could be uninitialized */
 #endif
 
-#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) \
+#if (defined(TARGET_I386) && defined(TARGET_ABI32)) \
+    || (defined(TARGET_ARM) && defined(TARGET_ABI32)) \
     || defined(TARGET_CRIS) || defined(TARGET_UNICORE32) \
     || defined(TARGET_OPENRISC)
 struct target_stat {
@@ -1836,6 +1837,28 @@ struct target_stat {
     abi_long       st_blocks;
     abi_ulong  __unused[3];
 };
+#elif defined(TARGET_ARM64)
+struct target_stat {
+    abi_ulong  st_dev;
+    abi_ulong  st_ino;
+    unsigned int st_mode;
+    unsigned int st_nlink;
+    unsigned int   st_uid;
+    unsigned int   st_gid;
+    abi_ulong  st_rdev;
+    abi_ulong  _pad1;
+    abi_long  st_size;
+    int        st_blksize;
+    int        __pad2;
+    abi_long   st_blocks;
+    abi_long  target_st_atime;
+    abi_ulong  target_st_atime_nsec;
+    abi_long  target_st_mtime;
+    abi_ulong  target_st_mtime_nsec;
+    abi_long  target_st_ctime;
+    abi_ulong  target_st_ctime_nsec;
+    unsigned int __unused[2];
+};
 #elif defined(TARGET_OPENRISC)
 struct target_stat {
     abi_ulong st_dev;
@@ -1918,7 +1941,8 @@ struct target_statfs64 {
 	uint32_t	f_spare[6];
 };
 #elif (defined(TARGET_PPC64) || defined(TARGET_X86_64) || \
-       defined(TARGET_SPARC64)) && !defined(TARGET_ABI32)
+       defined(TARGET_SPARC64) || defined(TARGET_ARM64)) && \
+       !defined(TARGET_ABI32)
 struct target_statfs {
 	abi_long f_type;
 	abi_long f_bsize;
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH 10/12] linux-user: Add signal handling for AArch64
  2013-03-06  2:01 [Qemu-devel] [PATCH 00/12] AArch64 preparation patch set Alexander Graf
                   ` (8 preceding siblings ...)
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 09/12] linux-user: Fix up AArch64 syscall handlers Alexander Graf
@ 2013-03-06  2:01 ` Alexander Graf
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 11/12] linux-user: Add AArch64 support Alexander Graf
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 12/12] ARM: Add arm64 target to configure Alexander Graf
  11 siblings, 0 replies; 22+ messages in thread
From: Alexander Graf @ 2013-03-06  2:01 UTC (permalink / raw)
  To: qemu-devel qemu-devel; +Cc: Peter Maydell, Riku Voipio, Andreas Schwab

From: Andreas Schwab <schwab@suse.de>

This patch adds signal handling for AArch64. The code is based on the
respective source in the Linux kernel.

Signed-off-by: Andreas Schwab <schwab@suse.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
 linux-user/arm/target_signal.h |    4 +
 linux-user/signal.c            |  263 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 267 insertions(+), 0 deletions(-)

diff --git a/linux-user/arm/target_signal.h b/linux-user/arm/target_signal.h
index 2b32813..ef7503c 100644
--- a/linux-user/arm/target_signal.h
+++ b/linux-user/arm/target_signal.h
@@ -23,7 +23,11 @@ typedef struct target_sigaltstack {
 
 static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
 {
+#ifdef TARGET_ARM64
+   return state->sp;
+#else
    return state->regs[13];
+#endif
 }
 
 #endif /* TARGET_SIGNAL_H */
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 1055507..9c02a04 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1090,6 +1090,269 @@ badframe:
 	return 0;
 }
 
+#elif defined(TARGET_ARM64)
+
+struct target_sigcontext {
+    uint64_t fault_address;
+    /* AArch64 registers */
+    uint64_t regs[31];
+    uint64_t sp;
+    uint64_t pc;
+    uint64_t pstate;
+    /* 4K reserved for FP/SIMD state and future expansion */
+    char __reserved[4096] __attribute__((__aligned__(16)));
+};
+
+struct target_ucontext {
+    abi_ulong tuc_flags;
+    abi_ulong tuc_link;
+    target_stack_t tuc_stack;
+    target_sigset_t tuc_sigmask;
+    /* glibc uses a 1024-bit sigset_t */
+    char __unused[1024 / 8 - sizeof(target_sigset_t)];
+    /* last for future expansion */
+    struct target_sigcontext tuc_mcontext;
+};
+
+/*
+ * Header to be used at the beginning of structures extending the user
+ * context. Such structures must be placed after the rt_sigframe on the stack
+ * and be 16-byte aligned. The last structure must be a dummy one with the
+ * magic and size set to 0.
+ */
+struct target_aarch64_ctx {
+    uint32_t magic;
+    uint32_t size;
+};
+
+#define TARGET_FPSIMD_MAGIC 0x46508001
+
+struct target_fpsimd_context {
+    struct target_aarch64_ctx head;
+    uint32_t fpsr;
+    uint32_t fpcr;
+    uint64_t vregs[32 * 2];
+};
+
+/*
+ * Auxiliary context saved in the sigcontext.__reserved array. Not exported to
+ * user space as it will change with the addition of new context. User space
+ * should check the magic/size information.
+ */
+struct target_aux_context {
+    struct target_fpsimd_context fpsimd;
+    /* additional context to be added before "end" */
+    struct target_aarch64_ctx end;
+};
+
+struct target_rt_sigframe {
+    struct target_siginfo info;
+    struct target_ucontext uc;
+    uint64_t fp;
+    uint64_t lr;
+    uint32_t tramp[2];
+};
+
+static int target_setup_sigframe(struct target_rt_sigframe *sf,
+				 CPUARMState *env,
+				 target_sigset_t *set)
+{
+    int i, err = 0;
+    struct target_aux_context *aux =
+        (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
+
+    /* set up the stack frame for unwinding */
+    err |= __put_user(env->xregs[29], &sf->fp);
+    err |= __put_user(env->xregs[30], &sf->lr);
+
+    for (i = 0; i < 31; i++) {
+        err |= __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
+    }
+    err |= __put_user(env->sp, &sf->uc.tuc_mcontext.sp);
+    err |= __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
+    err |= __put_user(env->pstate, &sf->uc.tuc_mcontext.pstate);
+
+    err |= __put_user(/*current->thread.fault_address*/ 0,
+		      &sf->uc.tuc_mcontext.fault_address);
+
+    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
+        err |= __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
+    }
+
+    for (i = 0; i < 32 * 2; i++) {
+        err |= __put_user(env->vfp.regs[i], &aux->fpsimd.vregs[i]);
+    }
+    err |= __put_user(/*env->fpsr*/0, &aux->fpsimd.fpsr);
+    err |= __put_user(/*env->fpcr*/0, &aux->fpsimd.fpcr);
+    err |= __put_user(TARGET_FPSIMD_MAGIC, &aux->fpsimd.head.magic);
+    err |= __put_user(sizeof(struct target_fpsimd_context),
+		      &aux->fpsimd.head.size);
+
+    /* set the "end" magic */
+    err |= __put_user(0, &aux->end.magic);
+    err |= __put_user(0, &aux->end.size);
+
+    return err;
+}
+
+static int target_restore_sigframe(CPUARMState *env,
+				   struct target_rt_sigframe *sf)
+{
+    sigset_t set;
+    int i, err = 0;
+    struct target_aux_context *aux =
+        (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
+    uint32_t magic, size;
+
+    target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
+    sigprocmask(SIG_SETMASK, &set, NULL);
+
+    for (i = 0; i < 31; i++) {
+        err |= __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
+    }
+
+    err |= __get_user(env->sp, &sf->uc.tuc_mcontext.sp);
+    err |= __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
+    err |= __get_user(env->pstate, &sf->uc.tuc_mcontext.pstate);
+
+    err |= __get_user(magic, &aux->fpsimd.head.magic);
+    err |= __get_user(size, &aux->fpsimd.head.size);
+    if (err) {
+        return err;
+    }
+    if (magic != TARGET_FPSIMD_MAGIC || size != sizeof(struct target_fpsimd_context)) {
+        return 1;
+    }
+
+    for (i = 0; i < 32 * 2; i++) {
+       err |= __get_user(env->vfp.regs[i], &aux->fpsimd.vregs[i]);
+    }
+
+#if 0
+    err |= __get_user(env->fpsr, &aux->fpsimd.fpsr);
+    err |= __get_user(env->fpcr, &aux->fpsimd.fpcr);
+#endif
+
+    return err;
+}
+
+static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env)
+{
+    abi_ulong sp;
+
+    sp = env->sp;
+
+    /*
+     * This is the X/Open sanctioned signal stack switching.
+     */
+    if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
+        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+    }
+
+    sp = (sp - sizeof(struct target_rt_sigframe)) & ~15;
+
+    return sp;
+}
+
+static void target_setup_frame(int usig, struct target_sigaction *ka,
+			       target_siginfo_t *info,
+			       target_sigset_t *set, CPUARMState *env)
+{
+    struct target_rt_sigframe *frame;
+    abi_ulong frame_addr;
+    int err = 0;
+
+    frame_addr = get_sigframe(ka, env);
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+	goto give_sigsegv;
+    }
+
+    err |= __put_user(0, &frame->uc.tuc_flags);
+    err |= __put_user(0, &frame->uc.tuc_link);
+
+    err |= __put_user(target_sigaltstack_used.ss_sp,
+                      &frame->uc.tuc_stack.ss_sp);
+    err |= __put_user(sas_ss_flags(env->sp),
+                      &frame->uc.tuc_stack.ss_flags);
+    err |= __put_user(target_sigaltstack_used.ss_size,
+                      &frame->uc.tuc_stack.ss_size);
+    err |= target_setup_sigframe(frame, env, set);
+    /* mov x8,#__NR_rt_sigreturn; svc #0 */
+    err |= __put_user(0xd2801168, &frame->tramp[0]);
+    err |= __put_user(0xd4000001, &frame->tramp[1]);
+    if (err == 0) {
+	env->xregs[0] = usig;
+	env->sp = frame_addr;
+	env->xregs[29] = env->sp + offsetof(struct target_rt_sigframe, fp);
+	env->pc = ka->_sa_handler;
+	env->xregs[30] = env->sp + offsetof(struct target_rt_sigframe, tramp);
+	if (info) {
+	    err |= copy_siginfo_to_user(&frame->info, info);
+	    env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
+	    env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
+	}
+    }
+
+    if (!err) {
+        unlock_user_struct(frame, frame_addr, 1);
+        return;
+    }
+
+ give_sigsegv:
+    unlock_user_struct(frame, frame_addr, 1);
+    force_sig(TARGET_SIGSEGV);
+}
+
+static void setup_rt_frame(int sig, struct target_sigaction *ka,
+			   target_siginfo_t *info,
+			   target_sigset_t *set, CPUARMState *env)
+{
+    target_setup_frame(sig, ka, info, set, env);
+}
+
+static void setup_frame(int sig, struct target_sigaction *ka,
+			target_sigset_t *set, CPUARMState *env)
+{
+    target_setup_frame(sig, ka, 0, set, env);
+}
+
+long do_rt_sigreturn (CPUARMState *env)
+{
+    struct target_rt_sigframe *frame;
+    abi_ulong frame_addr = env->sp;
+
+    if (frame_addr & 15) {
+        goto badframe;
+    }
+
+    if  (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+        goto badframe;
+    }
+
+    if (target_restore_sigframe(env, frame)) {
+        goto badframe;
+    }
+
+    if (do_sigaltstack (frame_addr +
+			offsetof (struct target_rt_sigframe, uc.tuc_stack),
+			0, get_sp_from_cpustate(env)) == -EFAULT) {
+        goto badframe;
+    }
+
+    unlock_user_struct(frame, frame_addr, 0);
+    return env->xregs[0];
+
+ badframe:
+    unlock_user_struct(frame, frame_addr, 0);
+    force_sig(TARGET_SIGSEGV);
+    return 0;
+}
+
+long do_sigreturn(CPUARMState *env)
+{
+    return do_rt_sigreturn(env);
+}
+
 #elif defined(TARGET_ARM)
 
 struct target_sigcontext {
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH 11/12] linux-user: Add AArch64 support
  2013-03-06  2:01 [Qemu-devel] [PATCH 00/12] AArch64 preparation patch set Alexander Graf
                   ` (9 preceding siblings ...)
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 10/12] linux-user: Add signal handling for AArch64 Alexander Graf
@ 2013-03-06  2:01 ` Alexander Graf
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 12/12] ARM: Add arm64 target to configure Alexander Graf
  11 siblings, 0 replies; 22+ messages in thread
From: Alexander Graf @ 2013-03-06  2:01 UTC (permalink / raw)
  To: qemu-devel qemu-devel; +Cc: Peter Maydell, Riku Voipio

This patch adds support for AArch64 in all the small corners of
linux-user and beyond.

Signed-off-by: Alexander Graf <agraf@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

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH 12/12] ARM: Add arm64 target to configure
  2013-03-06  2:01 [Qemu-devel] [PATCH 00/12] AArch64 preparation patch set Alexander Graf
                   ` (10 preceding siblings ...)
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 11/12] linux-user: Add AArch64 support Alexander Graf
@ 2013-03-06  2:01 ` Alexander Graf
  2013-03-06  3:58   ` Peter Maydell
  2013-03-06  7:01   ` Peter Maydell
  11 siblings, 2 replies; 22+ messages in thread
From: Alexander Graf @ 2013-03-06  2:01 UTC (permalink / raw)
  To: qemu-devel qemu-devel; +Cc: Peter Maydell, Riku Voipio

If we want to compile a target machine type that is AArch64 capable,
we need to add a new 64-bit capable ARM target. To make things easily
understandable, I call this arm64. That way we are

  1) Compatible with Linux
  2) In line with the other targets in QEMU

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 configure                |    9 +++++++++
 linux-user/Makefile.objs |    1 +
 2 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/configure b/configure
index 2f98c5a..a7541d3 100755
--- a/configure
+++ b/configure
@@ -3987,6 +3987,15 @@ case "$target_arch2" in
     target_llong_alignment=4
     target_libs_softmmu="$fdt_libs"
   ;;
+  arm64)
+    TARGET_BASE_ARCH=arm
+    TARGET_ABI_DIR=arm
+    bflt="yes"
+    target_nptl="yes"
+    gdb_xml_files="aarch64-core.xml aarch64-fpu.xml"
+    target_long_alignment=8
+    target_libs_softmmu="$fdt_libs"
+  ;;
   cris)
     target_nptl="yes"
   ;;
diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs
index 5899d72..7a2cb94 100644
--- a/linux-user/Makefile.objs
+++ b/linux-user/Makefile.objs
@@ -4,4 +4,5 @@ obj-y = main.o syscall.o strace.o mmap.o signal.o \
 obj-$(TARGET_HAS_BFLT) += flatload.o
 obj-$(TARGET_I386) += vm86.o
 obj-$(TARGET_ARM) += arm/nwfpe/
+obj-$(TARGET_ARM64) += arm/nwfpe/
 obj-$(TARGET_M68K) += m68k-sim.o
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH 12/12] ARM: Add arm64 target to configure
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 12/12] ARM: Add arm64 target to configure Alexander Graf
@ 2013-03-06  3:58   ` Peter Maydell
  2013-03-06  7:01   ` Peter Maydell
  1 sibling, 0 replies; 22+ messages in thread
From: Peter Maydell @ 2013-03-06  3:58 UTC (permalink / raw)
  To: Alexander Graf; +Cc: Riku Voipio, qemu-devel qemu-devel

On 6 March 2013 10:01, Alexander Graf <agraf@suse.de> wrote:
> If we want to compile a target machine type that is AArch64 capable,
> we need to add a new 64-bit capable ARM target. To make things easily
> understandable, I call this arm64.

We may have to have a naming argument later but I want to think
my position through first :-)

> --- a/configure
> +++ b/configure
> @@ -3987,6 +3987,15 @@ case "$target_arch2" in
>      target_llong_alignment=4
>      target_libs_softmmu="$fdt_libs"
>    ;;
> +  arm64)
> +    TARGET_BASE_ARCH=arm
> +    TARGET_ABI_DIR=arm

Hmm. Shouldn't the ABI dir be different? After all, the ABI is...

> +    bflt="yes"

Really?

> diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs
> index 5899d72..7a2cb94 100644
> --- a/linux-user/Makefile.objs
> +++ b/linux-user/Makefile.objs
> @@ -4,4 +4,5 @@ obj-y = main.o syscall.o strace.o mmap.o signal.o \
>  obj-$(TARGET_HAS_BFLT) += flatload.o
>  obj-$(TARGET_I386) += vm86.o
>  obj-$(TARGET_ARM) += arm/nwfpe/
> +obj-$(TARGET_ARM64) += arm/nwfpe/

I really don't want to drag the nwfpe FPA emulation code into
AArch64. It's pretty nearly obsolete for 32 bit ARM and it
definitely makes zero sense for 64 bit binaries.

-- PMM

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH 12/12] ARM: Add arm64 target to configure
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 12/12] ARM: Add arm64 target to configure Alexander Graf
  2013-03-06  3:58   ` Peter Maydell
@ 2013-03-06  7:01   ` Peter Maydell
  1 sibling, 0 replies; 22+ messages in thread
From: Peter Maydell @ 2013-03-06  7:01 UTC (permalink / raw)
  To: Alexander Graf; +Cc: Riku Voipio, qemu-devel qemu-devel

On 6 March 2013 10:01, Alexander Graf <agraf@suse.de> wrote:
> If we want to compile a target machine type that is AArch64 capable,
> we need to add a new 64-bit capable ARM target. To make things easily
> understandable, I call this arm64. That way we are
>
>   1) Compatible with Linux
>   2) In line with the other targets in QEMU

OK, here goes the naming argument. Generally in QEMU we call
the target name the same as the Linux reported architecture
(ie what "uname -m" reports). For consistency with that approach
we should thus be using "aarch64". (It's also what the gcc triplet
uses.) I don't think there's much of a good argument for 'arm64'
except personal aesthetic preference :-)

> +  arm64)
> +    TARGET_BASE_ARCH=arm
> +    TARGET_ABI_DIR=arm

I think you shouldn't set TARGET_ABI_DIR here (which will
cause us to go with the default of 'same as arch name',
so linux-user/aarch64/). This will mean you can avoid having
files like syscall_nr.h being of the form "#if 64 bits
[huge long list] #else [huge long list] #endif" -- instead
the two different ABIs just live in their own files in
split directories.

This is the way that qemu's x86, mips and sparc ports handle
their 64 bit ABIs, and I think it makes sense. (I'd actually
favour changing ppc to use a separate ppc64 directory whose
foo.h header files did a #include "../ppc/foo.h" where the
ABI is genuinely identical, and dropping ABI_DIR from
configure entirely. That's a separate argument though.)

(This will also work well with a potential refactoring of
linux-user to put more files in the $abi_dir/ subdirectories
rather than having #ifdefs in the top level files, but
since that's only 'potential' it doesn't count for a huge
amount.)

thanks
-- PMM

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH 07/12] linux-user: AArch64 requires at least 3.8.0
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 07/12] linux-user: AArch64 requires at least 3.8.0 Alexander Graf
@ 2013-03-06  7:04   ` Riku Voipio
  0 siblings, 0 replies; 22+ messages in thread
From: Riku Voipio @ 2013-03-06  7:04 UTC (permalink / raw)
  To: Alexander Graf; +Cc: Peter Maydell, Riku Voipio, qemu-devel qemu-devel

Hi,

Cool work and thanks for early sharing.

On Wed, Mar 06, 2013 at 03:01:15AM +0100, Alexander Graf wrote:
> Glibc 1.17 checks for the host kernel version on startup. Unfortunately,
> it also checks whether the host kernel version is recent enough for the
> target to run at all.
> 
> Since AArch64 support only got introduced in 3.8.0, that means that glibc
> refuses to run on any older kernel version than that.
> 
> To allow for execution of linux-user guests even on older host kernels,
> let's always fake the kernel version to 3.8.0 on AArch64 guests.

We already allow setting uname version at command line (-r) and with
./configure . A better place to hardcode this would be linux-user/main.c
where qemu_uname_release is set. Or even just setting
CONFIG_UNAME_RELEASE to the aarch64 config-target.mak 

Riku

> Signed-off-by: Alexander Graf <agraf@suse.de>
> ---
>  linux-user/syscall.c |    5 +++++
>  1 files changed, 5 insertions(+), 0 deletions(-)
> 
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 19630ea..38c0711 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -313,7 +313,12 @@ static int sys_uname(struct new_utsname *buf)
>    memset(buf, 0, sizeof(*buf));
>    COPY_UTSNAME_FIELD(buf->sysname, uts_buf.sysname);
>    COPY_UTSNAME_FIELD(buf->nodename, uts_buf.nodename);
> +#ifdef TARGET_ARM64
> +  /* glibc refuses to run on older kernels */
> +  COPY_UTSNAME_FIELD(buf->release, "3.8.0");
> +#else
>    COPY_UTSNAME_FIELD(buf->release, uts_buf.release);
> +#endif
>    COPY_UTSNAME_FIELD(buf->version, uts_buf.version);
>    COPY_UTSNAME_FIELD(buf->machine, uts_buf.machine);
>  #ifdef _GNU_SOURCE
> -- 
> 1.6.0.2

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH 04/12] ARM: Add AArch64 translation stub
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 04/12] ARM: Add AArch64 translation stub Alexander Graf
@ 2013-03-06  7:06   ` Laurent Desnogues
  2013-03-08  2:31   ` Peter Maydell
  1 sibling, 0 replies; 22+ messages in thread
From: Laurent Desnogues @ 2013-03-06  7:06 UTC (permalink / raw)
  To: Alexander Graf; +Cc: Peter Maydell, Riku Voipio, qemu-devel qemu-devel

(This mail was previously sent by accident to Alexander only.)

On Wed, Mar 6, 2013 at 3:01 AM, Alexander Graf <agraf@suse.de> wrote:
> We should translate AArch64 mode separately from AArch32 mode. In AArch64 mode,
> registers look vastly different, instruction encoding is completely different,
> basically the system turns into a different machine.
>
> So let's do a simple if() in translate.c to decide whether we can handle the
> current code in the legacy AArch32 code or in the new AArch64 code.
>
> So far, the translation always complains about unallocated instructions. There
> is no emulator functionality in this patch!
>
> Signed-off-by: Alexander Graf <agraf@suse.de>
> ---
>  target-arm/Makefile.objs   |    1 +
>  target-arm/translate-a64.c |  139 ++++++++++++++++++++++++++++++++++++++++++++
>  target-arm/translate.c     |   15 +++++
>  target-arm/translate.h     |    6 ++
>  4 files changed, 161 insertions(+), 0 deletions(-)
>  create mode 100644 target-arm/translate-a64.c
>
> diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
> index d89b57c..f9f0de4 100644
> --- a/target-arm/Makefile.objs
> +++ b/target-arm/Makefile.objs
> @@ -3,3 +3,4 @@ obj-$(CONFIG_SOFTMMU) += machine.o
>  obj-$(CONFIG_KVM) += kvm.o
>  obj-y += translate.o op_helper.o helper.o cpu.o
>  obj-y += neon_helper.o iwmmxt_helper.o
> +obj-$(TARGET_ARM64) += translate-a64.o
> diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
> new file mode 100644
> index 0000000..f354d08
> --- /dev/null
> +++ b/target-arm/translate-a64.c
> @@ -0,0 +1,139 @@
> +/*
> + *  AArch64 translation
> + *
> + *  Copyright (c) 2013 Alexander Graf <agraf@suse.de>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> + */
> +#include <stdarg.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <inttypes.h>
> +
> +#include "cpu.h"
> +#include "tcg-op.h"
> +#include "qemu/log.h"
> +#include "translate.h"
> +#include "qemu/host-utils.h"
> +
> +#include "helper.h"
> +#define GEN_HELPER 1
> +#include "helper.h"
> +
> +static TCGv_i64 cpu_X[32];
> +static TCGv_i64 cpu_pc;
> +static TCGv_i64 cpu_sp;
> +static TCGv_i32 pstate;
> +
> +static const char *regnames[] =
> +    { "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
> +      "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
> +      "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
> +      "x24", "x25", "x26", "x27", "x28", "x29", "lr", "xzr" };

Wouldn't it be better to use sp instead of xzr?  I would
expect the translator not to emit TCG ops with reg 31
meaning zero :-)


Laurent

> +
> +/* initialize TCG globals.  */
> +void a64_translate_init(void)
> +{
> +    int i;
> +
> +    cpu_pc = tcg_global_mem_new_i64(TCG_AREG0,
> +                                    offsetof(CPUARMState, pc),
> +                                    "pc");
> +    cpu_sp = tcg_global_mem_new_i64(TCG_AREG0,
> +                                    offsetof(CPUARMState, sp),
> +                                    "sp");
> +    for (i = 0; i < 32; i++) {
> +        cpu_X[i] = tcg_global_mem_new_i64(TCG_AREG0,
> +                                          offsetof(CPUARMState, xregs[i]),
> +                                          regnames[i]);
> +    }
> +
> +    pstate = tcg_global_mem_new_i32(TCG_AREG0,
> +                                    offsetof(CPUARMState, pstate),
> +                                    "pstate");
> +}
> +
> +void cpu_dump_state_a64(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf,
> +                        int flags)
> +{
> +    int i;
> +
> +    cpu_fprintf(f, "PC=%016"PRIx64"  SP=%016"PRIx64"\n", env->pc, env->sp);
> +    for(i = 0; i < 31; i++) {
> +        cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]);
> +        if ((i % 4) == 3)
> +            cpu_fprintf(f, "\n");
> +        else
> +            cpu_fprintf(f, " ");
> +    }
> +    cpu_fprintf(f, "XZR=%016"PRIx64"\n", env->xregs[31]);
> +    cpu_fprintf(f, "PSTATE=%c%c%c%c\n",
> +        env->pstate & PSTATE_N ? 'n' : '.',
> +        env->pstate & PSTATE_Z ? 'z' : '.',
> +        env->pstate & PSTATE_C ? 'c' : '.',
> +        env->pstate & PSTATE_V ? 'v' : '.');
> +    cpu_fprintf(f, "\n");
> +}
> +
> +void gen_a64_set_pc_im(uint64_t val)
> +{
> +    tcg_gen_movi_i64(cpu_pc, val);
> +}
> +
> +static void gen_exception(int excp)
> +{
> +    TCGv_i32 tmp = tcg_temp_new_i32();
> +    tcg_gen_movi_i32(tmp, excp);
> +    gen_helper_exception(cpu_env, tmp);
> +    tcg_temp_free_i32(tmp);
> +}
> +
> +static void gen_exception_insn(DisasContext *s, int offset, int excp)
> +{
> +    gen_a64_set_pc_im(s->pc - offset);
> +    gen_exception(excp);
> +    s->is_jmp = DISAS_JUMP;
> +}
> +
> +static void real_unallocated_encoding(DisasContext *s)
> +{
> +    fprintf(stderr, "Unknown instruction: %#x\n",
> +            arm_ldl_code(cpu_single_env, s->pc - 4, s->bswap_code));
> +    gen_exception_insn(s, 4, EXCP_UDEF);
> +}
> +
> +#define unallocated_encoding(s) do { \
> +    fprintf(stderr, "unallocated encoding at line: %d\n", __LINE__); \
> +    real_unallocated_encoding(s); \
> +    } while(0)
> +
> +void disas_a64_insn(CPUARMState *env, DisasContext *s)
> +{
> +    uint32_t insn;
> +
> +    insn = arm_ldl_code(env, s->pc, s->bswap_code);
> +    s->pc += 4;
> +
> +    switch ((insn >> 24) & 0x1f) {
> +    default:
> +        unallocated_encoding(s);
> +        break;
> +    }
> +
> +    if (unlikely(s->singlestep_enabled) && (s->is_jmp == DISAS_TB_JUMP)) {
> +        /* go through the main loop for single step */
> +        s->is_jmp = DISAS_JUMP;
> +    }
> +}
> diff --git a/target-arm/translate.c b/target-arm/translate.c
> index de04a0c..a3cb5ee 100644
> --- a/target-arm/translate.c
> +++ b/target-arm/translate.c
> @@ -112,6 +112,10 @@ void arm_translate_init(void)
>          offsetof(CPUARMState, exclusive_info), "exclusive_info");
>  #endif
>
> +#ifdef TARGET_ARM64
> +    a64_translate_init();
> +#endif
> +
>  #define GEN_HELPER 2
>  #include "helper.h"
>  }
> @@ -9944,6 +9948,9 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
>              gen_set_label(dc->condlabel);
>          }
>          if (dc->condjmp || !dc->is_jmp) {
> +            if (is_a64(env)) {
> +                gen_a64_set_pc_im(dc->pc);
> +            }
>              gen_set_pc_im(dc->pc);
>              dc->condjmp = 0;
>          }
> @@ -9967,6 +9974,9 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
>          gen_set_condexec(dc);
>          switch(dc->is_jmp) {
>          case DISAS_NEXT:
> +            if (is_a64(env)) {
> +                gen_a64_set_pc_im(dc->pc);
> +            }
>              gen_goto_tb(dc, 1, dc->pc);
>              break;
>          default:
> @@ -10038,6 +10048,11 @@ void cpu_dump_state(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf,
>      int i;
>      uint32_t psr;
>
> +    if (is_a64(env)) {
> +        cpu_dump_state_a64(env, f, cpu_fprintf, flags);
> +        return;
> +    }
> +
>      for(i=0;i<16;i++) {
>          cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
>          if ((i % 4) == 3)
> diff --git a/target-arm/translate.h b/target-arm/translate.h
> index 8ba1433..9086e43 100644
> --- a/target-arm/translate.h
> +++ b/target-arm/translate.h
> @@ -26,4 +26,10 @@ typedef struct DisasContext {
>
>  extern TCGv_ptr cpu_env;
>
> +void a64_translate_init(void);
> +void cpu_dump_state_a64(CPUARMState *env, FILE *f,
> +        fprintf_function cpu_fprintf, int flags);
> +void disas_a64_insn(CPUARMState *env, DisasContext *s);
> +void gen_a64_set_pc_im(uint64_t val);
> +
>  #endif /* TARGET_ARM_TRANSLATE_H */
> --
> 1.6.0.2
>
>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH 03/12] ARM: Prepare translation for AArch64 code
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 03/12] ARM: Prepare translation for AArch64 code Alexander Graf
@ 2013-03-06  7:11   ` Laurent Desnogues
  2013-03-06  9:36     ` Alexander Graf
  2013-03-08  2:27   ` Peter Maydell
  1 sibling, 1 reply; 22+ messages in thread
From: Laurent Desnogues @ 2013-03-06  7:11 UTC (permalink / raw)
  To: Alexander Graf; +Cc: Peter Maydell, Riku Voipio, qemu-devel qemu-devel

On Wed, Mar 6, 2013 at 3:01 AM, Alexander Graf <agraf@suse.de> wrote:
> This patch adds all the prerequisites for AArch64 support that didn't
> fit into split up patches. It extends important bits in the core cpu
> headers to also take AArch64 mode into account.
>
> Signed-off-by: Alexander Graf <agraf@suse.de>
> ---
>  include/elf.h          |    2 +
>  target-arm/cpu.h       |  103 ++++++++++++++++++++++++++++++++++++------------
>  target-arm/translate.c |   42 +++++++++++--------
>  3 files changed, 103 insertions(+), 44 deletions(-)
>
> diff --git a/include/elf.h b/include/elf.h
> index a21ea53..0ff0ea6 100644
> --- a/include/elf.h
> +++ b/include/elf.h
> @@ -109,6 +109,8 @@ typedef int64_t  Elf64_Sxword;
>  #define EM_OPENRISC     92        /* OpenCores OpenRISC */
>
>  #define EM_UNICORE32    110     /* UniCore32 */
> +#define EM_AARCH64      183     /* ARM 64-bit architecture */
> +
>
>  /*
>   * This is an interim value that we will use until the committee comes
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index c28a0d9..ec292c9 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -19,13 +19,19 @@
>  #ifndef CPU_ARM_H
>  #define CPU_ARM_H
>
> -#define TARGET_LONG_BITS 32
> +#include "config.h"
>
> -#define ELF_MACHINE    EM_ARM
> +#if defined (TARGET_ARM64)
> +  /* AArch64 definitions */
> +#  define TARGET_LONG_BITS 64
> +#  define ELF_MACHINE  EM_AARCH64
> +#else
> +#  define TARGET_LONG_BITS 32
> +#  define ELF_MACHINE  EM_ARM
> +#endif
>
>  #define CPUArchState struct CPUARMState
>
> -#include "config.h"
>  #include "qemu-common.h"
>  #include "exec/cpu-defs.h"
>
> @@ -79,6 +85,13 @@ struct arm_boot_info;
>  typedef struct CPUARMState {
>      /* Regs for current mode.  */
>      uint32_t regs[16];
> +
> +    /* Regs for A64 mode.  */
> +    uint64_t xregs[32];

I'm not sure it makes sense to allocate space for xregs[31].
If it is the zero register then you would anyway have special
cases in translation code to discard writes to reg 31 and so
it could be argued you could also special case reads from
reg 31 (and you should so that the optimizer knows it's zero).

Perhaps you could use xregs[31] as SP, which after all is
a more "regular" register than xzr.


Laurent

> +    uint64_t pc;
> +    uint64_t sp;
> +    uint32_t pstate;
> +
>      /* Frequently accessed CPSR bits are stored separately for efficiency.
>         This contains all the other bits.  Use cpsr_{read,write} to access
>         the whole CPSR.  */
> @@ -154,6 +167,11 @@ typedef struct CPUARMState {
>          uint32_t c15_power_control; /* power control */
>      } cp15;
>
> +    /* System registers (AArch64) */
> +    struct {
> +        uint64_t tpidr_el0;
> +    } sr;
> +
>      struct {
>          uint32_t other_sp;
>          uint32_t vecbase;
> @@ -170,7 +188,7 @@ typedef struct CPUARMState {
>
>      /* VFP coprocessor state.  */
>      struct {
> -        float64 regs[32];
> +        float64 regs[64];
>
>          uint32_t xregs[16];
>          /* We store these fpcsr fields separately for convenience.  */
> @@ -241,6 +259,24 @@ int bank_number(int mode);
>  void switch_mode(CPUARMState *, int);
>  uint32_t do_arm_semihosting(CPUARMState *env);
>
> +static inline bool is_a64(CPUARMState *env)
> +{
> +#ifdef TARGET_ARM64
> +    return true;
> +#else
> +    return false;
> +#endif
> +}
> +
> +#define PSTATE_N_SHIFT 3
> +#define PSTATE_N  (1 << PSTATE_N_SHIFT)
> +#define PSTATE_Z_SHIFT 2
> +#define PSTATE_Z  (1 << PSTATE_Z_SHIFT)
> +#define PSTATE_C_SHIFT 1
> +#define PSTATE_C  (1 << PSTATE_C_SHIFT)
> +#define PSTATE_V_SHIFT 0
> +#define PSTATE_V  (1 << PSTATE_V_SHIFT)
> +
>  /* you can call this signal handler from your SIGBUS and SIGSEGV
>     signal handlers to inform the virtual CPU of exceptions. non zero
>     is returned if the signal was handled by the virtual CPU.  */
> @@ -624,8 +660,13 @@ static inline bool cp_access_ok(CPUARMState *env,
>  #define TARGET_PAGE_BITS 10
>  #endif
>
> -#define TARGET_PHYS_ADDR_SPACE_BITS 40
> -#define TARGET_VIRT_ADDR_SPACE_BITS 32
> +#if defined (TARGET_ARM64)
> +#  define TARGET_PHYS_ADDR_SPACE_BITS 64
> +#  define TARGET_VIRT_ADDR_SPACE_BITS 64
> +#else
> +#  define TARGET_PHYS_ADDR_SPACE_BITS 40
> +#  define TARGET_VIRT_ADDR_SPACE_BITS 32
> +#endif
>
>  static inline CPUARMState *cpu_init(const char *cpu_model)
>  {
> @@ -699,25 +740,31 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
>  static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
>                                          target_ulong *cs_base, int *flags)
>  {
> -    int privmode;
> -    *pc = env->regs[15];
> -    *cs_base = 0;
> -    *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
> -        | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
> -        | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
> -        | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
> -        | (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT);
> -    if (arm_feature(env, ARM_FEATURE_M)) {
> -        privmode = !((env->v7m.exception == 0) && (env->v7m.control & 1));
> +    if (is_a64(env)) {
> +        *pc = env->pc;
> +        *flags = 0;
>      } else {
> -        privmode = (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR;
> -    }
> -    if (privmode) {
> -        *flags |= ARM_TBFLAG_PRIV_MASK;
> -    }
> -    if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
> -        *flags |= ARM_TBFLAG_VFPEN_MASK;
> +        int privmode;
> +        *pc = env->regs[15];
> +        *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
> +            | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
> +            | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
> +            | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
> +            | (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT);
> +        if (arm_feature(env, ARM_FEATURE_M)) {
> +            privmode = !((env->v7m.exception == 0) && (env->v7m.control & 1));
> +        } else {
> +            privmode = (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR;
> +        }
> +        if (privmode) {
> +            *flags |= ARM_TBFLAG_PRIV_MASK;
> +        }
> +        if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
> +            *flags |= ARM_TBFLAG_VFPEN_MASK;
> +        }
>      }
> +
> +    *cs_base = 0;
>  }
>
>  static inline bool cpu_has_work(CPUState *cpu)
> @@ -732,11 +779,15 @@ static inline bool cpu_has_work(CPUState *cpu)
>
>  static inline void cpu_pc_from_tb(CPUARMState *env, TranslationBlock *tb)
>  {
> -    env->regs[15] = tb->pc;
> +    if (is_a64(env)) {
> +        env->pc = tb->pc;
> +    } else {
> +        env->regs[15] = tb->pc;
> +    }
>  }
>
>  /* Load an instruction and return it in the standard little-endian order */
> -static inline uint32_t arm_ldl_code(CPUARMState *env, uint32_t addr,
> +static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
>                                      bool do_swap)
>  {
>      uint32_t insn = cpu_ldl_code(env, addr);
> @@ -747,7 +798,7 @@ static inline uint32_t arm_ldl_code(CPUARMState *env, uint32_t addr,
>  }
>
>  /* Ditto, for a halfword (Thumb) instruction */
> -static inline uint16_t arm_lduw_code(CPUARMState *env, uint32_t addr,
> +static inline uint16_t arm_lduw_code(CPUARMState *env, target_ulong addr,
>                                       bool do_swap)
>  {
>      uint16_t insn = cpu_lduw_code(env, addr);
> diff --git a/target-arm/translate.c b/target-arm/translate.c
> index f8838f3..de04a0c 100644
> --- a/target-arm/translate.c
> +++ b/target-arm/translate.c
> @@ -9749,7 +9749,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
>      uint16_t *gen_opc_end;
>      int j, lj;
>      target_ulong pc_start;
> -    uint32_t next_page_start;
> +    target_ulong next_page_start;
>      int num_insns;
>      int max_insns;
>
> @@ -9833,24 +9833,26 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
>          store_cpu_field(tmp, condexec_bits);
>        }
>      do {
> +        if (!is_a64(env)) {
>  #ifdef CONFIG_USER_ONLY
> -        /* Intercept jump to the magic kernel page.  */
> -        if (dc->pc >= 0xffff0000) {
> -            /* We always get here via a jump, so know we are not in a
> -               conditional execution block.  */
> -            gen_exception(EXCP_KERNEL_TRAP);
> -            dc->is_jmp = DISAS_UPDATE;
> -            break;
> -        }
> +            /* Intercept jump to the magic kernel page.  */
> +            if (dc->pc >= 0xffff0000) {
> +                /* We always get here via a jump, so know we are not in a
> +                   conditional execution block.  */
> +                gen_exception(EXCP_KERNEL_TRAP);
> +                dc->is_jmp = DISAS_UPDATE;
> +                break;
> +            }
>  #else
> -        if (dc->pc >= 0xfffffff0 && IS_M(env)) {
> -            /* We always get here via a jump, so know we are not in a
> -               conditional execution block.  */
> -            gen_exception(EXCP_EXCEPTION_EXIT);
> -            dc->is_jmp = DISAS_UPDATE;
> -            break;
> -        }
> +            if (dc->pc >= 0xfffffff0 && IS_M(env)) {
> +                /* We always get here via a jump, so know we are not in a
> +                   conditional execution block.  */
> +                gen_exception(EXCP_EXCEPTION_EXIT);
> +                dc->is_jmp = DISAS_UPDATE;
> +                break;
> +            }
>  #endif
> +        }
>
>          if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
>              QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> @@ -9904,7 +9906,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
>          }
>
>          if (tcg_check_temp_count()) {
> -            fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc);
> +            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n", dc->pc);
>          }
>
>          /* Translation stops when a conditional branch is encountered.
> @@ -10074,6 +10076,10 @@ void cpu_dump_state(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf,
>
>  void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
>  {
> -    env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
> +    if (is_a64(env)) {
> +        env->pc = tcg_ctx.gen_opc_pc[pc_pos];
> +    } else {
> +        env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
> +    }
>      env->condexec_bits = gen_opc_condexec_bits[pc_pos];
>  }
> --
> 1.6.0.2
>
>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH 03/12] ARM: Prepare translation for AArch64 code
  2013-03-06  7:11   ` Laurent Desnogues
@ 2013-03-06  9:36     ` Alexander Graf
  2013-03-06  9:46       ` Laurent Desnogues
  0 siblings, 1 reply; 22+ messages in thread
From: Alexander Graf @ 2013-03-06  9:36 UTC (permalink / raw)
  To: Laurent Desnogues; +Cc: Peter Maydell, Riku Voipio, qemu-devel qemu-devel



Am 06.03.2013 um 08:11 schrieb Laurent Desnogues <laurent.desnogues@gmail.com>:

> On Wed, Mar 6, 2013 at 3:01 AM, Alexander Graf <agraf@suse.de> wrote:
>> This patch adds all the prerequisites for AArch64 support that didn't
>> fit into split up patches. It extends important bits in the core cpu
>> headers to also take AArch64 mode into account.
>> 
>> Signed-off-by: Alexander Graf <agraf@suse.de>
>> ---
>> include/elf.h          |    2 +
>> target-arm/cpu.h       |  103 ++++++++++++++++++++++++++++++++++++------------
>> target-arm/translate.c |   42 +++++++++++--------
>> 3 files changed, 103 insertions(+), 44 deletions(-)
>> 
>> diff --git a/include/elf.h b/include/elf.h
>> index a21ea53..0ff0ea6 100644
>> --- a/include/elf.h
>> +++ b/include/elf.h
>> @@ -109,6 +109,8 @@ typedef int64_t  Elf64_Sxword;
>> #define EM_OPENRISC     92        /* OpenCores OpenRISC */
>> 
>> #define EM_UNICORE32    110     /* UniCore32 */
>> +#define EM_AARCH64      183     /* ARM 64-bit architecture */
>> +
>> 
>> /*
>>  * This is an interim value that we will use until the committee comes
>> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
>> index c28a0d9..ec292c9 100644
>> --- a/target-arm/cpu.h
>> +++ b/target-arm/cpu.h
>> @@ -19,13 +19,19 @@
>> #ifndef CPU_ARM_H
>> #define CPU_ARM_H
>> 
>> -#define TARGET_LONG_BITS 32
>> +#include "config.h"
>> 
>> -#define ELF_MACHINE    EM_ARM
>> +#if defined (TARGET_ARM64)
>> +  /* AArch64 definitions */
>> +#  define TARGET_LONG_BITS 64
>> +#  define ELF_MACHINE  EM_AARCH64
>> +#else
>> +#  define TARGET_LONG_BITS 32
>> +#  define ELF_MACHINE  EM_ARM
>> +#endif
>> 
>> #define CPUArchState struct CPUARMState
>> 
>> -#include "config.h"
>> #include "qemu-common.h"
>> #include "exec/cpu-defs.h"
>> 
>> @@ -79,6 +85,13 @@ struct arm_boot_info;
>> typedef struct CPUARMState {
>>     /* Regs for current mode.  */
>>     uint32_t regs[16];
>> +
>> +    /* Regs for A64 mode.  */
>> +    uint64_t xregs[32];
> 
> I'm not sure it makes sense to allocate space for xregs[31].
> If it is the zero register then you would anyway have special
> cases in translation code to discard writes to reg 31 and so
> it could be argued you could also special case reads from
> reg 31 (and you should so that the optimizer knows it's zero).
> 
> Perhaps you could use xregs[31] as SP, which after all is
> a more "regular" register than xzr.

Sp is a separate env field in my patch set. So yeah, I should just drop xregs[31] and always special case it I suppose. That's the best way to avoid accidents I hope :)

Alex

> 
> 
> Laurent
> 
>> +    uint64_t pc;
>> +    uint64_t sp;
>> +    uint32_t pstate;
>> +
>>     /* Frequently accessed CPSR bits are stored separately for efficiency.
>>        This contains all the other bits.  Use cpsr_{read,write} to access
>>        the whole CPSR.  */
>> @@ -154,6 +167,11 @@ typedef struct CPUARMState {
>>         uint32_t c15_power_control; /* power control */
>>     } cp15;
>> 
>> +    /* System registers (AArch64) */
>> +    struct {
>> +        uint64_t tpidr_el0;
>> +    } sr;
>> +
>>     struct {
>>         uint32_t other_sp;
>>         uint32_t vecbase;
>> @@ -170,7 +188,7 @@ typedef struct CPUARMState {
>> 
>>     /* VFP coprocessor state.  */
>>     struct {
>> -        float64 regs[32];
>> +        float64 regs[64];
>> 
>>         uint32_t xregs[16];
>>         /* We store these fpcsr fields separately for convenience.  */
>> @@ -241,6 +259,24 @@ int bank_number(int mode);
>> void switch_mode(CPUARMState *, int);
>> uint32_t do_arm_semihosting(CPUARMState *env);
>> 
>> +static inline bool is_a64(CPUARMState *env)
>> +{
>> +#ifdef TARGET_ARM64
>> +    return true;
>> +#else
>> +    return false;
>> +#endif
>> +}
>> +
>> +#define PSTATE_N_SHIFT 3
>> +#define PSTATE_N  (1 << PSTATE_N_SHIFT)
>> +#define PSTATE_Z_SHIFT 2
>> +#define PSTATE_Z  (1 << PSTATE_Z_SHIFT)
>> +#define PSTATE_C_SHIFT 1
>> +#define PSTATE_C  (1 << PSTATE_C_SHIFT)
>> +#define PSTATE_V_SHIFT 0
>> +#define PSTATE_V  (1 << PSTATE_V_SHIFT)
>> +
>> /* you can call this signal handler from your SIGBUS and SIGSEGV
>>    signal handlers to inform the virtual CPU of exceptions. non zero
>>    is returned if the signal was handled by the virtual CPU.  */
>> @@ -624,8 +660,13 @@ static inline bool cp_access_ok(CPUARMState *env,
>> #define TARGET_PAGE_BITS 10
>> #endif
>> 
>> -#define TARGET_PHYS_ADDR_SPACE_BITS 40
>> -#define TARGET_VIRT_ADDR_SPACE_BITS 32
>> +#if defined (TARGET_ARM64)
>> +#  define TARGET_PHYS_ADDR_SPACE_BITS 64
>> +#  define TARGET_VIRT_ADDR_SPACE_BITS 64
>> +#else
>> +#  define TARGET_PHYS_ADDR_SPACE_BITS 40
>> +#  define TARGET_VIRT_ADDR_SPACE_BITS 32
>> +#endif
>> 
>> static inline CPUARMState *cpu_init(const char *cpu_model)
>> {
>> @@ -699,25 +740,31 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
>> static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
>>                                         target_ulong *cs_base, int *flags)
>> {
>> -    int privmode;
>> -    *pc = env->regs[15];
>> -    *cs_base = 0;
>> -    *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
>> -        | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
>> -        | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
>> -        | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
>> -        | (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT);
>> -    if (arm_feature(env, ARM_FEATURE_M)) {
>> -        privmode = !((env->v7m.exception == 0) && (env->v7m.control & 1));
>> +    if (is_a64(env)) {
>> +        *pc = env->pc;
>> +        *flags = 0;
>>     } else {
>> -        privmode = (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR;
>> -    }
>> -    if (privmode) {
>> -        *flags |= ARM_TBFLAG_PRIV_MASK;
>> -    }
>> -    if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
>> -        *flags |= ARM_TBFLAG_VFPEN_MASK;
>> +        int privmode;
>> +        *pc = env->regs[15];
>> +        *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
>> +            | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
>> +            | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
>> +            | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
>> +            | (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT);
>> +        if (arm_feature(env, ARM_FEATURE_M)) {
>> +            privmode = !((env->v7m.exception == 0) && (env->v7m.control & 1));
>> +        } else {
>> +            privmode = (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR;
>> +        }
>> +        if (privmode) {
>> +            *flags |= ARM_TBFLAG_PRIV_MASK;
>> +        }
>> +        if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
>> +            *flags |= ARM_TBFLAG_VFPEN_MASK;
>> +        }
>>     }
>> +
>> +    *cs_base = 0;
>> }
>> 
>> static inline bool cpu_has_work(CPUState *cpu)
>> @@ -732,11 +779,15 @@ static inline bool cpu_has_work(CPUState *cpu)
>> 
>> static inline void cpu_pc_from_tb(CPUARMState *env, TranslationBlock *tb)
>> {
>> -    env->regs[15] = tb->pc;
>> +    if (is_a64(env)) {
>> +        env->pc = tb->pc;
>> +    } else {
>> +        env->regs[15] = tb->pc;
>> +    }
>> }
>> 
>> /* Load an instruction and return it in the standard little-endian order */
>> -static inline uint32_t arm_ldl_code(CPUARMState *env, uint32_t addr,
>> +static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
>>                                     bool do_swap)
>> {
>>     uint32_t insn = cpu_ldl_code(env, addr);
>> @@ -747,7 +798,7 @@ static inline uint32_t arm_ldl_code(CPUARMState *env, uint32_t addr,
>> }
>> 
>> /* Ditto, for a halfword (Thumb) instruction */
>> -static inline uint16_t arm_lduw_code(CPUARMState *env, uint32_t addr,
>> +static inline uint16_t arm_lduw_code(CPUARMState *env, target_ulong addr,
>>                                      bool do_swap)
>> {
>>     uint16_t insn = cpu_lduw_code(env, addr);
>> diff --git a/target-arm/translate.c b/target-arm/translate.c
>> index f8838f3..de04a0c 100644
>> --- a/target-arm/translate.c
>> +++ b/target-arm/translate.c
>> @@ -9749,7 +9749,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
>>     uint16_t *gen_opc_end;
>>     int j, lj;
>>     target_ulong pc_start;
>> -    uint32_t next_page_start;
>> +    target_ulong next_page_start;
>>     int num_insns;
>>     int max_insns;
>> 
>> @@ -9833,24 +9833,26 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
>>         store_cpu_field(tmp, condexec_bits);
>>       }
>>     do {
>> +        if (!is_a64(env)) {
>> #ifdef CONFIG_USER_ONLY
>> -        /* Intercept jump to the magic kernel page.  */
>> -        if (dc->pc >= 0xffff0000) {
>> -            /* We always get here via a jump, so know we are not in a
>> -               conditional execution block.  */
>> -            gen_exception(EXCP_KERNEL_TRAP);
>> -            dc->is_jmp = DISAS_UPDATE;
>> -            break;
>> -        }
>> +            /* Intercept jump to the magic kernel page.  */
>> +            if (dc->pc >= 0xffff0000) {
>> +                /* We always get here via a jump, so know we are not in a
>> +                   conditional execution block.  */
>> +                gen_exception(EXCP_KERNEL_TRAP);
>> +                dc->is_jmp = DISAS_UPDATE;
>> +                break;
>> +            }
>> #else
>> -        if (dc->pc >= 0xfffffff0 && IS_M(env)) {
>> -            /* We always get here via a jump, so know we are not in a
>> -               conditional execution block.  */
>> -            gen_exception(EXCP_EXCEPTION_EXIT);
>> -            dc->is_jmp = DISAS_UPDATE;
>> -            break;
>> -        }
>> +            if (dc->pc >= 0xfffffff0 && IS_M(env)) {
>> +                /* We always get here via a jump, so know we are not in a
>> +                   conditional execution block.  */
>> +                gen_exception(EXCP_EXCEPTION_EXIT);
>> +                dc->is_jmp = DISAS_UPDATE;
>> +                break;
>> +            }
>> #endif
>> +        }
>> 
>>         if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
>>             QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
>> @@ -9904,7 +9906,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
>>         }
>> 
>>         if (tcg_check_temp_count()) {
>> -            fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc);
>> +            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n", dc->pc);
>>         }
>> 
>>         /* Translation stops when a conditional branch is encountered.
>> @@ -10074,6 +10076,10 @@ void cpu_dump_state(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf,
>> 
>> void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
>> {
>> -    env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
>> +    if (is_a64(env)) {
>> +        env->pc = tcg_ctx.gen_opc_pc[pc_pos];
>> +    } else {
>> +        env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
>> +    }
>>     env->condexec_bits = gen_opc_condexec_bits[pc_pos];
>> }
>> --
>> 1.6.0.2
>> 
>> 

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH 03/12] ARM: Prepare translation for AArch64 code
  2013-03-06  9:36     ` Alexander Graf
@ 2013-03-06  9:46       ` Laurent Desnogues
  0 siblings, 0 replies; 22+ messages in thread
From: Laurent Desnogues @ 2013-03-06  9:46 UTC (permalink / raw)
  To: Alexander Graf; +Cc: Peter Maydell, Riku Voipio, qemu-devel qemu-devel

On Wed, Mar 6, 2013 at 10:36 AM, Alexander Graf <agraf@suse.de> wrote:
>
>
> Am 06.03.2013 um 08:11 schrieb Laurent Desnogues <laurent.desnogues@gmail.com>:
>
>> On Wed, Mar 6, 2013 at 3:01 AM, Alexander Graf <agraf@suse.de> wrote:
>>> This patch adds all the prerequisites for AArch64 support that didn't
>>> fit into split up patches. It extends important bits in the core cpu
>>> headers to also take AArch64 mode into account.
>>>
>>> Signed-off-by: Alexander Graf <agraf@suse.de>
>>> ---
>>> include/elf.h          |    2 +
>>> target-arm/cpu.h       |  103 ++++++++++++++++++++++++++++++++++++------------
>>> target-arm/translate.c |   42 +++++++++++--------
>>> 3 files changed, 103 insertions(+), 44 deletions(-)
>>>
>>> diff --git a/include/elf.h b/include/elf.h
>>> index a21ea53..0ff0ea6 100644
>>> --- a/include/elf.h
>>> +++ b/include/elf.h
>>> @@ -109,6 +109,8 @@ typedef int64_t  Elf64_Sxword;
>>> #define EM_OPENRISC     92        /* OpenCores OpenRISC */
>>>
>>> #define EM_UNICORE32    110     /* UniCore32 */
>>> +#define EM_AARCH64      183     /* ARM 64-bit architecture */
>>> +
>>>
>>> /*
>>>  * This is an interim value that we will use until the committee comes
>>> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
>>> index c28a0d9..ec292c9 100644
>>> --- a/target-arm/cpu.h
>>> +++ b/target-arm/cpu.h
>>> @@ -19,13 +19,19 @@
>>> #ifndef CPU_ARM_H
>>> #define CPU_ARM_H
>>>
>>> -#define TARGET_LONG_BITS 32
>>> +#include "config.h"
>>>
>>> -#define ELF_MACHINE    EM_ARM
>>> +#if defined (TARGET_ARM64)
>>> +  /* AArch64 definitions */
>>> +#  define TARGET_LONG_BITS 64
>>> +#  define ELF_MACHINE  EM_AARCH64
>>> +#else
>>> +#  define TARGET_LONG_BITS 32
>>> +#  define ELF_MACHINE  EM_ARM
>>> +#endif
>>>
>>> #define CPUArchState struct CPUARMState
>>>
>>> -#include "config.h"
>>> #include "qemu-common.h"
>>> #include "exec/cpu-defs.h"
>>>
>>> @@ -79,6 +85,13 @@ struct arm_boot_info;
>>> typedef struct CPUARMState {
>>>     /* Regs for current mode.  */
>>>     uint32_t regs[16];
>>> +
>>> +    /* Regs for A64 mode.  */
>>> +    uint64_t xregs[32];
>>
>> I'm not sure it makes sense to allocate space for xregs[31].
>> If it is the zero register then you would anyway have special
>> cases in translation code to discard writes to reg 31 and so
>> it could be argued you could also special case reads from
>> reg 31 (and you should so that the optimizer knows it's zero).
>>
>> Perhaps you could use xregs[31] as SP, which after all is
>> a more "regular" register than xzr.
>
> Sp is a separate env field in my patch set. So yeah, I should just drop xregs[31] and always special case it I suppose. That's the best way to avoid accidents I hope :)

I think that using xregs[31] as sp would ease code generation.
No need to special case both xzr and sp.

OTOH if you only declare 31 regs and you access xregs[31]
by accident you'd read/write pc which might help uncover
bugs faster, though I wouldn't want to use that "feature" to
ease development :-)


Laurent

> Alex
>
>>
>>
>> Laurent
>>
>>> +    uint64_t pc;
>>> +    uint64_t sp;
>>> +    uint32_t pstate;
>>> +
>>>     /* Frequently accessed CPSR bits are stored separately for efficiency.
>>>        This contains all the other bits.  Use cpsr_{read,write} to access
>>>        the whole CPSR.  */
>>> @@ -154,6 +167,11 @@ typedef struct CPUARMState {
>>>         uint32_t c15_power_control; /* power control */
>>>     } cp15;
>>>
>>> +    /* System registers (AArch64) */
>>> +    struct {
>>> +        uint64_t tpidr_el0;
>>> +    } sr;
>>> +
>>>     struct {
>>>         uint32_t other_sp;
>>>         uint32_t vecbase;
>>> @@ -170,7 +188,7 @@ typedef struct CPUARMState {
>>>
>>>     /* VFP coprocessor state.  */
>>>     struct {
>>> -        float64 regs[32];
>>> +        float64 regs[64];
>>>
>>>         uint32_t xregs[16];
>>>         /* We store these fpcsr fields separately for convenience.  */
>>> @@ -241,6 +259,24 @@ int bank_number(int mode);
>>> void switch_mode(CPUARMState *, int);
>>> uint32_t do_arm_semihosting(CPUARMState *env);
>>>
>>> +static inline bool is_a64(CPUARMState *env)
>>> +{
>>> +#ifdef TARGET_ARM64
>>> +    return true;
>>> +#else
>>> +    return false;
>>> +#endif
>>> +}
>>> +
>>> +#define PSTATE_N_SHIFT 3
>>> +#define PSTATE_N  (1 << PSTATE_N_SHIFT)
>>> +#define PSTATE_Z_SHIFT 2
>>> +#define PSTATE_Z  (1 << PSTATE_Z_SHIFT)
>>> +#define PSTATE_C_SHIFT 1
>>> +#define PSTATE_C  (1 << PSTATE_C_SHIFT)
>>> +#define PSTATE_V_SHIFT 0
>>> +#define PSTATE_V  (1 << PSTATE_V_SHIFT)
>>> +
>>> /* you can call this signal handler from your SIGBUS and SIGSEGV
>>>    signal handlers to inform the virtual CPU of exceptions. non zero
>>>    is returned if the signal was handled by the virtual CPU.  */
>>> @@ -624,8 +660,13 @@ static inline bool cp_access_ok(CPUARMState *env,
>>> #define TARGET_PAGE_BITS 10
>>> #endif
>>>
>>> -#define TARGET_PHYS_ADDR_SPACE_BITS 40
>>> -#define TARGET_VIRT_ADDR_SPACE_BITS 32
>>> +#if defined (TARGET_ARM64)
>>> +#  define TARGET_PHYS_ADDR_SPACE_BITS 64
>>> +#  define TARGET_VIRT_ADDR_SPACE_BITS 64
>>> +#else
>>> +#  define TARGET_PHYS_ADDR_SPACE_BITS 40
>>> +#  define TARGET_VIRT_ADDR_SPACE_BITS 32
>>> +#endif
>>>
>>> static inline CPUARMState *cpu_init(const char *cpu_model)
>>> {
>>> @@ -699,25 +740,31 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
>>> static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
>>>                                         target_ulong *cs_base, int *flags)
>>> {
>>> -    int privmode;
>>> -    *pc = env->regs[15];
>>> -    *cs_base = 0;
>>> -    *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
>>> -        | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
>>> -        | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
>>> -        | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
>>> -        | (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT);
>>> -    if (arm_feature(env, ARM_FEATURE_M)) {
>>> -        privmode = !((env->v7m.exception == 0) && (env->v7m.control & 1));
>>> +    if (is_a64(env)) {
>>> +        *pc = env->pc;
>>> +        *flags = 0;
>>>     } else {
>>> -        privmode = (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR;
>>> -    }
>>> -    if (privmode) {
>>> -        *flags |= ARM_TBFLAG_PRIV_MASK;
>>> -    }
>>> -    if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
>>> -        *flags |= ARM_TBFLAG_VFPEN_MASK;
>>> +        int privmode;
>>> +        *pc = env->regs[15];
>>> +        *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
>>> +            | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
>>> +            | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
>>> +            | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
>>> +            | (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT);
>>> +        if (arm_feature(env, ARM_FEATURE_M)) {
>>> +            privmode = !((env->v7m.exception == 0) && (env->v7m.control & 1));
>>> +        } else {
>>> +            privmode = (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR;
>>> +        }
>>> +        if (privmode) {
>>> +            *flags |= ARM_TBFLAG_PRIV_MASK;
>>> +        }
>>> +        if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
>>> +            *flags |= ARM_TBFLAG_VFPEN_MASK;
>>> +        }
>>>     }
>>> +
>>> +    *cs_base = 0;
>>> }
>>>
>>> static inline bool cpu_has_work(CPUState *cpu)
>>> @@ -732,11 +779,15 @@ static inline bool cpu_has_work(CPUState *cpu)
>>>
>>> static inline void cpu_pc_from_tb(CPUARMState *env, TranslationBlock *tb)
>>> {
>>> -    env->regs[15] = tb->pc;
>>> +    if (is_a64(env)) {
>>> +        env->pc = tb->pc;
>>> +    } else {
>>> +        env->regs[15] = tb->pc;
>>> +    }
>>> }
>>>
>>> /* Load an instruction and return it in the standard little-endian order */
>>> -static inline uint32_t arm_ldl_code(CPUARMState *env, uint32_t addr,
>>> +static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
>>>                                     bool do_swap)
>>> {
>>>     uint32_t insn = cpu_ldl_code(env, addr);
>>> @@ -747,7 +798,7 @@ static inline uint32_t arm_ldl_code(CPUARMState *env, uint32_t addr,
>>> }
>>>
>>> /* Ditto, for a halfword (Thumb) instruction */
>>> -static inline uint16_t arm_lduw_code(CPUARMState *env, uint32_t addr,
>>> +static inline uint16_t arm_lduw_code(CPUARMState *env, target_ulong addr,
>>>                                      bool do_swap)
>>> {
>>>     uint16_t insn = cpu_lduw_code(env, addr);
>>> diff --git a/target-arm/translate.c b/target-arm/translate.c
>>> index f8838f3..de04a0c 100644
>>> --- a/target-arm/translate.c
>>> +++ b/target-arm/translate.c
>>> @@ -9749,7 +9749,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
>>>     uint16_t *gen_opc_end;
>>>     int j, lj;
>>>     target_ulong pc_start;
>>> -    uint32_t next_page_start;
>>> +    target_ulong next_page_start;
>>>     int num_insns;
>>>     int max_insns;
>>>
>>> @@ -9833,24 +9833,26 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
>>>         store_cpu_field(tmp, condexec_bits);
>>>       }
>>>     do {
>>> +        if (!is_a64(env)) {
>>> #ifdef CONFIG_USER_ONLY
>>> -        /* Intercept jump to the magic kernel page.  */
>>> -        if (dc->pc >= 0xffff0000) {
>>> -            /* We always get here via a jump, so know we are not in a
>>> -               conditional execution block.  */
>>> -            gen_exception(EXCP_KERNEL_TRAP);
>>> -            dc->is_jmp = DISAS_UPDATE;
>>> -            break;
>>> -        }
>>> +            /* Intercept jump to the magic kernel page.  */
>>> +            if (dc->pc >= 0xffff0000) {
>>> +                /* We always get here via a jump, so know we are not in a
>>> +                   conditional execution block.  */
>>> +                gen_exception(EXCP_KERNEL_TRAP);
>>> +                dc->is_jmp = DISAS_UPDATE;
>>> +                break;
>>> +            }
>>> #else
>>> -        if (dc->pc >= 0xfffffff0 && IS_M(env)) {
>>> -            /* We always get here via a jump, so know we are not in a
>>> -               conditional execution block.  */
>>> -            gen_exception(EXCP_EXCEPTION_EXIT);
>>> -            dc->is_jmp = DISAS_UPDATE;
>>> -            break;
>>> -        }
>>> +            if (dc->pc >= 0xfffffff0 && IS_M(env)) {
>>> +                /* We always get here via a jump, so know we are not in a
>>> +                   conditional execution block.  */
>>> +                gen_exception(EXCP_EXCEPTION_EXIT);
>>> +                dc->is_jmp = DISAS_UPDATE;
>>> +                break;
>>> +            }
>>> #endif
>>> +        }
>>>
>>>         if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
>>>             QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
>>> @@ -9904,7 +9906,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
>>>         }
>>>
>>>         if (tcg_check_temp_count()) {
>>> -            fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc);
>>> +            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n", dc->pc);
>>>         }
>>>
>>>         /* Translation stops when a conditional branch is encountered.
>>> @@ -10074,6 +10076,10 @@ void cpu_dump_state(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf,
>>>
>>> void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
>>> {
>>> -    env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
>>> +    if (is_a64(env)) {
>>> +        env->pc = tcg_ctx.gen_opc_pc[pc_pos];
>>> +    } else {
>>> +        env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
>>> +    }
>>>     env->condexec_bits = gen_opc_condexec_bits[pc_pos];
>>> }
>>> --
>>> 1.6.0.2
>>>
>>>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH 03/12] ARM: Prepare translation for AArch64 code
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 03/12] ARM: Prepare translation for AArch64 code Alexander Graf
  2013-03-06  7:11   ` Laurent Desnogues
@ 2013-03-08  2:27   ` Peter Maydell
  1 sibling, 0 replies; 22+ messages in thread
From: Peter Maydell @ 2013-03-08  2:27 UTC (permalink / raw)
  To: Alexander Graf; +Cc: Riku Voipio, qemu-devel qemu-devel

On 6 March 2013 10:01, Alexander Graf <agraf@suse.de> wrote:
> @@ -699,25 +740,31 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
>  static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
>                                          target_ulong *cs_base, int *flags)
>  {
> -    int privmode;
> -    *pc = env->regs[15];
> -    *cs_base = 0;
> -    *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
> -        | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
> -        | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
> -        | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
> -        | (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT);
> -    if (arm_feature(env, ARM_FEATURE_M)) {
> -        privmode = !((env->v7m.exception == 0) && (env->v7m.control & 1));
> +    if (is_a64(env)) {
> +        *pc = env->pc;
> +        *flags = 0;
>      } else {

This isn't going to work for system emulation mode. We need a bit in the
tb->flags which is "CPU is in AArch64 state". I think most of the existing
TB flag bits will end up zero when in AArch64, but for simplicity I
think we should just define that the flag word layout is the same in
both cases.

> -        privmode = (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR;
> -    }
> -    if (privmode) {
> -        *flags |= ARM_TBFLAG_PRIV_MASK;
> -    }
> -    if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
> -        *flags |= ARM_TBFLAG_VFPEN_MASK;
> +        int privmode;
> +        *pc = env->regs[15];
> +        *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
> +            | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
> +            | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
> +            | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
> +            | (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT);
> +        if (arm_feature(env, ARM_FEATURE_M)) {
> +            privmode = !((env->v7m.exception == 0) && (env->v7m.control & 1));
> +        } else {
> +            privmode = (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR;
> +        }
> +        if (privmode) {
> +            *flags |= ARM_TBFLAG_PRIV_MASK;
> +        }
> +        if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
> +            *flags |= ARM_TBFLAG_VFPEN_MASK;
> +        }
>      }
> +
> +    *cs_base = 0;
>  }
>
>  static inline bool cpu_has_work(CPUState *cpu)
> @@ -732,11 +779,15 @@ static inline bool cpu_has_work(CPUState *cpu)
>
>  static inline void cpu_pc_from_tb(CPUARMState *env, TranslationBlock *tb)
>  {
> -    env->regs[15] = tb->pc;
> +    if (is_a64(env)) {
> +        env->pc = tb->pc;
> +    } else {
> +        env->regs[15] = tb->pc;
> +    }

This should be based on the "is AArch64" tb->flags bit rather than the env
field I guess. (Though I think it is not going to be possible to get here
with tb->flags and is_a64(env) giving different answers.)

>  }
>
>  /* Load an instruction and return it in the standard little-endian order */
> -static inline uint32_t arm_ldl_code(CPUARMState *env, uint32_t addr,
> +static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
>                                      bool do_swap)
>  {
>      uint32_t insn = cpu_ldl_code(env, addr);
> @@ -747,7 +798,7 @@ static inline uint32_t arm_ldl_code(CPUARMState *env, uint32_t addr,
>  }
>
>  /* Ditto, for a halfword (Thumb) instruction */
> -static inline uint16_t arm_lduw_code(CPUARMState *env, uint32_t addr,
> +static inline uint16_t arm_lduw_code(CPUARMState *env, target_ulong addr,
>                                       bool do_swap)
>  {
>      uint16_t insn = cpu_lduw_code(env, addr);
> diff --git a/target-arm/translate.c b/target-arm/translate.c
> index f8838f3..de04a0c 100644
> --- a/target-arm/translate.c
> +++ b/target-arm/translate.c
> @@ -9749,7 +9749,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
>      uint16_t *gen_opc_end;
>      int j, lj;
>      target_ulong pc_start;
> -    uint32_t next_page_start;
> +    target_ulong next_page_start;
>      int num_insns;
>      int max_insns;
>
> @@ -9833,24 +9833,26 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
>          store_cpu_field(tmp, condexec_bits);
>        }
>      do {
> +        if (!is_a64(env)) {

Since we can only flip between AArch64 and AArch32 at exception boundaries
I think that the right place to do the 'if is_a64() { translate_a64_stuff() }'
check is outside the 'for each insn in the block' loop, not inside it.
At that point this code path is only executed for AArch32 and you don't need
this check.

>  #ifdef CONFIG_USER_ONLY
> -        /* Intercept jump to the magic kernel page.  */
> -        if (dc->pc >= 0xffff0000) {
> -            /* We always get here via a jump, so know we are not in a
> -               conditional execution block.  */
> -            gen_exception(EXCP_KERNEL_TRAP);
> -            dc->is_jmp = DISAS_UPDATE;
> -            break;
> -        }
> +            /* Intercept jump to the magic kernel page.  */
> +            if (dc->pc >= 0xffff0000) {
> +                /* We always get here via a jump, so know we are not in a
> +                   conditional execution block.  */
> +                gen_exception(EXCP_KERNEL_TRAP);
> +                dc->is_jmp = DISAS_UPDATE;
> +                break;
> +            }
>  #else
> -        if (dc->pc >= 0xfffffff0 && IS_M(env)) {
> -            /* We always get here via a jump, so know we are not in a
> -               conditional execution block.  */
> -            gen_exception(EXCP_EXCEPTION_EXIT);
> -            dc->is_jmp = DISAS_UPDATE;
> -            break;
> -        }
> +            if (dc->pc >= 0xfffffff0 && IS_M(env)) {
> +                /* We always get here via a jump, so know we are not in a
> +                   conditional execution block.  */
> +                gen_exception(EXCP_EXCEPTION_EXIT);
> +                dc->is_jmp = DISAS_UPDATE;
> +                break;
> +            }
>  #endif
> +        }
>
>          if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
>              QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> @@ -9904,7 +9906,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
>          }
>
>          if (tcg_check_temp_count()) {
> -            fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc);
> +            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n", dc->pc);
>          }
>
>          /* Translation stops when a conditional branch is encountered.
> @@ -10074,6 +10076,10 @@ void cpu_dump_state(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf,
>
>  void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
>  {
> -    env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
> +    if (is_a64(env)) {
> +        env->pc = tcg_ctx.gen_opc_pc[pc_pos];
> +    } else {
> +        env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
> +    }
>      env->condexec_bits = gen_opc_condexec_bits[pc_pos];
>  }
> --
> 1.6.0.2
>

-- PMM

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH 04/12] ARM: Add AArch64 translation stub
  2013-03-06  2:01 ` [Qemu-devel] [PATCH 04/12] ARM: Add AArch64 translation stub Alexander Graf
  2013-03-06  7:06   ` Laurent Desnogues
@ 2013-03-08  2:31   ` Peter Maydell
  1 sibling, 0 replies; 22+ messages in thread
From: Peter Maydell @ 2013-03-08  2:31 UTC (permalink / raw)
  To: Alexander Graf; +Cc: Riku Voipio, qemu-devel qemu-devel

On 6 March 2013 10:01, Alexander Graf <agraf@suse.de> wrote:
> We should translate AArch64 mode separately from AArch32 mode. In AArch64 mode,
> registers look vastly different, instruction encoding is completely different,
> basically the system turns into a different machine.
>
> So let's do a simple if() in translate.c to decide whether we can handle the
> current code in the legacy AArch32 code or in the new AArch64 code.

> @@ -9944,6 +9948,9 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
>              gen_set_label(dc->condlabel);
>          }
>          if (dc->condjmp || !dc->is_jmp) {
> +            if (is_a64(env)) {
> +                gen_a64_set_pc_im(dc->pc);
> +            }
>              gen_set_pc_im(dc->pc);
>              dc->condjmp = 0;
>          }
> @@ -9967,6 +9974,9 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
>          gen_set_condexec(dc);
>          switch(dc->is_jmp) {
>          case DISAS_NEXT:
> +            if (is_a64(env)) {
> +                gen_a64_set_pc_im(dc->pc);
> +            }


As I said in a comment on another patch, I think these "if (is_a64())" checks
should be pulled out to a higher level than you have them. We should say
"if this TB is for a64 mode then call a function in translate-a64.c which
handles the entire TB translation". I think that will be easier to understand
(for instance all the stuff in the current arm/thumb top level loop for
handling conditional execution is entirely irrelevant for a64 and
just confusing).

thanks
-- PMM

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2013-03-08  2:31 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-06  2:01 [Qemu-devel] [PATCH 00/12] AArch64 preparation patch set Alexander Graf
2013-03-06  2:01 ` [Qemu-devel] [PATCH 01/12] ARM: Extract the disas struct to a header file Alexander Graf
2013-03-06  2:01 ` [Qemu-devel] [PATCH 02/12] ARM: Export cpu_env Alexander Graf
2013-03-06  2:01 ` [Qemu-devel] [PATCH 03/12] ARM: Prepare translation for AArch64 code Alexander Graf
2013-03-06  7:11   ` Laurent Desnogues
2013-03-06  9:36     ` Alexander Graf
2013-03-06  9:46       ` Laurent Desnogues
2013-03-08  2:27   ` Peter Maydell
2013-03-06  2:01 ` [Qemu-devel] [PATCH 04/12] ARM: Add AArch64 translation stub Alexander Graf
2013-03-06  7:06   ` Laurent Desnogues
2013-03-08  2:31   ` Peter Maydell
2013-03-06  2:01 ` [Qemu-devel] [PATCH 05/12] AArch64: Add gdb stub Alexander Graf
2013-03-06  2:01 ` [Qemu-devel] [PATCH 06/12] linux-user: Don't treat aarch64 cpu names specially Alexander Graf
2013-03-06  2:01 ` [Qemu-devel] [PATCH 07/12] linux-user: AArch64 requires at least 3.8.0 Alexander Graf
2013-03-06  7:04   ` Riku Voipio
2013-03-06  2:01 ` [Qemu-devel] [PATCH 08/12] linux-user: Add syscall handling for AArch64 Alexander Graf
2013-03-06  2:01 ` [Qemu-devel] [PATCH 09/12] linux-user: Fix up AArch64 syscall handlers Alexander Graf
2013-03-06  2:01 ` [Qemu-devel] [PATCH 10/12] linux-user: Add signal handling for AArch64 Alexander Graf
2013-03-06  2:01 ` [Qemu-devel] [PATCH 11/12] linux-user: Add AArch64 support Alexander Graf
2013-03-06  2:01 ` [Qemu-devel] [PATCH 12/12] ARM: Add arm64 target to configure Alexander Graf
2013-03-06  3:58   ` Peter Maydell
2013-03-06  7:01   ` Peter Maydell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).