ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / um / kernel / skas / process_kern.c
1 /* 
2  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3  * Licensed under the GPL
4  */
5
6 #include "linux/sched.h"
7 #include "linux/slab.h"
8 #include "linux/ptrace.h"
9 #include "kern_util.h"
10 #include "time_user.h"
11 #include "signal_user.h"
12 #include "skas.h"
13 #include "os.h"
14 #include "user_util.h"
15 #include "tlb.h"
16 #include "frame.h"
17 #include "kern.h"
18 #include "mode.h"
19
20 int singlestepping_skas(void)
21 {
22         int ret = current->ptrace & PT_DTRACE;
23
24         current->ptrace &= ~PT_DTRACE;
25         return(ret);
26 }
27
28 void *switch_to_skas(void *prev, void *next)
29 {
30         struct task_struct *from, *to;
31
32         from = prev;
33         to = next;
34
35         /* XXX need to check runqueues[cpu].idle */
36         if(current->pid == 0)
37                 switch_timers(0);
38
39         to->thread.prev_sched = from;
40         set_current(to);
41
42         switch_threads(&from->thread.mode.skas.switch_buf, 
43                        to->thread.mode.skas.switch_buf);
44
45         if(current->pid == 0)
46                 switch_timers(1);
47
48         return(current->thread.prev_sched);
49 }
50
51 extern void schedule_tail(struct task_struct *prev);
52
53 void new_thread_handler(int sig)
54 {
55         int (*fn)(void *), n;
56         void *arg;
57
58         fn = current->thread.request.u.thread.proc;
59         arg = current->thread.request.u.thread.arg;
60         change_sig(SIGUSR1, 1);
61         thread_wait(&current->thread.mode.skas.switch_buf, 
62                     current->thread.mode.skas.fork_buf);
63
64 #ifdef CONFIG_SMP
65         schedule_tail(NULL);
66 #endif
67         current->thread.prev_sched = NULL;
68
69         n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
70         if(n == 1)
71                 userspace(&current->thread.regs.regs);
72         else do_exit(0);
73 }
74
75 void new_thread_proc(void *stack, void (*handler)(int sig))
76 {
77         init_new_thread_stack(stack, handler);
78         os_usr1_process(os_getpid());
79 }
80
81 void release_thread_skas(struct task_struct *task)
82 {
83 }
84
85 void exit_thread_skas(void)
86 {
87 }
88
89 void fork_handler(int sig)
90 {
91         change_sig(SIGUSR1, 1);
92         thread_wait(&current->thread.mode.skas.switch_buf, 
93                     current->thread.mode.skas.fork_buf);
94         
95         force_flush_all();
96 #ifdef CONFIG_SMP
97         schedule_tail(current->thread.prev_sched);
98 #endif
99         current->thread.prev_sched = NULL;
100         unblock_signals();
101
102         userspace(&current->thread.regs.regs);
103 }
104
105 int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
106                      unsigned long stack_top, struct task_struct * p, 
107                      struct pt_regs *regs)
108 {
109         void (*handler)(int);
110
111         if(current->thread.forking){
112                 memcpy(&p->thread.regs.regs.skas, 
113                        &current->thread.regs.regs.skas, 
114                        sizeof(p->thread.regs.regs.skas));
115                 REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
116                 if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
117
118                 handler = fork_handler;
119         }
120         else {
121                 memcpy(p->thread.regs.regs.skas.regs, exec_regs, 
122                        sizeof(p->thread.regs.regs.skas.regs));
123                 memcpy(p->thread.regs.regs.skas.fp, exec_fp_regs, 
124                        sizeof(p->thread.regs.regs.skas.fp));
125                 memcpy(p->thread.regs.regs.skas.xfp, exec_fpx_regs, 
126                        sizeof(p->thread.regs.regs.skas.xfp));
127                 p->thread.request.u.thread = current->thread.request.u.thread;
128                 handler = new_thread_handler;
129         }
130
131         new_thread((void *) p->thread.kernel_stack, 
132                    &p->thread.mode.skas.switch_buf, 
133                    &p->thread.mode.skas.fork_buf, handler);
134         return(0);
135 }
136
137 void init_idle_skas(void)
138 {
139         cpu_tasks[current->thread_info->cpu].pid = os_getpid();
140         default_idle();
141 }
142
143 extern void start_kernel(void);
144
145 static int start_kernel_proc(void *unused)
146 {
147         int pid;
148
149         block_signals();
150         pid = os_getpid();
151
152         cpu_tasks[0].pid = pid;
153         cpu_tasks[0].task = current;
154 #ifdef CONFIG_SMP
155         cpu_online_map = cpumask_of_cpu(0);
156 #endif
157         start_kernel();
158         return(0);
159 }
160
161 int start_uml_skas(void)
162 {
163         start_userspace();
164         capture_signal_stack();
165
166         init_new_thread_signals(1);
167         idle_timer();
168
169         init_task.thread.request.u.thread.proc = start_kernel_proc;
170         init_task.thread.request.u.thread.arg = NULL;
171         return(start_idle_thread((void *) init_task.thread.kernel_stack,
172                                  &init_task.thread.mode.skas.switch_buf,
173                                  &init_task.thread.mode.skas.fork_buf));
174 }
175
176 int external_pid_skas(struct task_struct *task)
177 {
178         return(userspace_pid);
179 }
180
181 int thread_pid_skas(struct task_struct *task)
182 {
183         return(userspace_pid);
184 }
185
186 /*
187  * Overrides for Emacs so that we follow Linus's tabbing style.
188  * Emacs will notice this stuff at the end of the file and automatically
189  * adjust the settings for this buffer only.  This must remain at the end
190  * of the file.
191  * ---------------------------------------------------------------------------
192  * Local variables:
193  * c-file-style: "linux"
194  * End:
195  */