diff options
-rw-r--r-- | linux-user/aarch64/target_cpu.h | 5 | ||||
-rw-r--r-- | linux-user/arm/target_cpu.h | 2 | ||||
-rw-r--r-- | linux-user/main.c | 2 | ||||
-rw-r--r-- | target-arm/cpu.h | 18 | ||||
-rw-r--r-- | target-arm/helper.c | 22 |
5 files changed, 36 insertions, 13 deletions
diff --git a/linux-user/aarch64/target_cpu.h b/linux-user/aarch64/target_cpu.h index 6f5539b50f..21560ef832 100644 --- a/linux-user/aarch64/target_cpu.h +++ b/linux-user/aarch64/target_cpu.h @@ -29,7 +29,10 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp) static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls) { - env->sr.tpidr_el0 = newtls; + /* Note that AArch64 Linux keeps the TLS pointer in TPIDR; this is + * different from AArch32 Linux, which uses TPIDRRO. + */ + env->cp15.tpidr_el0 = newtls; } #endif diff --git a/linux-user/arm/target_cpu.h b/linux-user/arm/target_cpu.h index ed323c079d..39d65b692b 100644 --- a/linux-user/arm/target_cpu.h +++ b/linux-user/arm/target_cpu.h @@ -29,7 +29,7 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp) static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls) { - env->cp15.c13_tls2 = newtls; + env->cp15.tpidrro_el0 = newtls; } #endif diff --git a/linux-user/main.c b/linux-user/main.c index 54f71fe8f6..c0df8b5cd4 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -566,7 +566,7 @@ do_kernel_trap(CPUARMState *env) end_exclusive(); break; case 0xffff0fe0: /* __kernel_get_tls */ - env->regs[0] = env->cp15.c13_tls2; + env->regs[0] = env->cp15.tpidrro_el0; break; case 0xffff0f60: /* __kernel_cmpxchg64 */ arm_kernel_cmpxchg64_helper(env); diff --git a/target-arm/cpu.h b/target-arm/cpu.h index ab8ef17862..983aa31bef 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -66,6 +66,18 @@ /* ARM-specific interrupt pending bits. */ #define CPU_INTERRUPT_FIQ CPU_INTERRUPT_TGT_EXT_1 +/* The usual mapping for an AArch64 system register to its AArch32 + * counterpart is for the 32 bit world to have access to the lower + * half only (with writes leaving the upper half untouched). It's + * therefore useful to be able to pass TCG the offset of the least + * significant half of a uint64_t struct member. + */ +#ifdef HOST_WORDS_BIGENDIAN +#define offsetoflow32(S, M) offsetof(S, M + sizeof(uint32_t)) +#else +#define offsetoflow32(S, M) offsetof(S, M) +#endif + /* Meanings of the ARMCPU object's two inbound GPIO lines */ #define ARM_CPU_IRQ 0 #define ARM_CPU_FIQ 1 @@ -188,9 +200,9 @@ typedef struct CPUARMState { uint32_t c12_vbar; /* vector base address register */ uint32_t c13_fcse; /* FCSE PID. */ uint32_t c13_context; /* Context ID. */ - uint32_t c13_tls1; /* User RW Thread register. */ - uint32_t c13_tls2; /* User RO Thread register. */ - uint32_t c13_tls3; /* Privileged Thread register. */ + uint64_t tpidr_el0; /* User RW Thread register. */ + uint64_t tpidrro_el0; /* User RO Thread register. */ + uint64_t tpidr_el1; /* Privileged Thread register. */ uint32_t c14_cntfrq; /* Counter Frequency register */ uint32_t c14_cntkctl; /* Timer Control register */ ARMGenericTimer c14_timer[NUM_GTIMERS]; diff --git a/target-arm/helper.c b/target-arm/helper.c index 3efe8b4302..f91e3fd35d 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -740,18 +740,26 @@ static const ARMCPRegInfo t2ee_cp_reginfo[] = { }; static const ARMCPRegInfo v6k_cp_reginfo[] = { + { .name = "TPIDR_EL0", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 3, .opc2 = 2, .crn = 13, .crm = 0, + .access = PL0_RW, + .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el0), .resetvalue = 0 }, { .name = "TPIDRURW", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 2, .access = PL0_RW, - .fieldoffset = offsetof(CPUARMState, cp15.c13_tls1), - .resetvalue = 0 }, + .fieldoffset = offsetoflow32(CPUARMState, cp15.tpidr_el0), + .resetfn = arm_cp_reset_ignore }, + { .name = "TPIDRRO_EL0", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 3, .opc2 = 3, .crn = 13, .crm = 0, + .access = PL0_R|PL1_W, + .fieldoffset = offsetof(CPUARMState, cp15.tpidrro_el0), .resetvalue = 0 }, { .name = "TPIDRURO", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 3, .access = PL0_R|PL1_W, - .fieldoffset = offsetof(CPUARMState, cp15.c13_tls2), - .resetvalue = 0 }, - { .name = "TPIDRPRW", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 4, + .fieldoffset = offsetoflow32(CPUARMState, cp15.tpidrro_el0), + .resetfn = arm_cp_reset_ignore }, + { .name = "TPIDR_EL1", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .opc2 = 4, .crn = 13, .crm = 0, .access = PL1_RW, - .fieldoffset = offsetof(CPUARMState, cp15.c13_tls3), - .resetvalue = 0 }, + .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el1), .resetvalue = 0 }, REGINFO_SENTINEL }; |