提交 593cfa2b 编写于 作者: P Peter Maydell

target/arm: Hyp mode R14 is shared with User and System

Hyp mode is an exception to the general rule that each AArch32
mode has its own r13, r14 and SPSR -- it has a banked r13 and
SPSR but shares its r14 with User and System mode. We were
incorrectly implementing it as banked, which meant that on
entry to Hyp mode r14 was 0 rather than the USR/SYS r14.

We provide a new function r14_bank_number() which is like
the existing bank_number() but provides the index into
env->banked_r14[]; bank_number() provides the index to use
for env->banked_r13[] and env->banked_cpsr[].

All the points in the code that were using bank_number()
to index into env->banked_r14[] are updated for consintency:
 * switch_mode() -- this is the only place where we fix
   an actual bug
 * aarch64_sync_32_to_64() and aarch64_sync_64_to_32():
   no behavioural change as we already special-cased Hyp R14
 * kvm32.c: no behavioural change since the guest can't ever
   be in Hyp mode, but conceptually the right thing to do
 * msr_banked()/mrs_banked(): we can never get to the case
   that accesses banked_r14[] with tgtmode == ARM_CPU_MODE_HYP,
   so no behavioural change
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
Reviewed-by: NPhilippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: NEdgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: NAlex Bennée <alex.bennee@linaro.org>
Message-id: 20181109173553.22341-2-peter.maydell@linaro.org
上级 89430fc6
...@@ -6432,13 +6432,14 @@ static void switch_mode(CPUARMState *env, int mode) ...@@ -6432,13 +6432,14 @@ static void switch_mode(CPUARMState *env, int mode)
i = bank_number(old_mode); i = bank_number(old_mode);
env->banked_r13[i] = env->regs[13]; env->banked_r13[i] = env->regs[13];
env->banked_r14[i] = env->regs[14];
env->banked_spsr[i] = env->spsr; env->banked_spsr[i] = env->spsr;
i = bank_number(mode); i = bank_number(mode);
env->regs[13] = env->banked_r13[i]; env->regs[13] = env->banked_r13[i];
env->regs[14] = env->banked_r14[i];
env->spsr = env->banked_spsr[i]; env->spsr = env->banked_spsr[i];
env->banked_r14[r14_bank_number(old_mode)] = env->regs[14];
env->regs[14] = env->banked_r14[r14_bank_number(mode)];
} }
/* Physical Interrupt Target EL Lookup Table /* Physical Interrupt Target EL Lookup Table
...@@ -8017,7 +8018,7 @@ void aarch64_sync_32_to_64(CPUARMState *env) ...@@ -8017,7 +8018,7 @@ void aarch64_sync_32_to_64(CPUARMState *env)
if (mode == ARM_CPU_MODE_HYP) { if (mode == ARM_CPU_MODE_HYP) {
env->xregs[14] = env->regs[14]; env->xregs[14] = env->regs[14];
} else { } else {
env->xregs[14] = env->banked_r14[bank_number(ARM_CPU_MODE_USR)]; env->xregs[14] = env->banked_r14[r14_bank_number(ARM_CPU_MODE_USR)];
} }
} }
...@@ -8031,7 +8032,7 @@ void aarch64_sync_32_to_64(CPUARMState *env) ...@@ -8031,7 +8032,7 @@ void aarch64_sync_32_to_64(CPUARMState *env)
env->xregs[16] = env->regs[14]; env->xregs[16] = env->regs[14];
env->xregs[17] = env->regs[13]; env->xregs[17] = env->regs[13];
} else { } else {
env->xregs[16] = env->banked_r14[bank_number(ARM_CPU_MODE_IRQ)]; env->xregs[16] = env->banked_r14[r14_bank_number(ARM_CPU_MODE_IRQ)];
env->xregs[17] = env->banked_r13[bank_number(ARM_CPU_MODE_IRQ)]; env->xregs[17] = env->banked_r13[bank_number(ARM_CPU_MODE_IRQ)];
} }
...@@ -8039,7 +8040,7 @@ void aarch64_sync_32_to_64(CPUARMState *env) ...@@ -8039,7 +8040,7 @@ void aarch64_sync_32_to_64(CPUARMState *env)
env->xregs[18] = env->regs[14]; env->xregs[18] = env->regs[14];
env->xregs[19] = env->regs[13]; env->xregs[19] = env->regs[13];
} else { } else {
env->xregs[18] = env->banked_r14[bank_number(ARM_CPU_MODE_SVC)]; env->xregs[18] = env->banked_r14[r14_bank_number(ARM_CPU_MODE_SVC)];
env->xregs[19] = env->banked_r13[bank_number(ARM_CPU_MODE_SVC)]; env->xregs[19] = env->banked_r13[bank_number(ARM_CPU_MODE_SVC)];
} }
...@@ -8047,7 +8048,7 @@ void aarch64_sync_32_to_64(CPUARMState *env) ...@@ -8047,7 +8048,7 @@ void aarch64_sync_32_to_64(CPUARMState *env)
env->xregs[20] = env->regs[14]; env->xregs[20] = env->regs[14];
env->xregs[21] = env->regs[13]; env->xregs[21] = env->regs[13];
} else { } else {
env->xregs[20] = env->banked_r14[bank_number(ARM_CPU_MODE_ABT)]; env->xregs[20] = env->banked_r14[r14_bank_number(ARM_CPU_MODE_ABT)];
env->xregs[21] = env->banked_r13[bank_number(ARM_CPU_MODE_ABT)]; env->xregs[21] = env->banked_r13[bank_number(ARM_CPU_MODE_ABT)];
} }
...@@ -8055,7 +8056,7 @@ void aarch64_sync_32_to_64(CPUARMState *env) ...@@ -8055,7 +8056,7 @@ void aarch64_sync_32_to_64(CPUARMState *env)
env->xregs[22] = env->regs[14]; env->xregs[22] = env->regs[14];
env->xregs[23] = env->regs[13]; env->xregs[23] = env->regs[13];
} else { } else {
env->xregs[22] = env->banked_r14[bank_number(ARM_CPU_MODE_UND)]; env->xregs[22] = env->banked_r14[r14_bank_number(ARM_CPU_MODE_UND)];
env->xregs[23] = env->banked_r13[bank_number(ARM_CPU_MODE_UND)]; env->xregs[23] = env->banked_r13[bank_number(ARM_CPU_MODE_UND)];
} }
...@@ -8072,7 +8073,7 @@ void aarch64_sync_32_to_64(CPUARMState *env) ...@@ -8072,7 +8073,7 @@ void aarch64_sync_32_to_64(CPUARMState *env)
env->xregs[i] = env->fiq_regs[i - 24]; env->xregs[i] = env->fiq_regs[i - 24];
} }
env->xregs[29] = env->banked_r13[bank_number(ARM_CPU_MODE_FIQ)]; env->xregs[29] = env->banked_r13[bank_number(ARM_CPU_MODE_FIQ)];
env->xregs[30] = env->banked_r14[bank_number(ARM_CPU_MODE_FIQ)]; env->xregs[30] = env->banked_r14[r14_bank_number(ARM_CPU_MODE_FIQ)];
} }
env->pc = env->regs[15]; env->pc = env->regs[15];
...@@ -8122,7 +8123,7 @@ void aarch64_sync_64_to_32(CPUARMState *env) ...@@ -8122,7 +8123,7 @@ void aarch64_sync_64_to_32(CPUARMState *env)
if (mode == ARM_CPU_MODE_HYP) { if (mode == ARM_CPU_MODE_HYP) {
env->regs[14] = env->xregs[14]; env->regs[14] = env->xregs[14];
} else { } else {
env->banked_r14[bank_number(ARM_CPU_MODE_USR)] = env->xregs[14]; env->banked_r14[r14_bank_number(ARM_CPU_MODE_USR)] = env->xregs[14];
} }
} }
...@@ -8136,7 +8137,7 @@ void aarch64_sync_64_to_32(CPUARMState *env) ...@@ -8136,7 +8137,7 @@ void aarch64_sync_64_to_32(CPUARMState *env)
env->regs[14] = env->xregs[16]; env->regs[14] = env->xregs[16];
env->regs[13] = env->xregs[17]; env->regs[13] = env->xregs[17];
} else { } else {
env->banked_r14[bank_number(ARM_CPU_MODE_IRQ)] = env->xregs[16]; env->banked_r14[r14_bank_number(ARM_CPU_MODE_IRQ)] = env->xregs[16];
env->banked_r13[bank_number(ARM_CPU_MODE_IRQ)] = env->xregs[17]; env->banked_r13[bank_number(ARM_CPU_MODE_IRQ)] = env->xregs[17];
} }
...@@ -8144,7 +8145,7 @@ void aarch64_sync_64_to_32(CPUARMState *env) ...@@ -8144,7 +8145,7 @@ void aarch64_sync_64_to_32(CPUARMState *env)
env->regs[14] = env->xregs[18]; env->regs[14] = env->xregs[18];
env->regs[13] = env->xregs[19]; env->regs[13] = env->xregs[19];
} else { } else {
env->banked_r14[bank_number(ARM_CPU_MODE_SVC)] = env->xregs[18]; env->banked_r14[r14_bank_number(ARM_CPU_MODE_SVC)] = env->xregs[18];
env->banked_r13[bank_number(ARM_CPU_MODE_SVC)] = env->xregs[19]; env->banked_r13[bank_number(ARM_CPU_MODE_SVC)] = env->xregs[19];
} }
...@@ -8152,7 +8153,7 @@ void aarch64_sync_64_to_32(CPUARMState *env) ...@@ -8152,7 +8153,7 @@ void aarch64_sync_64_to_32(CPUARMState *env)
env->regs[14] = env->xregs[20]; env->regs[14] = env->xregs[20];
env->regs[13] = env->xregs[21]; env->regs[13] = env->xregs[21];
} else { } else {
env->banked_r14[bank_number(ARM_CPU_MODE_ABT)] = env->xregs[20]; env->banked_r14[r14_bank_number(ARM_CPU_MODE_ABT)] = env->xregs[20];
env->banked_r13[bank_number(ARM_CPU_MODE_ABT)] = env->xregs[21]; env->banked_r13[bank_number(ARM_CPU_MODE_ABT)] = env->xregs[21];
} }
...@@ -8160,7 +8161,7 @@ void aarch64_sync_64_to_32(CPUARMState *env) ...@@ -8160,7 +8161,7 @@ void aarch64_sync_64_to_32(CPUARMState *env)
env->regs[14] = env->xregs[22]; env->regs[14] = env->xregs[22];
env->regs[13] = env->xregs[23]; env->regs[13] = env->xregs[23];
} else { } else {
env->banked_r14[bank_number(ARM_CPU_MODE_UND)] = env->xregs[22]; env->banked_r14[r14_bank_number(ARM_CPU_MODE_UND)] = env->xregs[22];
env->banked_r13[bank_number(ARM_CPU_MODE_UND)] = env->xregs[23]; env->banked_r13[bank_number(ARM_CPU_MODE_UND)] = env->xregs[23];
} }
...@@ -8177,7 +8178,7 @@ void aarch64_sync_64_to_32(CPUARMState *env) ...@@ -8177,7 +8178,7 @@ void aarch64_sync_64_to_32(CPUARMState *env)
env->fiq_regs[i - 24] = env->xregs[i]; env->fiq_regs[i - 24] = env->xregs[i];
} }
env->banked_r13[bank_number(ARM_CPU_MODE_FIQ)] = env->xregs[29]; env->banked_r13[bank_number(ARM_CPU_MODE_FIQ)] = env->xregs[29];
env->banked_r14[bank_number(ARM_CPU_MODE_FIQ)] = env->xregs[30]; env->banked_r14[r14_bank_number(ARM_CPU_MODE_FIQ)] = env->xregs[30];
} }
env->regs[15] = env->pc; env->regs[15] = env->pc;
......
...@@ -145,6 +145,22 @@ static inline int bank_number(int mode) ...@@ -145,6 +145,22 @@ static inline int bank_number(int mode)
g_assert_not_reached(); g_assert_not_reached();
} }
/**
* r14_bank_number: Map CPU mode onto register bank for r14
*
* Given an AArch32 CPU mode, return the index into the saved register
* banks to use for the R14 (LR) in that mode. This is the same as
* bank_number(), except for the special case of Hyp mode, where
* R14 is shared with USR and SYS, unlike its R13 and SPSR.
* This should be used as the index into env->banked_r14[], and
* bank_number() used for the index into env->banked_r13[] and
* env->banked_spsr[].
*/
static inline int r14_bank_number(int mode)
{
return (mode == ARM_CPU_MODE_HYP) ? BANK_USRSYS : bank_number(mode);
}
void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu); void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu);
void arm_translate_init(void); void arm_translate_init(void);
......
...@@ -318,8 +318,8 @@ int kvm_arch_put_registers(CPUState *cs, int level) ...@@ -318,8 +318,8 @@ int kvm_arch_put_registers(CPUState *cs, int level)
memcpy(env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t)); memcpy(env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
} }
env->banked_r13[bn] = env->regs[13]; env->banked_r13[bn] = env->regs[13];
env->banked_r14[bn] = env->regs[14];
env->banked_spsr[bn] = env->spsr; env->banked_spsr[bn] = env->spsr;
env->banked_r14[r14_bank_number(mode)] = env->regs[14];
/* Now we can safely copy stuff down to the kernel */ /* Now we can safely copy stuff down to the kernel */
for (i = 0; i < ARRAY_SIZE(regs); i++) { for (i = 0; i < ARRAY_SIZE(regs); i++) {
...@@ -430,8 +430,8 @@ int kvm_arch_get_registers(CPUState *cs) ...@@ -430,8 +430,8 @@ int kvm_arch_get_registers(CPUState *cs)
memcpy(env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t)); memcpy(env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
} }
env->regs[13] = env->banked_r13[bn]; env->regs[13] = env->banked_r13[bn];
env->regs[14] = env->banked_r14[bn];
env->spsr = env->banked_spsr[bn]; env->spsr = env->banked_spsr[bn];
env->regs[14] = env->banked_r14[r14_bank_number(mode)];
/* VFP registers */ /* VFP registers */
r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP; r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
......
...@@ -694,7 +694,7 @@ void HELPER(msr_banked)(CPUARMState *env, uint32_t value, uint32_t tgtmode, ...@@ -694,7 +694,7 @@ void HELPER(msr_banked)(CPUARMState *env, uint32_t value, uint32_t tgtmode,
env->banked_r13[bank_number(tgtmode)] = value; env->banked_r13[bank_number(tgtmode)] = value;
break; break;
case 14: case 14:
env->banked_r14[bank_number(tgtmode)] = value; env->banked_r14[r14_bank_number(tgtmode)] = value;
break; break;
case 8 ... 12: case 8 ... 12:
switch (tgtmode) { switch (tgtmode) {
...@@ -725,7 +725,7 @@ uint32_t HELPER(mrs_banked)(CPUARMState *env, uint32_t tgtmode, uint32_t regno) ...@@ -725,7 +725,7 @@ uint32_t HELPER(mrs_banked)(CPUARMState *env, uint32_t tgtmode, uint32_t regno)
case 13: case 13:
return env->banked_r13[bank_number(tgtmode)]; return env->banked_r13[bank_number(tgtmode)];
case 14: case 14:
return env->banked_r14[bank_number(tgtmode)]; return env->banked_r14[r14_bank_number(tgtmode)];
case 8 ... 12: case 8 ... 12:
switch (tgtmode) { switch (tgtmode) {
case ARM_CPU_MODE_USR: case ARM_CPU_MODE_USR:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册