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