qemu/target/hppa/translate.c
/* On Linux, page zero is normally marked execute only + gateway.
   Therefore normal read or write is supposed to fail, but specific
   offsets have kernel code mapped to raise permissions to implement
   system calls.  Handling this via an explicit check here, rather
   in than the "be disp(sr2,r0)" instruction that probably sent us
   here, is the easiest way to handle the branch delay slot on the
   aforementioned BE.  */
On Linux, page zero is normally marked execute only + gateway.
Therefore normal read or write is supposed to fail, but specific
offsets have kernel code mapped to raise permissions to implement
system calls.  Handling this via an explicit check here, rather
in than the "be disp(sr2,r0)" instruction that probably sent us
here, is the easiest way to handle the branch delay slot on the
aforementioned BE.
On Linux page zero is normally marked execute only + gateway . Therefore normal read or write is supposed to fail but specific offsets have kernel code mapped to raise permissions to implement system calls . Handling this via an explicit check here rather in than the " be disp ( sr2 r0 ) " instruction that probably sent us here is the easiest way to handle the branch delay slot on the aforementioned BE .
static DisasJumpType do_page_zero(DisasContext *ctx)
{
    switch (ctx->null_cond.c) {
    case TCG_COND_NEVER:
        break;
    case TCG_COND_ALWAYS:
        tcg_gen_movi_reg(cpu_psw_n, 0);
        goto do_sigill;
    default:
        g_assert_not_reached();
    }
    if (ctx->iaoq_b != ctx->iaoq_f + 4) {
        goto do_sigill;
    }
    switch (ctx->iaoq_f & -4) {
    case 0x00: 
        gen_excp_1(EXCP_IMP);
        return DISAS_NORETURN;
    case 0xb0: 
        gen_excp_1(EXCP_SYSCALL_LWS);
        return DISAS_NORETURN;
    case 0xe0: 
        tcg_gen_st_reg(cpu_gr[26], cpu_env, offsetof(CPUHPPAState, cr[27]));
        tcg_gen_ori_reg(cpu_iaoq_f, cpu_gr[31], 3);
        tcg_gen_addi_reg(cpu_iaoq_b, cpu_iaoq_f, 4);
        return DISAS_IAQ_N_UPDATED;
    case 0x100: 
        gen_excp_1(EXCP_SYSCALL);
        return DISAS_NORETURN;
    default:
    do_sigill:
        gen_excp_1(EXCP_ILL);
        return DISAS_NORETURN;
    }
}
static DisasJumpType do_page_zero ( DisasContext * ctx ) { switch ( ctx -> null_cond . c ) { case TCG_COND_NEVER : break ; case TCG_COND_ALWAYS : tcg_gen_movi_reg ( cpu_psw_n , 0 ) ; goto do_sigill ; default : g_assert_not_reached ( ) ; } if ( ctx -> iaoq_b != ctx -> iaoq_f + 4 ) { goto do_sigill ; } switch ( ctx -> iaoq_f & -4 ) { case 0x00 : gen_excp_1 ( EXCP_IMP ) ; return DISAS_NORETURN ; case 0xb0 : gen_excp_1 ( EXCP_SYSCALL_LWS ) ; return DISAS_NORETURN ; case 0xe0 : tcg_gen_st_reg ( cpu_gr [ 26 ] , cpu_env , offsetof ( CPUHPPAState , cr [ 27 ] ) ) ; tcg_gen_ori_reg ( cpu_iaoq_f , cpu_gr [ 31 ] , 3 ) ; tcg_gen_addi_reg ( cpu_iaoq_b , cpu_iaoq_f , 4 ) ; return DISAS_IAQ_N_UPDATED ; case 0x100 : gen_excp_1 ( EXCP_SYSCALL ) ; return DISAS_NORETURN ; default : do_sigill : gen_excp_1 ( EXCP_ILL ) ; return DISAS_NORETURN ; } }
On Linux, page zero is normally marked execute only + gateway.
On Linux page zero is normally marked execute only + gateway .
/* If by some means we get here with PSW[N]=1, that implies that
       the B,GATE instruction would be skipped, and we'd fault on the
       next insn within the privilaged page.  */ /* Since this is always the first (and only) insn within the
           TB, we should know the state of PSW[N] from TB->FLAGS.  */ /* 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.  */ /* Null pointer call */ /* LWS */ /* SET_THREAD_POINTER */ /* SYSCALL */