[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v2 02/12] ARM: Prepare translation for AArch64 c
From: |
Alexander Graf |
Subject: |
Re: [Qemu-devel] [PATCH v2 02/12] ARM: Prepare translation for AArch64 code |
Date: |
Tue, 30 Apr 2013 11:36:18 +0200 |
On 30.04.2013, at 08:36, John Rigby wrote:
> From: Alexander Graf <address@hidden>
>
> 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.
>
> Add new ARM_TBFLAG_AARCH64_STATE flag that indicates an ARMv8 cpu
> running in aarch64 mode vs aarch32 mode.
>
> Signed-off-by: Alexander Graf <address@hidden>
> Signed-off-by: John Rigby <address@hidden>
> ---
> Changes in v2:
> - remove many uses of is_a64 as that is a indicator the target arch is
> aarch64 not what mode it is running in.
It indicates what mode the CPU is running on. The only reason it was defined
statically so far, was that linux-user was the only target I implemented. And
that one can't switch during runtime.
Alex
> - add ARM_TBFLAG_AARCH64_STATE and aarch64_state
>
> include/elf.h | 2 +
> target-arm/cpu.h | 138 ++++++++++++++++++++++++++++++++++--------------
> target-arm/translate.c | 14 +++--
> 3 files changed, 108 insertions(+), 46 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 5438444..3a79dfa 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_AARCH64)
> + /* 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,14 @@ struct arm_boot_info;
> typedef struct CPUARMState {
> /* Regs for current mode. */
> uint32_t regs[16];
> +
> + /* Regs for A64 mode. */
> + uint64_t xregs[31];
> + uint64_t pc;
> + uint64_t sp;
> + uint32_t pstate;
> + uint32_t aarch64_state; /* 1 if CPU is in aarch64 state */
> +
> /* 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 +168,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 +189,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. */
> @@ -240,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_AARCH64
> + 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. */
> @@ -623,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_AARCH64)
> +# 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)
> {
> @@ -661,21 +703,23 @@ static inline void cpu_clone_regs(CPUARMState *env,
> target_ulong newsp)
> #include "exec/cpu-all.h"
>
> /* Bit usage in the TB flags field: */
> -#define ARM_TBFLAG_THUMB_SHIFT 0
> -#define ARM_TBFLAG_THUMB_MASK (1 << ARM_TBFLAG_THUMB_SHIFT)
> -#define ARM_TBFLAG_VECLEN_SHIFT 1
> -#define ARM_TBFLAG_VECLEN_MASK (0x7 << ARM_TBFLAG_VECLEN_SHIFT)
> -#define ARM_TBFLAG_VECSTRIDE_SHIFT 4
> -#define ARM_TBFLAG_VECSTRIDE_MASK (0x3 << ARM_TBFLAG_VECSTRIDE_SHIFT)
> -#define ARM_TBFLAG_PRIV_SHIFT 6
> -#define ARM_TBFLAG_PRIV_MASK (1 << ARM_TBFLAG_PRIV_SHIFT)
> -#define ARM_TBFLAG_VFPEN_SHIFT 7
> -#define ARM_TBFLAG_VFPEN_MASK (1 << ARM_TBFLAG_VFPEN_SHIFT)
> -#define ARM_TBFLAG_CONDEXEC_SHIFT 8
> -#define ARM_TBFLAG_CONDEXEC_MASK (0xff << ARM_TBFLAG_CONDEXEC_SHIFT)
> -#define ARM_TBFLAG_BSWAP_CODE_SHIFT 16
> -#define ARM_TBFLAG_BSWAP_CODE_MASK (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT)
> -/* Bits 31..17 are currently unused. */
> +#define ARM_TBFLAG_THUMB_SHIFT 0
> +#define ARM_TBFLAG_THUMB_MASK (1 << ARM_TBFLAG_THUMB_SHIFT)
> +#define ARM_TBFLAG_VECLEN_SHIFT 1
> +#define ARM_TBFLAG_VECLEN_MASK (0x7 << ARM_TBFLAG_VECLEN_SHIFT)
> +#define ARM_TBFLAG_VECSTRIDE_SHIFT 4
> +#define ARM_TBFLAG_VECSTRIDE_MASK (0x3 << ARM_TBFLAG_VECSTRIDE_SHIFT)
> +#define ARM_TBFLAG_PRIV_SHIFT 6
> +#define ARM_TBFLAG_PRIV_MASK (1 << ARM_TBFLAG_PRIV_SHIFT)
> +#define ARM_TBFLAG_VFPEN_SHIFT 7
> +#define ARM_TBFLAG_VFPEN_MASK (1 << ARM_TBFLAG_VFPEN_SHIFT)
> +#define ARM_TBFLAG_CONDEXEC_SHIFT 8
> +#define ARM_TBFLAG_CONDEXEC_MASK (0xff << ARM_TBFLAG_CONDEXEC_SHIFT)
> +#define ARM_TBFLAG_BSWAP_CODE_SHIFT 16
> +#define ARM_TBFLAG_BSWAP_CODE_MASK (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT)
> +#define ARM_TBFLAG_AARCH64_STATE_SHIFT 17
> +#define ARM_TBFLAG_AARCH64_STATE_MASK (1 << ARM_TBFLAG_AARCH64_STATE_SHIFT)
> +/* Bits 31..18 are currently unused. */
>
> /* some convenience accessor macros */
> #define ARM_TBFLAG_THUMB(F) \
> @@ -692,29 +736,37 @@ static inline void cpu_clone_regs(CPUARMState *env,
> target_ulong newsp)
> (((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
> #define ARM_TBFLAG_BSWAP_CODE(F) \
> (((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT)
> +#define ARM_TBFLAG_AARCH64_STATE(F) \
> + (((F) & ARM_TBFLAG_AARCH64_STATE_MASK) >> ARM_TBFLAG_AARCH64_STATE_SHIFT)
>
> 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 = env->aarch64_state << ARM_TBFLAG_AARCH64_STATE_SHIFT;
> } 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)
> @@ -727,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 (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
> + 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);
> @@ -742,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 36537bd..a4b6d8a 100644
> --- a/target-arm/translate.c
> +++ b/target-arm/translate.c
> @@ -9750,7 +9750,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;
>
> @@ -9838,7 +9838,7 @@ static inline void
> gen_intermediate_code_internal(CPUARMState *env,
> /* 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. */
> + conditional execution block. */
> gen_exception(EXCP_KERNEL_TRAP);
> dc->is_jmp = DISAS_UPDATE;
> break;
> @@ -9846,7 +9846,7 @@ static inline void
> gen_intermediate_code_internal(CPUARMState *env,
> #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. */
> + conditional execution block. */
> gen_exception(EXCP_EXCEPTION_EXIT);
> dc->is_jmp = DISAS_UPDATE;
> break;
> @@ -9905,7 +9905,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.
> @@ -10075,6 +10075,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.7.9.5
>