⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 process.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
{	discard_lazy_cpu_state();}void flush_thread(void){#ifdef CONFIG_PPC64	struct thread_info *t = current_thread_info();	if (t->flags & _TIF_ABI_PENDING)		t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT);#endif	discard_lazy_cpu_state();#ifdef CONFIG_PPC64	/* for now */	if (current->thread.dabr) {		current->thread.dabr = 0;		set_dabr(0);	}#endif}voidrelease_thread(struct task_struct *t){}/* * This gets called before we allocate a new thread and copy * the current task into it. */void prepare_to_copy(struct task_struct *tsk){	flush_fp_to_thread(current);	flush_altivec_to_thread(current);	flush_spe_to_thread(current);}/* * Copy a thread.. */int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,		unsigned long unused, struct task_struct *p,		struct pt_regs *regs){	struct pt_regs *childregs, *kregs;	extern void ret_from_fork(void);	unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;	CHECK_FULL_REGS(regs);	/* Copy registers */	sp -= sizeof(struct pt_regs);	childregs = (struct pt_regs *) sp;	*childregs = *regs;	if ((childregs->msr & MSR_PR) == 0) {		/* for kernel thread, set `current' and stackptr in new task */		childregs->gpr[1] = sp + sizeof(struct pt_regs);#ifdef CONFIG_PPC32		childregs->gpr[2] = (unsigned long) p;#else		clear_tsk_thread_flag(p, TIF_32BIT);#endif		p->thread.regs = NULL;	/* no user register state */	} else {		childregs->gpr[1] = usp;		p->thread.regs = childregs;		if (clone_flags & CLONE_SETTLS) {#ifdef CONFIG_PPC64			if (!test_thread_flag(TIF_32BIT))				childregs->gpr[13] = childregs->gpr[6];			else#endif				childregs->gpr[2] = childregs->gpr[6];		}	}	childregs->gpr[3] = 0;  /* Result from fork() */	sp -= STACK_FRAME_OVERHEAD;	/*	 * The way this works is that at some point in the future	 * some task will call _switch to switch to the new task.	 * That will pop off the stack frame created below and start	 * the new task running at ret_from_fork.  The new task will	 * do some house keeping and then return from the fork or clone	 * system call, using the stack frame created above.	 */	sp -= sizeof(struct pt_regs);	kregs = (struct pt_regs *) sp;	sp -= STACK_FRAME_OVERHEAD;	p->thread.ksp = sp;#ifdef CONFIG_PPC64	if (cpu_has_feature(CPU_FTR_SLB)) {		unsigned long sp_vsid = get_kernel_vsid(sp);		unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp;		sp_vsid <<= SLB_VSID_SHIFT;		sp_vsid |= SLB_VSID_KERNEL | llp;		p->thread.ksp_vsid = sp_vsid;	}	/*	 * The PPC64 ABI makes use of a TOC to contain function 	 * pointers.  The function (ret_from_except) is actually a pointer	 * to the TOC entry.  The first entry is a pointer to the actual	 * function. 	 */	kregs->nip = *((unsigned long *)ret_from_fork);#else	kregs->nip = (unsigned long)ret_from_fork;	p->thread.last_syscall = -1;#endif	return 0;}/* * Set up a thread for executing a new program */void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp){#ifdef CONFIG_PPC64	unsigned long load_addr = regs->gpr[2];	/* saved by ELF_PLAT_INIT */#endif	set_fs(USER_DS);	/*	 * If we exec out of a kernel thread then thread.regs will not be	 * set.  Do it now.	 */	if (!current->thread.regs) {		struct pt_regs *regs = task_stack_page(current) + THREAD_SIZE;		current->thread.regs = regs - 1;	}	memset(regs->gpr, 0, sizeof(regs->gpr));	regs->ctr = 0;	regs->link = 0;	regs->xer = 0;	regs->ccr = 0;	regs->gpr[1] = sp;#ifdef CONFIG_PPC32	regs->mq = 0;	regs->nip = start;	regs->msr = MSR_USER;#else	if (!test_thread_flag(TIF_32BIT)) {		unsigned long entry, toc;		/* start is a relocated pointer to the function descriptor for		 * the elf _start routine.  The first entry in the function		 * descriptor is the entry address of _start and the second		 * entry is the TOC value we need to use.		 */		__get_user(entry, (unsigned long __user *)start);		__get_user(toc, (unsigned long __user *)start+1);		/* Check whether the e_entry function descriptor entries		 * need to be relocated before we can use them.		 */		if (load_addr != 0) {			entry += load_addr;			toc   += load_addr;		}		regs->nip = entry;		regs->gpr[2] = toc;		regs->msr = MSR_USER64;	} else {		regs->nip = start;		regs->gpr[2] = 0;		regs->msr = MSR_USER32;	}#endif	discard_lazy_cpu_state();	memset(current->thread.fpr, 0, sizeof(current->thread.fpr));	current->thread.fpscr.val = 0;#ifdef CONFIG_ALTIVEC	memset(current->thread.vr, 0, sizeof(current->thread.vr));	memset(&current->thread.vscr, 0, sizeof(current->thread.vscr));	current->thread.vscr.u[3] = 0x00010000; /* Java mode disabled */	current->thread.vrsave = 0;	current->thread.used_vr = 0;#endif /* CONFIG_ALTIVEC */#ifdef CONFIG_SPE	memset(current->thread.evr, 0, sizeof(current->thread.evr));	current->thread.acc = 0;	current->thread.spefscr = 0;	current->thread.used_spe = 0;#endif /* CONFIG_SPE */}#define PR_FP_ALL_EXCEPT (PR_FP_EXC_DIV | PR_FP_EXC_OVF | PR_FP_EXC_UND \		| PR_FP_EXC_RES | PR_FP_EXC_INV)int set_fpexc_mode(struct task_struct *tsk, unsigned int val){	struct pt_regs *regs = tsk->thread.regs;	/* This is a bit hairy.  If we are an SPE enabled  processor	 * (have embedded fp) we store the IEEE exception enable flags in	 * fpexc_mode.  fpexc_mode is also used for setting FP exception	 * mode (asyn, precise, disabled) for 'Classic' FP. */	if (val & PR_FP_EXC_SW_ENABLE) {#ifdef CONFIG_SPE		tsk->thread.fpexc_mode = val &			(PR_FP_EXC_SW_ENABLE | PR_FP_ALL_EXCEPT);		return 0;#else		return -EINVAL;#endif	}	/* on a CONFIG_SPE this does not hurt us.  The bits that	 * __pack_fe01 use do not overlap with bits used for	 * PR_FP_EXC_SW_ENABLE.  Additionally, the MSR[FE0,FE1] bits	 * on CONFIG_SPE implementations are reserved so writing to	 * them does not change anything */	if (val > PR_FP_EXC_PRECISE)		return -EINVAL;	tsk->thread.fpexc_mode = __pack_fe01(val);	if (regs != NULL && (regs->msr & MSR_FP) != 0)		regs->msr = (regs->msr & ~(MSR_FE0|MSR_FE1))			| tsk->thread.fpexc_mode;	return 0;}int get_fpexc_mode(struct task_struct *tsk, unsigned long adr){	unsigned int val;	if (tsk->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE)#ifdef CONFIG_SPE		val = tsk->thread.fpexc_mode;#else		return -EINVAL;#endif	else		val = __unpack_fe01(tsk->thread.fpexc_mode);	return put_user(val, (unsigned int __user *) adr);}#define TRUNC_PTR(x)	((typeof(x))(((unsigned long)(x)) & 0xffffffff))int sys_clone(unsigned long clone_flags, unsigned long usp,	      int __user *parent_tidp, void __user *child_threadptr,	      int __user *child_tidp, int p6,	      struct pt_regs *regs){	CHECK_FULL_REGS(regs);	if (usp == 0)		usp = regs->gpr[1];	/* stack pointer for child */#ifdef CONFIG_PPC64	if (test_thread_flag(TIF_32BIT)) {		parent_tidp = TRUNC_PTR(parent_tidp);		child_tidp = TRUNC_PTR(child_tidp);	}#endif 	return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp);}int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3,	     unsigned long p4, unsigned long p5, unsigned long p6,	     struct pt_regs *regs){	CHECK_FULL_REGS(regs);	return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL);}int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,	      unsigned long p4, unsigned long p5, unsigned long p6,	      struct pt_regs *regs){	CHECK_FULL_REGS(regs);	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1],			regs, 0, NULL, NULL);}int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,	       unsigned long a3, unsigned long a4, unsigned long a5,	       struct pt_regs *regs){	int error;	char *filename;	filename = getname((char __user *) a0);	error = PTR_ERR(filename);	if (IS_ERR(filename))		goto out;	flush_fp_to_thread(current);	flush_altivec_to_thread(current);	flush_spe_to_thread(current);	error = do_execve(filename, (char __user * __user *) a1,			  (char __user * __user *) a2, regs);	if (error == 0) {		task_lock(current);		current->ptrace &= ~PT_DTRACE;		task_unlock(current);	}	putname(filename);out:	return error;}int validate_sp(unsigned long sp, struct task_struct *p,		       unsigned long nbytes){	unsigned long stack_page = (unsigned long)task_stack_page(p);	if (sp >= stack_page + sizeof(struct thread_struct)	    && sp <= stack_page + THREAD_SIZE - nbytes)		return 1;#ifdef CONFIG_IRQSTACKS	stack_page = (unsigned long) hardirq_ctx[task_cpu(p)];	if (sp >= stack_page + sizeof(struct thread_struct)	    && sp <= stack_page + THREAD_SIZE - nbytes)		return 1;	stack_page = (unsigned long) softirq_ctx[task_cpu(p)];	if (sp >= stack_page + sizeof(struct thread_struct)	    && sp <= stack_page + THREAD_SIZE - nbytes)		return 1;#endif	return 0;}#ifdef CONFIG_PPC64#define MIN_STACK_FRAME	112	/* same as STACK_FRAME_OVERHEAD, in fact */#define FRAME_LR_SAVE	2#define INT_FRAME_SIZE	(sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD + 288)#define REGS_MARKER	0x7265677368657265ul#define FRAME_MARKER	12#else#define MIN_STACK_FRAME	16#define FRAME_LR_SAVE	1#define INT_FRAME_SIZE	(sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD)#define REGS_MARKER	0x72656773ul#define FRAME_MARKER	2#endifEXPORT_SYMBOL(validate_sp);unsigned long get_wchan(struct task_struct *p){	unsigned long ip, sp;	int count = 0;	if (!p || p == current || p->state == TASK_RUNNING)		return 0;	sp = p->thread.ksp;	if (!validate_sp(sp, p, MIN_STACK_FRAME))		return 0;	do {		sp = *(unsigned long *)sp;		if (!validate_sp(sp, p, MIN_STACK_FRAME))			return 0;		if (count > 0) {			ip = ((unsigned long *)sp)[FRAME_LR_SAVE];			if (!in_sched_functions(ip))				return ip;		}	} while (count++ < 16);	return 0;}static int kstack_depth_to_print = 64;void show_stack(struct task_struct *tsk, unsigned long *stack){	unsigned long sp, ip, lr, newsp;	int count = 0;	int firstframe = 1;	sp = (unsigned long) stack;	if (tsk == NULL)		tsk = current;	if (sp == 0) {		if (tsk == current)			asm("mr %0,1" : "=r" (sp));		else			sp = tsk->thread.ksp;	}	lr = 0;	printk("Call Trace:\n");	do {		if (!validate_sp(sp, tsk, MIN_STACK_FRAME))			return;		stack = (unsigned long *) sp;		newsp = stack[0];		ip = stack[FRAME_LR_SAVE];		if (!firstframe || ip != lr) {			printk("["REG"] ["REG"] ", sp, ip);			print_symbol("%s", ip);			if (firstframe)				printk(" (unreliable)");			printk("\n");		}		firstframe = 0;		/*		 * See if this is an exception frame.		 * We look for the "regshere" marker in the current frame.		 */		if (validate_sp(sp, tsk, INT_FRAME_SIZE)		    && stack[FRAME_MARKER] == REGS_MARKER) {			struct pt_regs *regs = (struct pt_regs *)				(sp + STACK_FRAME_OVERHEAD);			printk("--- Exception: %lx", regs->trap);			print_symbol(" at %s\n", regs->nip);			lr = regs->link;			print_symbol("    LR = %s\n", lr);			firstframe = 1;		}		sp = newsp;	} while (count++ < kstack_depth_to_print);}void dump_stack(void){	show_stack(current, NULL);}EXPORT_SYMBOL(dump_stack);#ifdef CONFIG_PPC64void ppc64_runlatch_on(void){	unsigned long ctrl;	if (cpu_has_feature(CPU_FTR_CTRL) && !test_thread_flag(TIF_RUNLATCH)) {		HMT_medium();		ctrl = mfspr(SPRN_CTRLF);		ctrl |= CTRL_RUNLATCH;		mtspr(SPRN_CTRLT, ctrl);		set_thread_flag(TIF_RUNLATCH);	}}void ppc64_runlatch_off(void){	unsigned long ctrl;	if (cpu_has_feature(CPU_FTR_CTRL) && test_thread_flag(TIF_RUNLATCH)) {		HMT_medium();		clear_thread_flag(TIF_RUNLATCH);		ctrl = mfspr(SPRN_CTRLF);		ctrl &= ~CTRL_RUNLATCH;		mtspr(SPRN_CTRLT, ctrl);	}}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -