[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 03/12] ARM: Prepare translation for AArch64 code
From: |
Laurent Desnogues |
Subject: |
Re: [Qemu-devel] [PATCH 03/12] ARM: Prepare translation for AArch64 code |
Date: |
Wed, 6 Mar 2013 10:46:26 +0100 |
On Wed, Mar 6, 2013 at 10:36 AM, Alexander Graf <address@hidden> wrote:
>
>
> Am 06.03.2013 um 08:11 schrieb Laurent Desnogues <address@hidden>:
>
>> On Wed, Mar 6, 2013 at 3:01 AM, Alexander Graf <address@hidden> 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 <address@hidden>
>>> ---
>>> 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
>>>
>>>
- [Qemu-devel] [PATCH 00/12] AArch64 preparation patch set, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 12/12] ARM: Add arm64 target to configure, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 02/12] ARM: Export cpu_env, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 09/12] linux-user: Fix up AArch64 syscall handlers, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 03/12] ARM: Prepare translation for AArch64 code, Alexander Graf, 2013/03/05
- Re: [Qemu-devel] [PATCH 03/12] ARM: Prepare translation for AArch64 code, Peter Maydell, 2013/03/07
- [Qemu-devel] [PATCH 05/12] AArch64: Add gdb stub, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 07/12] linux-user: AArch64 requires at least 3.8.0, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 11/12] linux-user: Add AArch64 support, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 01/12] ARM: Extract the disas struct to a header file, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 06/12] linux-user: Don't treat aarch64 cpu names specially, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 08/12] linux-user: Add syscall handling for AArch64, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 10/12] linux-user: Add signal handling for AArch64, Alexander Graf, 2013/03/05
- [Qemu-devel] [PATCH 04/12] ARM: Add AArch64 translation stub, Alexander Graf, 2013/03/05