From patchwork Mon Jul 1 17:35:05 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 18222 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-gh0-f200.google.com (mail-gh0-f200.google.com [209.85.160.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id E259F2774B for ; Mon, 1 Jul 2013 17:35:42 +0000 (UTC) Received: by mail-gh0-f200.google.com with SMTP id 10sf6326497ghy.7 for ; Mon, 01 Jul 2013 10:35:42 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:x-beenthere:x-forwarded-to:x-forwarded-for :delivered-to:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references:x-gm-message-state:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-google-group-id:list-post:list-help:list-archive:list-unsubscribe; bh=Yq/t0lEDPWgQJ0+TYlQStmeu+2XAyEOu75McZWmm/2k=; b=VQgh2Gvg9zfCOtMH7Vf9xCjfrzlAo1Bh9JkGVjCVaurdfHhT8b2oGwgpVQ8IjvpL3O b6n5xiwkXyWGdODf5VHw/M9p0Fm5o8iN/Qr25MPk9o2RPlbRrZQWrUlpdM1tqBpJj596 lOd1ynhgcGCksn19IF8YTeyiPd4RMl2R/8H21e7xqi2ZrT5ppzYLOjb5x6nMnKdamE0T KCzK73LHVc59XtXHRAPYMk4Jfk4vMRjfVj7uA7l/ghBKDhwgRo2fxKEbSXEfJW1CIQox LKg3YvXFqz7xQXEHGnkuuIRnGhJFj6S2IMW5pzJYKEglJV7Yhvinsl1l7VdwKATDUmUF /cnQ== X-Received: by 10.236.91.4 with SMTP id g4mr15331960yhf.30.1372700142619; Mon, 01 Jul 2013 10:35:42 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.27.66 with SMTP id r2ls2314722qeg.24.gmail; Mon, 01 Jul 2013 10:35:42 -0700 (PDT) X-Received: by 10.58.24.201 with SMTP id w9mr10095066vef.82.1372700142504; Mon, 01 Jul 2013 10:35:42 -0700 (PDT) Received: from mail-vb0-f49.google.com (mail-vb0-f49.google.com [209.85.212.49]) by mx.google.com with ESMTPS id s9si4996101vcm.22.2013.07.01.10.35.42 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 01 Jul 2013 10:35:42 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.212.49 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.212.49; Received: by mail-vb0-f49.google.com with SMTP id 12so3785917vbf.22 for ; Mon, 01 Jul 2013 10:35:42 -0700 (PDT) X-Received: by 10.220.83.69 with SMTP id e5mr7365869vcl.53.1372700142395; Mon, 01 Jul 2013 10:35:42 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.58.165.8 with SMTP id yu8csp289819veb; Mon, 1 Jul 2013 10:35:41 -0700 (PDT) X-Received: by 10.194.78.110 with SMTP id a14mr20799737wjx.84.1372700133617; Mon, 01 Jul 2013 10:35:33 -0700 (PDT) Received: from mnementh.archaic.org.uk (1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.1.0.0.b.8.0.1.0.0.2.ip6.arpa. [2001:8b0:1d0::1]) by mx.google.com with ESMTPS id kt2si6822065wjb.117.2013.07.01.10.35.32 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Mon, 01 Jul 2013 10:35:33 -0700 (PDT) Received-SPF: neutral (google.com: 2001:8b0:1d0::1 is neither permitted nor denied by best guess record for domain of pm215@archaic.org.uk) client-ip=2001:8b0:1d0::1; Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1Uti0X-0002KL-Ln; Mon, 01 Jul 2013 18:35:21 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, Alexander Graf , Andreas Schwab , "Mian M. Hamayun" Subject: [PATCH v5 06/21] target-arm: Prepare translation for AArch64 code Date: Mon, 1 Jul 2013 18:35:05 +0100 Message-Id: <1372700120-8896-7-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1372700120-8896-1-git-send-email-peter.maydell@linaro.org> References: <1372700120-8896-1-git-send-email-peter.maydell@linaro.org> X-Gm-Message-State: ALoCoQk1cHPAJ6zbU/VXn/l+5HlK6TEfsyk7DuMuIWWZoIkJzpn3Orx53IRZOelUFekWMJ+/KTJm X-Original-Sender: peter.maydell@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.212.49 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: Alexander Graf 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 translation buffer flag indicate an ARMv8 cpu running in aarch64 mode vs aarch32 mode. Signed-off-by: Alexander Graf Signed-off-by: John Rigby Message-id: 1368505980-17151-4-git-send-email-john.rigby@linaro.org [PMM: * rearranged tbflags so AArch64? is bit 31 and if it is set then 30..0 are freely available for whatever makes most sense for that mode * added version bump since we change VFP migration state * added a comment about how VFP/Neon register state works * physical address space is 48 bits, not 64 * added ARM_FEATURE_AARCH64 flag to identify 64-bit capable CPUs ] Signed-off-by: Peter Maydell --- target-arm/cpu.c | 8 +++ target-arm/cpu.h | 131 ++++++++++++++++++++++++++++++++++++++---------- target-arm/machine.c | 8 +-- target-arm/translate.c | 38 ++++++++++---- target-arm/translate.h | 1 + 5 files changed, 147 insertions(+), 39 deletions(-) diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 1bc227e..0a8c8df 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -80,6 +80,11 @@ static void arm_cpu_reset(CPUState *s) env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q'; } + if (arm_feature(env, ARM_FEATURE_AARCH64)) { + /* 64 bit CPUs always start in 64 bit mode */ + env->aarch64 = 1; + } + #if defined(CONFIG_USER_ONLY) env->uncached_cpsr = ARM_CPU_MODE_USR; /* For user mode we must enable access to coprocessors */ @@ -756,6 +761,9 @@ static void arm_any_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_THUMB2EE); set_feature(&cpu->env, ARM_FEATURE_ARM_DIV); set_feature(&cpu->env, ARM_FEATURE_V7MP); +#ifdef TARGET_AARCH64 + set_feature(&cpu->env, ARM_FEATURE_AARCH64); +#endif cpu->midr = 0xffffffff; } diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 1f3beac..78614a4 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,20 @@ struct arm_boot_info; typedef struct CPUARMState { /* Regs for current mode. */ uint32_t regs[16]; + + /* 32/64 switch only happens when taking and returning from + * exceptions so the overlap semantics are taken care of then + * instead of having a complicated union. + */ + /* Regs for A64 mode. */ + uint64_t xregs[32]; + uint64_t pc; + /* TODO: pstate doesn't correspond to an architectural register; + * it would be better modelled as the underlying fields. + */ + uint32_t pstate; + uint32_t aarch64; /* 1 if CPU is in aarch64 state; inverse of PSTATE.nRW */ + /* 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 +174,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 +195,22 @@ typedef struct CPUARMState { /* VFP coprocessor state. */ struct { - float64 regs[32]; + /* VFP/Neon register state. Note that the mapping between S, D and Q + * views of the register bank differs between AArch64 and AArch32: + * In AArch32: + * Qn = regs[2n+1]:regs[2n] + * Dn = regs[n] + * Sn = regs[n/2] bits 31..0 for even n, and bits 63..32 for odd n + * (and regs[32] to regs[63] are inaccessible) + * In AArch64: + * Qn = regs[2n+1]:regs[2n] + * Dn = regs[2n] + * Sn = regs[2n] bits 31..0 + * This corresponds to the architecturally defined mapping between + * the two execution states, and means we do not need to explicitly + * map these registers when changing states. + */ + float64 regs[64]; uint32_t xregs[16]; /* We store these fpcsr fields separately for convenience. */ @@ -240,6 +280,20 @@ int bank_number(int mode); void switch_mode(CPUARMState *, int); uint32_t do_arm_semihosting(CPUARMState *env); +static inline bool is_a64(CPUARMState *env) +{ + return env->aarch64; +} + +#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. */ @@ -392,6 +446,7 @@ enum arm_features { ARM_FEATURE_MPIDR, /* has cp15 MPIDR */ ARM_FEATURE_PXN, /* has Privileged Execute Never bit */ ARM_FEATURE_LPAE, /* has Large Physical Address Extension */ + ARM_FEATURE_AARCH64, /* supports 64 bit mode */ }; static inline int arm_feature(CPUARMState *env, int feature) @@ -708,8 +763,13 @@ bool write_cpustate_to_list(ARMCPU *cpu); #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 48 +# 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) { @@ -745,7 +805,13 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp) #include "exec/cpu-all.h" -/* Bit usage in the TB flags field: */ +/* Bit usage in the TB flags field: bit 31 indicates whether we are + * in 32 or 64 bit mode. The meaning of the other bits depends on that. + */ +#define ARM_TBFLAG_AARCH64_STATE_SHIFT 31 +#define ARM_TBFLAG_AARCH64_STATE_MASK (1U << ARM_TBFLAG_AARCH64_STATE_SHIFT) + +/* Bit usage when in AArch32 state: */ #define ARM_TBFLAG_THUMB_SHIFT 0 #define ARM_TBFLAG_THUMB_MASK (1 << ARM_TBFLAG_THUMB_SHIFT) #define ARM_TBFLAG_VECLEN_SHIFT 1 @@ -760,9 +826,12 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp) #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. */ + +/* Bit usage when in AArch64 state: currently no bits defined */ /* some convenience accessor macros */ +#define ARM_TBFLAG_AARCH64_STATE(F) \ + (((F) & ARM_TBFLAG_AARCH64_STATE_MASK) >> ARM_TBFLAG_AARCH64_STATE_SHIFT) #define ARM_TBFLAG_THUMB(F) \ (((F) & ARM_TBFLAG_THUMB_MASK) >> ARM_TBFLAG_THUMB_SHIFT) #define ARM_TBFLAG_VECLEN(F) \ @@ -781,25 +850,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 = ARM_TBFLAG_AARCH64_STATE_MASK; } 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) @@ -812,7 +887,11 @@ 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 */ diff --git a/target-arm/machine.c b/target-arm/machine.c index 6d4c2d4..722516f 100644 --- a/target-arm/machine.c +++ b/target-arm/machine.c @@ -37,11 +37,11 @@ static const VMStateInfo vmstate_fpscr = { static const VMStateDescription vmstate_vfp = { .name = "cpu/vfp", - .version_id = 2, - .minimum_version_id = 2, - .minimum_version_id_old = 2, + .version_id = 3, + .minimum_version_id = 3, + .minimum_version_id_old = 3, .fields = (VMStateField[]) { - VMSTATE_FLOAT64_ARRAY(env.vfp.regs, ARMCPU, 32), + VMSTATE_FLOAT64_ARRAY(env.vfp.regs, ARMCPU, 64), /* The xregs array is a little awkward because element 1 (FPSCR) * requires a specific accessor, so we have to split it up in * the vmstate: diff --git a/target-arm/translate.c b/target-arm/translate.c index c87a1f8..2935cea 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -9884,16 +9884,32 @@ static inline void gen_intermediate_code_internal(CPUARMState *env, dc->pc = pc_start; dc->singlestep_enabled = env->singlestep_enabled; dc->condjmp = 0; - dc->thumb = ARM_TBFLAG_THUMB(tb->flags); - dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags); - dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1; - dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4; + + if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) { + dc->aarch64 = 1; + dc->thumb = 0; + dc->bswap_code = 0; + dc->condexec_mask = 0; + dc->condexec_cond = 0; +#if !defined(CONFIG_USER_ONLY) + dc->user = 0; +#endif + dc->vfp_enabled = 0; + dc->vec_len = 0; + dc->vec_stride = 0; + } else { + dc->aarch64 = 0; + dc->thumb = ARM_TBFLAG_THUMB(tb->flags); + dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags); + dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1; + dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4; #if !defined(CONFIG_USER_ONLY) - dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0); + dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0); #endif - dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags); - dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags); - dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags); + dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags); + dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags); + dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags); + } cpu_F0s = tcg_temp_new_i32(); cpu_F1s = tcg_temp_new_i32(); cpu_F0d = tcg_temp_new_i64(); @@ -10196,6 +10212,10 @@ void arm_cpu_dump_state(CPUState *cs, 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]; } diff --git a/target-arm/translate.h b/target-arm/translate.h index 8ba1433..5be2eed 100644 --- a/target-arm/translate.h +++ b/target-arm/translate.h @@ -22,6 +22,7 @@ typedef struct DisasContext { int vfp_enabled; int vec_len; int vec_stride; + int aarch64; } DisasContext; extern TCGv_ptr cpu_env;