root/arch/alpha/kernel/process.c

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

DEFINITIONS

This source file includes following definitions.
  1. sys_sethae
  2. sys_idle
  3. hard_reset_now
  4. show_regs
  5. exit_thread
  6. flush_thread
  7. release_thread
  8. alpha_clone
  9. copy_thread
  10. dump_thread
  11. sys_execve

   1 /*
   2  *  linux/arch/alpha/kernel/process.c
   3  *
   4  *  Copyright (C) 1995  Linus Torvalds
   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 #include <linux/utsname.h>
  23 #include <linux/time.h>
  24 #include <linux/major.h>
  25 #include <linux/stat.h>
  26 #include <linux/mman.h>
  27 
  28 #include <asm/reg.h>
  29 #include <asm/segment.h>
  30 #include <asm/system.h>
  31 #include <asm/io.h>
  32 
  33 asmlinkage int sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2,
     /* [previous][next][first][last][top][bottom][index][help] */
  34         unsigned long a3, unsigned long a4, unsigned long a5,
  35         struct pt_regs regs)
  36 {
  37         (&regs)->hae = hae;
  38         return 0;
  39 }
  40 
  41 asmlinkage int sys_idle(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  42 {
  43         if (current->pid != 0)
  44                 return -EPERM;
  45 
  46         /* endless idle loop with no priority at all */
  47         current->counter = -100;
  48         for (;;) {
  49                 schedule();
  50         }
  51 }
  52 
  53 void hard_reset_now(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  54 {
  55         halt();
  56 }
  57 
  58 void show_regs(struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
  59 {
  60         printk("\nps: %04lx pc: [<%016lx>]\n", regs->ps, regs->pc);
  61         printk("rp: [<%016lx>] sp: %p\n", regs->r26, regs+1);
  62         printk(" r0: %016lx  r1: %016lx  r2: %016lx  r3: %016lx\n",
  63                regs->r0, regs->r1, regs->r2, regs->r3);
  64         printk(" r4: %016lx  r5: %016lx  r6: %016lx  r7: %016lx\n",
  65                regs->r4, regs->r5, regs->r6, regs->r7);
  66         printk(" r8: %016lx r16: %016lx r17: %016lx r18: %016lx\n",
  67                regs->r8, regs->r16, regs->r17, regs->r18);
  68         printk("r19: %016lx r20: %016lx r21: %016lx r22: %016lx\n",
  69                regs->r19, regs->r20, regs->r21, regs->r22);
  70         printk("r23: %016lx r24: %016lx r25: %016lx r26: %016lx\n",
  71                regs->r23, regs->r24, regs->r25, regs->r26);
  72         printk("r27: %016lx r28: %016lx r29: %016lx hae: %016lx\n",
  73                regs->r27, regs->r28, regs->gp, regs->hae);
  74 }
  75 
  76 /*
  77  * Free current thread data structures etc..
  78  */
  79 void exit_thread(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  80 {
  81 }
  82 
  83 void flush_thread(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  84 {
  85 }
  86 
  87 void release_thread(struct task_struct *dead_task)
     /* [previous][next][first][last][top][bottom][index][help] */
  88 {
  89 }
  90 
  91 /*
  92  * "alpha_clone()".. By the time we get here, the
  93  * non-volatile registers have also been saved on the
  94  * stack. We do some ugly pointer stuff here.. (see
  95  * also copy_thread)
  96  *
  97  * Notice that "fork()" is implemented in terms of clone,
  98  * with parameters (SIGCHLD, 0).
  99  */
 100 int alpha_clone(unsigned long clone_flags, unsigned long usp,
     /* [previous][next][first][last][top][bottom][index][help] */
 101         struct switch_stack * swstack)
 102 {
 103         if (!usp)
 104                 usp = rdusp();
 105         return do_fork(clone_flags, usp, (struct pt_regs *) (swstack+1));
 106 }
 107 
 108 extern void ret_from_sys_call(void);
 109 /*
 110  * Copy an alpha thread..
 111  *
 112  * Note the "stack_offset" stuff: when returning to kernel mode, we need
 113  * to have some extra stack-space for the kernel stack that still exists
 114  * after the "ret_from_sys_call". When returning to user mode, we only
 115  * want the space needed by the syscall stack frame (ie "struct pt_regs").
 116  * Use the passed "regs" pointer to determine how much space we need
 117  * for a kernel fork().
 118  */
 119 void copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
     /* [previous][next][first][last][top][bottom][index][help] */
 120         struct task_struct * p, struct pt_regs * regs)
 121 {
 122         struct pt_regs * childregs;
 123         struct switch_stack * childstack, *stack;
 124         unsigned long stack_offset;
 125 
 126         stack_offset = PAGE_SIZE - sizeof(struct pt_regs);
 127         if (!(regs->ps & 8))
 128                 stack_offset = (PAGE_SIZE-1) & (unsigned long) regs;
 129         childregs = (struct pt_regs *) (p->kernel_stack_page + stack_offset);
 130                 
 131         *childregs = *regs;
 132         childregs->r0 = 0;
 133         childregs->r19 = 0;
 134         childregs->r20 = 1;     /* OSF/1 has some strange fork() semantics.. */
 135         regs->r20 = 0;
 136         stack = ((struct switch_stack *) regs) - 1;
 137         childstack = ((struct switch_stack *) childregs) - 1;
 138         *childstack = *stack;
 139         childstack->r26 = (unsigned long) ret_from_sys_call;
 140         p->tss.usp = usp;
 141         p->tss.ksp = (unsigned long) childstack;
 142         p->tss.flags = 1;
 143         p->mm->context = 0;
 144 }
 145 
 146 /*
 147  * fill in the user structure for a core dump..
 148  */
 149 void dump_thread(struct pt_regs * pt, struct user * dump)
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151         /* switch stack follows right below pt_regs: */
 152         struct switch_stack * sw = ((struct switch_stack *) pt) - 1;
 153 
 154         dump->magic = CMAGIC;
 155         dump->start_code  = current->mm->start_code;
 156         dump->start_data  = current->mm->start_data;
 157         dump->start_stack = rdusp() & ~(PAGE_SIZE - 1);
 158         dump->u_tsize = (current->mm->end_code - dump->start_code) >> PAGE_SHIFT;
 159         dump->u_dsize = (current->mm->brk + (PAGE_SIZE - 1) - dump->start_data) >> PAGE_SHIFT;
 160         dump->u_ssize =
 161           (current->mm->start_stack - dump->start_stack + PAGE_SIZE - 1) >> PAGE_SHIFT;
 162 
 163         /*
 164          * We store the registers in an order/format that is
 165          * compatible with DEC Unix/OSF/1 as this makes life easier
 166          * for gdb.
 167          */
 168         dump->regs[EF_V0]  = pt->r0;
 169         dump->regs[EF_T0]  = pt->r1;
 170         dump->regs[EF_T1]  = pt->r2;
 171         dump->regs[EF_T2]  = pt->r3;
 172         dump->regs[EF_T3]  = pt->r4;
 173         dump->regs[EF_T4]  = pt->r5;
 174         dump->regs[EF_T5]  = pt->r6;
 175         dump->regs[EF_T6]  = pt->r7;
 176         dump->regs[EF_T7]  = pt->r8;
 177         dump->regs[EF_S0]  = sw->r9;
 178         dump->regs[EF_S1]  = sw->r10;
 179         dump->regs[EF_S2]  = sw->r11;
 180         dump->regs[EF_S3]  = sw->r12;
 181         dump->regs[EF_S4]  = sw->r13;
 182         dump->regs[EF_S5]  = sw->r14;
 183         dump->regs[EF_S6]  = sw->r15;
 184         dump->regs[EF_A3]  = pt->r19;
 185         dump->regs[EF_A4]  = pt->r20;
 186         dump->regs[EF_A5]  = pt->r21;
 187         dump->regs[EF_T8]  = pt->r22;
 188         dump->regs[EF_T9]  = pt->r23;
 189         dump->regs[EF_T10] = pt->r24;
 190         dump->regs[EF_T11] = pt->r25;
 191         dump->regs[EF_RA]  = pt->r26;
 192         dump->regs[EF_T12] = pt->r27;
 193         dump->regs[EF_AT]  = pt->r28;
 194         dump->regs[EF_SP]  = rdusp();
 195         dump->regs[EF_PS]  = pt->ps;
 196         dump->regs[EF_PC]  = pt->pc;
 197         dump->regs[EF_GP]  = pt->gp;
 198         dump->regs[EF_A0]  = pt->r16;
 199         dump->regs[EF_A1]  = pt->r17;
 200         dump->regs[EF_A2]  = pt->r18;
 201         memcpy((char *)dump->regs + EF_SIZE, sw->fp, 32 * 8);
 202 }
 203 
 204 /*
 205  * sys_execve() executes a new program.
 206  *
 207  * This works due to the alpha calling sequence: the first 6 args
 208  * are gotten from registers, while the rest is on the stack, so
 209  * we get a0-a5 for free, and then magically find "struct pt_regs"
 210  * on the stack for us..
 211  *
 212  * Don't do this at home.
 213  */
 214 asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
     /* [previous][next][first][last][top][bottom][index][help] */
 215         unsigned long a3, unsigned long a4, unsigned long a5,
 216         struct pt_regs regs)
 217 {
 218         int error;
 219         char * filename;
 220 
 221         error = getname((char *) a0, &filename);
 222         if (error)
 223                 return error;
 224         error = do_execve(filename, (char **) a1, (char **) a2, &regs);
 225         putname(filename);
 226         return error;
 227 }

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