linux-user/aarch64: Check syndrome for EXCP_UDEF

Note that we have been passing the incorrect code for most
exception codes: uncategorized (do_el0_undef),
systemregistertrap (do_el0_sys), smetrap (do_sme_acc),
btitrap (do_el0_bti) and illegalstate (bad_el0_sync).
Only pacfail uses ILL_ILLOPN (do_el0_fpac).

Note that EC_MOP (do_el0_mops) ought not signal at all.
For now, preserve existing behavior signalling ILL_ILLOPN.

List all other exception codes and document why they do
not apply to user-only.

Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20250830054128.448363-3-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2025-08-30 15:40:06 +10:00 committed by Peter Maydell
parent 71eba04575
commit 5fe3151c5e

View file

@ -65,6 +65,79 @@ static void signal_for_exception(CPUARMState *env, vaddr addr)
si_code = TARGET_BUS_ADRALN;
break;
case EC_UNCATEGORIZED: /* E.g. undefined instruction */
case EC_SYSTEMREGISTERTRAP: /* E.g. inaccessible register */
case EC_SMETRAP: /* E.g. invalid insn in streaming state */
case EC_BTITRAP: /* E.g. invalid guarded branch target */
case EC_ILLEGALSTATE:
/*
* Illegal state happens via an ERET from a privileged mode,
* so is not normally possible from user-only. However, gdbstub
* is not prevented from writing CPSR_IL, aka PSTATE.IL, which
* would generate a trap from the next translated block.
* In the kernel, default case -> el0_inv -> bad_el0_sync.
*/
si_signo = TARGET_SIGILL;
si_code = TARGET_ILL_ILLOPC;
break;
case EC_PACFAIL:
si_signo = TARGET_SIGILL;
si_code = TARGET_ILL_ILLOPN;
break;
case EC_MOP:
/*
* FIXME: The kernel fixes up wrong-option exceptions.
* For QEMU linux-user mode, you can only get these if
* the process is doing something silly (not executing
* the MOPS instructions in the required P/M/E sequence),
* so it is not a problem in practice that we do not.
*
* We ought ideally to implement the same "rewind to the
* start of the sequence" logic that the kernel does in
* arm64_mops_reset_regs(). In the meantime, deliver
* the guest a SIGILL, with the same ILLOPN si_code
* we've always used for this.
*/
si_signo = TARGET_SIGILL;
si_code = TARGET_ILL_ILLOPN;
break;
case EC_WFX_TRAP: /* user-only WFI implemented as NOP */
case EC_CP15RTTRAP: /* AArch32 */
case EC_CP15RRTTRAP: /* AArch32 */
case EC_CP14RTTRAP: /* AArch32 */
case EC_CP14DTTRAP: /* AArch32 */
case EC_ADVSIMDFPACCESSTRAP: /* user-only does not disable fpu */
case EC_FPIDTRAP: /* AArch32 */
case EC_PACTRAP: /* user-only does not disable pac regs */
case EC_BXJTRAP: /* AArch32 */
case EC_CP14RRTTRAP: /* AArch32 */
case EC_AA32_SVC: /* AArch32 */
case EC_AA32_HVC: /* AArch32 */
case EC_AA32_SMC: /* AArch32 */
case EC_AA64_SVC: /* generates EXCP_SWI */
case EC_AA64_HVC: /* user-only generates EC_UNCATEGORIZED */
case EC_AA64_SMC: /* user-only generates EC_UNCATEGORIZED */
case EC_SVEACCESSTRAP: /* user-only does not disable sve */
case EC_ERETTRAP: /* user-only generates EC_UNCATEGORIZED */
case EC_GPC: /* user-only has no EL3 gpc tables */
case EC_INSNABORT_SAME_EL: /* el0 cannot trap to el0 */
case EC_DATAABORT_SAME_EL: /* el0 cannot trap to el0 */
case EC_SPALIGNMENT: /* sp alignment checks not implemented */
case EC_AA32_FPTRAP: /* fp exceptions not implemented */
case EC_AA64_FPTRAP: /* fp exceptions not implemented */
case EC_SERROR: /* user-only does not have hw faults */
case EC_BREAKPOINT: /* user-only does not have hw debug */
case EC_BREAKPOINT_SAME_EL: /* user-only does not have hw debug */
case EC_SOFTWARESTEP: /* user-only does not have hw debug */
case EC_SOFTWARESTEP_SAME_EL: /* user-only does not have hw debug */
case EC_WATCHPOINT: /* user-only does not have hw debug */
case EC_WATCHPOINT_SAME_EL: /* user-only does not have hw debug */
case EC_AA32_BKPT: /* AArch32 */
case EC_VECTORCATCH: /* AArch32 */
case EC_AA64_BKPT: /* generates EXCP_BKPT */
default:
g_assert_not_reached();
}
@ -108,7 +181,7 @@ void cpu_loop(CPUARMState *env)
/* just indicate that signals should be handled asap */
break;
case EXCP_UDEF:
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->pc);
signal_for_exception(env, env->pc);
break;
case EXCP_PREFETCH_ABORT:
case EXCP_DATA_ABORT: