aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel')
-rw-r--r--arch/um/kernel/exec.c20
-rw-r--r--arch/um/kernel/irq.c4
-rw-r--r--arch/um/kernel/physmem.c4
-rw-r--r--arch/um/kernel/process.c120
-rw-r--r--arch/um/kernel/ptrace.c6
-rw-r--r--arch/um/kernel/reboot.c21
-rw-r--r--arch/um/kernel/signal.c1
-rw-r--r--arch/um/kernel/skas/Makefile2
-rw-r--r--arch/um/kernel/skas/exec.c40
-rw-r--r--arch/um/kernel/skas/mem.c22
-rw-r--r--arch/um/kernel/skas/mmu.c4
-rw-r--r--arch/um/kernel/skas/process.c158
-rw-r--r--arch/um/kernel/skas/syscall.c4
-rw-r--r--arch/um/kernel/skas/tlb.c164
-rw-r--r--arch/um/kernel/syscall.c1
-rw-r--r--arch/um/kernel/time.c7
-rw-r--r--arch/um/kernel/tlb.c134
-rw-r--r--arch/um/kernel/trap.c10
-rw-r--r--arch/um/kernel/um_arch.c22
19 files changed, 309 insertions, 435 deletions
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 8f774c25b765..5064fb691eb5 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -18,17 +18,31 @@
18#include "irq_user.h" 18#include "irq_user.h"
19#include "tlb.h" 19#include "tlb.h"
20#include "os.h" 20#include "os.h"
21#include "mode_kern.h" 21#include "skas/skas.h"
22 22
23void flush_thread(void) 23void flush_thread(void)
24{ 24{
25 void *data = NULL;
26 unsigned long end = proc_mm ? task_size : CONFIG_STUB_START;
27 int ret;
28
25 arch_flush_thread(&current->thread.arch); 29 arch_flush_thread(&current->thread.arch);
26 flush_thread_skas(); 30
31 ret = unmap(&current->mm->context.skas.id, 0, end, 1, &data);
32 if(ret){
33 printk("flush_thread - clearing address space failed, "
34 "err = %d\n", ret);
35 force_sig(SIGKILL, current);
36 }
37
38 __switch_mm(&current->mm->context.skas.id);
27} 39}
28 40
29void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) 41void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
30{ 42{
31 start_thread_skas(regs, eip, esp); 43 set_fs(USER_DS);
44 PT_REGS_IP(regs) = eip;
45 PT_REGS_SP(regs) = esp;
32} 46}
33 47
34#ifdef CONFIG_TTY_LOG 48#ifdef CONFIG_TTY_LOG
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index ec1ed680032b..b10ee28b97cb 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -91,7 +91,7 @@ static struct irq_fd **last_irq_ptr = &active_fds;
91 91
92extern void free_irqs(void); 92extern void free_irqs(void);
93 93
94void sigio_handler(int sig, union uml_pt_regs *regs) 94void sigio_handler(int sig, struct uml_pt_regs *regs)
95{ 95{
96 struct irq_fd *irq_fd; 96 struct irq_fd *irq_fd;
97 int n; 97 int n;
@@ -344,7 +344,7 @@ int deactivate_all_fds(void)
344 * SMP cross-CPU interrupts have their own specific 344 * SMP cross-CPU interrupts have their own specific
345 * handlers). 345 * handlers).
346 */ 346 */
347unsigned int do_IRQ(int irq, union uml_pt_regs *regs) 347unsigned int do_IRQ(int irq, struct uml_pt_regs *regs)
348{ 348{
349 struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs); 349 struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs);
350 irq_enter(); 350 irq_enter();
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index f7b2f3594793..90e89e838173 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -10,7 +10,7 @@
10#include "as-layout.h" 10#include "as-layout.h"
11#include "init.h" 11#include "init.h"
12#include "kern.h" 12#include "kern.h"
13#include "mode_kern.h" 13#include "mem_user.h"
14#include "os.h" 14#include "os.h"
15 15
16static int physmem_fd = -1; 16static int physmem_fd = -1;
@@ -61,7 +61,7 @@ static unsigned long kmem_top = 0;
61unsigned long get_kmem_end(void) 61unsigned long get_kmem_end(void)
62{ 62{
63 if (kmem_top == 0) 63 if (kmem_top == 0)
64 kmem_top = kmem_end_skas; 64 kmem_top = host_task_size - 1024 * 1024;
65 return kmem_top; 65 return kmem_top;
66} 66}
67 67
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 22ad46fd2c08..d3b9c62e73c7 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -43,8 +43,7 @@
43#include "frame_kern.h" 43#include "frame_kern.h"
44#include "sigcontext.h" 44#include "sigcontext.h"
45#include "os.h" 45#include "os.h"
46#include "mode.h" 46#include "skas.h"
47#include "mode_kern.h"
48 47
49/* This is a per-cpu array. A processor only modifies its entry and it only 48/* This is a per-cpu array. A processor only modifies its entry and it only
50 * cares about its entry, so it's OK if another processor is modifying its 49 * cares about its entry, so it's OK if another processor is modifying its
@@ -54,7 +53,8 @@ struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
54 53
55static inline int external_pid(struct task_struct *task) 54static inline int external_pid(struct task_struct *task)
56{ 55{
57 return external_pid_skas(task); 56 /* FIXME: Need to look up userspace_pid by cpu */
57 return(userspace_pid[0]);
58} 58}
59 59
60int pid_to_processor_id(int pid) 60int pid_to_processor_id(int pid)
@@ -104,6 +104,8 @@ static inline void set_current(struct task_struct *task)
104 { external_pid(task), task }); 104 { external_pid(task), task });
105} 105}
106 106
107extern void arch_switch_to(struct task_struct *from, struct task_struct *to);
108
107void *_switch_to(void *prev, void *next, void *last) 109void *_switch_to(void *prev, void *next, void *last)
108{ 110{
109 struct task_struct *from = prev; 111 struct task_struct *from = prev;
@@ -114,7 +116,19 @@ void *_switch_to(void *prev, void *next, void *last)
114 116
115 do { 117 do {
116 current->thread.saved_task = NULL; 118 current->thread.saved_task = NULL;
117 switch_to_skas(prev, next); 119
120 /* XXX need to check runqueues[cpu].idle */
121 if(current->pid == 0)
122 switch_timers(0);
123
124 switch_threads(&from->thread.switch_buf,
125 &to->thread.switch_buf);
126
127 arch_switch_to(current->thread.prev_sched, current);
128
129 if(current->pid == 0)
130 switch_timers(1);
131
118 if(current->thread.saved_task) 132 if(current->thread.saved_task)
119 show_regs(&(current->thread.regs)); 133 show_regs(&(current->thread.regs));
120 next= current->thread.saved_task; 134 next= current->thread.saved_task;
@@ -133,11 +147,6 @@ void interrupt_end(void)
133 do_signal(); 147 do_signal();
134} 148}
135 149
136void release_thread(struct task_struct *task)
137{
138 release_thread_skas(task);
139}
140
141void exit_thread(void) 150void exit_thread(void)
142{ 151{
143} 152}
@@ -147,27 +156,95 @@ void *get_current(void)
147 return current; 156 return current;
148} 157}
149 158
159extern void schedule_tail(struct task_struct *prev);
160
161/* This is called magically, by its address being stuffed in a jmp_buf
162 * and being longjmp-d to.
163 */
164void new_thread_handler(void)
165{
166 int (*fn)(void *), n;
167 void *arg;
168
169 if(current->thread.prev_sched != NULL)
170 schedule_tail(current->thread.prev_sched);
171 current->thread.prev_sched = NULL;
172
173 fn = current->thread.request.u.thread.proc;
174 arg = current->thread.request.u.thread.arg;
175
176 /* The return value is 1 if the kernel thread execs a process,
177 * 0 if it just exits
178 */
179 n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
180 if(n == 1){
181 /* Handle any immediate reschedules or signals */
182 interrupt_end();
183 userspace(&current->thread.regs.regs);
184 }
185 else do_exit(0);
186}
187
188/* Called magically, see new_thread_handler above */
189void fork_handler(void)
190{
191 force_flush_all();
192 if(current->thread.prev_sched == NULL)
193 panic("blech");
194
195 schedule_tail(current->thread.prev_sched);
196
197 /* XXX: if interrupt_end() calls schedule, this call to
198 * arch_switch_to isn't needed. We could want to apply this to
199 * improve performance. -bb */
200 arch_switch_to(current->thread.prev_sched, current);
201
202 current->thread.prev_sched = NULL;
203
204 /* Handle any immediate reschedules or signals */
205 interrupt_end();
206
207 userspace(&current->thread.regs.regs);
208}
209
150int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, 210int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
151 unsigned long stack_top, struct task_struct * p, 211 unsigned long stack_top, struct task_struct * p,
152 struct pt_regs *regs) 212 struct pt_regs *regs)
153{ 213{
154 int ret; 214 void (*handler)(void);
215 int ret = 0;
155 216
156 p->thread = (struct thread_struct) INIT_THREAD; 217 p->thread = (struct thread_struct) INIT_THREAD;
157 ret = copy_thread_skas(nr, clone_flags, sp, stack_top, p, regs);
158 218
159 if (ret || !current->thread.forking) 219 if(current->thread.forking){
160 goto out; 220 memcpy(&p->thread.regs.regs, &regs->regs,
221 sizeof(p->thread.regs.regs));
222 REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.regs, 0);
223 if(sp != 0)
224 REGS_SP(p->thread.regs.regs.regs) = sp;
161 225
162 clear_flushed_tls(p); 226 handler = fork_handler;
163 227
164 /* 228 arch_copy_thread(&current->thread.arch, &p->thread.arch);
165 * Set a new TLS for the child thread? 229 }
166 */ 230 else {
167 if (clone_flags & CLONE_SETTLS) 231 init_thread_registers(&p->thread.regs.regs);
168 ret = arch_copy_tls(p); 232 p->thread.request.u.thread = current->thread.request.u.thread;
233 handler = new_thread_handler;
234 }
235
236 new_thread(task_stack_page(p), &p->thread.switch_buf, handler);
237
238 if (current->thread.forking) {
239 clear_flushed_tls(p);
240
241 /*
242 * Set a new TLS for the child thread?
243 */
244 if (clone_flags & CLONE_SETTLS)
245 ret = arch_copy_tls(p);
246 }
169 247
170out:
171 return ret; 248 return ret;
172} 249}
173 250
@@ -198,7 +275,8 @@ void default_idle(void)
198 275
199void cpu_idle(void) 276void cpu_idle(void)
200{ 277{
201 init_idle_skas(); 278 cpu_tasks[current_thread->cpu].pid = os_getpid();
279 default_idle();
202} 280}
203 281
204void *um_virt_to_phys(struct task_struct *task, unsigned long addr, 282void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 36debc0de594..bbc3a4a9a0fa 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -228,7 +228,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
228#ifdef PTRACE_ARCH_PRCTL 228#ifdef PTRACE_ARCH_PRCTL
229 case PTRACE_ARCH_PRCTL: 229 case PTRACE_ARCH_PRCTL:
230 /* XXX Calls ptrace on the host - needs some SMP thinking */ 230 /* XXX Calls ptrace on the host - needs some SMP thinking */
231 ret = arch_prctl_skas(child, data, (void *) addr); 231 ret = arch_prctl(child, data, (void *) addr);
232 break; 232 break;
233#endif 233#endif
234 default: 234 default:
@@ -239,7 +239,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
239 return ret; 239 return ret;
240} 240}
241 241
242void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs, 242void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs,
243 int error_code) 243 int error_code)
244{ 244{
245 struct siginfo info; 245 struct siginfo info;
@@ -258,7 +258,7 @@ void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs,
258/* XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and 258/* XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and
259 * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check 259 * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check
260 */ 260 */
261void syscall_trace(union uml_pt_regs *regs, int entryexit) 261void syscall_trace(struct uml_pt_regs *regs, int entryexit)
262{ 262{
263 int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit; 263 int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit;
264 int tracesysgood; 264 int tracesysgood;
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 4a0def32e323..f3bd18bbf07f 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -9,13 +9,30 @@
9#include "kern_util.h" 9#include "kern_util.h"
10#include "kern.h" 10#include "kern.h"
11#include "os.h" 11#include "os.h"
12#include "mode.h" 12#include "skas.h"
13 13
14void (*pm_power_off)(void); 14void (*pm_power_off)(void);
15 15
16static void kill_off_processes(void) 16static void kill_off_processes(void)
17{ 17{
18 kill_off_processes_skas(); 18 if(proc_mm)
19 /*
20 * FIXME: need to loop over userspace_pids
21 */
22 os_kill_ptraced_process(userspace_pid[0], 1);
23 else {
24 struct task_struct *p;
25 int pid, me;
26
27 me = os_getpid();
28 for_each_process(p){
29 if(p->mm == NULL)
30 continue;
31
32 pid = p->mm->context.skas.id.u.pid;
33 os_kill_ptraced_process(pid, 1);
34 }
35 }
19} 36}
20 37
21void uml_cleanup(void) 38void uml_cleanup(void)
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index c4020c3d7857..4dab7e417ba9 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -23,7 +23,6 @@
23#include "kern.h" 23#include "kern.h"
24#include "frame_kern.h" 24#include "frame_kern.h"
25#include "sigcontext.h" 25#include "sigcontext.h"
26#include "mode.h"
27 26
28EXPORT_SYMBOL(block_signals); 27EXPORT_SYMBOL(block_signals);
29EXPORT_SYMBOL(unblock_signals); 28EXPORT_SYMBOL(unblock_signals);
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index 3e3fa7e7e3cf..b2823cdd783e 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -3,7 +3,7 @@
3# Licensed under the GPL 3# Licensed under the GPL
4# 4#
5 5
6obj-y := clone.o exec.o mem.o mmu.o process.o syscall.o tlb.o uaccess.o 6obj-y := clone.o mmu.o process.o syscall.o uaccess.o
7 7
8# 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
9# 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
deleted file mode 100644
index 580eb6468949..000000000000
--- a/arch/um/kernel/skas/exec.c
+++ /dev/null
@@ -1,40 +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 void *data = NULL;
21 unsigned long end = proc_mm ? task_size : CONFIG_STUB_START;
22 int ret;
23
24 ret = unmap(&current->mm->context.skas.id, 0, end, 1, &data);
25 if(ret){
26 printk("flush_thread_skas - clearing address space failed, "
27 "err = %d\n", ret);
28 force_sig(SIGKILL, current);
29 }
30
31 switch_mm_skas(&current->mm->context.skas.id);
32}
33
34void start_thread_skas(struct pt_regs *regs, unsigned long eip,
35 unsigned long esp)
36{
37 set_fs(USER_DS);
38 PT_REGS_IP(regs) = eip;
39 PT_REGS_SP(regs) = esp;
40}
diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c
deleted file mode 100644
index 7c18dfcd7d8e..000000000000
--- a/arch/um/kernel/skas/mem.c
+++ /dev/null
@@ -1,22 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include "linux/mm.h"
7#include "asm/pgtable.h"
8#include "mem_user.h"
9#include "skas.h"
10
11unsigned long set_task_sizes_skas(unsigned long *task_size_out)
12{
13 /* Round up to the nearest 4M */
14 unsigned long host_task_size = ROUND_4M((unsigned long)
15 &host_task_size);
16
17 if (!skas_needs_stub)
18 *task_size_out = host_task_size;
19 else *task_size_out = CONFIG_STUB_START & PGDIR_MASK;
20
21 return host_task_size;
22}
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 2c6d090a2e87..902d74138952 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -71,7 +71,7 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
71 return(-ENOMEM); 71 return(-ENOMEM);
72} 72}
73 73
74int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) 74int init_new_context(struct task_struct *task, struct mm_struct *mm)
75{ 75{
76 struct mmu_context_skas *from_mm = NULL; 76 struct mmu_context_skas *from_mm = NULL;
77 struct mmu_context_skas *to_mm = &mm->context.skas; 77 struct mmu_context_skas *to_mm = &mm->context.skas;
@@ -137,7 +137,7 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
137 return ret; 137 return ret;
138} 138}
139 139
140void destroy_context_skas(struct mm_struct *mm) 140void destroy_context(struct mm_struct *mm)
141{ 141{
142 struct mmu_context_skas *mmu = &mm->context.skas; 142 struct mmu_context_skas *mmu = &mm->context.skas;
143 143
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 48051a98525f..dabae62d52be 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -18,129 +18,22 @@
18#include "os.h" 18#include "os.h"
19#include "tlb.h" 19#include "tlb.h"
20#include "kern.h" 20#include "kern.h"
21#include "mode.h"
22#include "registers.h" 21#include "registers.h"
23 22
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); 23extern void schedule_tail(struct task_struct *prev);
45 24
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) 25int new_mm(unsigned long stack)
127{ 26{
128 int fd; 27 int fd;
129 28
130 fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); 29 fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
131 if(fd < 0) 30 if(fd < 0)
132 return(fd); 31 return fd;
133 32
134 if(skas_needs_stub) 33 if(skas_needs_stub)
135 map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); 34 map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
136 35
137 return(fd); 36 return fd;
138}
139
140void init_idle_skas(void)
141{
142 cpu_tasks[current_thread->cpu].pid = os_getpid();
143 default_idle();
144} 37}
145 38
146extern void start_kernel(void); 39extern void start_kernel(void);
@@ -158,14 +51,14 @@ static int __init start_kernel_proc(void *unused)
158 cpu_online_map = cpumask_of_cpu(0); 51 cpu_online_map = cpumask_of_cpu(0);
159#endif 52#endif
160 start_kernel(); 53 start_kernel();
161 return(0); 54 return 0;
162} 55}
163 56
164extern int userspace_pid[]; 57extern int userspace_pid[];
165 58
166extern char cpu0_irqstack[]; 59extern char cpu0_irqstack[];
167 60
168int __init start_uml_skas(void) 61int __init start_uml(void)
169{ 62{
170 stack_protections((unsigned long) &cpu0_irqstack); 63 stack_protections((unsigned long) &cpu0_irqstack);
171 set_sigstack(cpu0_irqstack, THREAD_SIZE); 64 set_sigstack(cpu0_irqstack, THREAD_SIZE);
@@ -176,49 +69,14 @@ int __init start_uml_skas(void)
176 69
177 init_task.thread.request.u.thread.proc = start_kernel_proc; 70 init_task.thread.request.u.thread.proc = start_kernel_proc;
178 init_task.thread.request.u.thread.arg = NULL; 71 init_task.thread.request.u.thread.arg = NULL;
179 return(start_idle_thread(task_stack_page(&init_task), 72 return start_idle_thread(task_stack_page(&init_task),
180 &init_task.thread.mode.skas.switch_buf)); 73 &init_task.thread.switch_buf);
181}
182
183int external_pid_skas(struct task_struct *task)
184{
185 /* FIXME: Need to look up userspace_pid by cpu */
186 return(userspace_pid[0]);
187}
188
189int thread_pid_skas(struct task_struct *task)
190{
191 /* FIXME: Need to look up userspace_pid by cpu */
192 return(userspace_pid[0]);
193}
194
195void kill_off_processes_skas(void)
196{
197 if(proc_mm)
198 /*
199 * FIXME: need to loop over userspace_pids in
200 * kill_off_processes_skas
201 */
202 os_kill_ptraced_process(userspace_pid[0], 1);
203 else {
204 struct task_struct *p;
205 int pid, me;
206
207 me = os_getpid();
208 for_each_process(p){
209 if(p->mm == NULL)
210 continue;
211
212 pid = p->mm->context.skas.id.u.pid;
213 os_kill_ptraced_process(pid, 1);
214 }
215 }
216} 74}
217 75
218unsigned long current_stub_stack(void) 76unsigned long current_stub_stack(void)
219{ 77{
220 if(current->mm == NULL) 78 if(current->mm == NULL)
221 return(0); 79 return 0;
222 80
223 return(current->mm->context.skas.id.stack); 81 return current->mm->context.skas.id.stack;
224} 82}
diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c
index 0ae4eea21be4..e183da633c89 100644
--- a/arch/um/kernel/skas/syscall.c
+++ b/arch/um/kernel/skas/syscall.c
@@ -13,7 +13,7 @@
13#include "kern_util.h" 13#include "kern_util.h"
14#include "syscall.h" 14#include "syscall.h"
15 15
16void handle_syscall(union uml_pt_regs *r) 16void handle_syscall(struct uml_pt_regs *r)
17{ 17{
18 struct pt_regs *regs = container_of(r, struct pt_regs, regs); 18 struct pt_regs *regs = container_of(r, struct pt_regs, regs);
19 long result; 19 long result;
@@ -37,7 +37,7 @@ void handle_syscall(union uml_pt_regs *r)
37 result = -ENOSYS; 37 result = -ENOSYS;
38 else result = EXECUTE_SYSCALL(syscall, regs); 38 else result = EXECUTE_SYSCALL(syscall, regs);
39 39
40 REGS_SET_SYSCALL_RETURN(r->skas.regs, result); 40 REGS_SET_SYSCALL_RETURN(r->regs, result);
41 41
42 syscall_trace(r, 1); 42 syscall_trace(r, 1);
43} 43}
diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c
deleted file mode 100644
index c0f0693743ba..000000000000
--- a/arch/um/kernel/skas/tlb.c
+++ /dev/null
@@ -1,164 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Copyright 2003 PathScale, Inc.
4 * Licensed under the GPL
5 */
6
7#include "linux/stddef.h"
8#include "linux/sched.h"
9#include "linux/mm.h"
10#include "asm/page.h"
11#include "asm/pgtable.h"
12#include "asm/mmu.h"
13#include "mem_user.h"
14#include "mem.h"
15#include "skas.h"
16#include "os.h"
17#include "tlb.h"
18
19static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last,
20 int finished, void **flush)
21{
22 struct host_vm_op *op;
23 int i, ret = 0;
24
25 for(i = 0; i <= last && !ret; i++){
26 op = &ops[i];
27 switch(op->type){
28 case MMAP:
29 ret = map(&mmu->skas.id, op->u.mmap.addr,
30 op->u.mmap.len, op->u.mmap.prot,
31 op->u.mmap.fd, op->u.mmap.offset, finished,
32 flush);
33 break;
34 case MUNMAP:
35 ret = unmap(&mmu->skas.id, op->u.munmap.addr,
36 op->u.munmap.len, finished, flush);
37 break;
38 case MPROTECT:
39 ret = protect(&mmu->skas.id, op->u.mprotect.addr,
40 op->u.mprotect.len, op->u.mprotect.prot,
41 finished, flush);
42 break;
43 default:
44 printk("Unknown op type %d in do_ops\n", op->type);
45 break;
46 }
47 }
48
49 return ret;
50}
51
52extern int proc_mm;
53
54static void fix_range(struct mm_struct *mm, unsigned long start_addr,
55 unsigned long end_addr, int force)
56{
57 if(!proc_mm && (end_addr > CONFIG_STUB_START))
58 end_addr = CONFIG_STUB_START;
59
60 fix_range_common(mm, start_addr, end_addr, force, do_ops);
61}
62
63void __flush_tlb_one_skas(unsigned long addr)
64{
65 flush_tlb_kernel_range_common(addr, addr + PAGE_SIZE);
66}
67
68void flush_tlb_range_skas(struct vm_area_struct *vma, unsigned long start,
69 unsigned long end)
70{
71 if(vma->vm_mm == NULL)
72 flush_tlb_kernel_range_common(start, end);
73 else fix_range(vma->vm_mm, start, end, 0);
74}
75
76void flush_tlb_mm_skas(struct mm_struct *mm)
77{
78 unsigned long end;
79
80 /* Don't bother flushing if this address space is about to be
81 * destroyed.
82 */
83 if(atomic_read(&mm->mm_users) == 0)
84 return;
85
86 end = proc_mm ? task_size : CONFIG_STUB_START;
87 fix_range(mm, 0, end, 0);
88}
89
90void force_flush_all_skas(void)
91{
92 struct mm_struct *mm = current->mm;
93 struct vm_area_struct *vma = mm->mmap;
94
95 while(vma != NULL) {
96 fix_range(mm, vma->vm_start, vma->vm_end, 1);
97 vma = vma->vm_next;
98 }
99}
100
101void flush_tlb_page_skas(struct vm_area_struct *vma, unsigned long address)
102{
103 pgd_t *pgd;
104 pud_t *pud;
105 pmd_t *pmd;
106 pte_t *pte;
107 struct mm_struct *mm = vma->vm_mm;
108 void *flush = NULL;
109 int r, w, x, prot, err = 0;
110 struct mm_id *mm_id;
111
112 pgd = pgd_offset(mm, address);
113 if(!pgd_present(*pgd))
114 goto kill;
115
116 pud = pud_offset(pgd, address);
117 if(!pud_present(*pud))
118 goto kill;
119
120 pmd = pmd_offset(pud, address);
121 if(!pmd_present(*pmd))
122 goto kill;
123
124 pte = pte_offset_kernel(pmd, address);
125
126 r = pte_read(*pte);
127 w = pte_write(*pte);
128 x = pte_exec(*pte);
129 if (!pte_young(*pte)) {
130 r = 0;
131 w = 0;
132 } else if (!pte_dirty(*pte)) {
133 w = 0;
134 }
135
136 mm_id = &mm->context.skas.id;
137 prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
138 (x ? UM_PROT_EXEC : 0));
139 if(pte_newpage(*pte)){
140 if(pte_present(*pte)){
141 unsigned long long offset;
142 int fd;
143
144 fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset);
145 err = map(mm_id, address, PAGE_SIZE, prot, fd, offset,
146 1, &flush);
147 }
148 else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush);
149 }
150 else if(pte_newprot(*pte))
151 err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush);
152
153 if(err)
154 goto kill;
155
156 *pte = pte_mkuptodate(*pte);
157
158 return;
159
160kill:
161 printk("Failed to flush page for address 0x%lx\n", address);
162 force_sig(SIGKILL, current);
163}
164
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index 138bcb43b997..ebb29f5259a9 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -20,7 +20,6 @@
20#include "asm/uaccess.h" 20#include "asm/uaccess.h"
21#include "kern_util.h" 21#include "kern_util.h"
22#include "sysdep/syscalls.h" 22#include "sysdep/syscalls.h"
23#include "mode_kern.h"
24 23
25/* Unlocked, I don't care if this is a bit off */ 24/* Unlocked, I don't care if this is a bit off */
26int nsyscalls = 0; 25int nsyscalls = 0;
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 3571703a7cb4..90e24e2dbeaa 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -18,7 +18,6 @@
18#include "asm/param.h" 18#include "asm/param.h"
19#include "asm/current.h" 19#include "asm/current.h"
20#include "kern_util.h" 20#include "kern_util.h"
21#include "mode.h"
22#include "os.h" 21#include "os.h"
23 22
24int hz(void) 23int hz(void)
@@ -39,7 +38,7 @@ static unsigned long long prev_nsecs[NR_CPUS];
39static long long delta[NR_CPUS]; /* Deviation per interval */ 38static long long delta[NR_CPUS]; /* Deviation per interval */
40#endif 39#endif
41 40
42void timer_irq(union uml_pt_regs *regs) 41void timer_irq(struct uml_pt_regs *regs)
43{ 42{
44 unsigned long long ticks = 0; 43 unsigned long long ticks = 0;
45#ifdef CONFIG_UML_REAL_TIME_CLOCK 44#ifdef CONFIG_UML_REAL_TIME_CLOCK
@@ -175,13 +174,13 @@ int do_settimeofday(struct timespec *tv)
175 return 0; 174 return 0;
176} 175}
177 176
178void timer_handler(int sig, union uml_pt_regs *regs) 177void timer_handler(int sig, struct uml_pt_regs *regs)
179{ 178{
180 if(current_thread->cpu == 0) 179 if(current_thread->cpu == 0)
181 timer_irq(regs); 180 timer_irq(regs);
182 local_irq_disable(); 181 local_irq_disable();
183 irq_enter(); 182 irq_enter();
184 update_process_times((regs)->skas.is_user); 183 update_process_times(regs->is_user);
185 irq_exit(); 184 irq_exit();
186 local_irq_enable(); 185 local_irq_enable();
187} 186}
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index 312e8ba30cd3..12b8c637527d 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -8,12 +8,12 @@
8#include "asm/pgalloc.h" 8#include "asm/pgalloc.h"
9#include "asm/pgtable.h" 9#include "asm/pgtable.h"
10#include "asm/tlbflush.h" 10#include "asm/tlbflush.h"
11#include "mode_kern.h"
12#include "as-layout.h" 11#include "as-layout.h"
13#include "tlb.h" 12#include "tlb.h"
14#include "mem.h" 13#include "mem.h"
15#include "mem_user.h" 14#include "mem_user.h"
16#include "os.h" 15#include "os.h"
16#include "skas.h"
17 17
18static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, 18static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
19 unsigned int prot, struct host_vm_op *ops, int *index, 19 unsigned int prot, struct host_vm_op *ops, int *index,
@@ -341,6 +341,71 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
341 return(updated); 341 return(updated);
342} 342}
343 343
344void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
345{
346 pgd_t *pgd;
347 pud_t *pud;
348 pmd_t *pmd;
349 pte_t *pte;
350 struct mm_struct *mm = vma->vm_mm;
351 void *flush = NULL;
352 int r, w, x, prot, err = 0;
353 struct mm_id *mm_id;
354
355 address &= PAGE_MASK;
356 pgd = pgd_offset(mm, address);
357 if(!pgd_present(*pgd))
358 goto kill;
359
360 pud = pud_offset(pgd, address);
361 if(!pud_present(*pud))
362 goto kill;
363
364 pmd = pmd_offset(pud, address);
365 if(!pmd_present(*pmd))
366 goto kill;
367
368 pte = pte_offset_kernel(pmd, address);
369
370 r = pte_read(*pte);
371 w = pte_write(*pte);
372 x = pte_exec(*pte);
373 if (!pte_young(*pte)) {
374 r = 0;
375 w = 0;
376 } else if (!pte_dirty(*pte)) {
377 w = 0;
378 }
379
380 mm_id = &mm->context.skas.id;
381 prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
382 (x ? UM_PROT_EXEC : 0));
383 if(pte_newpage(*pte)){
384 if(pte_present(*pte)){
385 unsigned long long offset;
386 int fd;
387
388 fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset);
389 err = map(mm_id, address, PAGE_SIZE, prot, fd, offset,
390 1, &flush);
391 }
392 else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush);
393 }
394 else if(pte_newprot(*pte))
395 err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush);
396
397 if(err)
398 goto kill;
399
400 *pte = pte_mkuptodate(*pte);
401
402 return;
403
404kill:
405 printk("Failed to flush page for address 0x%lx\n", address);
406 force_sig(SIGKILL, current);
407}
408
344pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) 409pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
345{ 410{
346 return(pgd_offset(mm, address)); 411 return(pgd_offset(mm, address));
@@ -387,21 +452,80 @@ void flush_tlb_kernel_vm(void)
387 452
388void __flush_tlb_one(unsigned long addr) 453void __flush_tlb_one(unsigned long addr)
389{ 454{
390 __flush_tlb_one_skas(addr); 455 flush_tlb_kernel_range_common(addr, addr + PAGE_SIZE);
456}
457
458static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last,
459 int finished, void **flush)
460{
461 struct host_vm_op *op;
462 int i, ret = 0;
463
464 for(i = 0; i <= last && !ret; i++){
465 op = &ops[i];
466 switch(op->type){
467 case MMAP:
468 ret = map(&mmu->skas.id, op->u.mmap.addr,
469 op->u.mmap.len, op->u.mmap.prot,
470 op->u.mmap.fd, op->u.mmap.offset, finished,
471 flush);
472 break;
473 case MUNMAP:
474 ret = unmap(&mmu->skas.id, op->u.munmap.addr,
475 op->u.munmap.len, finished, flush);
476 break;
477 case MPROTECT:
478 ret = protect(&mmu->skas.id, op->u.mprotect.addr,
479 op->u.mprotect.len, op->u.mprotect.prot,
480 finished, flush);
481 break;
482 default:
483 printk("Unknown op type %d in do_ops\n", op->type);
484 break;
485 }
486 }
487
488 return ret;
489}
490
491static void fix_range(struct mm_struct *mm, unsigned long start_addr,
492 unsigned long end_addr, int force)
493{
494 if(!proc_mm && (end_addr > CONFIG_STUB_START))
495 end_addr = CONFIG_STUB_START;
496
497 fix_range_common(mm, start_addr, end_addr, force, do_ops);
391} 498}
392 499
393void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, 500void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
394 unsigned long end) 501 unsigned long end)
395{ 502{
396 flush_tlb_range_skas(vma, start, end); 503 if(vma->vm_mm == NULL)
504 flush_tlb_kernel_range_common(start, end);
505 else fix_range(vma->vm_mm, start, end, 0);
397} 506}
398 507
399void flush_tlb_mm(struct mm_struct *mm) 508void flush_tlb_mm(struct mm_struct *mm)
400{ 509{
401 flush_tlb_mm_skas(mm); 510 unsigned long end;
511
512 /* Don't bother flushing if this address space is about to be
513 * destroyed.
514 */
515 if(atomic_read(&mm->mm_users) == 0)
516 return;
517
518 end = proc_mm ? task_size : CONFIG_STUB_START;
519 fix_range(mm, 0, end, 0);
402} 520}
403 521
404void force_flush_all(void) 522void force_flush_all(void)
405{ 523{
406 force_flush_all_skas(); 524 struct mm_struct *mm = current->mm;
525 struct vm_area_struct *vma = mm->mmap;
526
527 while(vma != NULL) {
528 fix_range(mm, vma->vm_start, vma->vm_end, 1);
529 vma = vma->vm_next;
530 }
407} 531}
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 4b472ca53485..eac63fb6183c 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -128,7 +128,7 @@ static void bad_segv(struct faultinfo fi, unsigned long ip)
128 force_sig_info(SIGSEGV, &si, current); 128 force_sig_info(SIGSEGV, &si, current);
129} 129}
130 130
131static void segv_handler(int sig, union uml_pt_regs *regs) 131static void segv_handler(int sig, struct uml_pt_regs *regs)
132{ 132{
133 struct faultinfo * fi = UPT_FAULTINFO(regs); 133 struct faultinfo * fi = UPT_FAULTINFO(regs);
134 134
@@ -146,7 +146,7 @@ static void segv_handler(int sig, union uml_pt_regs *regs)
146 * give us bad data! 146 * give us bad data!
147 */ 147 */
148unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, 148unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
149 union uml_pt_regs *regs) 149 struct uml_pt_regs *regs)
150{ 150{
151 struct siginfo si; 151 struct siginfo si;
152 void *catcher; 152 void *catcher;
@@ -214,7 +214,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
214 return 0; 214 return 0;
215} 215}
216 216
217void relay_signal(int sig, union uml_pt_regs *regs) 217void relay_signal(int sig, struct uml_pt_regs *regs)
218{ 218{
219 if (arch_handle_signal(sig, regs)) 219 if (arch_handle_signal(sig, regs))
220 return; 220 return;
@@ -230,14 +230,14 @@ void relay_signal(int sig, union uml_pt_regs *regs)
230 force_sig(sig, current); 230 force_sig(sig, current);
231} 231}
232 232
233static void bus_handler(int sig, union uml_pt_regs *regs) 233static void bus_handler(int sig, struct uml_pt_regs *regs)
234{ 234{
235 if (current->thread.fault_catcher != NULL) 235 if (current->thread.fault_catcher != NULL)
236 do_longjmp(current->thread.fault_catcher, 1); 236 do_longjmp(current->thread.fault_catcher, 1);
237 else relay_signal(sig, regs); 237 else relay_signal(sig, regs);
238} 238}
239 239
240static void winch(int sig, union uml_pt_regs *regs) 240static void winch(int sig, struct uml_pt_regs *regs)
241{ 241{
242 do_IRQ(WINCH_IRQ, regs); 242 do_IRQ(WINCH_IRQ, regs);
243} 243}
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 9f3a207eb81f..5f3e13c365e5 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -35,8 +35,6 @@
35#include "initrd.h" 35#include "initrd.h"
36#include "init.h" 36#include "init.h"
37#include "os.h" 37#include "os.h"
38#include "mode_kern.h"
39#include "mode.h"
40#include "skas.h" 38#include "skas.h"
41 39
42#define DEFAULT_COMMAND_LINE "root=98:0" 40#define DEFAULT_COMMAND_LINE "root=98:0"
@@ -67,7 +65,8 @@ struct cpuinfo_um boot_cpu_data = {
67 65
68unsigned long thread_saved_pc(struct task_struct *task) 66unsigned long thread_saved_pc(struct task_struct *task)
69{ 67{
70 return os_process_pc(thread_pid_skas(task)); 68 /* FIXME: Need to look up userspace_pid by cpu */
69 return os_process_pc(userspace_pid[0]);
71} 70}
72 71
73/* Changed in setup_arch, which is called in early boot */ 72/* Changed in setup_arch, which is called in early boot */
@@ -253,6 +252,19 @@ EXPORT_SYMBOL(end_iomem);
253 252
254extern char __binary_start; 253extern char __binary_start;
255 254
255static unsigned long set_task_sizes_skas(unsigned long *task_size_out)
256{
257 /* Round up to the nearest 4M */
258 unsigned long host_task_size = ROUND_4M((unsigned long)
259 &host_task_size);
260
261 if (!skas_needs_stub)
262 *task_size_out = host_task_size;
263 else *task_size_out = CONFIG_STUB_START & PGDIR_MASK;
264
265 return host_task_size;
266}
267
256int __init linux_main(int argc, char **argv) 268int __init linux_main(int argc, char **argv)
257{ 269{
258 unsigned long avail, diff; 270 unsigned long avail, diff;
@@ -289,7 +301,7 @@ int __init linux_main(int argc, char **argv)
289 os_fill_handlinfo(handlinfo_kern); 301 os_fill_handlinfo(handlinfo_kern);
290 302
291 brk_start = (unsigned long) sbrk(0); 303 brk_start = (unsigned long) sbrk(0);
292 before_mem_skas(brk_start); 304
293 /* Increase physical memory size for exec-shield users 305 /* Increase physical memory size for exec-shield users
294 so they actually get what they asked for. This should 306 so they actually get what they asked for. This should
295 add zero for non-exec shield users */ 307 add zero for non-exec shield users */
@@ -354,7 +366,7 @@ int __init linux_main(int argc, char **argv)
354 stack_protections((unsigned long) &init_thread_info); 366 stack_protections((unsigned long) &init_thread_info);
355 os_flush_stdout(); 367 os_flush_stdout();
356 368
357 return start_uml_skas(); 369 return start_uml();
358} 370}
359 371
360extern int uml_exitcode; 372extern int uml_exitcode;