📄 process.c
字号:
* copy altiVec info - assume lazy altiVec switch * - kumar */ if (regs->msr & MSR_VEC) giveup_altivec(current); memcpy(&p->thread.vr, ¤t->thread.vr, sizeof(p->thread.vr)); p->thread.vscr = current->thread.vscr; childregs->msr &= ~MSR_VEC;#endif /* CONFIG_ALTIVEC */ return 0;}/* * Set up a thread for executing a new program */void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp){ unsigned long entry, toc, load_addr = regs->gpr[2]; /* fdptr 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. */ set_fs(USER_DS); __get_user(entry, (unsigned long *)fdptr); __get_user(toc, (unsigned long *)fdptr+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[1] = sp; regs->gpr[2] = toc; regs->msr = MSR_USER64;#ifndef CONFIG_SMP if (last_task_used_math == current) last_task_used_math = 0; if (last_task_used_altivec == current) last_task_used_altivec = 0;#endif /* CONFIG_SMP */ memset(current->thread.fpr, 0, sizeof(current->thread.fpr)); current->thread.fpscr = 0;#ifdef CONFIG_ALTIVEC memset(¤t->thread.vr[0], 0,offsetof(struct thread_struct,vrsave[2])- offsetof(struct thread_struct,vr[0])); current->thread.vscr.u[3] = 0x00010000; /* Java mode disabled */#endif /* CONFIG_ALTIVEC */}# define PR_FP_EXC_DISABLED 0 /* FP exceptions disabled */# define PR_FP_EXC_NONRECOV 1 /* async non-recoverable exc. mode */# define PR_FP_EXC_ASYNC 2 /* async recoverable exception mode */# define PR_FP_EXC_PRECISE 3 /* precise exception mode */int set_fpexc_mode(struct task_struct *tsk, unsigned int val){ struct pt_regs *regs = tsk->thread.regs; 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; val = __unpack_fe01(tsk->thread.fpexc_mode); return put_user(val, (unsigned int *) adr);}int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs){ return do_fork(p1, regs->gpr[1], regs, 0);}int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs){ return do_fork(SIGCHLD, regs->gpr[1], regs, 0);}int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs){ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0);}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 *) a0); error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; if (regs->msr & MSR_FP) giveup_fpu(current);#ifdef CONFIG_ALTIVEC if (regs->msr & MSR_VEC) giveup_altivec(current);#endif /* CONFIG_ALTIVEC */ error = do_execve(filename, (char **) a1, (char **) a2, regs); if (error == 0) current->ptrace &= ~PT_DTRACE; putname(filename);out: return error;}struct task_struct * alloc_task_struct(void){ struct task_struct * new_task_ptr; new_task_ptr = ((struct task_struct *) __get_free_pages(GFP_KERNEL, get_order(THREAD_SIZE))); return new_task_ptr;}void free_task_struct(struct task_struct * task_ptr){ free_pages((unsigned long)(task_ptr), get_order(THREAD_SIZE));}void initialize_paca_hardware_interrupt_stack(void){ extern struct systemcfg *systemcfg; int i; unsigned long stack; unsigned long end_of_stack =0; for (i=1; i < systemcfg->processorCount; i++) { /* Carve out storage for the hardware interrupt stack */ stack = __get_free_pages(GFP_KERNEL, get_order(8*PAGE_SIZE)); if ( !stack ) { printk("ERROR, cannot find space for hardware stack.\n"); panic(" no hardware stack "); } /* Store the stack value in the PACA for the processor */ paca[i].xHrdIntStack = stack + (8*PAGE_SIZE) - STACK_FRAME_OVERHEAD; paca[i].xHrdIntCount = 0; } /* * __get_free_pages() might give us a page > KERNBASE+256M which * is mapped with large ptes so we can't set up the guard page. */ if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) return; for (i=0; i < systemcfg->processorCount; i++) { /* set page at the top of stack to be protected - prevent overflow */ end_of_stack = paca[i].xHrdIntStack - (8*PAGE_SIZE - STACK_FRAME_OVERHEAD); ppc_md.hpte_updateboltedpp(PP_RXRX,end_of_stack); }}extern char _stext[], _etext[];char * ppc_find_proc_name( unsigned * p, char * buf, unsigned buflen ){ unsigned long tb_flags; unsigned short name_len; unsigned long tb_start, code_start, code_ptr, code_offset; unsigned code_len; strcpy( buf, "Unknown" ); code_ptr = (unsigned long)p; code_offset = 0; if ( ( (unsigned long)p >= (unsigned long)_stext ) && ( (unsigned long)p <= (unsigned long)_etext ) ) { while ( (unsigned long)p <= (unsigned long)_etext ) { if ( *p == 0 ) { tb_start = (unsigned long)p; ++p; /* Point to traceback flags */ tb_flags = *((unsigned long *)p); p += 2; /* Skip over traceback flags */ if ( tb_flags & TB_NAME_PRESENT ) { if ( tb_flags & TB_PARMINFO ) ++p; /* skip over parminfo data */ if ( tb_flags & TB_HAS_TBOFF ) { code_len = *p; /* get code length */ code_start = tb_start - code_len; code_offset = code_ptr - code_start + 1; if ( code_offset > 0x100000 ) break; ++p; /* skip over code size */ } name_len = *((unsigned short *)p); if ( name_len > (buflen-20) ) name_len = buflen-20; memcpy( buf, ((char *)p)+2, name_len ); buf[name_len] = 0; if ( code_offset ) sprintf( buf+name_len, "+0x%lx", code_offset-1 ); } break; } ++p; } } return buf;}voidprint_backtrace(unsigned long *sp){ int cnt = 0; unsigned long i; char name_buf[256]; printk("Call backtrace: \n"); while (sp) { if (__get_user(i, &sp[2])) break; printk("%016lX ", i); printk("%s\n", ppc_find_proc_name((unsigned *)i, name_buf, 256)); if (cnt > 32) break; if (__get_user(sp, (unsigned long **)sp)) break; } printk("\n");}/* * These bracket the sleeping functions.. */extern void scheduling_functions_start_here(void);extern void scheduling_functions_end_here(void);#define first_sched (*(unsigned long *)scheduling_functions_start_here)#define last_sched (*(unsigned long *)scheduling_functions_end_here)unsigned long get_wchan(struct task_struct *p){ unsigned long ip, sp; unsigned long stack_page = (unsigned long)p; int count = 0; if (!p || p == current || p->state == TASK_RUNNING) return 0; sp = p->thread.ksp; do { sp = *(unsigned long *)sp; if (sp < (stack_page + (2 * PAGE_SIZE)) || sp >= (stack_page + THREAD_SIZE)) return 0; if (count > 0) { ip = *(unsigned long *)(sp + 16); /* * XXX we mask the upper 32 bits until procps * gets fixed. */ if (ip < first_sched || ip >= last_sched) return (ip); } } while (count++ < 16); return 0;}void show_trace_task(struct task_struct *p){ unsigned long ip, sp; unsigned long stack_page = (unsigned long)p; int count = 0; if (!p) return; printk("Call Trace: "); sp = p->thread.ksp; do { sp = *(unsigned long *)sp; if (sp < (stack_page + (2 * PAGE_SIZE)) || sp >= (stack_page + THREAD_SIZE)) break; if (count > 0) { ip = *(unsigned long *)(sp + 16); printk("[%016lx] ", ip); } } while (count++ < 16); printk("\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -