target/arm: Allow for floating point in callee stack integrity check

The magic value pushed onto the callee stack as an integrity
check is different if floating point is present.

Backports commit 0dc51d66fcfcc4c72011cdafb401fd876ca216e7 from qemu
This commit is contained in:
Peter Maydell 2019-04-30 10:36:56 -04:00 committed by Lioncash
parent 746d377221
commit 2244bb085a
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -7784,6 +7784,21 @@ load_fail:
return false;
}
static uint32_t v7m_integrity_sig(CPUARMState *env, uint32_t lr)
{
/*
* Return the integrity signature value for the callee-saves
* stack frame section. @lr is the exception return payload/LR value
* whose FType bit forms bit 0 of the signature if FP is present.
*/
uint32_t sig = 0xfefa125a;
if (!arm_feature(env, ARM_FEATURE_VFP) || (lr & R_V7M_EXCRET_FTYPE_MASK)) {
sig |= 1;
}
return sig;
}
static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
bool ignore_faults)
{
@ -7798,6 +7813,7 @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
bool stacked_ok;
uint32_t limit;
bool want_psp;
uint32_t sig;
if (dotailchain) {
bool mode = lr & R_V7M_EXCRET_MODE_MASK;
@ -7839,8 +7855,9 @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
/* Write as much of the stack frame as we can. A write failure may
* cause us to pend a derived exception.
*/
sig = v7m_integrity_sig(env, lr);
stacked_ok =
v7m_stack_write(cpu, frameptr, 0xfefa125b, mmu_idx, ignore_faults) &&
v7m_stack_write(cpu, frameptr, sig, mmu_idx, ignore_faults) &&
v7m_stack_write(cpu, frameptr + 0x8, env->regs[4], mmu_idx,
ignore_faults) &&
v7m_stack_write(cpu, frameptr + 0xc, env->regs[5], mmu_idx,
@ -8452,12 +8469,11 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
if (return_to_secure &&
((excret & R_V7M_EXCRET_ES_MASK) == 0 ||
(excret & R_V7M_EXCRET_DCRS_MASK) == 0)) {
uint32_t expected_sig = 0xfefa125b;
uint32_t actual_sig;
pop_ok = v7m_stack_read(cpu, &actual_sig, frameptr, mmu_idx);
if (pop_ok && expected_sig != actual_sig) {
if (pop_ok && v7m_integrity_sig(env, excret) != actual_sig) {
/* Take a SecureFault on the current stack */
env->v7m.sfsr |= R_V7M_SFSR_INVIS_MASK;
// Unicorn: commented out