arch/mips/kernel/ptrace.c

Source file repositories/reference/linux-study-clean/arch/mips/kernel/ptrace.c

File Facts

System
Linux kernel
Corpus path
arch/mips/kernel/ptrace.c
Extension
.c
Size
33502 bytes
Lines
1373
Domain
Architecture Layer
Bucket
arch/mips
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration 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 msa_control_regs {
	unsigned int fir;
	unsigned int fcsr;
	unsigned int msair;
	unsigned int msacsr;
};

static void copy_pad_fprs(struct task_struct *target,
			 const struct user_regset *regset,
			 struct membuf *to,
			 unsigned int live_sz)
{
	int i, j;
	unsigned long long fill = ~0ull;
	unsigned int cp_sz, pad_sz;

	cp_sz = min(regset->size, live_sz);
	pad_sz = regset->size - cp_sz;
	WARN_ON(pad_sz % sizeof(fill));

	for (i = 0; i < NUM_FPU_REGS; i++) {
		membuf_write(to, &target->thread.fpu.fpr[i], cp_sz);
		for (j = 0; j < (pad_sz / sizeof(fill)); j++)
			membuf_store(to, fill);
	}
}

static int msa_get(struct task_struct *target,
		   const struct user_regset *regset,
		   struct membuf to)
{
	const unsigned int wr_size = NUM_FPU_REGS * regset->size;
	const struct msa_control_regs ctrl_regs = {
		.fir = boot_cpu_data.fpu_id,
		.fcsr = target->thread.fpu.fcr31,
		.msair = boot_cpu_data.msa_id,
		.msacsr = target->thread.fpu.msacsr,
	};

	if (!tsk_used_math(target)) {
		/* The task hasn't used FP or MSA, fill with 0xff */
		copy_pad_fprs(target, regset, &to, 0);
	} else if (!test_tsk_thread_flag(target, TIF_MSA_CTX_LIVE)) {
		/* Copy scalar FP context, fill the rest with 0xff */
		copy_pad_fprs(target, regset, &to, 8);
	} else if (sizeof(target->thread.fpu.fpr[0]) == regset->size) {
		/* Trivially copy the vector registers */
		membuf_write(&to, &target->thread.fpu.fpr, wr_size);
	} else {
		/* Copy as much context as possible, fill the rest with 0xff */
		copy_pad_fprs(target, regset, &to,
				sizeof(target->thread.fpu.fpr[0]));
	}

	return membuf_write(&to, &ctrl_regs, sizeof(ctrl_regs));
}

static int msa_set(struct task_struct *target,
		   const struct user_regset *regset,
		   unsigned int pos, unsigned int count,
		   const void *kbuf, const void __user *ubuf)
{
	const unsigned int wr_size = NUM_FPU_REGS * regset->size;
	struct msa_control_regs ctrl_regs;
	unsigned int cp_sz;
	int i, err, start;

	init_fp_ctx(target);

	if (sizeof(target->thread.fpu.fpr[0]) == regset->size) {
		/* Trivially copy the vector registers */
		err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
					 &target->thread.fpu.fpr,
					 0, wr_size);
	} else {
		/* Copy as much context as possible */
		cp_sz = min_t(unsigned int, regset->size,
			      sizeof(target->thread.fpu.fpr[0]));

		i = start = err = 0;
		for (; i < NUM_FPU_REGS; i++, start += regset->size) {
			err |= user_regset_copyin(&pos, &count, &kbuf, &ubuf,
						  &target->thread.fpu.fpr[i],
						  start, start + cp_sz);
		}
	}

	if (!err)
		err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl_regs,
					 wr_size, wr_size + sizeof(ctrl_regs));

Annotation

Implementation Notes