📄 process.c
字号:
/* $Id: process.c,v 1.131 2002/02/09 19:49:30 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1997, 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) *//* * This file handles the architecture-dependent parts of process handling.. */#include <stdarg.h>#include <linux/config.h>#include <linux/errno.h>#include <linux/module.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/kallsyms.h>#include <linux/mm.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <linux/stddef.h>#include <linux/ptrace.h>#include <linux/slab.h>#include <linux/user.h>#include <linux/a.out.h>#include <linux/config.h>#include <linux/reboot.h>#include <linux/delay.h>#include <linux/compat.h>#include <linux/init.h>#include <asm/oplib.h>#include <asm/uaccess.h>#include <asm/system.h>#include <asm/page.h>#include <asm/pgalloc.h>#include <asm/pgtable.h>#include <asm/processor.h>#include <asm/pstate.h>#include <asm/elf.h>#include <asm/fpumacro.h>#include <asm/head.h>#include <asm/cpudata.h>#include <asm/unistd.h>/* #define VERBOSE_SHOWREGS *//* * Nothing special yet... */void default_idle(void){}#ifndef CONFIG_SMP/* * the idle loop on a Sparc... ;) */int cpu_idle(void){ if (current->pid != 0) return -EPERM; /* endless idle loop with no priority at all */ for (;;) { /* If current->work.need_resched is zero we should really * setup for a system wakup event and execute a shutdown * instruction. * * But this requires writing back the contents of the * L2 cache etc. so implement this later. -DaveM */ while (!need_resched()) barrier(); schedule(); check_pgt_cache(); } return 0;}#else/* * the idle loop on a UltraMultiPenguin... */#define idle_me_harder() (cpu_data(smp_processor_id()).idle_volume += 1)#define unidle_me() (cpu_data(smp_processor_id()).idle_volume = 0)int cpu_idle(void){ set_thread_flag(TIF_POLLING_NRFLAG); while(1) { if (need_resched()) { unidle_me(); clear_thread_flag(TIF_POLLING_NRFLAG); schedule(); set_thread_flag(TIF_POLLING_NRFLAG); check_pgt_cache(); } idle_me_harder(); /* The store ordering is so that IRQ handlers on * other cpus see our increasing idleness for the buddy * redistribution algorithm. -DaveM */ membar("#StoreStore | #StoreLoad"); }}#endifextern char reboot_command [];extern void (*prom_palette)(int);extern void (*prom_keyboard)(void);void machine_halt(void){ if (!serial_console && prom_palette) prom_palette (1); if (prom_keyboard) prom_keyboard(); prom_halt(); panic("Halt failed!");}EXPORT_SYMBOL(machine_halt);void machine_alt_power_off(void){ if (!serial_console && prom_palette) prom_palette(1); if (prom_keyboard) prom_keyboard(); prom_halt_power_off(); panic("Power-off failed!");}void machine_restart(char * cmd){ char *p; p = strchr (reboot_command, '\n'); if (p) *p = 0; if (!serial_console && prom_palette) prom_palette (1); if (prom_keyboard) prom_keyboard(); if (cmd) prom_reboot(cmd); if (*reboot_command) prom_reboot(reboot_command); prom_reboot(""); panic("Reboot failed!");}EXPORT_SYMBOL(machine_restart);static void show_regwindow32(struct pt_regs *regs){ struct reg_window32 __user *rw; struct reg_window32 r_w; mm_segment_t old_fs; __asm__ __volatile__ ("flushw"); rw = (struct reg_window32 __user *)((long)(unsigned)regs->u_regs[14]); old_fs = get_fs(); set_fs (USER_DS); if (copy_from_user (&r_w, rw, sizeof(r_w))) { set_fs (old_fs); return; } set_fs (old_fs); printk("l0: %08x l1: %08x l2: %08x l3: %08x " "l4: %08x l5: %08x l6: %08x l7: %08x\n", r_w.locals[0], r_w.locals[1], r_w.locals[2], r_w.locals[3], r_w.locals[4], r_w.locals[5], r_w.locals[6], r_w.locals[7]); printk("i0: %08x i1: %08x i2: %08x i3: %08x " "i4: %08x i5: %08x i6: %08x i7: %08x\n", r_w.ins[0], r_w.ins[1], r_w.ins[2], r_w.ins[3], r_w.ins[4], r_w.ins[5], r_w.ins[6], r_w.ins[7]);}static void show_regwindow(struct pt_regs *regs){ struct reg_window __user *rw; struct reg_window *rwk; struct reg_window r_w; mm_segment_t old_fs; if ((regs->tstate & TSTATE_PRIV) || !(test_thread_flag(TIF_32BIT))) { __asm__ __volatile__ ("flushw"); rw = (struct reg_window __user *) (regs->u_regs[14] + STACK_BIAS); rwk = (struct reg_window *) (regs->u_regs[14] + STACK_BIAS); if (!(regs->tstate & TSTATE_PRIV)) { old_fs = get_fs(); set_fs (USER_DS); if (copy_from_user (&r_w, rw, sizeof(r_w))) { set_fs (old_fs); return; } rwk = &r_w; set_fs (old_fs); } } else { show_regwindow32(regs); return; } printk("l0: %016lx l1: %016lx l2: %016lx l3: %016lx\n", rwk->locals[0], rwk->locals[1], rwk->locals[2], rwk->locals[3]); printk("l4: %016lx l5: %016lx l6: %016lx l7: %016lx\n", rwk->locals[4], rwk->locals[5], rwk->locals[6], rwk->locals[7]); printk("i0: %016lx i1: %016lx i2: %016lx i3: %016lx\n", rwk->ins[0], rwk->ins[1], rwk->ins[2], rwk->ins[3]); printk("i4: %016lx i5: %016lx i6: %016lx i7: %016lx\n", rwk->ins[4], rwk->ins[5], rwk->ins[6], rwk->ins[7]); if (regs->tstate & TSTATE_PRIV) print_symbol("I7: <%s>\n", rwk->ins[7]);}void show_stackframe(struct sparc_stackf *sf){ unsigned long size; unsigned long *stk; int i; printk("l0: %016lx l1: %016lx l2: %016lx l3: %016lx\n" "l4: %016lx l5: %016lx l6: %016lx l7: %016lx\n", sf->locals[0], sf->locals[1], sf->locals[2], sf->locals[3], sf->locals[4], sf->locals[5], sf->locals[6], sf->locals[7]); printk("i0: %016lx i1: %016lx i2: %016lx i3: %016lx\n" "i4: %016lx i5: %016lx fp: %016lx ret_pc: %016lx\n", sf->ins[0], sf->ins[1], sf->ins[2], sf->ins[3], sf->ins[4], sf->ins[5], (unsigned long)sf->fp, sf->callers_pc); printk("sp: %016lx x0: %016lx x1: %016lx x2: %016lx\n" "x3: %016lx x4: %016lx x5: %016lx xx: %016lx\n", (unsigned long)sf->structptr, sf->xargs[0], sf->xargs[1], sf->xargs[2], sf->xargs[3], sf->xargs[4], sf->xargs[5], sf->xxargs[0]); size = ((unsigned long)sf->fp) - ((unsigned long)sf); size -= STACKFRAME_SZ; stk = (unsigned long *)((unsigned long)sf + STACKFRAME_SZ); i = 0; do { printk("s%d: %016lx\n", i++, *stk++); } while ((size -= sizeof(unsigned long)));}void show_stackframe32(struct sparc_stackf32 *sf){ unsigned long size; unsigned *stk; int i; printk("l0: %08x l1: %08x l2: %08x l3: %08x\n", sf->locals[0], sf->locals[1], sf->locals[2], sf->locals[3]); printk("l4: %08x l5: %08x l6: %08x l7: %08x\n", sf->locals[4], sf->locals[5], sf->locals[6], sf->locals[7]); printk("i0: %08x i1: %08x i2: %08x i3: %08x\n", sf->ins[0], sf->ins[1], sf->ins[2], sf->ins[3]); printk("i4: %08x i5: %08x fp: %08x ret_pc: %08x\n", sf->ins[4], sf->ins[5], sf->fp, sf->callers_pc); printk("sp: %08x x0: %08x x1: %08x x2: %08x\n" "x3: %08x x4: %08x x5: %08x xx: %08x\n", sf->structptr, sf->xargs[0], sf->xargs[1], sf->xargs[2], sf->xargs[3], sf->xargs[4], sf->xargs[5], sf->xxargs[0]); size = ((unsigned long)sf->fp) - ((unsigned long)sf); size -= STACKFRAME32_SZ; stk = (unsigned *)((unsigned long)sf + STACKFRAME32_SZ); i = 0; do { printk("s%d: %08x\n", i++, *stk++); } while ((size -= sizeof(unsigned)));}#ifdef CONFIG_SMPstatic spinlock_t regdump_lock = SPIN_LOCK_UNLOCKED;#endifvoid __show_regs(struct pt_regs * regs){#ifdef CONFIG_SMP unsigned long flags; /* Protect against xcall ipis which might lead to livelock on the lock */ __asm__ __volatile__("rdpr %%pstate, %0\n\t" "wrpr %0, %1, %%pstate" : "=r" (flags) : "i" (PSTATE_IE)); spin_lock(®dump_lock);#endif printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x %s\n", regs->tstate, regs->tpc, regs->tnpc, regs->y, print_tainted()); print_symbol("TPC: <%s>\n", regs->tpc); printk("g0: %016lx g1: %016lx g2: %016lx g3: %016lx\n", regs->u_regs[0], regs->u_regs[1], regs->u_regs[2], regs->u_regs[3]); printk("g4: %016lx g5: %016lx g6: %016lx g7: %016lx\n", regs->u_regs[4], regs->u_regs[5], regs->u_regs[6], regs->u_regs[7]); printk("o0: %016lx o1: %016lx o2: %016lx o3: %016lx\n", regs->u_regs[8], regs->u_regs[9], regs->u_regs[10], regs->u_regs[11]); printk("o4: %016lx o5: %016lx sp: %016lx ret_pc: %016lx\n", regs->u_regs[12], regs->u_regs[13], regs->u_regs[14], regs->u_regs[15]); print_symbol("RPC: <%s>\n", regs->u_regs[15]); show_regwindow(regs);#ifdef CONFIG_SMP spin_unlock(®dump_lock); __asm__ __volatile__("wrpr %0, 0, %%pstate" : : "r" (flags));#endif}#ifdef VERBOSE_SHOWREGSstatic void idump_from_user (unsigned int *pc){ int i; int code; if((((unsigned long) pc) & 3)) return; pc -= 3; for(i = -3; i < 6; i++) { get_user(code, pc); printk("%c%08x%c",i?' ':'<',code,i?' ':'>'); pc++; } printk("\n");}#endifvoid show_regs(struct pt_regs *regs){#ifdef VERBOSE_SHOWREGS extern long etrap, etraptl1;#endif __show_regs(regs);#ifdef CONFIG_SMP { extern void smp_report_regs(void); smp_report_regs(); }#endif#ifdef VERBOSE_SHOWREGS if (regs->tpc >= &etrap && regs->tpc < &etraptl1 && regs->u_regs[14] >= (long)current - PAGE_SIZE && regs->u_regs[14] < (long)current + 6 * PAGE_SIZE) { printk ("*********parent**********\n"); __show_regs((struct pt_regs *)(regs->u_regs[14] + PTREGS_OFF)); idump_from_user(((struct pt_regs *)(regs->u_regs[14] + PTREGS_OFF))->tpc); printk ("*********endpar**********\n"); }#endif}void show_regs32(struct pt_regs32 *regs){ printk("PSR: %08x PC: %08x NPC: %08x Y: %08x %s\n", regs->psr, regs->pc, regs->npc, regs->y, print_tainted()); printk("g0: %08x g1: %08x g2: %08x g3: %08x ", regs->u_regs[0], regs->u_regs[1], regs->u_regs[2], regs->u_regs[3]); printk("g4: %08x g5: %08x g6: %08x g7: %08x\n", regs->u_regs[4], regs->u_regs[5], regs->u_regs[6], regs->u_regs[7]); printk("o0: %08x o1: %08x o2: %08x o3: %08x ", regs->u_regs[8], regs->u_regs[9], regs->u_regs[10], regs->u_regs[11]); printk("o4: %08x o5: %08x sp: %08x ret_pc: %08x\n", regs->u_regs[12], regs->u_regs[13], regs->u_regs[14], regs->u_regs[15]);}unsigned long thread_saved_pc(struct task_struct *tsk){ struct thread_info *ti = tsk->thread_info; unsigned long ret = 0xdeadbeefUL; if (ti && ti->ksp) { unsigned long *sp; sp = (unsigned long *)(ti->ksp + STACK_BIAS); if (((unsigned long)sp & (sizeof(long) - 1)) == 0UL && sp[14]) { unsigned long *fp; fp = (unsigned long *)(sp[14] + STACK_BIAS); if (((unsigned long)fp & (sizeof(long) - 1)) == 0UL) ret = fp[15]; } } return ret;}/* Free current thread data structures etc.. */void exit_thread(void){ struct thread_info *t = current_thread_info(); if (t->utraps) { if (t->utraps[0] < 2) kfree (t->utraps); else t->utraps[0]--; } if (test_and_clear_thread_flag(TIF_PERFCTR)) { t->user_cntd0 = t->user_cntd1 = NULL; t->pcr_reg = 0; write_pcr(0); }}void flush_thread(void){ struct thread_info *t = current_thread_info(); if (t->flags & _TIF_ABI_PENDING) t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT); if (t->task->mm) { unsigned long pgd_cache = 0UL; if (test_thread_flag(TIF_32BIT)) { struct mm_struct *mm = t->task->mm; pgd_t *pgd0 = &mm->pgd[0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -