From patchwork Tue May 14 04:32:51 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Rigby X-Patchwork-Id: 243592 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 2E5CC2C00B8 for ; Tue, 14 May 2013 14:34:17 +1000 (EST) Received: from localhost ([::1]:36283 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Uc6wJ-0007Qa-B1 for incoming@patchwork.ozlabs.org; Tue, 14 May 2013 00:34:15 -0400 Received: from eggs.gnu.org ([208.118.235.92]:58434) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Uc6vi-0007K6-LZ for qemu-devel@nongnu.org; Tue, 14 May 2013 00:33:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Uc6vf-0008ML-15 for qemu-devel@nongnu.org; Tue, 14 May 2013 00:33:38 -0400 Received: from mail-da0-x233.google.com ([2607:f8b0:400e:c00::233]:48529) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Uc6ve-0008MB-O2 for qemu-devel@nongnu.org; Tue, 14 May 2013 00:33:34 -0400 Received: by mail-da0-f51.google.com with SMTP id h15so60168dan.10 for ; Mon, 13 May 2013 21:33:34 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references:x-gm-message-state; bh=ocO+p++tXGmKXWMHURp8/Ep6L0HHMGvOiZHYCpmJLJQ=; b=OfK5XrMWg2hnoXkzFqMhBmp4GsxBfModtlyk3eRNPDYMIKKDzsSHpPkm2r/Nt+9rnU dbf1L1sYRV+VKVMHSwgTV/bngasrHNhjUh7doYmYROy+lTXFC+H2UDUXZn7rsgPnISES nh8vJZH6sLaUlBzEq3/kL80ooau8r+G0MF1leVsqZw8V+XYVMtc4EuMIwMAeT0LatSBv zf/6+pHSK/BlZn4uasvbW1dAlZFb71DrzMD+Ik+Zn9v4n0ifpeT7/B7Y+5fn5ABJBMrM UNh6JJyCN22g7hn1DgKH/vFGJLGDrX2n5iTV6dxXCZ2aVztOQRJHXQ0JWTAIQNAe4sPl ewDw== X-Received: by 10.66.21.10 with SMTP id r10mr8997802pae.183.1368506013888; Mon, 13 May 2013 21:33:33 -0700 (PDT) Received: from localhost.localdomain (c-76-23-54-220.hsd1.ut.comcast.net. [76.23.54.220]) by mx.google.com with ESMTPSA id yj2sm12841472pbb.40.2013.05.13.21.33.31 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 13 May 2013 21:33:32 -0700 (PDT) From: John Rigby To: qemu-devel@nongnu.org Date: Mon, 13 May 2013 22:32:51 -0600 Message-Id: <1368505980-17151-4-git-send-email-john.rigby@linaro.org> X-Mailer: git-send-email 1.8.2.2 In-Reply-To: <1368505980-17151-1-git-send-email-john.rigby@linaro.org> References: <1368505980-17151-1-git-send-email-john.rigby@linaro.org> X-Gm-Message-State: ALoCoQkGSdQKHid69L6xihn0YwJdkEAZY/z3wFCGWqQA3I918evz/CxKIqWTxO1O9P+pmDrVinmW X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:400e:c00::233 Cc: 'Peter Maydell , John Rigby , 'Alexander Graf , Paul Brook Subject: [Qemu-devel] [PATCH v4 03/12] ARM: Prepare translation for AArch64 code X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- Changes in v2: - remove many uses of is_a64 that are not needed since the 32/64 choice happens at a higher level - add ARM_TBFLAG_AARCH64_STATE and aarch64_state Changes in v3: - change xregs array len back to 32 as in v1 - sp field in CPUARMState has been removed xregs[31] is now sp - add comment explaining that 32 and 64 bit arch registers are separate with copy semantics handled and exception and return from exception time - changed arch64_state field in CPUARMState to plain arch64 - test arch64 in is_a64 - fix some checkpatch.pl errors include/elf.h | 2 + target-arm/cpu.h | 140 ++++++++++++++++++++++++++++++++++--------------- target-arm/machine.c | 2 +- target-arm/translate.c | 15 ++++-- 4 files changed, 112 insertions(+), 47 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..c486eb5 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,16 @@ 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 is taken care of then + * instead of having a complicated union. */ + /* Regs for A64 mode. */ + uint64_t xregs[32]; + uint64_t pc; + uint32_t pstate; + uint32_t aarch64; /* 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 +170,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 +191,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 +261,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 env->aarch64; +#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 +662,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 +705,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 +738,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 << 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 +781,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 +800,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/machine.c b/target-arm/machine.c index 4dd057c..1718368 100644 --- a/target-arm/machine.c +++ b/target-arm/machine.c @@ -39,7 +39,7 @@ static const VMStateDescription vmstate_vfp = { .minimum_version_id = 2, .minimum_version_id_old = 2, .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 36537bd..66d4892 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,8 @@ 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 +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]; }