target/arm: Restore M-profile CONTROL.SPSEL before any tailchaining

On exception return for M-profile, we must restore the CONTROL.SPSEL
bit from the EXCRET value before we do any kind of tailchaining,
including for the derived exceptions on integrity check failures.
Otherwise we will give the guest an incorrect EXCRET.SPSEL value on
exception entry for the tailchained exception.

Backports commit 89b1fec193b81b6ad0bd2975f2fa179980cc722e from qemu
This commit is contained in:
Peter Maydell 2018-08-16 06:58:33 -04:00 committed by Lioncash
parent e044c59cc1
commit e3be0c4aa6
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -6328,6 +6328,16 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
}
}
/*
* Set CONTROL.SPSEL from excret.SPSEL. Since we're still in
* Handler mode (and will be until we write the new XPSR.Interrupt
* field) this does not switch around the current stack pointer.
* We must do this before we do any kind of tailchaining, including
* for the derived exceptions on integrity check failures, or we will
* give the guest an incorrect EXCRET.SPSEL value on exception entry.
*/
write_v7m_control_spsel_for_secstate(env, return_to_sp_process, exc_secure);
if (sfault) {
env->v7m.sfsr |= R_V7M_SFSR_INVER_MASK;
// Unicorn: commented out
@ -6351,12 +6361,6 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
return;
}
/* Set CONTROL.SPSEL from excret.SPSEL. Since we're still in
* Handler mode (and will be until we write the new XPSR.Interrupt
* field) this does not switch around the current stack pointer.
*/
write_v7m_control_spsel_for_secstate(env, return_to_sp_process, exc_secure);
switch_v7m_security_state(env, return_to_secure);
{