e16309d532276828c81171e8179c30684dea9394
[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 #include "filehandle.h"
20 #include "proc_mm.h"
21
22 int singlestepping_skas(void)
23 {
24         int ret = current->ptrace & PT_DTRACE;
25
26         current->ptrace &= ~PT_DTRACE;
27         return(ret);
28 }
29
30 void *switch_to_skas(void *prev, void *next)
31 {
32         struct task_struct *from, *to;
33
34         from = prev;
35         to = next;
36
37         /* XXX need to check runqueues[cpu].idle */
38         if(current->pid == 0)
39                 switch_timers(0);
40
41         to->thread.prev_sched = from;
42         set_current(to);
43
44         switch_threads(&from->thread.mode.skas.switch_buf, 
45                        to->thread.mode.skas.switch_buf);
46
47         if(current->pid == 0)
48                 switch_timers(1);
49
50         return(current->thread.prev_sched);
51 }
52
53 extern void schedule_tail(struct task_struct *prev);
54
55 void new_thread_handler(int sig)
56 {
57         int (*fn)(void *), n;
58         void *arg;
59
60         fn = current->thread.request.u.thread.proc;
61         arg = current->thread.request.u.thread.arg;
62         change_sig(SIGUSR1, 1);
63         thread_wait(&current->thread.mode.skas.switch_buf, 
64                     current->thread.mode.skas.fork_buf);
65
66         if(current->thread.prev_sched != NULL)
67                 schedule_tail(current->thread.prev_sched);
68         current->thread.prev_sched = NULL;
69
70         /* The return value is 1 if the kernel thread execs a process,
71          * 0 if it just exits
72          */
73         n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
74         if(n == 1)
75                 userspace(&current->thread.regs.regs);
76         else do_exit(0);
77 }
78
79 void new_thread_proc(void *stack, void (*handler)(int sig))
80 {
81         init_new_thread_stack(stack, handler);
82         os_usr1_process(os_getpid());
83 }
84
85 void release_thread_skas(struct task_struct *task)
86 {
87 }
88
89 void exit_thread_skas(void)
90 {
91 }
92
93 void fork_handler(int sig)
94 {
95         change_sig(SIGUSR1, 1);
96         thread_wait(&current->thread.mode.skas.switch_buf, 
97                     current->thread.mode.skas.fork_buf);
98         
99         force_flush_all();
100         if(current->thread.prev_sched == NULL)
101                 panic("blech");
102         
103         schedule_tail(current->thread.prev_sched);
104         current->thread.prev_sched = NULL;
105
106         userspace(&current->thread.regs.regs);
107 }
108
109 int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
110                      unsigned long stack_top, struct task_struct * p, 
111                      struct pt_regs *regs)
112 {
113         void (*handler)(int);
114
115         if(current->thread.forking){
116                 memcpy(&p->thread.regs.regs.skas, 
117                        &current->thread.regs.regs.skas, 
118                        sizeof(p->thread.regs.regs.skas));
119                 REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
120                 if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
121
122                 handler = fork_handler;
123         }
124         else {
125                 memcpy(p->thread.regs.regs.skas.regs, exec_regs, 
126                        sizeof(p->thread.regs.regs.skas.regs));
127                 memcpy(p->thread.regs.regs.skas.fp, exec_fp_regs, 
128                        sizeof(p->thread.regs.regs.skas.fp));
129                 memcpy(p->thread.regs.regs.skas.xfp, exec_fpx_regs, 
130                        sizeof(p->thread.regs.regs.skas.xfp));
131                 p->thread.request.u.thread = current->thread.request.u.thread;
132                 handler = new_thread_handler;
133         }
134
135         new_thread(p->thread_info, &p->thread.mode.skas.switch_buf, 
136                    &p->thread.mode.skas.fork_buf, handler);
137         return(0);
138 }
139
140 int new_mm(int from)
141 {
142         struct proc_mm_op copy;
143         int n, fd;
144
145         fd = open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
146         if(fd < 0)
147                 return(fd);
148
149         if(from != -1){
150                 copy = ((struct proc_mm_op) { .op       = MM_COPY_SEGMENTS,
151                                               .u        = 
152                                               { .copy_segments  = from } } );
153                 n = os_write_file(fd, &copy, sizeof(copy));
154                 if(n != sizeof(copy)) 
155                         printk("new_mm : /proc/mm copy_segments failed, "
156                                "err = %d\n", -n);
157         }
158
159         return(fd);
160 }
161
162 void init_idle_skas(void)
163 {
164         cpu_tasks[current_thread->cpu].pid = os_getpid();
165         default_idle();
166 }
167
168 extern void start_kernel(void);
169
170 static int start_kernel_proc(void *unused)
171 {
172         int pid;
173
174         block_signals();
175         pid = os_getpid();
176
177         cpu_tasks[0].pid = pid;
178         cpu_tasks[0].task = current;
179 #ifdef CONFIG_SMP
180         cpu_online_map = cpumask_of_cpu(0);
181 #endif
182         start_kernel();
183         return(0);
184 }
185
186 int start_uml_skas(void)
187 {
188         start_userspace(0);
189         capture_signal_stack();
190
191         init_new_thread_signals(1);
192         uml_idle_timer();
193
194         init_task.thread.request.u.thread.proc = start_kernel_proc;
195         init_task.thread.request.u.thread.arg = NULL;
196         return(start_idle_thread(init_task.thread_info,
197                                  &init_task.thread.mode.skas.switch_buf,
198                                  &init_task.thread.mode.skas.fork_buf));
199 }
200
201 int external_pid_skas(struct task_struct *task)
202 {
203 #warning Need to look up userspace_pid by cpu   
204         return(userspace_pid[0]);
205 }
206
207 int thread_pid_skas(struct task_struct *task)
208 {
209 #warning Need to look up userspace_pid by cpu   
210         return(userspace_pid[0]);
211 }
212
213 /*
214  * Overrides for Emacs so that we follow Linus's tabbing style.
215  * Emacs will notice this stuff at the end of the file and automatically
216  * adjust the settings for this buffer only.  This must remain at the end
217  * of the file.
218  * ---------------------------------------------------------------------------
219  * Local variables:
220  * c-file-style: "linux"
221  * End:
222  */