target/hppa: Implement PSW_B

PSW_B causes B,GATE to trap as an illegal instruction, removing our
previous sequential execution test that was merely an approximation.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2024-04-16 20:50:30 -07:00
parent d27fe7c3af
commit 5ae8adbb01
1 changed files with 6 additions and 19 deletions

View File

@ -2062,11 +2062,8 @@ static void do_page_zero(DisasContext *ctx)
g_assert_not_reached();
}
/* Check that we didn't arrive here via some means that allowed
non-sequential instruction execution. Normally the PSW[B] bit
detects this by disallowing the B,GATE instruction to execute
under such conditions. */
if (iaqe_variable(&ctx->iaq_b) || ctx->iaq_b.disp != 4) {
/* If PSW[B] is set, the B,GATE insn would trap. */
if (ctx->psw_xb & PSW_B) {
goto do_sigill;
}
@ -3965,23 +3962,13 @@ static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
{
int64_t disp = a->disp;
nullify_over(ctx);
/* Make sure the caller hasn't done something weird with the queue.
* ??? This is not quite the same as the PSW[B] bit, which would be
* expensive to track. Real hardware will trap for
* b gateway
* b gateway+4 (in delay slot of first branch)
* However, checking for a non-sequential instruction queue *will*
* diagnose the security hole
* b gateway
* b evil
* in which instructions at evil would run with increased privs.
*/
if (iaqe_variable(&ctx->iaq_b) || ctx->iaq_b.disp != ctx->iaq_f.disp + 4) {
/* Trap if PSW[B] is set. */
if (ctx->psw_xb & PSW_B) {
return gen_illegal(ctx);
}
nullify_over(ctx);
#ifndef CONFIG_USER_ONLY
if (ctx->tb_flags & PSW_C) {
int type = hppa_artype_for_page(cpu_env(ctx->cs), ctx->base.pc_next);