arch/arm64/kernel/signal.c

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

File Facts

System
Linux kernel
Corpus path
arch/arm64/kernel/signal.c
Extension
.c
Size
44022 bytes
Lines
1761
Domain
Architecture Layer
Bucket
arch/arm64
Inferred role
Architecture Layer: syscall or user/kernel boundary
Status
core 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

SYSCALL_DEFINE0(rt_sigreturn)
{
	struct pt_regs *regs = current_pt_regs();
	struct rt_sigframe __user *frame;
	struct user_access_state ua_state = {};

	/* Always make any pending restarted system calls return -EINTR */
	current->restart_block.fn = do_no_restart_syscall;

	/*
	 * Since we stacked the signal on a 128-bit boundary, then 'sp' should
	 * be word aligned here.
	 */
	if (regs->sp & 15)
		goto badframe;

	frame = (struct rt_sigframe __user *)regs->sp;

	if (!access_ok(frame, sizeof (*frame)))
		goto badframe;

	if (restore_sigframe(regs, frame, &ua_state))
		goto badframe;

	if (gcs_restore_signal())
		goto badframe;

	if (restore_altstack(&frame->uc.uc_stack))
		goto badframe;

	restore_user_access_state(&ua_state);

	return regs->regs[0];

badframe:
	arm64_notify_segfault(regs->sp);
	return 0;
}

/*
 * Determine the layout of optional records in the signal frame
 *
 * add_all: if true, lays out the biggest possible signal frame for
 *	this task; otherwise, generates a layout for the current state
 *	of the task.
 */
static int setup_sigframe_layout(struct rt_sigframe_user_layout *user,
				 bool add_all)
{
	int err;

	if (system_supports_fpsimd()) {
		err = sigframe_alloc(user, &user->fpsimd_offset,
				     sizeof(struct fpsimd_context));
		if (err)
			return err;
	}

	/* fault information, if valid */
	if (add_all || current->thread.fault_code) {
		err = sigframe_alloc(user, &user->esr_offset,
				     sizeof(struct esr_context));
		if (err)
			return err;
	}

#ifdef CONFIG_ARM64_GCS
	if (system_supports_gcs() && (add_all || current->thread.gcspr_el0)) {
		err = sigframe_alloc(user, &user->gcs_offset,
				     sizeof(struct gcs_context));
		if (err)
			return err;
	}
#endif

	if (system_supports_sve() || system_supports_sme()) {
		unsigned int vq = 0;

		if (add_all || current->thread.fp_type == FP_STATE_SVE ||
		    thread_sm_enabled(&current->thread)) {
			int vl = max(sve_max_vl(), sme_max_vl());

			if (!add_all)
				vl = thread_get_cur_vl(&current->thread);

			vq = sve_vq_from_vl(vl);
		}

		err = sigframe_alloc(user, &user->sve_offset,
				     SVE_SIG_CONTEXT_SIZE(vq));

Annotation

Implementation Notes