arch/sparc/kernel/process_64.c

Source file repositories/reference/linux-study-clean/arch/sparc/kernel/process_64.c

File Facts

System
Linux kernel
Corpus path
arch/sparc/kernel/process_64.c
Extension
.c
Size
17704 bytes
Lines
699
Domain
Architecture Layer
Bucket
arch/sparc
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

core_initcall(sparc_sysrq_init);

#endif

/* Free current thread data structures etc.. */
void exit_thread(struct task_struct *tsk)
{
	struct thread_info *t = task_thread_info(tsk);

	if (t->utraps) {
		if (t->utraps[0] < 2)
			kfree (t->utraps);
		else
			t->utraps[0]--;
	}
}

void flush_thread(void)
{
	struct thread_info *t = current_thread_info();
	struct mm_struct *mm;

	mm = t->task->mm;
	if (mm)
		tsb_context_switch(mm);

	set_thread_wsaved(0);

	/* Clear FPU register state. */
	t->fpsaved[0] = 0;
}

/* It's a bit more tricky when 64-bit tasks are involved... */
static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
{
	bool stack_64bit = test_thread_64bit_stack(psp);
	unsigned long fp, distance, rval;

	if (stack_64bit) {
		csp += STACK_BIAS;
		psp += STACK_BIAS;
		__get_user(fp, &(((struct reg_window __user *)psp)->ins[6]));
		fp += STACK_BIAS;
		if (test_thread_flag(TIF_32BIT))
			fp &= 0xffffffff;
	} else
		__get_user(fp, &(((struct reg_window32 __user *)psp)->ins[6]));

	/* Now align the stack as this is mandatory in the Sparc ABI
	 * due to how register windows work.  This hides the
	 * restriction from thread libraries etc.
	 */
	csp &= ~15UL;

	distance = fp - psp;
	rval = (csp - distance);
	if (raw_copy_in_user((void __user *)rval, (void __user *)psp, distance))
		rval = 0;
	else if (!stack_64bit) {
		if (put_user(((u32)csp),
			     &(((struct reg_window32 __user *)rval)->ins[6])))
			rval = 0;
	} else {
		if (put_user(((u64)csp - STACK_BIAS),
			     &(((struct reg_window __user *)rval)->ins[6])))
			rval = 0;
		else
			rval = rval - STACK_BIAS;
	}

	return rval;
}

/* Standard stuff. */
static inline void shift_window_buffer(int first_win, int last_win,
				       struct thread_info *t)
{
	int i;

	for (i = first_win; i < last_win; i++) {
		t->rwbuf_stkptrs[i] = t->rwbuf_stkptrs[i+1];
		memcpy(&t->reg_window[i], &t->reg_window[i+1],
		       sizeof(struct reg_window));
	}
}

void synchronize_user_stack(void)
{
	struct thread_info *t = current_thread_info();
	unsigned long window;

Annotation

Implementation Notes