File: /usr/src/linux/arch/parisc/kernel/process.c

1     /*
2      *  linux/arch/parisc/kernel/process.c
3      *	based on the work for i386
4      */
5     
6     /*
7      * This file handles the architecture-dependent parts of process handling..
8      */
9     
10     #define __KERNEL_SYSCALLS__
11     #include <stdarg.h>
12     
13     #include <linux/errno.h>
14     #include <linux/sched.h>
15     #include <linux/kernel.h>
16     #include <linux/mm.h>
17     #include <linux/smp.h>
18     #include <linux/smp_lock.h>
19     #include <linux/stddef.h>
20     #include <linux/unistd.h>
21     #include <linux/ptrace.h>
22     #include <linux/slab.h>
23     #include <linux/vmalloc.h>
24     #include <linux/interrupt.h>
25     #include <linux/reboot.h>
26     #include <linux/init.h>
27     #include <linux/version.h>
28     #include <linux/elf.h>
29     
30     #include <asm/machdep.h>
31     #include <asm/offset.h>
32     #include <asm/uaccess.h>
33     #include <asm/pgtable.h>
34     #include <asm/system.h>
35     #include <asm/io.h>
36     #include <asm/gsc.h>
37     #include <asm/processor.h>
38     
39     spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED;
40     
41     #ifdef __LP64__
42     /* The 64-bit code should work equally well in 32-bit land but I didn't
43      * want to take the time to confirm that.  -PB
44      */
45     extern unsigned int ret_from_kernel_thread;
46     #else
47     asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread");
48     #endif
49     
50     
51     int hlt_counter=0;
52     
53     void disable_hlt(void)
54     {
55     	hlt_counter++;
56     }
57     
58     void enable_hlt(void)
59     {
60     	hlt_counter--;
61     }
62     
63     /*
64      * The idle thread. There's no useful work to be
65      * done, so just try to conserve power and have a
66      * low exit latency (ie sit in a loop waiting for
67      * somebody to say that they'd like to reschedule)
68      */
69     void cpu_idle(void)
70     {
71     	/* endless idle loop with no priority at all */
72     	init_idle();
73     	current->nice = 20;
74     	current->counter = -100;
75     
76     	while (1) {
77     		while (!current->need_resched) {
78     		}
79     		schedule();
80     		check_pgt_cache();
81     	}
82     }
83     
84     void __init reboot_setup(char *str, int *ints)
85     {
86     }
87     
88     struct notifier_block *mach_notifier;
89     
90     void machine_restart(char *ptr)
91     {
92     	notifier_call_chain(&mach_notifier, MACH_RESTART, ptr);
93     }
94     
95     void machine_halt(void)
96     {
97     	notifier_call_chain(&mach_notifier, MACH_HALT, NULL);
98     }
99     
100     void machine_power_on(void)
101     {
102     	notifier_call_chain(&mach_notifier, MACH_POWER_ON, NULL);
103     }
104     
105     void machine_power_off(void)
106     {
107     	notifier_call_chain(&mach_notifier, MACH_POWER_OFF, NULL);
108     }
109     
110     
111     void machine_heartbeat(void)
112     {
113     }
114     
115     
116     /*
117      * Create a kernel thread
118      */
119     
120     extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
121     pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
122     {
123     
124     	/*
125     	 * FIXME: Once we are sure we don't need any debug here,
126     	 *	  kernel_thread can become a #define.
127     	 */
128     
129     	return __kernel_thread(fn, arg, flags);
130     }
131     
132     /*
133      * Free current thread data structures etc..
134      */
135     void exit_thread(void)
136     {
137     }
138     
139     void flush_thread(void)
140     {
141     	set_fs(USER_DS);
142     }
143     
144     void release_thread(struct task_struct *dead_task)
145     {
146     }
147     
148     /*
149      * Fill in the FPU structure for a core dump.
150      */
151     int dump_fpu (struct pt_regs * regs, elf_fpregset_t *r)
152     {
153     	memcpy(r, regs->fr, sizeof *r);
154     	return 1;
155     }
156     
157     /* Note that "fork()" is implemented in terms of clone, with
158        parameters (SIGCHLD, regs->gr[30], regs). */
159     int
160     sys_clone(unsigned long clone_flags, unsigned long usp,
161     	  struct pt_regs *regs)
162     {
163     	return do_fork(clone_flags, usp, regs, 0);
164     }
165     
166     int
167     sys_vfork(struct pt_regs *regs)
168     {
169     	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
170     		       regs->gr[30], regs, 0);
171     }
172     
173     int
174     copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
175     	    unsigned long unused,	/* in ia64 this is "user_stack_size" */
176     	    struct task_struct * p, struct pt_regs * pregs)
177     {
178     	struct pt_regs * cregs = &(p->thread.regs);
179     	long ksp;
180     
181     	*cregs = *pregs;
182     
183     	/* Set the return value for the child.  Note that this is not
184                actually restored by the syscall exit path, but we put it
185                here for consistency in case of signals. */
186     	cregs->gr[28] = 0; /* child */
187     
188     	/*
189     	 * We need to differentiate between a user fork and a
190     	 * kernel fork. We can't use user_mode, because the
191     	 * the syscall path doesn't save iaoq. Right now
192     	 * We rely on the fact that kernel_thread passes
193     	 * in zero for usp.
194     	 */
195     	if (usp == 0) {
196     		/* Kernel Thread */
197     		ksp = (((unsigned long)(p)) + TASK_SZ_ALGN);
198     		cregs->ksp = ksp;	    /* always return to kernel */
199     #ifdef __LP64__
200     		cregs->kpc = (unsigned long) &ret_from_kernel_thread;
201     #else
202     		cregs->kpc = (unsigned long) ret_from_kernel_thread;
203     #endif
204     
205     		/*
206     		 * Copy function and argument to be called from
207     		 * ret_from_kernel_thread.
208     		 */
209     		cregs->gr[26] = pregs->gr[26];
210     		cregs->gr[25] = pregs->gr[25];
211     
212     	} else {
213     		/* User Thread:
214     		 *
215     		 * Use same stack depth as parent when in wrapper
216     		 *
217     		 * Note that the fork wrappers are responsible
218     		 * for setting gr[20] and gr[21].
219     		 */
220     
221     		cregs->ksp = ((unsigned long)(p))
222     			+ (pregs->gr[20] & (INIT_TASK_SIZE - 1));
223     		cregs->kpc = pregs->gr[21];
224     	}
225     
226     	return 0;
227     }
228     
229     /*
230      * sys_execve() executes a new program.
231      */
232     
233     asmlinkage int sys_execve(struct pt_regs *regs)
234     {
235     	int error;
236     	char *filename;
237     
238     	filename = getname((char *) regs->gr[26]);
239     	error = PTR_ERR(filename);
240     	if (IS_ERR(filename))
241     		goto out;
242     	error = do_execve(filename, (char **) regs->gr[25],
243     		(char **) regs->gr[24], regs);
244     	if (error == 0)
245     		current->ptrace &= ~PT_DTRACE;
246     	putname(filename);
247     out:
248     
249     	return error;
250     }
251