arch/riscv/kernel/compat_signal.c

Source file repositories/reference/linux-study-clean/arch/riscv/kernel/compat_signal.c

File Facts

System
Linux kernel
Corpus path
arch/riscv/kernel/compat_signal.c
Extension
.c
Size
6864 bytes
Lines
246
Domain
Architecture Layer
Bucket
arch/riscv
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

struct compat_sigcontext {
	struct compat_user_regs_struct sc_regs;
	union __riscv_fp_state sc_fpregs;
};

struct compat_ucontext {
	compat_ulong_t		uc_flags;
	struct compat_ucontext	*uc_link;
	compat_stack_t		uc_stack;
	sigset_t		uc_sigmask;
	/* There's some padding here to allow sigset_t to be expanded in the
	 * future.  Though this is unlikely, other architectures put uc_sigmask
	 * at the end of this structure and explicitly state it can be
	 * expanded, so we didn't want to box ourselves in here. */
	__u8		  __unused[1024 / 8 - sizeof(sigset_t)];
	/* We can't put uc_sigmask at the end of this structure because we need
	 * to be able to expand sigcontext in the future.  For example, the
	 * vector ISA extension will almost certainly add ISA state.  We want
	 * to ensure all user-visible ISA state can be saved and restored via a
	 * ucontext, so we're putting this at the end in order to allow for
	 * infinite extensibility.  Since we know this will be extended and we
	 * assume sigset_t won't be extended an extreme amount, we're
	 * prioritizing this. */
	struct compat_sigcontext uc_mcontext;
};

struct compat_rt_sigframe {
	struct compat_siginfo info;
	struct compat_ucontext uc;
};

#ifdef CONFIG_FPU
static long compat_restore_fp_state(struct pt_regs *regs,
	union __riscv_fp_state __user *sc_fpregs)
{
	long err;
	struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
	size_t i;

	err = __copy_from_user(&current->thread.fstate, state, sizeof(*state));
	if (unlikely(err))
		return err;

	fstate_restore(current, regs);

	/* We support no other extension state at this time. */
	for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
		u32 value;

		err = __get_user(value, &sc_fpregs->q.reserved[i]);
		if (unlikely(err))
			break;
		if (value != 0)
			return -EINVAL;
	}

	return err;
}

static long compat_save_fp_state(struct pt_regs *regs,
			  union __riscv_fp_state __user *sc_fpregs)
{
	long err;
	struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
	size_t i;

	fstate_save(current, regs);
	err = __copy_to_user(state, &current->thread.fstate, sizeof(*state));
	if (unlikely(err))
		return err;

	/* We support no other extension state at this time. */
	for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
		err = __put_user(0, &sc_fpregs->q.reserved[i]);
		if (unlikely(err))
			break;
	}

	return err;
}
#else
#define compat_save_fp_state(task, regs) (0)
#define compat_restore_fp_state(task, regs) (0)
#endif

static long compat_restore_sigcontext(struct pt_regs *regs,
	struct compat_sigcontext __user *sc)
{
	long err;
	struct compat_user_regs_struct cregs;

Annotation

Implementation Notes