root/arch/sparc/kernel/process.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sys_idle
  2. hard_reset_now
  3. show_regwindow
  4. show_regs
  5. exit_thread
  6. release_thread
  7. flush_thread
  8. copy_thread
  9. dump_thread
  10. dump_fpu
  11. sparc_execve
  12. start_thread

   1 /*  $Id: process.c,v 1.29 1995/11/25 00:58:17 davem Exp $
   2  *  linux/arch/sparc/kernel/process.c
   3  *
   4  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
   5  */
   6 
   7 /*
   8  * This file handles the architecture-dependent parts of process handling..
   9  */
  10 
  11 #include <linux/errno.h>
  12 #include <linux/sched.h>
  13 #include <linux/kernel.h>
  14 #include <linux/mm.h>
  15 #include <linux/stddef.h>
  16 #include <linux/unistd.h>
  17 #include <linux/ptrace.h>
  18 #include <linux/malloc.h>
  19 #include <linux/ldt.h>
  20 #include <linux/user.h>
  21 #include <linux/a.out.h>
  22 
  23 #include <asm/auxio.h>
  24 #include <asm/oplib.h>
  25 #include <asm/segment.h>
  26 #include <asm/system.h>
  27 #include <asm/page.h>
  28 #include <asm/pgtable.h>
  29 #include <asm/processor.h>
  30 #include <asm/psr.h>
  31 
  32 int current_user_segment = USER_DS; /* the return value from get_fs */
  33 
  34 /*
  35  * the idle loop on a Sparc... ;)
  36  */
  37 asmlinkage int sys_idle(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  38 {
  39         if (current->pid != 0)
  40                 return -EPERM;
  41 
  42         /* endless idle loop with no priority at all */
  43         current->counter = -100;
  44         for (;;) {
  45                 schedule();
  46         }
  47 }
  48 
  49 void hard_reset_now(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  50 {
  51         prom_halt();
  52 }
  53 
  54 void show_regwindow(struct reg_window *rw)
     /* [previous][next][first][last][top][bottom][index][help] */
  55 {
  56         printk("l0:%08lx l1:%08lx l2:%08lx l3:%08lx l4:%08lx l5:%08lx l6:%08lx l7:%08lx\n",
  57                rw->locals[0], rw->locals[1], rw->locals[2], rw->locals[3],
  58                rw->locals[4], rw->locals[5], rw->locals[6], rw->locals[7]);
  59         printk("i0:%08lx i1:%08lx i2:%08lx i3:%08lx i4:%08lx i5:%08lx i6:%08lx i7:%08lx\n",
  60                rw->ins[0], rw->ins[1], rw->ins[2], rw->ins[3],
  61                rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]);
  62 }
  63 
  64 void show_regs(struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
  65 {
  66         printk("PSR: %08lx PC: %08lx NPC: %08lx Y: %08lx\n", regs->psr,
  67                regs->pc, regs->npc, regs->y);
  68         printk("%%g0: %08lx %%g1: %08lx %%g2: %08lx %%g3: %08lx\n",
  69                regs->u_regs[0], regs->u_regs[1], regs->u_regs[2],
  70                regs->u_regs[3]);
  71         printk("%%g4: %08lx %%g5: %08lx %%g6: %08lx %%g7: %08lx\n",
  72                regs->u_regs[4], regs->u_regs[5], regs->u_regs[6],
  73                regs->u_regs[7]);
  74         printk("%%o0: %08lx %%o1: %08lx %%o2: %08lx %%o3: %08lx\n",
  75                regs->u_regs[8], regs->u_regs[9], regs->u_regs[10],
  76                regs->u_regs[11]);
  77         printk("%%o4: %08lx %%o5: %08lx %%sp: %08lx %%ret_pc: %08lx\n",
  78                regs->u_regs[12], regs->u_regs[13], regs->u_regs[14],
  79                regs->u_regs[15]);
  80 }
  81 
  82 /*
  83  * Free current thread data structures etc..
  84  */
  85 void exit_thread(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  86 {
  87         if(last_task_used_math == current)
  88                 last_task_used_math = NULL;
  89         mmu_exit_hook(current);
  90 }
  91 
  92 /*
  93  * Free old dead task when we know it can never be on the cpu again.
  94  */
  95 void release_thread(struct task_struct *dead_task)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97         mmu_release_hook(dead_task);
  98 }
  99 
 100 void flush_thread(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102         /* Make sure old user windows don't get in the way. */
 103         mmu_flush_hook(current);
 104         flush_user_windows();
 105         current->signal &= ~(1<<(SIGILL-1));
 106         current->tss.w_saved = 0;
 107         current->tss.uwinmask = 0;
 108 
 109         current->tss.sig_address = 0;
 110         current->tss.sig_desc = 0;
 111 
 112         /* Signal stack state does not inherit. XXX Really? XXX */
 113         current->tss.sstk_info.cur_status = 0;
 114         current->tss.sstk_info.the_stack = 0;
 115 
 116         memset(&current->tss.reg_window[0], 0,
 117                (sizeof(struct reg_window) * NSWINS));
 118         memset(&current->tss.rwbuf_stkptrs[0], 0,
 119                (sizeof(unsigned long) * NSWINS));
 120 }
 121 
 122 /*
 123  * Copy a Sparc thread.  The fork() return value conventions
 124  * under SunOS are nothing short of bletcherous:
 125  * Parent -->  %o0 == childs  pid, %o1 == 0
 126  * Child  -->  %o0 == parents pid, %o1 == 1
 127  *
 128  * I'm feeling sick...
 129  */
 130 extern void ret_sys_call(void);
 131 
 132 void copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
     /* [previous][next][first][last][top][bottom][index][help] */
 133                  struct task_struct *p, struct pt_regs *regs)
 134 {
 135         struct pt_regs *childregs;
 136         struct sparc_stackf *old_stack, *new_stack;
 137         unsigned long stack_offset, kthread_usp = 0;
 138 
 139         mmu_task_cacheflush(current);
 140         p->tss.context = -1;
 141 
 142         /* Calculate offset to stack_frame & pt_regs */
 143         stack_offset = (PAGE_SIZE - TRACEREG_SZ);
 144         childregs = ((struct pt_regs *) (p->kernel_stack_page + stack_offset));
 145         *childregs = *regs;
 146         new_stack = (((struct sparc_stackf *) childregs) - 1);
 147         old_stack = (((struct sparc_stackf *) regs) - 1);
 148         *new_stack = *old_stack;
 149         p->tss.ksp = (unsigned long) new_stack;
 150         p->tss.kpc = (((unsigned long) ret_sys_call) - 0x8);
 151 
 152         /* As a special case, if this is a kernel fork we need
 153          * to give the child a new fresh stack for when it returns
 154          * from the syscall. (ie. the "user" stack)  This happens
 155          * only once and we count on the page acquisition happening
 156          * successfully.
 157          */
 158         if(regs->psr & PSR_PS) {
 159                  unsigned long n_stack = get_free_page(GFP_KERNEL);
 160                  childregs->u_regs[UREG_FP] = (n_stack | (sp & 0xfff));
 161                  memcpy((char *)n_stack,(char *)(sp & PAGE_MASK),PAGE_SIZE);
 162                  kthread_usp = n_stack;
 163         }
 164 
 165         /* Set the return value for the child. */
 166         childregs->u_regs[UREG_I0] = current->pid;
 167         childregs->u_regs[UREG_I1] = 1;
 168 
 169         /* Set the return value for the parent. */
 170         regs->u_regs[UREG_I1] = 0;
 171 
 172         mmu_fork_hook(p, kthread_usp);
 173 }
 174 
 175 /*
 176  * fill in the user structure for a core dump..
 177  */
 178 void dump_thread(struct pt_regs * regs, struct user * dump)
     /* [previous][next][first][last][top][bottom][index][help] */
 179 {
 180 }
 181 
 182 /*
 183  * fill in the fpu structure for a core dump.
 184  */
 185 int dump_fpu (void *fpu_structure)
     /* [previous][next][first][last][top][bottom][index][help] */
 186 {
 187         /* Currently we report that we couldn't dump the fpu structure */
 188         return 0;
 189 }
 190 
 191 /*
 192  * sparc_execve() executes a new program after the asm stub has set
 193  * things up for us.  This should basically do what I want it to.
 194  */
 195 asmlinkage int sparc_execve(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 196 {
 197         int error;
 198         char *filename;
 199 
 200         flush_user_windows();
 201         mmu_task_cacheflush(current);
 202         error = getname((char *) regs->u_regs[UREG_I0], &filename);
 203         if(error)
 204                 return error;
 205         error = do_execve(filename, (char **) regs->u_regs[UREG_I1],
 206                           (char **) regs->u_regs[UREG_I2], regs);
 207         putname(filename);
 208         return error;
 209 }
 210 
 211 void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
     /* [previous][next][first][last][top][bottom][index][help] */
 212 {
 213         unsigned long saved_psr = (regs->psr & (PSR_CWP)) | PSR_S;
 214 
 215         memset(regs, 0, sizeof(struct pt_regs));
 216         regs->pc = ((pc & (~3)) - 4); /* whee borken a.out header fields... */
 217         regs->npc = regs->pc + 4;
 218         regs->psr = saved_psr;
 219         regs->u_regs[UREG_G1] = sp; /* Base of arg/env stack area */
 220 
 221         /* XXX More mysterious netbsd garbage... XXX */
 222         regs->u_regs[UREG_G2] = regs->u_regs[UREG_G7] = regs->npc;
 223 
 224         /* Allocate one reg window because the first jump into
 225          * user mode will restore one register window by definition
 226          * of the 'rett' instruction.  Also, SunOS crt.o code
 227          * depends upon the arg/envp area being _exactly_ one
 228          * register window above %sp when the process begins
 229          * execution.
 230          */
 231         sp -= REGWIN_SZ;
 232         regs->u_regs[UREG_FP] = sp;
 233 }

/* [previous][next][first][last][top][bottom][index][help] */