aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel')
-rw-r--r--arch/um/kernel/Makefile7
-rw-r--r--arch/um/kernel/helper.c165
-rw-r--r--arch/um/kernel/ksyms.c1
-rw-r--r--arch/um/kernel/main.c270
-rw-r--r--arch/um/kernel/mem.c4
-rw-r--r--arch/um/kernel/physmem.c4
-rw-r--r--arch/um/kernel/ptrace.c50
-rw-r--r--arch/um/kernel/sigio_user.c3
-rw-r--r--arch/um/kernel/skas/include/mmu-skas.h2
-rw-r--r--arch/um/kernel/skas/include/skas.h3
-rw-r--r--arch/um/kernel/skas/mem.c2
-rw-r--r--arch/um/kernel/skas/mmu.c44
-rw-r--r--arch/um/kernel/skas/process.c17
-rw-r--r--arch/um/kernel/skas/process_kern.c2
-rw-r--r--arch/um/kernel/tt/uaccess_user.c1
-rw-r--r--arch/um/kernel/uaccess.c30
-rw-r--r--arch/um/kernel/uaccess_user.c64
-rw-r--r--arch/um/kernel/um_arch.c10
-rw-r--r--arch/um/kernel/user_util.c1
19 files changed, 93 insertions, 587 deletions
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 1a0001b3850c..3de9d21e36bf 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -7,10 +7,10 @@ extra-y := vmlinux.lds
7clean-files := 7clean-files :=
8 8
9obj-y = config.o exec_kern.o exitcode.o \ 9obj-y = config.o exec_kern.o exitcode.o \
10 helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o physmem.o \ 10 init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \
11 process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ 11 process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \
12 signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \ 12 signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \
13 time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \ 13 time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o \
14 umid.o user_util.o 14 umid.o user_util.o
15 15
16obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o 16obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
@@ -24,8 +24,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/
24 24
25user-objs-$(CONFIG_TTY_LOG) += tty_log.o 25user-objs-$(CONFIG_TTY_LOG) += tty_log.o
26 26
27USER_OBJS := $(user-objs-y) config.o helper.o main.o time.o tty_log.o umid.o \ 27USER_OBJS := $(user-objs-y) config.o time.o tty_log.o umid.o user_util.o
28 user_util.o
29 28
30include arch/um/scripts/Makefile.rules 29include arch/um/scripts/Makefile.rules
31 30
diff --git a/arch/um/kernel/helper.c b/arch/um/kernel/helper.c
deleted file mode 100644
index 33fb0bd3b11a..000000000000
--- a/arch/um/kernel/helper.c
+++ /dev/null
@@ -1,165 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <unistd.h>
9#include <errno.h>
10#include <sched.h>
11#include <sys/signal.h>
12#include <sys/wait.h>
13#include "user.h"
14#include "kern_util.h"
15#include "user_util.h"
16#include "helper.h"
17#include "os.h"
18
19struct helper_data {
20 void (*pre_exec)(void*);
21 void *pre_data;
22 char **argv;
23 int fd;
24};
25
26/* Debugging aid, changed only from gdb */
27int helper_pause = 0;
28
29static void helper_hup(int sig)
30{
31}
32
33static int helper_child(void *arg)
34{
35 struct helper_data *data = arg;
36 char **argv = data->argv;
37 int errval;
38
39 if(helper_pause){
40 signal(SIGHUP, helper_hup);
41 pause();
42 }
43 if(data->pre_exec != NULL)
44 (*data->pre_exec)(data->pre_data);
45 execvp(argv[0], argv);
46 errval = errno;
47 printk("execvp of '%s' failed - errno = %d\n", argv[0], errno);
48 os_write_file(data->fd, &errval, sizeof(errval));
49 os_kill_process(os_getpid(), 0);
50 return(0);
51}
52
53/* Returns either the pid of the child process we run or -E* on failure.
54 * XXX The alloc_stack here breaks if this is called in the tracing thread */
55int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
56 unsigned long *stack_out)
57{
58 struct helper_data data;
59 unsigned long stack, sp;
60 int pid, fds[2], ret, n;
61
62 if((stack_out != NULL) && (*stack_out != 0))
63 stack = *stack_out;
64 else stack = alloc_stack(0, um_in_interrupt());
65 if(stack == 0)
66 return(-ENOMEM);
67
68 ret = os_pipe(fds, 1, 0);
69 if(ret < 0){
70 printk("run_helper : pipe failed, ret = %d\n", -ret);
71 goto out_free;
72 }
73
74 ret = os_set_exec_close(fds[1], 1);
75 if(ret < 0){
76 printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n",
77 -ret);
78 goto out_close;
79 }
80
81 sp = stack + page_size() - sizeof(void *);
82 data.pre_exec = pre_exec;
83 data.pre_data = pre_data;
84 data.argv = argv;
85 data.fd = fds[1];
86 pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
87 if(pid < 0){
88 ret = -errno;
89 printk("run_helper : clone failed, errno = %d\n", errno);
90 goto out_close;
91 }
92
93 os_close_file(fds[1]);
94 fds[1] = -1;
95
96 /*Read the errno value from the child.*/
97 n = os_read_file(fds[0], &ret, sizeof(ret));
98 if(n < 0){
99 printk("run_helper : read on pipe failed, ret = %d\n", -n);
100 ret = n;
101 os_kill_process(pid, 1);
102 }
103 else if(n != 0){
104 CATCH_EINTR(n = waitpid(pid, NULL, 0));
105 ret = -errno;
106 } else {
107 ret = pid;
108 }
109
110out_close:
111 if (fds[1] != -1)
112 os_close_file(fds[1]);
113 os_close_file(fds[0]);
114out_free:
115 if(stack_out == NULL)
116 free_stack(stack, 0);
117 else *stack_out = stack;
118 return(ret);
119}
120
121int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
122 unsigned long *stack_out, int stack_order)
123{
124 unsigned long stack, sp;
125 int pid, status, err;
126
127 stack = alloc_stack(stack_order, um_in_interrupt());
128 if(stack == 0) return(-ENOMEM);
129
130 sp = stack + (page_size() << stack_order) - sizeof(void *);
131 pid = clone(proc, (void *) sp, flags | SIGCHLD, arg);
132 if(pid < 0){
133 err = -errno;
134 printk("run_helper_thread : clone failed, errno = %d\n",
135 errno);
136 return err;
137 }
138 if(stack_out == NULL){
139 CATCH_EINTR(pid = waitpid(pid, &status, 0));
140 if(pid < 0){
141 err = -errno;
142 printk("run_helper_thread - wait failed, errno = %d\n",
143 errno);
144 pid = err;
145 }
146 if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
147 printk("run_helper_thread - thread returned status "
148 "0x%x\n", status);
149 free_stack(stack, stack_order);
150 }
151 else *stack_out = stack;
152 return(pid);
153}
154
155int helper_wait(int pid)
156{
157 int ret;
158
159 CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG));
160 if(ret < 0){
161 ret = -errno;
162 printk("helper_wait : waitpid failed, errno = %d\n", errno);
163 }
164 return(ret);
165}
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index a97a72e516aa..7713e7a6f476 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -20,7 +20,6 @@
20#include "user_util.h" 20#include "user_util.h"
21#include "mem_user.h" 21#include "mem_user.h"
22#include "os.h" 22#include "os.h"
23#include "helper.h"
24 23
25EXPORT_SYMBOL(stop); 24EXPORT_SYMBOL(stop);
26EXPORT_SYMBOL(uml_physmem); 25EXPORT_SYMBOL(uml_physmem);
diff --git a/arch/um/kernel/main.c b/arch/um/kernel/main.c
deleted file mode 100644
index d31027f0fe39..000000000000
--- a/arch/um/kernel/main.c
+++ /dev/null
@@ -1,270 +0,0 @@
1/*
2 * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <unistd.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <signal.h>
11#include <errno.h>
12#include <sys/resource.h>
13#include <sys/mman.h>
14#include <sys/user.h>
15#include <asm/page.h>
16#include "user_util.h"
17#include "kern_util.h"
18#include "mem_user.h"
19#include "signal_user.h"
20#include "time_user.h"
21#include "irq_user.h"
22#include "user.h"
23#include "init.h"
24#include "mode.h"
25#include "choose-mode.h"
26#include "uml-config.h"
27#include "os.h"
28
29/* Set in set_stklim, which is called from main and __wrap_malloc.
30 * __wrap_malloc only calls it if main hasn't started.
31 */
32unsigned long stacksizelim;
33
34/* Set in main */
35char *linux_prog;
36
37#define PGD_BOUND (4 * 1024 * 1024)
38#define STACKSIZE (8 * 1024 * 1024)
39#define THREAD_NAME_LEN (256)
40
41static void set_stklim(void)
42{
43 struct rlimit lim;
44
45 if(getrlimit(RLIMIT_STACK, &lim) < 0){
46 perror("getrlimit");
47 exit(1);
48 }
49 if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){
50 lim.rlim_cur = STACKSIZE;
51 if(setrlimit(RLIMIT_STACK, &lim) < 0){
52 perror("setrlimit");
53 exit(1);
54 }
55 }
56 stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1);
57}
58
59static __init void do_uml_initcalls(void)
60{
61 initcall_t *call;
62
63 call = &__uml_initcall_start;
64 while (call < &__uml_initcall_end){;
65 (*call)();
66 call++;
67 }
68}
69
70static void last_ditch_exit(int sig)
71{
72 signal(SIGINT, SIG_DFL);
73 signal(SIGTERM, SIG_DFL);
74 signal(SIGHUP, SIG_DFL);
75 uml_cleanup();
76 exit(1);
77}
78
79extern int uml_exitcode;
80
81extern void scan_elf_aux( char **envp);
82
83int main(int argc, char **argv, char **envp)
84{
85 char **new_argv;
86 sigset_t mask;
87 int ret, i, err;
88
89 /* Enable all signals except SIGIO - in some environments, we can
90 * enter with some signals blocked
91 */
92
93 sigemptyset(&mask);
94 sigaddset(&mask, SIGIO);
95 if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){
96 perror("sigprocmask");
97 exit(1);
98 }
99
100#ifdef UML_CONFIG_CMDLINE_ON_HOST
101 /* Allocate memory for thread command lines */
102 if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){
103
104 char padding[THREAD_NAME_LEN] = {
105 [ 0 ... THREAD_NAME_LEN - 2] = ' ', '\0'
106 };
107
108 new_argv = malloc((argc + 2) * sizeof(char*));
109 if(!new_argv) {
110 perror("Allocating extended argv");
111 exit(1);
112 }
113
114 new_argv[0] = argv[0];
115 new_argv[1] = padding;
116
117 for(i = 2; i <= argc; i++)
118 new_argv[i] = argv[i - 1];
119 new_argv[argc + 1] = NULL;
120
121 execvp(new_argv[0], new_argv);
122 perror("execing with extended args");
123 exit(1);
124 }
125#endif
126
127 linux_prog = argv[0];
128
129 set_stklim();
130
131 new_argv = malloc((argc + 1) * sizeof(char *));
132 if(new_argv == NULL){
133 perror("Mallocing argv");
134 exit(1);
135 }
136 for(i=0;i<argc;i++){
137 new_argv[i] = strdup(argv[i]);
138 if(new_argv[i] == NULL){
139 perror("Mallocing an arg");
140 exit(1);
141 }
142 }
143 new_argv[argc] = NULL;
144
145 set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
146 set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
147 set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
148
149 scan_elf_aux( envp);
150
151 do_uml_initcalls();
152 ret = linux_main(argc, argv);
153
154 /* Disable SIGPROF - I have no idea why libc doesn't do this or turn
155 * off the profiling time, but UML dies with a SIGPROF just before
156 * exiting when profiling is active.
157 */
158 change_sig(SIGPROF, 0);
159
160 /* This signal stuff used to be in the reboot case. However,
161 * sometimes a SIGVTALRM can come in when we're halting (reproducably
162 * when writing out gcov information, presumably because that takes
163 * some time) and cause a segfault.
164 */
165
166 /* stop timers and set SIG*ALRM to be ignored */
167 disable_timer();
168
169 /* disable SIGIO for the fds and set SIGIO to be ignored */
170 err = deactivate_all_fds();
171 if(err)
172 printf("deactivate_all_fds failed, errno = %d\n", -err);
173
174 /* Let any pending signals fire now. This ensures
175 * that they won't be delivered after the exec, when
176 * they are definitely not expected.
177 */
178 unblock_signals();
179
180 /* Reboot */
181 if(ret){
182 printf("\n");
183 execvp(new_argv[0], new_argv);
184 perror("Failed to exec kernel");
185 ret = 1;
186 }
187 printf("\n");
188 return(uml_exitcode);
189}
190
191#define CAN_KMALLOC() \
192 (kmalloc_ok && CHOOSE_MODE((os_getpid() != tracing_pid), 1))
193
194extern void *__real_malloc(int);
195
196void *__wrap_malloc(int size)
197{
198 void *ret;
199
200 if(!CAN_KMALLOC())
201 return(__real_malloc(size));
202 else if(size <= PAGE_SIZE) /* finding contiguos pages can be hard*/
203 ret = um_kmalloc(size);
204 else ret = um_vmalloc(size);
205
206 /* glibc people insist that if malloc fails, errno should be
207 * set by malloc as well. So we do.
208 */
209 if(ret == NULL)
210 errno = ENOMEM;
211
212 return(ret);
213}
214
215void *__wrap_calloc(int n, int size)
216{
217 void *ptr = __wrap_malloc(n * size);
218
219 if(ptr == NULL) return(NULL);
220 memset(ptr, 0, n * size);
221 return(ptr);
222}
223
224extern void __real_free(void *);
225
226extern unsigned long high_physmem;
227
228void __wrap_free(void *ptr)
229{
230 unsigned long addr = (unsigned long) ptr;
231
232 /* We need to know how the allocation happened, so it can be correctly
233 * freed. This is done by seeing what region of memory the pointer is
234 * in -
235 * physical memory - kmalloc/kfree
236 * kernel virtual memory - vmalloc/vfree
237 * anywhere else - malloc/free
238 * If kmalloc is not yet possible, then either high_physmem and/or
239 * end_vm are still 0 (as at startup), in which case we call free, or
240 * we have set them, but anyway addr has not been allocated from those
241 * areas. So, in both cases __real_free is called.
242 *
243 * CAN_KMALLOC is checked because it would be bad to free a buffer
244 * with kmalloc/vmalloc after they have been turned off during
245 * shutdown.
246 * XXX: However, we sometimes shutdown CAN_KMALLOC temporarily, so
247 * there is a possibility for memory leaks.
248 */
249
250 if((addr >= uml_physmem) && (addr < high_physmem)){
251 if(CAN_KMALLOC())
252 kfree(ptr);
253 }
254 else if((addr >= start_vm) && (addr < end_vm)){
255 if(CAN_KMALLOC())
256 vfree(ptr);
257 }
258 else __real_free(ptr);
259}
260
261/*
262 * Overrides for Emacs so that we follow Linus's tabbing style.
263 * Emacs will notice this stuff at the end of the file and automatically
264 * adjust the settings for this buffer only. This must remain at the end
265 * of the file.
266 * ---------------------------------------------------------------------------
267 * Local variables:
268 * c-file-style: "linux"
269 * End:
270 */
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 462cc9d65386..fa4f915be5c5 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -234,8 +234,8 @@ void paging_init(void)
234 empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); 234 empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
235 for(i=0;i<sizeof(zones_size)/sizeof(zones_size[0]);i++) 235 for(i=0;i<sizeof(zones_size)/sizeof(zones_size[0]);i++)
236 zones_size[i] = 0; 236 zones_size[i] = 0;
237 zones_size[0] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT); 237 zones_size[ZONE_DMA] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT);
238 zones_size[2] = highmem >> PAGE_SHIFT; 238 zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT;
239 free_area_init(zones_size); 239 free_area_init(zones_size);
240 240
241 /* 241 /*
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index ea670fcc8af5..f3b583a878a6 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -246,7 +246,7 @@ int is_remapped(void *virt)
246/* Changed during early boot */ 246/* Changed during early boot */
247unsigned long high_physmem; 247unsigned long high_physmem;
248 248
249extern unsigned long physmem_size; 249extern unsigned long long physmem_size;
250 250
251int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem) 251int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem)
252{ 252{
@@ -321,7 +321,7 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
321extern int __syscall_stub_start, __binary_start; 321extern int __syscall_stub_start, __binary_start;
322 322
323void setup_physmem(unsigned long start, unsigned long reserve_end, 323void setup_physmem(unsigned long start, unsigned long reserve_end,
324 unsigned long len, unsigned long highmem) 324 unsigned long len, unsigned long long highmem)
325{ 325{
326 unsigned long reserve = reserve_end - start; 326 unsigned long reserve = reserve_end - start;
327 int pfn = PFN_UP(__pa(reserve_end)); 327 int pfn = PFN_UP(__pa(reserve_end));
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 71af4d503899..98e09395c093 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -43,53 +43,10 @@ void ptrace_disable(struct task_struct *child)
43extern int peek_user(struct task_struct * child, long addr, long data); 43extern int peek_user(struct task_struct * child, long addr, long data);
44extern int poke_user(struct task_struct * child, long addr, long data); 44extern int poke_user(struct task_struct * child, long addr, long data);
45 45
46long sys_ptrace(long request, long pid, long addr, long data) 46long arch_ptrace(struct task_struct *child, long request, long addr, long data)
47{ 47{
48 struct task_struct *child;
49 int i, ret; 48 int i, ret;
50 49
51 lock_kernel();
52 ret = -EPERM;
53 if (request == PTRACE_TRACEME) {
54 /* are we already being traced? */
55 if (current->ptrace & PT_PTRACED)
56 goto out;
57
58 ret = security_ptrace(current->parent, current);
59 if (ret)
60 goto out;
61
62 /* set the ptrace bit in the process flags. */
63 current->ptrace |= PT_PTRACED;
64 ret = 0;
65 goto out;
66 }
67 ret = -ESRCH;
68 read_lock(&tasklist_lock);
69 child = find_task_by_pid(pid);
70 if (child)
71 get_task_struct(child);
72 read_unlock(&tasklist_lock);
73 if (!child)
74 goto out;
75
76 ret = -EPERM;
77 if (pid == 1) /* you may not mess with init */
78 goto out_tsk;
79
80 if (request == PTRACE_ATTACH) {
81 ret = ptrace_attach(child);
82 goto out_tsk;
83 }
84
85#ifdef SUBACH_PTRACE_SPECIAL
86 SUBARCH_PTRACE_SPECIAL(child,request,addr,data);
87#endif
88
89 ret = ptrace_check_attach(child, request == PTRACE_KILL);
90 if (ret < 0)
91 goto out_tsk;
92
93 switch (request) { 50 switch (request) {
94 /* when I and D space are separate, these will need to be fixed. */ 51 /* when I and D space are separate, these will need to be fixed. */
95 case PTRACE_PEEKTEXT: /* read word at location addr. */ 52 case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -282,10 +239,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
282 ret = ptrace_request(child, request, addr, data); 239 ret = ptrace_request(child, request, addr, data);
283 break; 240 break;
284 } 241 }
285 out_tsk: 242
286 put_task_struct(child);
287 out:
288 unlock_kernel();
289 return ret; 243 return ret;
290} 244}
291 245
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index a52751108aa1..48b1f644b9a6 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -18,7 +18,6 @@
18#include "kern_util.h" 18#include "kern_util.h"
19#include "user_util.h" 19#include "user_util.h"
20#include "sigio.h" 20#include "sigio.h"
21#include "helper.h"
22#include "os.h" 21#include "os.h"
23 22
24/* Changed during early boot */ 23/* Changed during early boot */
@@ -225,7 +224,7 @@ static int need_poll(int n)
225 next_poll.used = n; 224 next_poll.used = n;
226 return(0); 225 return(0);
227 } 226 }
228 if(next_poll.poll != NULL) kfree(next_poll.poll); 227 kfree(next_poll.poll);
229 next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd)); 228 next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd));
230 if(next_poll.poll == NULL){ 229 if(next_poll.poll == NULL){
231 printk("need_poll : failed to allocate new pollfds\n"); 230 printk("need_poll : failed to allocate new pollfds\n");
diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h
index 09536f81ee42..44110c521e49 100644
--- a/arch/um/kernel/skas/include/mmu-skas.h
+++ b/arch/um/kernel/skas/include/mmu-skas.h
@@ -8,6 +8,7 @@
8 8
9#include "linux/config.h" 9#include "linux/config.h"
10#include "mm_id.h" 10#include "mm_id.h"
11#include "asm/ldt.h"
11 12
12struct mmu_context_skas { 13struct mmu_context_skas {
13 struct mm_id id; 14 struct mm_id id;
@@ -15,6 +16,7 @@ struct mmu_context_skas {
15#ifdef CONFIG_3_LEVEL_PGTABLES 16#ifdef CONFIG_3_LEVEL_PGTABLES
16 unsigned long last_pmd; 17 unsigned long last_pmd;
17#endif 18#endif
19 uml_ldt_t ldt;
18}; 20};
19 21
20extern void switch_mm_skas(struct mm_id * mm_idp); 22extern void switch_mm_skas(struct mm_id * mm_idp);
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
index 060934740f9f..daa2f85b684c 100644
--- a/arch/um/kernel/skas/include/skas.h
+++ b/arch/um/kernel/skas/include/skas.h
@@ -10,7 +10,8 @@
10#include "sysdep/ptrace.h" 10#include "sysdep/ptrace.h"
11 11
12extern int userspace_pid[]; 12extern int userspace_pid[];
13extern int proc_mm, ptrace_faultinfo; 13extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
14extern int skas_needs_stub;
14 15
15extern void switch_threads(void *me, void *next); 16extern void switch_threads(void *me, void *next);
16extern void thread_wait(void *sw, void *fb); 17extern void thread_wait(void *sw, void *fb);
diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c
index 147466d7ff4f..88ab96c609ce 100644
--- a/arch/um/kernel/skas/mem.c
+++ b/arch/um/kernel/skas/mem.c
@@ -20,7 +20,7 @@ unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
20 *task_size_out = CONFIG_HOST_TASK_SIZE; 20 *task_size_out = CONFIG_HOST_TASK_SIZE;
21#else 21#else
22 *host_size_out = top; 22 *host_size_out = top;
23 if (proc_mm && ptrace_faultinfo) 23 if (!skas_needs_stub)
24 *task_size_out = top; 24 *task_size_out = top;
25 else *task_size_out = CONFIG_STUB_START & PGDIR_MASK; 25 else *task_size_out = CONFIG_STUB_START & PGDIR_MASK;
26#endif 26#endif
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 9e5e39cea821..677871f1b37c 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -15,6 +15,7 @@
15#include "asm/mmu.h" 15#include "asm/mmu.h"
16#include "asm/pgalloc.h" 16#include "asm/pgalloc.h"
17#include "asm/pgtable.h" 17#include "asm/pgtable.h"
18#include "asm/ldt.h"
18#include "os.h" 19#include "os.h"
19#include "skas.h" 20#include "skas.h"
20 21
@@ -74,13 +75,12 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
74 75
75int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) 76int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
76{ 77{
77 struct mm_struct *cur_mm = current->mm; 78 struct mmu_context_skas *from_mm = NULL;
78 struct mm_id *cur_mm_id = &cur_mm->context.skas.id; 79 struct mmu_context_skas *to_mm = &mm->context.skas;
79 struct mm_id *mm_id = &mm->context.skas.id;
80 unsigned long stack = 0; 80 unsigned long stack = 0;
81 int from, ret = -ENOMEM; 81 int from_fd, ret = -ENOMEM;
82 82
83 if(!proc_mm || !ptrace_faultinfo){ 83 if(skas_needs_stub){
84 stack = get_zeroed_page(GFP_KERNEL); 84 stack = get_zeroed_page(GFP_KERNEL);
85 if(stack == 0) 85 if(stack == 0)
86 goto out; 86 goto out;
@@ -102,33 +102,43 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
102 102
103 mm->nr_ptes--; 103 mm->nr_ptes--;
104 } 104 }
105 mm_id->stack = stack; 105
106 to_mm->id.stack = stack;
107 if(current->mm != NULL && current->mm != &init_mm)
108 from_mm = &current->mm->context.skas;
106 109
107 if(proc_mm){ 110 if(proc_mm){
108 if((cur_mm != NULL) && (cur_mm != &init_mm)) 111 if(from_mm)
109 from = cur_mm_id->u.mm_fd; 112 from_fd = from_mm->id.u.mm_fd;
110 else from = -1; 113 else from_fd = -1;
111 114
112 ret = new_mm(from, stack); 115 ret = new_mm(from_fd, stack);
113 if(ret < 0){ 116 if(ret < 0){
114 printk("init_new_context_skas - new_mm failed, " 117 printk("init_new_context_skas - new_mm failed, "
115 "errno = %d\n", ret); 118 "errno = %d\n", ret);
116 goto out_free; 119 goto out_free;
117 } 120 }
118 mm_id->u.mm_fd = ret; 121 to_mm->id.u.mm_fd = ret;
119 } 122 }
120 else { 123 else {
121 if((cur_mm != NULL) && (cur_mm != &init_mm)) 124 if(from_mm)
122 mm_id->u.pid = copy_context_skas0(stack, 125 to_mm->id.u.pid = copy_context_skas0(stack,
123 cur_mm_id->u.pid); 126 from_mm->id.u.pid);
124 else mm_id->u.pid = start_userspace(stack); 127 else to_mm->id.u.pid = start_userspace(stack);
128 }
129
130 ret = init_new_ldt(to_mm, from_mm);
131 if(ret < 0){
132 printk("init_new_context_skas - init_ldt"
133 " failed, errno = %d\n", ret);
134 goto out_free;
125 } 135 }
126 136
127 return 0; 137 return 0;
128 138
129 out_free: 139 out_free:
130 if(mm_id->stack != 0) 140 if(to_mm->id.stack != 0)
131 free_page(mm_id->stack); 141 free_page(to_mm->id.stack);
132 out: 142 out:
133 return ret; 143 return ret;
134} 144}
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 5cd0e9929789..599d679bd4fc 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -69,6 +69,17 @@ void wait_stub_done(int pid, int sig, char * fname)
69 69
70 if((n < 0) || !WIFSTOPPED(status) || 70 if((n < 0) || !WIFSTOPPED(status) ||
71 (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ 71 (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){
72 unsigned long regs[FRAME_SIZE];
73 if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
74 printk("Failed to get registers from stub, "
75 "errno = %d\n", errno);
76 else {
77 int i;
78
79 printk("Stub registers -\n");
80 for(i = 0; i < FRAME_SIZE; i++)
81 printk("\t%d - %lx\n", i, regs[i]);
82 }
72 panic("%s : failed to wait for SIGUSR1/SIGTRAP, " 83 panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
73 "pid = %d, n = %d, errno = %d, status = 0x%x\n", 84 "pid = %d, n = %d, errno = %d, status = 0x%x\n",
74 fname, pid, n, errno, status); 85 fname, pid, n, errno, status);
@@ -370,9 +381,9 @@ int copy_context_skas0(unsigned long new_stack, int pid)
370} 381}
371 382
372/* 383/*
373 * This is used only, if proc_mm is available, while PTRACE_FAULTINFO 384 * This is used only, if stub pages are needed, while proc_mm is
374 * isn't. Opening /proc/mm creates a new mm_context, which lacks the stub-pages 385 * availabl. Opening /proc/mm creates a new mm_context, which lacks
375 * Thus, we map them using /proc/mm-fd 386 * the stub-pages. Thus, we map them using /proc/mm-fd
376 */ 387 */
377void map_stub_pages(int fd, unsigned long code, 388void map_stub_pages(int fd, unsigned long code,
378 unsigned long data, unsigned long stack) 389 unsigned long data, unsigned long stack)
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index efe92e8aa2a9..9c990253966c 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -145,7 +145,7 @@ int new_mm(int from, unsigned long stack)
145 "err = %d\n", -n); 145 "err = %d\n", -n);
146 } 146 }
147 147
148 if(!ptrace_faultinfo) 148 if(skas_needs_stub)
149 map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); 149 map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
150 150
151 return(fd); 151 return(fd);
diff --git a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c
index 8c220f054b61..6c92bbccb49c 100644
--- a/arch/um/kernel/tt/uaccess_user.c
+++ b/arch/um/kernel/tt/uaccess_user.c
@@ -10,6 +10,7 @@
10#include "uml_uaccess.h" 10#include "uml_uaccess.h"
11#include "task.h" 11#include "task.h"
12#include "kern_util.h" 12#include "kern_util.h"
13#include "os.h"
13 14
14int __do_copy_from_user(void *to, const void *from, int n, 15int __do_copy_from_user(void *to, const void *from, int n,
15 void **fault_addr, void **fault_catcher) 16 void **fault_addr, void **fault_catcher)
diff --git a/arch/um/kernel/uaccess.c b/arch/um/kernel/uaccess.c
new file mode 100644
index 000000000000..054e3de0784e
--- /dev/null
+++ b/arch/um/kernel/uaccess.c
@@ -0,0 +1,30 @@
1/*
2 * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
3 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
4 * Licensed under the GPL
5 */
6
7/* These are here rather than tt/uaccess.c because skas mode needs them in
8 * order to do SIGBUS recovery when a tmpfs mount runs out of room.
9 */
10
11#include <linux/string.h>
12#include "os.h"
13
14void __do_copy(void *to, const void *from, int n)
15{
16 memcpy(to, from, n);
17}
18
19
20int __do_copy_to_user(void *to, const void *from, int n,
21 void **fault_addr, void **fault_catcher)
22{
23 unsigned long fault;
24 int faulted;
25
26 fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
27 __do_copy, &faulted);
28 if(!faulted) return(0);
29 else return(n - (fault - (unsigned long) to));
30}
diff --git a/arch/um/kernel/uaccess_user.c b/arch/um/kernel/uaccess_user.c
deleted file mode 100644
index d035257ed0af..000000000000
--- a/arch/um/kernel/uaccess_user.c
+++ /dev/null
@@ -1,64 +0,0 @@
1/*
2 * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
3 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
4 * Licensed under the GPL
5 */
6
7#include <setjmp.h>
8#include <string.h>
9
10/* These are here rather than tt/uaccess.c because skas mode needs them in
11 * order to do SIGBUS recovery when a tmpfs mount runs out of room.
12 */
13
14unsigned long __do_user_copy(void *to, const void *from, int n,
15 void **fault_addr, void **fault_catcher,
16 void (*op)(void *to, const void *from,
17 int n), int *faulted_out)
18{
19 unsigned long *faddrp = (unsigned long *) fault_addr, ret;
20
21 sigjmp_buf jbuf;
22 *fault_catcher = &jbuf;
23 if(sigsetjmp(jbuf, 1) == 0){
24 (*op)(to, from, n);
25 ret = 0;
26 *faulted_out = 0;
27 }
28 else {
29 ret = *faddrp;
30 *faulted_out = 1;
31 }
32 *fault_addr = NULL;
33 *fault_catcher = NULL;
34 return ret;
35}
36
37void __do_copy(void *to, const void *from, int n)
38{
39 memcpy(to, from, n);
40}
41
42
43int __do_copy_to_user(void *to, const void *from, int n,
44 void **fault_addr, void **fault_catcher)
45{
46 unsigned long fault;
47 int faulted;
48
49 fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
50 __do_copy, &faulted);
51 if(!faulted) return(0);
52 else return(n - (fault - (unsigned long) to));
53}
54
55/*
56 * Overrides for Emacs so that we follow Linus's tabbing style.
57 * Emacs will notice this stuff at the end of the file and automatically
58 * adjust the settings for this buffer only. This must remain at the end
59 * of the file.
60 * ---------------------------------------------------------------------------
61 * Local variables:
62 * c-file-style: "linux"
63 * End:
64 */
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 93dc782dc1cc..142a9493912b 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -137,7 +137,7 @@ static char *argv1_end = NULL;
137 137
138/* Set in early boot */ 138/* Set in early boot */
139static int have_root __initdata = 0; 139static int have_root __initdata = 0;
140long physmem_size = 32 * 1024 * 1024; 140long long physmem_size = 32 * 1024 * 1024;
141 141
142void set_cmdline(char *cmd) 142void set_cmdline(char *cmd)
143{ 143{
@@ -402,7 +402,7 @@ int linux_main(int argc, char **argv)
402#ifndef CONFIG_HIGHMEM 402#ifndef CONFIG_HIGHMEM
403 highmem = 0; 403 highmem = 0;
404 printf("CONFIG_HIGHMEM not enabled - physical memory shrunk " 404 printf("CONFIG_HIGHMEM not enabled - physical memory shrunk "
405 "to %ld bytes\n", physmem_size); 405 "to %lu bytes\n", physmem_size);
406#endif 406#endif
407 } 407 }
408 408
@@ -414,8 +414,8 @@ int linux_main(int argc, char **argv)
414 414
415 setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); 415 setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
416 if(init_maps(physmem_size, iomem_size, highmem)){ 416 if(init_maps(physmem_size, iomem_size, highmem)){
417 printf("Failed to allocate mem_map for %ld bytes of physical " 417 printf("Failed to allocate mem_map for %lu bytes of physical "
418 "memory and %ld bytes of highmem\n", physmem_size, 418 "memory and %lu bytes of highmem\n", physmem_size,
419 highmem); 419 highmem);
420 exit(1); 420 exit(1);
421 } 421 }
@@ -426,7 +426,7 @@ int linux_main(int argc, char **argv)
426 end_vm = start_vm + virtmem_size; 426 end_vm = start_vm + virtmem_size;
427 427
428 if(virtmem_size < physmem_size) 428 if(virtmem_size < physmem_size)
429 printf("Kernel virtual memory size shrunk to %ld bytes\n", 429 printf("Kernel virtual memory size shrunk to %lu bytes\n",
430 virtmem_size); 430 virtmem_size);
431 431
432 uml_postsetup(); 432 uml_postsetup();
diff --git a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c
index 41d17c71511c..4c231161f257 100644
--- a/arch/um/kernel/user_util.c
+++ b/arch/um/kernel/user_util.c
@@ -27,7 +27,6 @@
27#include "user.h" 27#include "user.h"
28#include "mem_user.h" 28#include "mem_user.h"
29#include "init.h" 29#include "init.h"
30#include "helper.h"
31#include "ptrace_user.h" 30#include "ptrace_user.h"
32#include "uml-config.h" 31#include "uml-config.h"
33 32