aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/um/kernel/Makefile2
-rw-r--r--arch/um/kernel/process.c (renamed from arch/um/kernel/process_kern.c)33
-rw-r--r--arch/um/kernel/skas/Makefile3
-rw-r--r--arch/um/kernel/skas/exec.c30
-rw-r--r--arch/um/kernel/skas/exec_kern.c41
-rw-r--r--arch/um/kernel/skas/process.c217
-rw-r--r--arch/um/kernel/skas/process_kern.c529
7 files changed, 663 insertions, 192 deletions
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index a2d93065b2d0..6fa63a2a89e3 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -7,7 +7,7 @@ extra-y := vmlinux.lds
7clean-files := 7clean-files :=
8 8
9obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \ 9obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
10 physmem.o process_kern.o ptrace.o reboot.o resource.o sigio.o \ 10 physmem.o process.o ptrace.o reboot.o resource.o sigio.o \
11 signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \ 11 signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \
12 um_arch.o umid.o 12 um_arch.o umid.o
13 13
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process.c
index 537895d68ad1..fe6c64abda5b 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process.c
@@ -1,10 +1,9 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Copyright 2003 PathScale, Inc. 3 * Copyright 2003 PathScale, Inc.
4 * Licensed under the GPL 4 * Licensed under the GPL
5 */ 5 */
6 6
7#include "linux/config.h"
8#include "linux/kernel.h" 7#include "linux/kernel.h"
9#include "linux/sched.h" 8#include "linux/sched.h"
10#include "linux/interrupt.h" 9#include "linux/interrupt.h"
@@ -113,11 +112,11 @@ void set_current(void *t)
113 112
114void *_switch_to(void *prev, void *next, void *last) 113void *_switch_to(void *prev, void *next, void *last)
115{ 114{
116 struct task_struct *from = prev; 115 struct task_struct *from = prev;
117 struct task_struct *to= next; 116 struct task_struct *to= next;
118 117
119 to->thread.prev_sched = from; 118 to->thread.prev_sched = from;
120 set_current(to); 119 set_current(to);
121 120
122 do { 121 do {
123 current->thread.saved_task = NULL ; 122 current->thread.saved_task = NULL ;
@@ -128,7 +127,7 @@ void *_switch_to(void *prev, void *next, void *last)
128 prev= current; 127 prev= current;
129 } while(current->thread.saved_task); 128 } while(current->thread.saved_task);
130 129
131 return(current->thread.prev_sched); 130 return(current->thread.prev_sched);
132 131
133} 132}
134 133
@@ -142,19 +141,19 @@ void release_thread(struct task_struct *task)
142{ 141{
143 CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task)); 142 CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task));
144} 143}
145 144
146void exit_thread(void) 145void exit_thread(void)
147{ 146{
148 unprotect_stack((unsigned long) current_thread); 147 unprotect_stack((unsigned long) current_thread);
149} 148}
150 149
151void *get_current(void) 150void *get_current(void)
152{ 151{
153 return(current); 152 return(current);
154} 153}
155 154
156int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, 155int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
157 unsigned long stack_top, struct task_struct * p, 156 unsigned long stack_top, struct task_struct * p,
158 struct pt_regs *regs) 157 struct pt_regs *regs)
159{ 158{
160 int ret; 159 int ret;
@@ -183,11 +182,11 @@ void initial_thread_cb(void (*proc)(void *), void *arg)
183 int save_kmalloc_ok = kmalloc_ok; 182 int save_kmalloc_ok = kmalloc_ok;
184 183
185 kmalloc_ok = 0; 184 kmalloc_ok = 0;
186 CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc, 185 CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
187 arg); 186 arg);
188 kmalloc_ok = save_kmalloc_ok; 187 kmalloc_ok = save_kmalloc_ok;
189} 188}
190 189
191unsigned long stack_sp(unsigned long page) 190unsigned long stack_sp(unsigned long page)
192{ 191{
193 return(page + PAGE_SIZE - sizeof(void *)); 192 return(page + PAGE_SIZE - sizeof(void *));
@@ -211,7 +210,7 @@ void default_idle(void)
211 */ 210 */
212 if(need_resched()) 211 if(need_resched())
213 schedule(); 212 schedule();
214 213
215 idle_sleep(10); 214 idle_sleep(10);
216 } 215 }
217} 216}
@@ -226,7 +225,7 @@ int page_size(void)
226 return(PAGE_SIZE); 225 return(PAGE_SIZE);
227} 226}
228 227
229void *um_virt_to_phys(struct task_struct *task, unsigned long addr, 228void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
230 pte_t *pte_out) 229 pte_t *pte_out)
231{ 230{
232 pgd_t *pgd; 231 pgd_t *pgd;
@@ -235,7 +234,7 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
235 pte_t *pte; 234 pte_t *pte;
236 pte_t ptent; 235 pte_t ptent;
237 236
238 if(task->mm == NULL) 237 if(task->mm == NULL)
239 return(ERR_PTR(-EINVAL)); 238 return(ERR_PTR(-EINVAL));
240 pgd = pgd_offset(task->mm, addr); 239 pgd = pgd_offset(task->mm, addr);
241 if(!pgd_present(*pgd)) 240 if(!pgd_present(*pgd))
@@ -246,7 +245,7 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
246 return(ERR_PTR(-EINVAL)); 245 return(ERR_PTR(-EINVAL));
247 246
248 pmd = pmd_offset(pud, addr); 247 pmd = pmd_offset(pud, addr);
249 if(!pmd_present(*pmd)) 248 if(!pmd_present(*pmd))
250 return(ERR_PTR(-EINVAL)); 249 return(ERR_PTR(-EINVAL));
251 250
252 pte = pte_offset_kernel(pmd, addr); 251 pte = pte_offset_kernel(pmd, addr);
@@ -271,7 +270,7 @@ char *current_cmd(void)
271 270
272void force_sigbus(void) 271void force_sigbus(void)
273{ 272{
274 printk(KERN_ERR "Killing pid %d because of a lack of memory\n", 273 printk(KERN_ERR "Killing pid %d because of a lack of memory\n",
275 current->pid); 274 current->pid);
276 lock_kernel(); 275 lock_kernel();
277 sigaddset(&current->pending.signal, SIGBUS); 276 sigaddset(&current->pending.signal, SIGBUS);
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index ea3a8e409a6e..3e3fa7e7e3cf 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -3,8 +3,7 @@
3# Licensed under the GPL 3# Licensed under the GPL
4# 4#
5 5
6obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \ 6obj-y := clone.o exec.o mem.o mmu.o process.o syscall.o tlb.o uaccess.o
7 syscall.o tlb.o uaccess.o
8 7
9# clone.o is in the stub, so it can't be built with profiling 8# clone.o is in the stub, so it can't be built with profiling
10# GCC hardened also auto-enables -fpic, but we need %ebx so it can't work -> 9# GCC hardened also auto-enables -fpic, but we need %ebx so it can't work ->
diff --git a/arch/um/kernel/skas/exec.c b/arch/um/kernel/skas/exec.c
new file mode 100644
index 000000000000..54b795951372
--- /dev/null
+++ b/arch/um/kernel/skas/exec.c
@@ -0,0 +1,30 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include "linux/kernel.h"
7#include "asm/current.h"
8#include "asm/page.h"
9#include "asm/signal.h"
10#include "asm/ptrace.h"
11#include "asm/uaccess.h"
12#include "asm/mmu_context.h"
13#include "tlb.h"
14#include "skas.h"
15#include "um_mmu.h"
16#include "os.h"
17
18void flush_thread_skas(void)
19{
20 force_flush_all();
21 switch_mm_skas(&current->mm->context.skas.id);
22}
23
24void start_thread_skas(struct pt_regs *regs, unsigned long eip,
25 unsigned long esp)
26{
27 set_fs(USER_DS);
28 PT_REGS_IP(regs) = eip;
29 PT_REGS_SP(regs) = esp;
30}
diff --git a/arch/um/kernel/skas/exec_kern.c b/arch/um/kernel/skas/exec_kern.c
deleted file mode 100644
index 77ed7bbab219..000000000000
--- a/arch/um/kernel/skas/exec_kern.c
+++ /dev/null
@@ -1,41 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include "linux/kernel.h"
7#include "asm/current.h"
8#include "asm/page.h"
9#include "asm/signal.h"
10#include "asm/ptrace.h"
11#include "asm/uaccess.h"
12#include "asm/mmu_context.h"
13#include "tlb.h"
14#include "skas.h"
15#include "um_mmu.h"
16#include "os.h"
17
18void flush_thread_skas(void)
19{
20 force_flush_all();
21 switch_mm_skas(&current->mm->context.skas.id);
22}
23
24void start_thread_skas(struct pt_regs *regs, unsigned long eip,
25 unsigned long esp)
26{
27 set_fs(USER_DS);
28 PT_REGS_IP(regs) = eip;
29 PT_REGS_SP(regs) = esp;
30}
31
32/*
33 * Overrides for Emacs so that we follow Linus's tabbing style.
34 * Emacs will notice this stuff at the end of the file and automatically
35 * adjust the settings for this buffer only. This must remain at the end
36 * of the file.
37 * ---------------------------------------------------------------------------
38 * Local variables:
39 * c-file-style: "linux"
40 * End:
41 */
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
new file mode 100644
index 000000000000..ae4fa71d3b8b
--- /dev/null
+++ b/arch/um/kernel/skas/process.c
@@ -0,0 +1,217 @@
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 "skas.h"
17#include "os.h"
18#include "user_util.h"
19#include "tlb.h"
20#include "kern.h"
21#include "mode.h"
22#include "registers.h"
23
24void switch_to_skas(void *prev, void *next)
25{
26 struct task_struct *from, *to;
27
28 from = prev;
29 to = next;
30
31 /* XXX need to check runqueues[cpu].idle */
32 if(current->pid == 0)
33 switch_timers(0);
34
35 switch_threads(&from->thread.mode.skas.switch_buf,
36 &to->thread.mode.skas.switch_buf);
37
38 arch_switch_to_skas(current->thread.prev_sched, current);
39
40 if(current->pid == 0)
41 switch_timers(1);
42}
43
44extern void schedule_tail(struct task_struct *prev);
45
46/* This is called magically, by its address being stuffed in a jmp_buf
47 * and being longjmp-d to.
48 */
49void new_thread_handler(void)
50{
51 int (*fn)(void *), n;
52 void *arg;
53
54 if(current->thread.prev_sched != NULL)
55 schedule_tail(current->thread.prev_sched);
56 current->thread.prev_sched = NULL;
57
58 fn = current->thread.request.u.thread.proc;
59 arg = current->thread.request.u.thread.arg;
60
61 /* The return value is 1 if the kernel thread execs a process,
62 * 0 if it just exits
63 */
64 n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
65 if(n == 1){
66 /* Handle any immediate reschedules or signals */
67 interrupt_end();
68 userspace(&current->thread.regs.regs);
69 }
70 else do_exit(0);
71}
72
73void release_thread_skas(struct task_struct *task)
74{
75}
76
77/* Called magically, see new_thread_handler above */
78void fork_handler(void)
79{
80 force_flush_all();
81 if(current->thread.prev_sched == NULL)
82 panic("blech");
83
84 schedule_tail(current->thread.prev_sched);
85
86 /* XXX: if interrupt_end() calls schedule, this call to
87 * arch_switch_to_skas isn't needed. We could want to apply this to
88 * improve performance. -bb */
89 arch_switch_to_skas(current->thread.prev_sched, current);
90
91 current->thread.prev_sched = NULL;
92
93/* Handle any immediate reschedules or signals */
94 interrupt_end();
95
96 userspace(&current->thread.regs.regs);
97}
98
99int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
100 unsigned long stack_top, struct task_struct * p,
101 struct pt_regs *regs)
102{
103 void (*handler)(void);
104
105 if(current->thread.forking){
106 memcpy(&p->thread.regs.regs.skas, &regs->regs.skas,
107 sizeof(p->thread.regs.regs.skas));
108 REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
109 if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
110
111 handler = fork_handler;
112
113 arch_copy_thread(&current->thread.arch, &p->thread.arch);
114 }
115 else {
116 init_thread_registers(&p->thread.regs.regs);
117 p->thread.request.u.thread = current->thread.request.u.thread;
118 handler = new_thread_handler;
119 }
120
121 new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf,
122 handler);
123 return(0);
124}
125
126int new_mm(unsigned long stack)
127{
128 int fd;
129
130 fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
131 if(fd < 0)
132 return(fd);
133
134 if(skas_needs_stub)
135 map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
136
137 return(fd);
138}
139
140void init_idle_skas(void)
141{
142 cpu_tasks[current_thread->cpu].pid = os_getpid();
143 default_idle();
144}
145
146extern void start_kernel(void);
147
148static int start_kernel_proc(void *unused)
149{
150 int pid;
151
152 block_signals();
153 pid = os_getpid();
154
155 cpu_tasks[0].pid = pid;
156 cpu_tasks[0].task = current;
157#ifdef CONFIG_SMP
158 cpu_online_map = cpumask_of_cpu(0);
159#endif
160 start_kernel();
161 return(0);
162}
163
164extern int userspace_pid[];
165
166int start_uml_skas(void)
167{
168 if(proc_mm)
169 userspace_pid[0] = start_userspace(0);
170
171 init_new_thread_signals();
172
173 init_task.thread.request.u.thread.proc = start_kernel_proc;
174 init_task.thread.request.u.thread.arg = NULL;
175 return(start_idle_thread(task_stack_page(&init_task),
176 &init_task.thread.mode.skas.switch_buf));
177}
178
179int external_pid_skas(struct task_struct *task)
180{
181#warning Need to look up userspace_pid by cpu
182 return(userspace_pid[0]);
183}
184
185int thread_pid_skas(struct task_struct *task)
186{
187#warning Need to look up userspace_pid by cpu
188 return(userspace_pid[0]);
189}
190
191void kill_off_processes_skas(void)
192{
193 if(proc_mm)
194#warning need to loop over userspace_pids in kill_off_processes_skas
195 os_kill_ptraced_process(userspace_pid[0], 1);
196 else {
197 struct task_struct *p;
198 int pid, me;
199
200 me = os_getpid();
201 for_each_process(p){
202 if(p->mm == NULL)
203 continue;
204
205 pid = p->mm->context.skas.id.u.pid;
206 os_kill_ptraced_process(pid, 1);
207 }
208 }
209}
210
211unsigned long current_stub_stack(void)
212{
213 if(current->mm == NULL)
214 return(0);
215
216 return(current->mm->context.skas.id.stack);
217}
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index c73d47c57abe..0f3d5d084dc7 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -1,217 +1,484 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Copyright 2003 PathScale, Inc.
3 * Licensed under the GPL 4 * Licensed under the GPL
4 */ 5 */
5 6
7#include "linux/config.h"
8#include "linux/kernel.h"
6#include "linux/sched.h" 9#include "linux/sched.h"
10#include "linux/interrupt.h"
11#include "linux/string.h"
12#include "linux/mm.h"
7#include "linux/slab.h" 13#include "linux/slab.h"
8#include "linux/ptrace.h" 14#include "linux/utsname.h"
9#include "linux/proc_fs.h" 15#include "linux/fs.h"
10#include "linux/file.h" 16#include "linux/utime.h"
11#include "linux/errno.h" 17#include "linux/smp_lock.h"
18#include "linux/module.h"
12#include "linux/init.h" 19#include "linux/init.h"
20#include "linux/capability.h"
21#include "linux/vmalloc.h"
22#include "linux/spinlock.h"
23#include "linux/proc_fs.h"
24#include "linux/ptrace.h"
25#include "linux/random.h"
26#include "linux/personality.h"
27#include "asm/unistd.h"
28#include "asm/mman.h"
29#include "asm/segment.h"
30#include "asm/stat.h"
31#include "asm/pgtable.h"
32#include "asm/processor.h"
33#include "asm/tlbflush.h"
13#include "asm/uaccess.h" 34#include "asm/uaccess.h"
14#include "asm/atomic.h" 35#include "asm/user.h"
15#include "kern_util.h"
16#include "skas.h"
17#include "os.h"
18#include "user_util.h" 36#include "user_util.h"
19#include "tlb.h" 37#include "kern_util.h"
20#include "kern.h" 38#include "kern.h"
39#include "signal_kern.h"
40#include "init.h"
41#include "irq_user.h"
42#include "mem_user.h"
43#include "tlb.h"
44#include "frame_kern.h"
45#include "sigcontext.h"
46#include "os.h"
21#include "mode.h" 47#include "mode.h"
22#include "registers.h" 48#include "mode_kern.h"
49#include "choose-mode.h"
50
51/* This is a per-cpu array. A processor only modifies its entry and it only
52 * cares about its entry, so it's OK if another processor is modifying its
53 * entry.
54 */
55struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
56
57int external_pid(void *t)
58{
59 struct task_struct *task = t ? t : current;
60
61 return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task));
62}
63
64int pid_to_processor_id(int pid)
65{
66 int i;
23 67
24void switch_to_skas(void *prev, void *next) 68 for(i = 0; i < ncpus; i++){
69 if(cpu_tasks[i].pid == pid) return(i);
70 }
71 return(-1);
72}
73
74void free_stack(unsigned long stack, int order)
25{ 75{
26 struct task_struct *from, *to; 76 free_pages(stack, order);
77}
27 78
28 from = prev; 79unsigned long alloc_stack(int order, int atomic)
29 to = next; 80{
81 unsigned long page;
82 gfp_t flags = GFP_KERNEL;
30 83
31 /* XXX need to check runqueues[cpu].idle */ 84 if (atomic)
32 if(current->pid == 0) 85 flags = GFP_ATOMIC;
33 switch_timers(0); 86 page = __get_free_pages(flags, order);
87 if(page == 0)
88 return(0);
89 stack_protections(page);
90 return(page);
91}
34 92
35 switch_threads(&from->thread.mode.skas.switch_buf, 93int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
36 &to->thread.mode.skas.switch_buf); 94{
95 int pid;
96
97 current->thread.request.u.thread.proc = fn;
98 current->thread.request.u.thread.arg = arg;
99 pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0,
100 &current->thread.regs, 0, NULL, NULL);
101 if(pid < 0)
102 panic("do_fork failed in kernel_thread, errno = %d", pid);
103 return(pid);
104}
37 105
38 arch_switch_to_skas(current->thread.prev_sched, current); 106void set_current(void *t)
107{
108 struct task_struct *task = t;
39 109
40 if(current->pid == 0) 110 cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
41 switch_timers(1); 111 { external_pid(task), task });
42} 112}
43 113
44extern void schedule_tail(struct task_struct *prev); 114void *_switch_to(void *prev, void *next, void *last)
115{
116 struct task_struct *from = prev;
117 struct task_struct *to= next;
45 118
46/* This is called magically, by its address being stuffed in a jmp_buf 119 to->thread.prev_sched = from;
47 * and being longjmp-d to. 120 set_current(to);
48 */ 121
49void new_thread_handler(void) 122 do {
123 current->thread.saved_task = NULL ;
124 CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next);
125 if(current->thread.saved_task)
126 show_regs(&(current->thread.regs));
127 next= current->thread.saved_task;
128 prev= current;
129 } while(current->thread.saved_task);
130
131 return(current->thread.prev_sched);
132
133}
134
135void interrupt_end(void)
50{ 136{
51 int (*fn)(void *), n; 137 if(need_resched()) schedule();
52 void *arg; 138 if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal();
139}
53 140
54 if(current->thread.prev_sched != NULL) 141void release_thread(struct task_struct *task)
55 schedule_tail(current->thread.prev_sched); 142{
56 current->thread.prev_sched = NULL; 143 CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task));
144}
57 145
58 fn = current->thread.request.u.thread.proc; 146void exit_thread(void)
59 arg = current->thread.request.u.thread.arg; 147{
148 unprotect_stack((unsigned long) current_thread);
149}
60 150
61 /* The return value is 1 if the kernel thread execs a process, 151void *get_current(void)
62 * 0 if it just exits 152{
153 return(current);
154}
155
156int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
157 unsigned long stack_top, struct task_struct * p,
158 struct pt_regs *regs)
159{
160 int ret;
161
162 p->thread = (struct thread_struct) INIT_THREAD;
163 ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr,
164 clone_flags, sp, stack_top, p, regs);
165
166 if (ret || !current->thread.forking)
167 goto out;
168
169 clear_flushed_tls(p);
170
171 /*
172 * Set a new TLS for the child thread?
63 */ 173 */
64 n = run_kernel_thread(fn, arg, &current->thread.exec_buf); 174 if (clone_flags & CLONE_SETTLS)
65 if(n == 1){ 175 ret = arch_copy_tls(p);
66 /* Handle any immediate reschedules or signals */ 176
67 interrupt_end(); 177out:
68 userspace(&current->thread.regs.regs); 178 return ret;
179}
180
181void initial_thread_cb(void (*proc)(void *), void *arg)
182{
183 int save_kmalloc_ok = kmalloc_ok;
184
185 kmalloc_ok = 0;
186 CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
187 arg);
188 kmalloc_ok = save_kmalloc_ok;
189}
190
191unsigned long stack_sp(unsigned long page)
192{
193 return(page + PAGE_SIZE - sizeof(void *));
194}
195
196int current_pid(void)
197{
198 return(current->pid);
199}
200
201void default_idle(void)
202{
203 CHOOSE_MODE(uml_idle_timer(), (void) 0);
204
205 while(1){
206 /* endless idle loop with no priority at all */
207
208 /*
209 * although we are an idle CPU, we do not want to
210 * get into the scheduler unnecessarily.
211 */
212 if(need_resched())
213 schedule();
214
215 idle_sleep(10);
69 } 216 }
70 else do_exit(0);
71} 217}
72 218
73void release_thread_skas(struct task_struct *task) 219void cpu_idle(void)
74{ 220{
221 CHOOSE_MODE(init_idle_tt(), init_idle_skas());
75} 222}
76 223
77/* Called magically, see new_thread_handler above */ 224int page_size(void)
78void fork_handler(void)
79{ 225{
80 force_flush_all(); 226 return(PAGE_SIZE);
81 if(current->thread.prev_sched == NULL) 227}
82 panic("blech");
83 228
84 schedule_tail(current->thread.prev_sched); 229void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
230 pte_t *pte_out)
231{
232 pgd_t *pgd;
233 pud_t *pud;
234 pmd_t *pmd;
235 pte_t *pte;
236 pte_t ptent;
237
238 if(task->mm == NULL)
239 return(ERR_PTR(-EINVAL));
240 pgd = pgd_offset(task->mm, addr);
241 if(!pgd_present(*pgd))
242 return(ERR_PTR(-EINVAL));
243
244 pud = pud_offset(pgd, addr);
245 if(!pud_present(*pud))
246 return(ERR_PTR(-EINVAL));
247
248 pmd = pmd_offset(pud, addr);
249 if(!pmd_present(*pmd))
250 return(ERR_PTR(-EINVAL));
251
252 pte = pte_offset_kernel(pmd, addr);
253 ptent = *pte;
254 if(!pte_present(ptent))
255 return(ERR_PTR(-EINVAL));
256
257 if(pte_out != NULL)
258 *pte_out = ptent;
259 return((void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK));
260}
85 261
86 /* XXX: if interrupt_end() calls schedule, this call to 262char *current_cmd(void)
87 * arch_switch_to_skas isn't needed. We could want to apply this to 263{
88 * improve performance. -bb */ 264#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM)
89 arch_switch_to_skas(current->thread.prev_sched, current); 265 return("(Unknown)");
266#else
267 void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);
268 return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);
269#endif
270}
90 271
91 current->thread.prev_sched = NULL; 272void force_sigbus(void)
273{
274 printk(KERN_ERR "Killing pid %d because of a lack of memory\n",
275 current->pid);
276 lock_kernel();
277 sigaddset(&current->pending.signal, SIGBUS);
278 recalc_sigpending();
279 current->flags |= PF_SIGNALED;
280 do_exit(SIGBUS | 0x80);
281}
92 282
93/* Handle any immediate reschedules or signals */ 283void dump_thread(struct pt_regs *regs, struct user *u)
94 interrupt_end(); 284{
285}
95 286
96 userspace(&current->thread.regs.regs); 287void enable_hlt(void)
288{
289 panic("enable_hlt");
97} 290}
98 291
99int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, 292EXPORT_SYMBOL(enable_hlt);
100 unsigned long stack_top, struct task_struct * p, 293
101 struct pt_regs *regs) 294void disable_hlt(void)
102{ 295{
103 void (*handler)(void); 296 panic("disable_hlt");
297}
104 298
105 if(current->thread.forking){ 299EXPORT_SYMBOL(disable_hlt);
106 memcpy(&p->thread.regs.regs.skas, &regs->regs.skas,
107 sizeof(p->thread.regs.regs.skas));
108 REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
109 if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
110 300
111 handler = fork_handler; 301void *um_kmalloc(int size)
302{
303 return kmalloc(size, GFP_KERNEL);
304}
112 305
113 arch_copy_thread(&current->thread.arch, &p->thread.arch); 306void *um_kmalloc_atomic(int size)
114 } 307{
115 else { 308 return kmalloc(size, GFP_ATOMIC);
116 init_thread_registers(&p->thread.regs.regs); 309}
117 p->thread.request.u.thread = current->thread.request.u.thread;
118 handler = new_thread_handler;
119 }
120 310
121 new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf, 311void *um_vmalloc(int size)
122 handler); 312{
123 return(0); 313 return vmalloc(size);
124} 314}
125 315
126int new_mm(unsigned long stack) 316void *um_vmalloc_atomic(int size)
127{ 317{
128 int fd; 318 return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
319}
129 320
130 fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); 321int __cant_sleep(void) {
131 if(fd < 0) 322 return in_atomic() || irqs_disabled() || in_interrupt();
132 return(fd); 323 /* Is in_interrupt() really needed? */
324}
133 325
134 if(skas_needs_stub) 326unsigned long get_fault_addr(void)
135 map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); 327{
328 return((unsigned long) current->thread.fault_addr);
329}
136 330
137 return(fd); 331EXPORT_SYMBOL(get_fault_addr);
332
333void not_implemented(void)
334{
335 printk(KERN_DEBUG "Something isn't implemented in here\n");
138} 336}
139 337
140void init_idle_skas(void) 338EXPORT_SYMBOL(not_implemented);
339
340int user_context(unsigned long sp)
141{ 341{
142 cpu_tasks[current_thread->cpu].pid = os_getpid(); 342 unsigned long stack;
143 default_idle(); 343
344 stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
345 return(stack != (unsigned long) current_thread);
144} 346}
145 347
146extern void start_kernel(void); 348extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
147 349
148static int start_kernel_proc(void *unused) 350void do_uml_exitcalls(void)
149{ 351{
150 int pid; 352 exitcall_t *call;
353
354 call = &__uml_exitcall_end;
355 while (--call >= &__uml_exitcall_begin)
356 (*call)();
357}
151 358
152 block_signals(); 359char *uml_strdup(char *string)
153 pid = os_getpid(); 360{
361 return kstrdup(string, GFP_KERNEL);
362}
154 363
155 cpu_tasks[0].pid = pid; 364int copy_to_user_proc(void __user *to, void *from, int size)
156 cpu_tasks[0].task = current; 365{
366 return(copy_to_user(to, from, size));
367}
368
369int copy_from_user_proc(void *to, void __user *from, int size)
370{
371 return(copy_from_user(to, from, size));
372}
373
374int clear_user_proc(void __user *buf, int size)
375{
376 return(clear_user(buf, size));
377}
378
379int strlen_user_proc(char __user *str)
380{
381 return(strlen_user(str));
382}
383
384int smp_sigio_handler(void)
385{
157#ifdef CONFIG_SMP 386#ifdef CONFIG_SMP
158 cpu_online_map = cpumask_of_cpu(0); 387 int cpu = current_thread->cpu;
388 IPI_handler(cpu);
389 if(cpu != 0)
390 return(1);
159#endif 391#endif
160 start_kernel();
161 return(0); 392 return(0);
162} 393}
163 394
164extern int userspace_pid[]; 395int cpu(void)
165
166int start_uml_skas(void)
167{ 396{
168 if(proc_mm) 397 return(current_thread->cpu);
169 userspace_pid[0] = start_userspace(0); 398}
170 399
171 init_new_thread_signals(); 400static atomic_t using_sysemu = ATOMIC_INIT(0);
401int sysemu_supported;
172 402
173 init_task.thread.request.u.thread.proc = start_kernel_proc; 403void set_using_sysemu(int value)
174 init_task.thread.request.u.thread.arg = NULL; 404{
175 return(start_idle_thread(task_stack_page(&init_task), 405 if (value > sysemu_supported)
176 &init_task.thread.mode.skas.switch_buf)); 406 return;
407 atomic_set(&using_sysemu, value);
177} 408}
178 409
179int external_pid_skas(struct task_struct *task) 410int get_using_sysemu(void)
180{ 411{
181#warning Need to look up userspace_pid by cpu 412 return atomic_read(&using_sysemu);
182 return(userspace_pid[0]);
183} 413}
184 414
185int thread_pid_skas(struct task_struct *task) 415static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
186{ 416{
187#warning Need to look up userspace_pid by cpu 417 if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
188 return(userspace_pid[0]); 418 *eof = 1;
419
420 return strlen(buf);
189} 421}
190 422
191void kill_off_processes_skas(void) 423static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned long count,void *data)
192{ 424{
193 if(proc_mm) 425 char tmp[2];
194#warning need to loop over userspace_pids in kill_off_processes_skas
195 os_kill_ptraced_process(userspace_pid[0], 1);
196 else {
197 struct task_struct *p;
198 int pid, me;
199 426
200 me = os_getpid(); 427 if (copy_from_user(tmp, buf, 1))
201 for_each_process(p){ 428 return -EFAULT;
202 if(p->mm == NULL)
203 continue;
204 429
205 pid = p->mm->context.skas.id.u.pid; 430 if (tmp[0] >= '0' && tmp[0] <= '2')
206 os_kill_ptraced_process(pid, 1); 431 set_using_sysemu(tmp[0] - '0');
207 } 432 return count; /*We use the first char, but pretend to write everything*/
433}
434
435int __init make_proc_sysemu(void)
436{
437 struct proc_dir_entry *ent;
438 if (!sysemu_supported)
439 return 0;
440
441 ent = create_proc_entry("sysemu", 0600, &proc_root);
442
443 if (ent == NULL)
444 {
445 printk(KERN_WARNING "Failed to register /proc/sysemu\n");
446 return(0);
208 } 447 }
448
449 ent->read_proc = proc_read_sysemu;
450 ent->write_proc = proc_write_sysemu;
451
452 return 0;
209} 453}
210 454
211unsigned long current_stub_stack(void) 455late_initcall(make_proc_sysemu);
456
457int singlestepping(void * t)
212{ 458{
213 if(current->mm == NULL) 459 struct task_struct *task = t ? t : current;
460
461 if ( ! (task->ptrace & PT_DTRACE) )
214 return(0); 462 return(0);
215 463
216 return(current->mm->context.skas.id.stack); 464 if (task->thread.singlestep_syscall)
465 return(1);
466
467 return 2;
468}
469
470/*
471 * Only x86 and x86_64 have an arch_align_stack().
472 * All other arches have "#define arch_align_stack(x) (x)"
473 * in their asm/system.h
474 * As this is included in UML from asm-um/system-generic.h,
475 * we can use it to behave as the subarch does.
476 */
477#ifndef arch_align_stack
478unsigned long arch_align_stack(unsigned long sp)
479{
480 if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
481 sp -= get_random_int() % 8192;
482 return sp & ~0xf;
217} 483}
484#endif