arch/arm64/kernel/entry-common.c

Source file repositories/reference/linux-study-clean/arch/arm64/kernel/entry-common.c

File Facts

System
Linux kernel
Corpus path
arch/arm64/kernel/entry-common.c
Extension
.c
Size
25689 bytes
Lines
1015
Domain
Architecture Layer
Bucket
arch/arm64
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

static void cortex_a76_erratum_1463225_svc_handler(void) { }
static bool cortex_a76_erratum_1463225_debug_handler(struct pt_regs *regs)
{
	return false;
}
#endif /* CONFIG_ARM64_ERRATUM_1463225 */

/*
 * As per the ABI exit SME streaming mode and clear the SVE state not
 * shared with FPSIMD on syscall entry.
 */
static inline void fpsimd_syscall_enter(void)
{
	/* Ensure PSTATE.SM is clear, but leave PSTATE.ZA as-is. */
	if (system_supports_sme())
		sme_smstop_sm();

	/*
	 * The CPU is not in streaming mode. If non-streaming SVE is not
	 * supported, there is no SVE state that needs to be discarded.
	 */
	if (!system_supports_sve())
		return;

	if (test_thread_flag(TIF_SVE))
		sve_flush_live();

	/*
	 * Any live non-FPSIMD SVE state has been zeroed. Allow
	 * fpsimd_save_user_state() to lazily discard SVE state until either
	 * the live state is unbound or fpsimd_syscall_exit() is called.
	 */
	__this_cpu_write(fpsimd_last_state.to_save, FP_STATE_FPSIMD);
}

static __always_inline void fpsimd_syscall_exit(void)
{
	if (!system_supports_sve())
		return;

	/*
	 * The current task's user FPSIMD/SVE/SME state is now bound to this
	 * CPU. The fpsimd_last_state.to_save value is either:
	 *
	 * - FP_STATE_FPSIMD, if the state has not been reloaded on this CPU
	 *   since fpsimd_syscall_enter().
	 *
	 * - FP_STATE_CURRENT, if the state has been reloaded on this CPU at
	 *   any point.
	 *
	 * Reset this to FP_STATE_CURRENT to stop lazy discarding.
	 */
	__this_cpu_write(fpsimd_last_state.to_save, FP_STATE_CURRENT);
}

/*
 * In debug exception context, we explicitly disable preemption despite
 * having interrupts disabled.
 * This serves two purposes: it makes it much less likely that we would
 * accidentally schedule in exception context and it will force a warning
 * if we somehow manage to schedule by accident.
 */
static void debug_exception_enter(struct pt_regs *regs)
{
	preempt_disable();

	/* This code is a bit fragile.  Test it. */
	RCU_LOCKDEP_WARN(!rcu_is_watching(), "exception_enter didn't work");
}
NOKPROBE_SYMBOL(debug_exception_enter);

static void debug_exception_exit(struct pt_regs *regs)
{
	preempt_enable_no_resched();
}
NOKPROBE_SYMBOL(debug_exception_exit);

UNHANDLED(el1t, 64, sync)
UNHANDLED(el1t, 64, irq)
UNHANDLED(el1t, 64, fiq)
UNHANDLED(el1t, 64, error)

static void noinstr el1_abort(struct pt_regs *regs, unsigned long esr)
{
	unsigned long far = read_sysreg(far_el1);
	irqentry_state_t state;

	state = arm64_enter_from_kernel_mode(regs);
	local_daif_inherit(regs);
	do_mem_abort(far, esr, regs);

Annotation

Implementation Notes