URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [ppc/] [kernel/] [process.c] - Rev 1765
Compare with Previous | Blame | View Log
/* * linux/arch/ppc/kernel/process.c * * Copyright (C) 1995 Linus Torvalds * Adapted for PowerPC by Gary Thomas */ /* * This file handles the architecture-dependent parts of process handling.. */ #include <linux/errno.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/mm.h> #include <linux/stddef.h> #include <linux/unistd.h> #include <linux/ptrace.h> #include <linux/malloc.h> #include <linux/ldt.h> #include <linux/user.h> #include <linux/a.out.h> #include <asm/pgtable.h> #include <asm/segment.h> #include <asm/system.h> #include <asm/io.h> #include <asm/ppc_machine.h> int dump_fpu() { return (1); } void switch_to(struct task_struct *prev, struct task_struct *new) { struct pt_regs *regs; struct thread_struct *new_tss, *old_tss; int s = _disable_interrupts(); regs = new->tss.ksp; #if 0 printk("Task %x(%d) -> %x(%d)", current, current->pid, new, new->pid); printk(" - IP: %x, SR: %x, SP: %x\n", regs->nip, regs->msr, regs); #endif new_tss = &new->tss; old_tss = ¤t->tss; current_set[0] = new; /* FIX ME! */ _switch(old_tss, new_tss); #if 0 printk("Back in task %x(%d)\n", current, current->pid); #endif _enable_interrupts(s); } asmlinkage int sys_idle(void) { if (current->pid != 0) return -EPERM; /* endless idle loop with no priority at all */ current->counter = -100; for (;;) { schedule(); } } void hard_reset_now(void) { halt(); } void show_regs(struct pt_regs * regs) { _panic("show_regs"); } /* * Free current thread data structures etc.. */ void exit_thread(void) { } void flush_thread(void) { } void release_thread(struct task_struct *t) { } /* * Copy a thread.. */ void copy_thread(int nr, unsigned long clone_flags, unsigned long usp, struct task_struct * p, struct pt_regs * regs) { int i; SEGREG *segs; struct pt_regs * childregs; #if 0 printk("copy thread - NR: %d, Flags: %x, USP: %x, Task: %x, Regs: %x\n", nr, clone_flags, usp, p, regs); #endif /* Construct segment registers */ segs = p->tss.segs; for (i = 0; i < 8; i++) { segs[i].ks = 0; segs[i].kp = 1; segs[i].vsid = i | (nr << 4); } if ((p->mm->context == 0) || (p->mm->count == 1)) { p->mm->context = (nr<<4); #if 0 printk("Setting MM[%x] Context = %x Task = %x Current = %x/%x\n", p->mm, p->mm->context, p, current, current->mm); #endif } /* Last 8 are shared with kernel & everybody else... */ for (i = 8; i < 16; i++) { segs[i].ks = 0; segs[i].kp = 1; segs[i].vsid = i; } /* Copy registers */ #ifdef STACK_HAS_TWO_PAGES childregs = ((struct pt_regs *) (p->kernel_stack_page + 2*PAGE_SIZE)) - 2; #else childregs = ((struct pt_regs *) (p->kernel_stack_page + 1*PAGE_SIZE)) - 2; #endif *childregs = *regs; /* STRUCT COPY */ childregs->gpr[3] = 0; /* Result from fork() */ p->tss.ksp = childregs; if (usp >= (unsigned long)regs) { /* Stack is in kernel space - must adjust */ childregs->gpr[1] = childregs+1; } else { /* Provided stack is in user space */ childregs->gpr[1] = usp; } } /* * fill in the user structure for a core dump.. */ void dump_thread(struct pt_regs * regs, struct user * dump) { } #if 0 /* * Do necessary setup to start up a newly executed thread. */ void start_thread(struct pt_regs * regs, unsigned long eip, unsigned long esp) { regs->nip = eip; regs->gpr[1] = esp; regs->msr = MSR_USER; #if 0 { int len; len = (unsigned long)0x80000000 - esp; if (len > 128) len = 128; printk("Start thread [%x] at PC: %x, SR: %x, SP: %x\n", regs, eip, regs->msr, esp); dump_buf(esp, len); dump_buf(eip, 0x80); } #endif } #endif asmlinkage 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); } /* * sys_execve() executes a new program. * * This works due to the PowerPC calling sequence: the first 6 args * are gotten from registers, while the rest is on the stack, so * we get a0-a5 for free, and then magically find "struct pt_regs" * on the stack for us.. * * Don't do this at home. */ asmlinkage 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; error = getname((char *) a0, &filename); if (error) { printk("Error getting EXEC name: %d\n", error); return error; } flush_instruction_cache(); error = do_execve(filename, (char **) a1, (char **) a2, regs); #if 0 if (error) { printk("EXECVE - file = '%s', error = %d\n", filename, error); } #endif putname(filename); return error; } /* * This doesn't actually work correctly like this: we need to do the * same stack setups that fork() does first. */ asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs) { unsigned long clone_flags = p1; int res; res = do_fork(clone_flags, regs->gpr[1], regs); return res; } void print_backtrace(unsigned long *sp) { int cnt = 0; printk("... Call backtrace:\n"); while (*sp) { printk("%08X ", sp[1]); sp = *sp; if (++cnt == 8) { printk("\n"); } if (cnt > 32) break; } printk("\n"); } void print_user_backtrace(unsigned long *sp) { int cnt = 0; printk("... [User] Call backtrace:\n"); while (valid_addr(sp) && *sp) { printk("%08X ", sp[1]); sp = *sp; if (++cnt == 8) { printk("\n"); } if (cnt > 16) break; } printk("\n"); } void print_kernel_backtrace(void) { unsigned long *_get_SP(void); print_backtrace(_get_SP()); }