diff options
author | Paul Mackerras <paulus@samba.org> | 2006-07-31 20:37:25 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-07-31 20:37:25 -0400 |
commit | 57cad8084e0837e0f2c97da789ec9b3f36809be9 (patch) | |
tree | e9c790afb4286f78cb08d9664f58baa7e876fe55 /arch/um/kernel | |
parent | cb18bd40030c879cd93fef02fd579f74dbab473d (diff) | |
parent | 49b1e3ea19b1c95c2f012b8331ffb3b169e4c042 (diff) |
Merge branch 'merge'
Diffstat (limited to 'arch/um/kernel')
24 files changed, 264 insertions, 425 deletions
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index fe08971b64cf..a2d93065b2d0 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile | |||
@@ -6,16 +6,14 @@ | |||
6 | extra-y := vmlinux.lds | 6 | extra-y := vmlinux.lds |
7 | clean-files := | 7 | clean-files := |
8 | 8 | ||
9 | obj-y = config.o exec_kern.o exitcode.o \ | 9 | obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \ |
10 | init_task.o irq.o ksyms.o mem.o physmem.o \ | 10 | physmem.o process_kern.o ptrace.o reboot.o resource.o sigio.o \ |
11 | process_kern.o ptrace.o reboot.o resource.o sigio_kern.o \ | 11 | signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \ |
12 | signal_kern.o smp.o syscall_kern.o sysrq.o \ | 12 | um_arch.o umid.o |
13 | time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o | ||
14 | 13 | ||
15 | obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o | 14 | obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o |
16 | obj-$(CONFIG_GPROF) += gprof_syms.o | 15 | obj-$(CONFIG_GPROF) += gprof_syms.o |
17 | obj-$(CONFIG_GCOV) += gmon_syms.o | 16 | obj-$(CONFIG_GCOV) += gmon_syms.o |
18 | obj-$(CONFIG_SYSCALL_DEBUG) += syscall.o | ||
19 | 17 | ||
20 | obj-$(CONFIG_MODE_TT) += tt/ | 18 | obj-$(CONFIG_MODE_TT) += tt/ |
21 | obj-$(CONFIG_MODE_SKAS) += skas/ | 19 | obj-$(CONFIG_MODE_SKAS) += skas/ |
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index 2517ecb8bf27..68ed24df5c8f 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S | |||
@@ -26,6 +26,7 @@ SECTIONS | |||
26 | 26 | ||
27 | /* Read-only sections, merged into text segment: */ | 27 | /* Read-only sections, merged into text segment: */ |
28 | .hash : { *(.hash) } | 28 | .hash : { *(.hash) } |
29 | .gnu.hash : { *(.gnu.hash) } | ||
29 | .dynsym : { *(.dynsym) } | 30 | .dynsym : { *(.dynsym) } |
30 | .dynstr : { *(.dynstr) } | 31 | .dynstr : { *(.dynstr) } |
31 | .gnu.version : { *(.gnu.version) } | 32 | .gnu.version : { *(.gnu.version) } |
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec.c index c0cb627bf594..fc38a6d5906d 100644 --- a/arch/um/kernel/exec_kern.c +++ b/arch/um/kernel/exec.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
@@ -31,18 +31,27 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) | |||
31 | CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp); | 31 | CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp); |
32 | } | 32 | } |
33 | 33 | ||
34 | #ifdef CONFIG_TTY_LOG | ||
35 | extern void log_exec(char **argv, void *tty); | ||
36 | #endif | ||
37 | |||
34 | static long execve1(char *file, char __user * __user *argv, | 38 | static long execve1(char *file, char __user * __user *argv, |
35 | char __user *__user *env) | 39 | char __user *__user *env) |
36 | { | 40 | { |
37 | long error; | 41 | long error; |
38 | 42 | ||
39 | #ifdef CONFIG_TTY_LOG | 43 | #ifdef CONFIG_TTY_LOG |
40 | log_exec(argv, current->tty); | 44 | task_lock(current); |
45 | log_exec(argv, current->signal->tty); | ||
46 | task_unlock(current); | ||
41 | #endif | 47 | #endif |
42 | error = do_execve(file, argv, env, ¤t->thread.regs); | 48 | error = do_execve(file, argv, env, ¤t->thread.regs); |
43 | if (error == 0){ | 49 | if (error == 0){ |
44 | task_lock(current); | 50 | task_lock(current); |
45 | current->ptrace &= ~PT_DTRACE; | 51 | current->ptrace &= ~PT_DTRACE; |
52 | #ifdef SUBARCH_EXECVE1 | ||
53 | SUBARCH_EXECVE1(¤t->thread.regs.regs); | ||
54 | #endif | ||
46 | task_unlock(current); | 55 | task_unlock(current); |
47 | set_cmdline(current_cmd()); | 56 | set_cmdline(current_cmd()); |
48 | } | 57 | } |
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index bfd0bdc8cd40..589c69a75043 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c | |||
@@ -110,18 +110,7 @@ void sigio_handler(int sig, union uml_pt_regs *regs) | |||
110 | free_irqs(); | 110 | free_irqs(); |
111 | } | 111 | } |
112 | 112 | ||
113 | static void maybe_sigio_broken(int fd, int type) | 113 | static DEFINE_SPINLOCK(irq_lock); |
114 | { | ||
115 | if (os_isatty(fd)) { | ||
116 | if ((type == IRQ_WRITE) && !pty_output_sigio) { | ||
117 | write_sigio_workaround(); | ||
118 | add_sigio_fd(fd, 0); | ||
119 | } else if ((type == IRQ_READ) && !pty_close_sigio) { | ||
120 | write_sigio_workaround(); | ||
121 | add_sigio_fd(fd, 1); | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | 114 | ||
126 | int activate_fd(int irq, int fd, int type, void *dev_id) | 115 | int activate_fd(int irq, int fd, int type, void *dev_id) |
127 | { | 116 | { |
@@ -166,7 +155,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id) | |||
166 | * this is called only from process context, and can be locked with | 155 | * this is called only from process context, and can be locked with |
167 | * a semaphore. | 156 | * a semaphore. |
168 | */ | 157 | */ |
169 | flags = irq_lock(); | 158 | spin_lock_irqsave(&irq_lock, flags); |
170 | for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { | 159 | for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { |
171 | if ((irq_fd->fd == fd) && (irq_fd->type == type)) { | 160 | if ((irq_fd->fd == fd) && (irq_fd->type == type)) { |
172 | printk("Registering fd %d twice\n", fd); | 161 | printk("Registering fd %d twice\n", fd); |
@@ -199,7 +188,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id) | |||
199 | * so we will not be able to put new pollfd struct to pollfds | 188 | * so we will not be able to put new pollfd struct to pollfds |
200 | * then we free the buffer tmp_fds and try again. | 189 | * then we free the buffer tmp_fds and try again. |
201 | */ | 190 | */ |
202 | irq_unlock(flags); | 191 | spin_unlock_irqrestore(&irq_lock, flags); |
203 | kfree(tmp_pfd); | 192 | kfree(tmp_pfd); |
204 | tmp_pfd = NULL; | 193 | tmp_pfd = NULL; |
205 | 194 | ||
@@ -207,24 +196,24 @@ int activate_fd(int irq, int fd, int type, void *dev_id) | |||
207 | if (tmp_pfd == NULL) | 196 | if (tmp_pfd == NULL) |
208 | goto out_kfree; | 197 | goto out_kfree; |
209 | 198 | ||
210 | flags = irq_lock(); | 199 | spin_lock_irqsave(&irq_lock, flags); |
211 | } | 200 | } |
212 | /*-------------*/ | 201 | /*-------------*/ |
213 | 202 | ||
214 | *last_irq_ptr = new_fd; | 203 | *last_irq_ptr = new_fd; |
215 | last_irq_ptr = &new_fd->next; | 204 | last_irq_ptr = &new_fd->next; |
216 | 205 | ||
217 | irq_unlock(flags); | 206 | spin_unlock_irqrestore(&irq_lock, flags); |
218 | 207 | ||
219 | /* This calls activate_fd, so it has to be outside the critical | 208 | /* This calls activate_fd, so it has to be outside the critical |
220 | * section. | 209 | * section. |
221 | */ | 210 | */ |
222 | maybe_sigio_broken(fd, type); | 211 | maybe_sigio_broken(fd, (type == IRQ_READ)); |
223 | 212 | ||
224 | return(0); | 213 | return(0); |
225 | 214 | ||
226 | out_unlock: | 215 | out_unlock: |
227 | irq_unlock(flags); | 216 | spin_unlock_irqrestore(&irq_lock, flags); |
228 | out_kfree: | 217 | out_kfree: |
229 | kfree(new_fd); | 218 | kfree(new_fd); |
230 | out: | 219 | out: |
@@ -235,9 +224,9 @@ static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) | |||
235 | { | 224 | { |
236 | unsigned long flags; | 225 | unsigned long flags; |
237 | 226 | ||
238 | flags = irq_lock(); | 227 | spin_lock_irqsave(&irq_lock, flags); |
239 | os_free_irq_by_cb(test, arg, active_fds, &last_irq_ptr); | 228 | os_free_irq_by_cb(test, arg, active_fds, &last_irq_ptr); |
240 | irq_unlock(flags); | 229 | spin_unlock_irqrestore(&irq_lock, flags); |
241 | } | 230 | } |
242 | 231 | ||
243 | struct irq_and_dev { | 232 | struct irq_and_dev { |
@@ -304,19 +293,19 @@ void reactivate_fd(int fd, int irqnum) | |||
304 | unsigned long flags; | 293 | unsigned long flags; |
305 | int i; | 294 | int i; |
306 | 295 | ||
307 | flags = irq_lock(); | 296 | spin_lock_irqsave(&irq_lock, flags); |
308 | irq = find_irq_by_fd(fd, irqnum, &i); | 297 | irq = find_irq_by_fd(fd, irqnum, &i); |
309 | if (irq == NULL) { | 298 | if (irq == NULL) { |
310 | irq_unlock(flags); | 299 | spin_unlock_irqrestore(&irq_lock, flags); |
311 | return; | 300 | return; |
312 | } | 301 | } |
313 | os_set_pollfd(i, irq->fd); | 302 | os_set_pollfd(i, irq->fd); |
314 | irq_unlock(flags); | 303 | spin_unlock_irqrestore(&irq_lock, flags); |
315 | 304 | ||
316 | /* This calls activate_fd, so it has to be outside the critical | 305 | /* This calls activate_fd, so it has to be outside the critical |
317 | * section. | 306 | * section. |
318 | */ | 307 | */ |
319 | maybe_sigio_broken(fd, irq->type); | 308 | maybe_sigio_broken(fd, (irq->type == IRQ_READ)); |
320 | } | 309 | } |
321 | 310 | ||
322 | void deactivate_fd(int fd, int irqnum) | 311 | void deactivate_fd(int fd, int irqnum) |
@@ -325,13 +314,13 @@ void deactivate_fd(int fd, int irqnum) | |||
325 | unsigned long flags; | 314 | unsigned long flags; |
326 | int i; | 315 | int i; |
327 | 316 | ||
328 | flags = irq_lock(); | 317 | spin_lock_irqsave(&irq_lock, flags); |
329 | irq = find_irq_by_fd(fd, irqnum, &i); | 318 | irq = find_irq_by_fd(fd, irqnum, &i); |
330 | if (irq == NULL) | 319 | if (irq == NULL) |
331 | goto out; | 320 | goto out; |
332 | os_set_pollfd(i, -1); | 321 | os_set_pollfd(i, -1); |
333 | out: | 322 | out: |
334 | irq_unlock(flags); | 323 | spin_unlock_irqrestore(&irq_lock, flags); |
335 | } | 324 | } |
336 | 325 | ||
337 | int deactivate_all_fds(void) | 326 | int deactivate_all_fds(void) |
@@ -350,13 +339,14 @@ int deactivate_all_fds(void) | |||
350 | return 0; | 339 | return 0; |
351 | } | 340 | } |
352 | 341 | ||
342 | #ifdef CONFIG_MODE_TT | ||
353 | void forward_interrupts(int pid) | 343 | void forward_interrupts(int pid) |
354 | { | 344 | { |
355 | struct irq_fd *irq; | 345 | struct irq_fd *irq; |
356 | unsigned long flags; | 346 | unsigned long flags; |
357 | int err; | 347 | int err; |
358 | 348 | ||
359 | flags = irq_lock(); | 349 | spin_lock_irqsave(&irq_lock, flags); |
360 | for (irq = active_fds; irq != NULL; irq = irq->next) { | 350 | for (irq = active_fds; irq != NULL; irq = irq->next) { |
361 | err = os_set_owner(irq->fd, pid); | 351 | err = os_set_owner(irq->fd, pid); |
362 | if (err < 0) { | 352 | if (err < 0) { |
@@ -369,8 +359,9 @@ void forward_interrupts(int pid) | |||
369 | 359 | ||
370 | irq->pid = pid; | 360 | irq->pid = pid; |
371 | } | 361 | } |
372 | irq_unlock(flags); | 362 | spin_unlock_irqrestore(&irq_lock, flags); |
373 | } | 363 | } |
364 | #endif | ||
374 | 365 | ||
375 | /* | 366 | /* |
376 | * do_IRQ handles all normal device IRQ's (the special | 367 | * do_IRQ handles all normal device IRQ's (the special |
@@ -403,21 +394,6 @@ int um_request_irq(unsigned int irq, int fd, int type, | |||
403 | EXPORT_SYMBOL(um_request_irq); | 394 | EXPORT_SYMBOL(um_request_irq); |
404 | EXPORT_SYMBOL(reactivate_fd); | 395 | EXPORT_SYMBOL(reactivate_fd); |
405 | 396 | ||
406 | static DEFINE_SPINLOCK(irq_spinlock); | ||
407 | |||
408 | unsigned long irq_lock(void) | ||
409 | { | ||
410 | unsigned long flags; | ||
411 | |||
412 | spin_lock_irqsave(&irq_spinlock, flags); | ||
413 | return flags; | ||
414 | } | ||
415 | |||
416 | void irq_unlock(unsigned long flags) | ||
417 | { | ||
418 | spin_unlock_irqrestore(&irq_spinlock, flags); | ||
419 | } | ||
420 | |||
421 | /* hw_interrupt_type must define (startup || enable) && | 397 | /* hw_interrupt_type must define (startup || enable) && |
422 | * (shutdown || disable) && end */ | 398 | * (shutdown || disable) && end */ |
423 | static void dummy(unsigned int irq) | 399 | static void dummy(unsigned int irq) |
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index 432cf0b97a13..c97045d6d89f 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c | |||
@@ -88,12 +88,6 @@ EXPORT_SYMBOL(dump_thread); | |||
88 | EXPORT_SYMBOL(do_gettimeofday); | 88 | EXPORT_SYMBOL(do_gettimeofday); |
89 | EXPORT_SYMBOL(do_settimeofday); | 89 | EXPORT_SYMBOL(do_settimeofday); |
90 | 90 | ||
91 | /* This is here because UML expands lseek to sys_lseek, not to a system | ||
92 | * call instruction. | ||
93 | */ | ||
94 | EXPORT_SYMBOL(sys_lseek); | ||
95 | EXPORT_SYMBOL(sys_wait4); | ||
96 | |||
97 | #ifdef CONFIG_SMP | 91 | #ifdef CONFIG_SMP |
98 | 92 | ||
99 | /* required for SMP */ | 93 | /* required for SMP */ |
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 44e41a35f000..61280167c560 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c | |||
@@ -24,8 +24,6 @@ | |||
24 | #include "init.h" | 24 | #include "init.h" |
25 | #include "kern_constants.h" | 25 | #include "kern_constants.h" |
26 | 26 | ||
27 | extern char __binary_start; | ||
28 | |||
29 | /* Changed during early boot */ | 27 | /* Changed during early boot */ |
30 | unsigned long *empty_zero_page = NULL; | 28 | unsigned long *empty_zero_page = NULL; |
31 | unsigned long *empty_bad_page = NULL; | 29 | unsigned long *empty_bad_page = NULL; |
@@ -65,8 +63,6 @@ static void setup_highmem(unsigned long highmem_start, | |||
65 | 63 | ||
66 | void mem_init(void) | 64 | void mem_init(void) |
67 | { | 65 | { |
68 | unsigned long start; | ||
69 | |||
70 | max_low_pfn = (high_physmem - uml_physmem) >> PAGE_SHIFT; | 66 | max_low_pfn = (high_physmem - uml_physmem) >> PAGE_SHIFT; |
71 | 67 | ||
72 | /* clear the zero-page */ | 68 | /* clear the zero-page */ |
@@ -81,13 +77,6 @@ void mem_init(void) | |||
81 | free_bootmem(__pa(brk_end), uml_reserved - brk_end); | 77 | free_bootmem(__pa(brk_end), uml_reserved - brk_end); |
82 | uml_reserved = brk_end; | 78 | uml_reserved = brk_end; |
83 | 79 | ||
84 | /* Fill in any hole at the start of the binary */ | ||
85 | start = (unsigned long) &__binary_start & PAGE_MASK; | ||
86 | if(uml_physmem != start){ | ||
87 | map_memory(uml_physmem, __pa(uml_physmem), start - uml_physmem, | ||
88 | 1, 1, 0); | ||
89 | } | ||
90 | |||
91 | /* this will put all low memory onto the freelists */ | 80 | /* this will put all low memory onto the freelists */ |
92 | totalram_pages = free_all_bootmem(); | 81 | totalram_pages = free_all_bootmem(); |
93 | totalhigh_pages = highmem >> PAGE_SHIFT; | 82 | totalhigh_pages = highmem >> PAGE_SHIFT; |
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index 166cb09cae4c..abafa64b8727 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c | |||
@@ -317,7 +317,7 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len, | |||
317 | } | 317 | } |
318 | } | 318 | } |
319 | 319 | ||
320 | extern int __syscall_stub_start, __binary_start; | 320 | extern int __syscall_stub_start; |
321 | 321 | ||
322 | void setup_physmem(unsigned long start, unsigned long reserve_end, | 322 | void setup_physmem(unsigned long start, unsigned long reserve_end, |
323 | unsigned long len, unsigned long long highmem) | 323 | unsigned long len, unsigned long long highmem) |
diff --git a/arch/um/kernel/sigio_kern.c b/arch/um/kernel/sigio.c index 51b677083948..0ad755ceb212 100644 --- a/arch/um/kernel/sigio_kern.c +++ b/arch/um/kernel/sigio.c | |||
@@ -31,7 +31,7 @@ int write_sigio_irq(int fd) | |||
31 | int err; | 31 | int err; |
32 | 32 | ||
33 | err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, | 33 | err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, |
34 | IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "write sigio", | 34 | IRQF_DISABLED|IRQF_SAMPLE_RANDOM, "write sigio", |
35 | NULL); | 35 | NULL); |
36 | if(err){ | 36 | if(err){ |
37 | printk("write_sigio_irq : um_request_irq failed, err = %d\n", | 37 | printk("write_sigio_irq : um_request_irq failed, err = %d\n", |
@@ -53,17 +53,3 @@ void sigio_unlock(void) | |||
53 | { | 53 | { |
54 | spin_unlock(&sigio_spinlock); | 54 | spin_unlock(&sigio_spinlock); |
55 | } | 55 | } |
56 | |||
57 | extern void sigio_cleanup(void); | ||
58 | __uml_exitcall(sigio_cleanup); | ||
59 | |||
60 | /* | ||
61 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
62 | * Emacs will notice this stuff at the end of the file and automatically | ||
63 | * adjust the settings for this buffer only. This must remain at the end | ||
64 | * of the file. | ||
65 | * --------------------------------------------------------------------------- | ||
66 | * Local variables: | ||
67 | * c-file-style: "linux" | ||
68 | * End: | ||
69 | */ | ||
diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal.c index da17b7541e08..4aa9808ba264 100644 --- a/arch/um/kernel/signal_kern.c +++ b/arch/um/kernel/signal.c | |||
@@ -1,4 +1,4 @@ | |||
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 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
@@ -36,7 +36,7 @@ EXPORT_SYMBOL(unblock_signals); | |||
36 | 36 | ||
37 | /* | 37 | /* |
38 | * OK, we're invoking a handler | 38 | * OK, we're invoking a handler |
39 | */ | 39 | */ |
40 | static int handle_signal(struct pt_regs *regs, unsigned long signr, | 40 | static int handle_signal(struct pt_regs *regs, unsigned long signr, |
41 | struct k_sigaction *ka, siginfo_t *info, | 41 | struct k_sigaction *ka, siginfo_t *info, |
42 | sigset_t *oldset) | 42 | sigset_t *oldset) |
@@ -88,7 +88,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, | |||
88 | force_sigsegv(signr, current); | 88 | force_sigsegv(signr, current); |
89 | } else { | 89 | } else { |
90 | spin_lock_irq(¤t->sighand->siglock); | 90 | spin_lock_irq(¤t->sighand->siglock); |
91 | sigorsets(¤t->blocked, ¤t->blocked, | 91 | sigorsets(¤t->blocked, ¤t->blocked, |
92 | &ka->sa.sa_mask); | 92 | &ka->sa.sa_mask); |
93 | if(!(ka->sa.sa_flags & SA_NODEFER)) | 93 | if(!(ka->sa.sa_flags & SA_NODEFER)) |
94 | sigaddset(¤t->blocked, signr); | 94 | sigaddset(¤t->blocked, signr); |
@@ -136,7 +136,7 @@ static int kern_do_signal(struct pt_regs *regs) | |||
136 | PT_REGS_RESTART_SYSCALL(regs); | 136 | PT_REGS_RESTART_SYSCALL(regs); |
137 | break; | 137 | break; |
138 | case -ERESTART_RESTARTBLOCK: | 138 | case -ERESTART_RESTARTBLOCK: |
139 | PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall; | 139 | PT_REGS_ORIG_SYSCALL(regs) = __NR_restart_syscall; |
140 | PT_REGS_RESTART_SYSCALL(regs); | 140 | PT_REGS_RESTART_SYSCALL(regs); |
141 | break; | 141 | break; |
142 | } | 142 | } |
@@ -146,7 +146,7 @@ static int kern_do_signal(struct pt_regs *regs) | |||
146 | * you set a breakpoint on a system call instruction and singlestep | 146 | * you set a breakpoint on a system call instruction and singlestep |
147 | * from it, the tracing thread used to PTRACE_SINGLESTEP the process | 147 | * from it, the tracing thread used to PTRACE_SINGLESTEP the process |
148 | * rather than PTRACE_SYSCALL it, allowing the system call to execute | 148 | * rather than PTRACE_SYSCALL it, allowing the system call to execute |
149 | * on the host. The tracing thread will check this flag and | 149 | * on the host. The tracing thread will check this flag and |
150 | * PTRACE_SYSCALL if necessary. | 150 | * PTRACE_SYSCALL if necessary. |
151 | */ | 151 | */ |
152 | if(current->ptrace & PT_DTRACE) | 152 | if(current->ptrace & PT_DTRACE) |
diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c index 88ab96c609ce..27bbf54b1e52 100644 --- a/arch/um/kernel/skas/mem.c +++ b/arch/um/kernel/skas/mem.c | |||
@@ -9,31 +9,19 @@ | |||
9 | #include "mem_user.h" | 9 | #include "mem_user.h" |
10 | #include "skas.h" | 10 | #include "skas.h" |
11 | 11 | ||
12 | unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, | 12 | unsigned long set_task_sizes_skas(unsigned long *task_size_out) |
13 | unsigned long *task_size_out) | ||
14 | { | 13 | { |
15 | /* Round up to the nearest 4M */ | 14 | /* Round up to the nearest 4M */ |
16 | unsigned long top = ROUND_4M((unsigned long) &arg); | 15 | unsigned long host_task_size = ROUND_4M((unsigned long) |
16 | &host_task_size); | ||
17 | 17 | ||
18 | #ifdef CONFIG_HOST_TASK_SIZE | 18 | #ifdef CONFIG_HOST_TASK_SIZE |
19 | *host_size_out = CONFIG_HOST_TASK_SIZE; | 19 | *host_size_out = ROUND_4M(CONFIG_HOST_TASK_SIZE); |
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; | ||
23 | if (!skas_needs_stub) | 22 | if (!skas_needs_stub) |
24 | *task_size_out = top; | 23 | *task_size_out = host_task_size; |
25 | else *task_size_out = CONFIG_STUB_START & PGDIR_MASK; | 24 | else *task_size_out = CONFIG_STUB_START & PGDIR_MASK; |
26 | #endif | 25 | #endif |
27 | return(((unsigned long) set_task_sizes_skas) & ~0xffffff); | 26 | return host_task_size; |
28 | } | 27 | } |
29 | |||
30 | /* | ||
31 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
32 | * Emacs will notice this stuff at the end of the file and automatically | ||
33 | * adjust the settings for this buffer only. This must remain at the end | ||
34 | * of the file. | ||
35 | * --------------------------------------------------------------------------- | ||
36 | * Local variables: | ||
37 | * c-file-style: "linux" | ||
38 | * End: | ||
39 | */ | ||
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index 2135eaf98a93..55caeec8b257 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c | |||
@@ -177,7 +177,7 @@ int start_uml_skas(void) | |||
177 | if(proc_mm) | 177 | if(proc_mm) |
178 | userspace_pid[0] = start_userspace(0); | 178 | userspace_pid[0] = start_userspace(0); |
179 | 179 | ||
180 | init_new_thread_signals(1); | 180 | init_new_thread_signals(); |
181 | 181 | ||
182 | init_task.thread.request.u.thread.proc = start_kernel_proc; | 182 | init_task.thread.request.u.thread.proc = start_kernel_proc; |
183 | init_task.thread.request.u.thread.arg = NULL; | 183 | init_task.thread.request.u.thread.arg = NULL; |
diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c index 51fb94076fcf..0ae4eea21be4 100644 --- a/arch/um/kernel/skas/syscall.c +++ b/arch/um/kernel/skas/syscall.c | |||
@@ -18,11 +18,7 @@ void handle_syscall(union uml_pt_regs *r) | |||
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; |
20 | int syscall; | 20 | int syscall; |
21 | #ifdef UML_CONFIG_SYSCALL_DEBUG | ||
22 | int index; | ||
23 | 21 | ||
24 | index = record_syscall_start(UPT_SYSCALL_NR(r)); | ||
25 | #endif | ||
26 | syscall_trace(r, 0); | 22 | syscall_trace(r, 0); |
27 | 23 | ||
28 | current->thread.nsyscalls++; | 24 | current->thread.nsyscalls++; |
@@ -44,7 +40,4 @@ void handle_syscall(union uml_pt_regs *r) | |||
44 | REGS_SET_SYSCALL_RETURN(r->skas.regs, result); | 40 | REGS_SET_SYSCALL_RETURN(r->skas.regs, result); |
45 | 41 | ||
46 | syscall_trace(r, 1); | 42 | syscall_trace(r, 1); |
47 | #ifdef UML_CONFIG_SYSCALL_DEBUG | ||
48 | record_syscall_end(index, result); | ||
49 | #endif | ||
50 | } | 43 | } |
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index 1731d90e6850..48cf88dd02d4 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c | |||
@@ -1,36 +1,166 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/sched.h" | ||
7 | #include "linux/file.h" | ||
8 | #include "linux/smp_lock.h" | ||
9 | #include "linux/mm.h" | ||
10 | #include "linux/utsname.h" | ||
11 | #include "linux/msg.h" | ||
12 | #include "linux/shm.h" | ||
13 | #include "linux/sys.h" | ||
14 | #include "linux/syscalls.h" | ||
15 | #include "linux/unistd.h" | ||
16 | #include "linux/slab.h" | ||
17 | #include "linux/utime.h" | ||
18 | #include "asm/mman.h" | ||
19 | #include "asm/uaccess.h" | ||
6 | #include "kern_util.h" | 20 | #include "kern_util.h" |
7 | #include "syscall.h" | 21 | #include "user_util.h" |
8 | #include "os.h" | 22 | #include "sysdep/syscalls.h" |
23 | #include "mode_kern.h" | ||
24 | #include "choose-mode.h" | ||
9 | 25 | ||
10 | struct { | 26 | /* Unlocked, I don't care if this is a bit off */ |
11 | int syscall; | 27 | int nsyscalls = 0; |
12 | int pid; | ||
13 | long result; | ||
14 | unsigned long long start; | ||
15 | unsigned long long end; | ||
16 | } syscall_record[1024]; | ||
17 | 28 | ||
18 | int record_syscall_start(int syscall) | 29 | long sys_fork(void) |
19 | { | 30 | { |
20 | int max, index; | 31 | long ret; |
21 | 32 | ||
22 | max = sizeof(syscall_record)/sizeof(syscall_record[0]); | 33 | current->thread.forking = 1; |
23 | index = next_syscall_index(max); | 34 | ret = do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), |
35 | ¤t->thread.regs, 0, NULL, NULL); | ||
36 | current->thread.forking = 0; | ||
37 | return(ret); | ||
38 | } | ||
39 | |||
40 | long sys_vfork(void) | ||
41 | { | ||
42 | long ret; | ||
43 | |||
44 | current->thread.forking = 1; | ||
45 | ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, | ||
46 | UPT_SP(¤t->thread.regs.regs), | ||
47 | ¤t->thread.regs, 0, NULL, NULL); | ||
48 | current->thread.forking = 0; | ||
49 | return(ret); | ||
50 | } | ||
51 | |||
52 | /* common code for old and new mmaps */ | ||
53 | long sys_mmap2(unsigned long addr, unsigned long len, | ||
54 | unsigned long prot, unsigned long flags, | ||
55 | unsigned long fd, unsigned long pgoff) | ||
56 | { | ||
57 | long error = -EBADF; | ||
58 | struct file * file = NULL; | ||
59 | |||
60 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
61 | if (!(flags & MAP_ANONYMOUS)) { | ||
62 | file = fget(fd); | ||
63 | if (!file) | ||
64 | goto out; | ||
65 | } | ||
66 | |||
67 | down_write(¤t->mm->mmap_sem); | ||
68 | error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
69 | up_write(¤t->mm->mmap_sem); | ||
70 | |||
71 | if (file) | ||
72 | fput(file); | ||
73 | out: | ||
74 | return error; | ||
75 | } | ||
76 | |||
77 | long old_mmap(unsigned long addr, unsigned long len, | ||
78 | unsigned long prot, unsigned long flags, | ||
79 | unsigned long fd, unsigned long offset) | ||
80 | { | ||
81 | long err = -EINVAL; | ||
82 | if (offset & ~PAGE_MASK) | ||
83 | goto out; | ||
84 | |||
85 | err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); | ||
86 | out: | ||
87 | return err; | ||
88 | } | ||
89 | /* | ||
90 | * sys_pipe() is the normal C calling standard for creating | ||
91 | * a pipe. It's not the way unix traditionally does this, though. | ||
92 | */ | ||
93 | long sys_pipe(unsigned long __user * fildes) | ||
94 | { | ||
95 | int fd[2]; | ||
96 | long error; | ||
97 | |||
98 | error = do_pipe(fd); | ||
99 | if (!error) { | ||
100 | if (copy_to_user(fildes, fd, sizeof(fd))) | ||
101 | error = -EFAULT; | ||
102 | } | ||
103 | return error; | ||
104 | } | ||
24 | 105 | ||
25 | syscall_record[index].syscall = syscall; | 106 | |
26 | syscall_record[index].pid = current_pid(); | 107 | long sys_uname(struct old_utsname __user * name) |
27 | syscall_record[index].result = 0xdeadbeef; | 108 | { |
28 | syscall_record[index].start = os_nsecs(); | 109 | long err; |
29 | return(index); | 110 | if (!name) |
111 | return -EFAULT; | ||
112 | down_read(&uts_sem); | ||
113 | err = copy_to_user(name, &system_utsname, sizeof (*name)); | ||
114 | up_read(&uts_sem); | ||
115 | return err?-EFAULT:0; | ||
30 | } | 116 | } |
31 | 117 | ||
32 | void record_syscall_end(int index, long result) | 118 | long sys_olduname(struct oldold_utsname __user * name) |
33 | { | 119 | { |
34 | syscall_record[index].result = result; | 120 | long error; |
35 | syscall_record[index].end = os_nsecs(); | 121 | |
122 | if (!name) | ||
123 | return -EFAULT; | ||
124 | if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) | ||
125 | return -EFAULT; | ||
126 | |||
127 | down_read(&uts_sem); | ||
128 | |||
129 | error = __copy_to_user(&name->sysname,&system_utsname.sysname, | ||
130 | __OLD_UTS_LEN); | ||
131 | error |= __put_user(0,name->sysname+__OLD_UTS_LEN); | ||
132 | error |= __copy_to_user(&name->nodename,&system_utsname.nodename, | ||
133 | __OLD_UTS_LEN); | ||
134 | error |= __put_user(0,name->nodename+__OLD_UTS_LEN); | ||
135 | error |= __copy_to_user(&name->release,&system_utsname.release, | ||
136 | __OLD_UTS_LEN); | ||
137 | error |= __put_user(0,name->release+__OLD_UTS_LEN); | ||
138 | error |= __copy_to_user(&name->version,&system_utsname.version, | ||
139 | __OLD_UTS_LEN); | ||
140 | error |= __put_user(0,name->version+__OLD_UTS_LEN); | ||
141 | error |= __copy_to_user(&name->machine,&system_utsname.machine, | ||
142 | __OLD_UTS_LEN); | ||
143 | error |= __put_user(0,name->machine+__OLD_UTS_LEN); | ||
144 | |||
145 | up_read(&uts_sem); | ||
146 | |||
147 | error = error ? -EFAULT : 0; | ||
148 | |||
149 | return error; | ||
150 | } | ||
151 | |||
152 | DEFINE_SPINLOCK(syscall_lock); | ||
153 | |||
154 | static int syscall_index = 0; | ||
155 | |||
156 | int next_syscall_index(int limit) | ||
157 | { | ||
158 | int ret; | ||
159 | |||
160 | spin_lock(&syscall_lock); | ||
161 | ret = syscall_index; | ||
162 | if(++syscall_index == limit) | ||
163 | syscall_index = 0; | ||
164 | spin_unlock(&syscall_lock); | ||
165 | return(ret); | ||
36 | } | 166 | } |
diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c deleted file mode 100644 index 37d3978337d8..000000000000 --- a/arch/um/kernel/syscall_kern.c +++ /dev/null | |||
@@ -1,166 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/sched.h" | ||
7 | #include "linux/file.h" | ||
8 | #include "linux/smp_lock.h" | ||
9 | #include "linux/mm.h" | ||
10 | #include "linux/utsname.h" | ||
11 | #include "linux/msg.h" | ||
12 | #include "linux/shm.h" | ||
13 | #include "linux/sys.h" | ||
14 | #include "linux/syscalls.h" | ||
15 | #include "linux/unistd.h" | ||
16 | #include "linux/slab.h" | ||
17 | #include "linux/utime.h" | ||
18 | #include "asm/mman.h" | ||
19 | #include "asm/uaccess.h" | ||
20 | #include "kern_util.h" | ||
21 | #include "user_util.h" | ||
22 | #include "sysdep/syscalls.h" | ||
23 | #include "mode_kern.h" | ||
24 | #include "choose-mode.h" | ||
25 | |||
26 | /* Unlocked, I don't care if this is a bit off */ | ||
27 | int nsyscalls = 0; | ||
28 | |||
29 | long sys_fork(void) | ||
30 | { | ||
31 | long ret; | ||
32 | |||
33 | current->thread.forking = 1; | ||
34 | ret = do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), | ||
35 | ¤t->thread.regs, 0, NULL, NULL); | ||
36 | current->thread.forking = 0; | ||
37 | return(ret); | ||
38 | } | ||
39 | |||
40 | long sys_vfork(void) | ||
41 | { | ||
42 | long ret; | ||
43 | |||
44 | current->thread.forking = 1; | ||
45 | ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, | ||
46 | UPT_SP(¤t->thread.regs.regs), | ||
47 | ¤t->thread.regs, 0, NULL, NULL); | ||
48 | current->thread.forking = 0; | ||
49 | return(ret); | ||
50 | } | ||
51 | |||
52 | /* common code for old and new mmaps */ | ||
53 | long sys_mmap2(unsigned long addr, unsigned long len, | ||
54 | unsigned long prot, unsigned long flags, | ||
55 | unsigned long fd, unsigned long pgoff) | ||
56 | { | ||
57 | long error = -EBADF; | ||
58 | struct file * file = NULL; | ||
59 | |||
60 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
61 | if (!(flags & MAP_ANONYMOUS)) { | ||
62 | file = fget(fd); | ||
63 | if (!file) | ||
64 | goto out; | ||
65 | } | ||
66 | |||
67 | down_write(¤t->mm->mmap_sem); | ||
68 | error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
69 | up_write(¤t->mm->mmap_sem); | ||
70 | |||
71 | if (file) | ||
72 | fput(file); | ||
73 | out: | ||
74 | return error; | ||
75 | } | ||
76 | |||
77 | long old_mmap(unsigned long addr, unsigned long len, | ||
78 | unsigned long prot, unsigned long flags, | ||
79 | unsigned long fd, unsigned long offset) | ||
80 | { | ||
81 | long err = -EINVAL; | ||
82 | if (offset & ~PAGE_MASK) | ||
83 | goto out; | ||
84 | |||
85 | err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); | ||
86 | out: | ||
87 | return err; | ||
88 | } | ||
89 | /* | ||
90 | * sys_pipe() is the normal C calling standard for creating | ||
91 | * a pipe. It's not the way unix traditionally does this, though. | ||
92 | */ | ||
93 | long sys_pipe(unsigned long __user * fildes) | ||
94 | { | ||
95 | int fd[2]; | ||
96 | long error; | ||
97 | |||
98 | error = do_pipe(fd); | ||
99 | if (!error) { | ||
100 | if (copy_to_user(fildes, fd, sizeof(fd))) | ||
101 | error = -EFAULT; | ||
102 | } | ||
103 | return error; | ||
104 | } | ||
105 | |||
106 | |||
107 | long sys_uname(struct old_utsname __user * name) | ||
108 | { | ||
109 | long err; | ||
110 | if (!name) | ||
111 | return -EFAULT; | ||
112 | down_read(&uts_sem); | ||
113 | err=copy_to_user(name, &system_utsname, sizeof (*name)); | ||
114 | up_read(&uts_sem); | ||
115 | return err?-EFAULT:0; | ||
116 | } | ||
117 | |||
118 | long sys_olduname(struct oldold_utsname __user * name) | ||
119 | { | ||
120 | long error; | ||
121 | |||
122 | if (!name) | ||
123 | return -EFAULT; | ||
124 | if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) | ||
125 | return -EFAULT; | ||
126 | |||
127 | down_read(&uts_sem); | ||
128 | |||
129 | error = __copy_to_user(&name->sysname,&system_utsname.sysname, | ||
130 | __OLD_UTS_LEN); | ||
131 | error |= __put_user(0,name->sysname+__OLD_UTS_LEN); | ||
132 | error |= __copy_to_user(&name->nodename,&system_utsname.nodename, | ||
133 | __OLD_UTS_LEN); | ||
134 | error |= __put_user(0,name->nodename+__OLD_UTS_LEN); | ||
135 | error |= __copy_to_user(&name->release,&system_utsname.release, | ||
136 | __OLD_UTS_LEN); | ||
137 | error |= __put_user(0,name->release+__OLD_UTS_LEN); | ||
138 | error |= __copy_to_user(&name->version,&system_utsname.version, | ||
139 | __OLD_UTS_LEN); | ||
140 | error |= __put_user(0,name->version+__OLD_UTS_LEN); | ||
141 | error |= __copy_to_user(&name->machine,&system_utsname.machine, | ||
142 | __OLD_UTS_LEN); | ||
143 | error |= __put_user(0,name->machine+__OLD_UTS_LEN); | ||
144 | |||
145 | up_read(&uts_sem); | ||
146 | |||
147 | error = error ? -EFAULT : 0; | ||
148 | |||
149 | return error; | ||
150 | } | ||
151 | |||
152 | DEFINE_SPINLOCK(syscall_lock); | ||
153 | |||
154 | static int syscall_index = 0; | ||
155 | |||
156 | int next_syscall_index(int limit) | ||
157 | { | ||
158 | int ret; | ||
159 | |||
160 | spin_lock(&syscall_lock); | ||
161 | ret = syscall_index; | ||
162 | if(++syscall_index == limit) | ||
163 | syscall_index = 0; | ||
164 | spin_unlock(&syscall_lock); | ||
165 | return(ret); | ||
166 | } | ||
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time.c index d7e044b5e5ee..552ca1cb9847 100644 --- a/arch/um/kernel/time_kern.c +++ b/arch/um/kernel/time.c | |||
@@ -38,7 +38,6 @@ unsigned long long sched_clock(void) | |||
38 | /* Changed at early boot */ | 38 | /* Changed at early boot */ |
39 | int timer_irq_inited = 0; | 39 | int timer_irq_inited = 0; |
40 | 40 | ||
41 | static int first_tick; | ||
42 | static unsigned long long prev_nsecs; | 41 | static unsigned long long prev_nsecs; |
43 | #ifdef CONFIG_UML_REAL_TIME_CLOCK | 42 | #ifdef CONFIG_UML_REAL_TIME_CLOCK |
44 | static long long delta; /* Deviation per interval */ | 43 | static long long delta; /* Deviation per interval */ |
@@ -48,15 +47,8 @@ void timer_irq(union uml_pt_regs *regs) | |||
48 | { | 47 | { |
49 | unsigned long long ticks = 0; | 48 | unsigned long long ticks = 0; |
50 | 49 | ||
51 | if(!timer_irq_inited){ | ||
52 | /* This is to ensure that ticks don't pile up when | ||
53 | * the timer handler is suspended */ | ||
54 | first_tick = 0; | ||
55 | return; | ||
56 | } | ||
57 | |||
58 | if(first_tick){ | ||
59 | #ifdef CONFIG_UML_REAL_TIME_CLOCK | 50 | #ifdef CONFIG_UML_REAL_TIME_CLOCK |
51 | if(prev_nsecs){ | ||
60 | /* We've had 1 tick */ | 52 | /* We've had 1 tick */ |
61 | unsigned long long nsecs = os_nsecs(); | 53 | unsigned long long nsecs = os_nsecs(); |
62 | 54 | ||
@@ -69,44 +61,17 @@ void timer_irq(union uml_pt_regs *regs) | |||
69 | 61 | ||
70 | ticks += (delta * HZ) / BILLION; | 62 | ticks += (delta * HZ) / BILLION; |
71 | delta -= (ticks * BILLION) / HZ; | 63 | delta -= (ticks * BILLION) / HZ; |
64 | } | ||
65 | else prev_nsecs = os_nsecs(); | ||
72 | #else | 66 | #else |
73 | ticks = 1; | 67 | ticks = 1; |
74 | #endif | 68 | #endif |
75 | } | ||
76 | else { | ||
77 | prev_nsecs = os_nsecs(); | ||
78 | first_tick = 1; | ||
79 | } | ||
80 | |||
81 | while(ticks > 0){ | 69 | while(ticks > 0){ |
82 | do_IRQ(TIMER_IRQ, regs); | 70 | do_IRQ(TIMER_IRQ, regs); |
83 | ticks--; | 71 | ticks--; |
84 | } | 72 | } |
85 | } | 73 | } |
86 | 74 | ||
87 | |||
88 | void time_init_kern(void) | ||
89 | { | ||
90 | long long nsecs; | ||
91 | |||
92 | nsecs = os_nsecs(); | ||
93 | set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION, | ||
94 | -nsecs % BILLION); | ||
95 | } | ||
96 | |||
97 | void do_boot_timer_handler(struct sigcontext * sc) | ||
98 | { | ||
99 | unsigned long flags; | ||
100 | struct pt_regs regs; | ||
101 | |||
102 | CHOOSE_MODE((void) (UPT_SC(®s.regs) = sc), | ||
103 | (void) (regs.regs.skas.is_user = 0)); | ||
104 | |||
105 | write_seqlock_irqsave(&xtime_lock, flags); | ||
106 | do_timer(®s); | ||
107 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
108 | } | ||
109 | |||
110 | static DEFINE_SPINLOCK(timer_spinlock); | 75 | static DEFINE_SPINLOCK(timer_spinlock); |
111 | 76 | ||
112 | static unsigned long long local_offset = 0; | 77 | static unsigned long long local_offset = 0; |
@@ -142,6 +107,32 @@ irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs) | |||
142 | return IRQ_HANDLED; | 107 | return IRQ_HANDLED; |
143 | } | 108 | } |
144 | 109 | ||
110 | static void register_timer(void) | ||
111 | { | ||
112 | int err; | ||
113 | |||
114 | err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL); | ||
115 | if(err != 0) | ||
116 | printk(KERN_ERR "timer_init : request_irq failed - " | ||
117 | "errno = %d\n", -err); | ||
118 | |||
119 | timer_irq_inited = 1; | ||
120 | |||
121 | user_time_init(); | ||
122 | } | ||
123 | |||
124 | extern void (*late_time_init)(void); | ||
125 | |||
126 | void time_init(void) | ||
127 | { | ||
128 | long long nsecs; | ||
129 | |||
130 | nsecs = os_nsecs(); | ||
131 | set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION, | ||
132 | -nsecs % BILLION); | ||
133 | late_time_init = register_timer; | ||
134 | } | ||
135 | |||
145 | void do_gettimeofday(struct timeval *tv) | 136 | void do_gettimeofday(struct timeval *tv) |
146 | { | 137 | { |
147 | unsigned long long nsecs = get_time(); | 138 | unsigned long long nsecs = get_time(); |
@@ -189,18 +180,3 @@ void timer_handler(int sig, union uml_pt_regs *regs) | |||
189 | if(current_thread->cpu == 0) | 180 | if(current_thread->cpu == 0) |
190 | timer_irq(regs); | 181 | timer_irq(regs); |
191 | } | 182 | } |
192 | |||
193 | int __init timer_init(void) | ||
194 | { | ||
195 | int err; | ||
196 | |||
197 | user_time_init(); | ||
198 | err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL); | ||
199 | if(err != 0) | ||
200 | printk(KERN_ERR "timer_init : request_irq failed - " | ||
201 | "errno = %d\n", -err); | ||
202 | timer_irq_inited = 1; | ||
203 | return(0); | ||
204 | } | ||
205 | |||
206 | arch_initcall(timer_init); | ||
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap.c index 02f6d4d8dc3a..ac70fa5a2e2a 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include "os.h" | 35 | #include "os.h" |
36 | 36 | ||
37 | /* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */ | 37 | /* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */ |
38 | int handle_page_fault(unsigned long address, unsigned long ip, | 38 | int handle_page_fault(unsigned long address, unsigned long ip, |
39 | int is_write, int is_user, int *code_out) | 39 | int is_write, int is_user, int *code_out) |
40 | { | 40 | { |
41 | struct mm_struct *mm = current->mm; | 41 | struct mm_struct *mm = current->mm; |
@@ -55,20 +55,20 @@ int handle_page_fault(unsigned long address, unsigned long ip, | |||
55 | 55 | ||
56 | down_read(&mm->mmap_sem); | 56 | down_read(&mm->mmap_sem); |
57 | vma = find_vma(mm, address); | 57 | vma = find_vma(mm, address); |
58 | if(!vma) | 58 | if(!vma) |
59 | goto out; | 59 | goto out; |
60 | else if(vma->vm_start <= address) | 60 | else if(vma->vm_start <= address) |
61 | goto good_area; | 61 | goto good_area; |
62 | else if(!(vma->vm_flags & VM_GROWSDOWN)) | 62 | else if(!(vma->vm_flags & VM_GROWSDOWN)) |
63 | goto out; | 63 | goto out; |
64 | else if(is_user && !ARCH_IS_STACKGROW(address)) | 64 | else if(is_user && !ARCH_IS_STACKGROW(address)) |
65 | goto out; | 65 | goto out; |
66 | else if(expand_stack(vma, address)) | 66 | else if(expand_stack(vma, address)) |
67 | goto out; | 67 | goto out; |
68 | 68 | ||
69 | good_area: | 69 | good_area: |
70 | *code_out = SEGV_ACCERR; | 70 | *code_out = SEGV_ACCERR; |
71 | if(is_write && !(vma->vm_flags & VM_WRITE)) | 71 | if(is_write && !(vma->vm_flags & VM_WRITE)) |
72 | goto out; | 72 | goto out; |
73 | 73 | ||
74 | /* Don't require VM_READ|VM_EXEC for write faults! */ | 74 | /* Don't require VM_READ|VM_EXEC for write faults! */ |
@@ -184,14 +184,14 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) | |||
184 | else if(catcher != NULL){ | 184 | else if(catcher != NULL){ |
185 | current->thread.fault_addr = (void *) address; | 185 | current->thread.fault_addr = (void *) address; |
186 | do_longjmp(catcher, 1); | 186 | do_longjmp(catcher, 1); |
187 | } | 187 | } |
188 | else if(current->thread.fault_addr != NULL) | 188 | else if(current->thread.fault_addr != NULL) |
189 | panic("fault_addr set but no fault catcher"); | 189 | panic("fault_addr set but no fault catcher"); |
190 | else if(!is_user && arch_fixup(ip, sc)) | 190 | else if(!is_user && arch_fixup(ip, sc)) |
191 | return(0); | 191 | return(0); |
192 | 192 | ||
193 | if(!is_user) | 193 | if(!is_user) |
194 | panic("Kernel mode fault at addr 0x%lx, ip 0x%lx", | 194 | panic("Kernel mode fault at addr 0x%lx, ip 0x%lx", |
195 | address, ip); | 195 | address, ip); |
196 | 196 | ||
197 | if (err == -EACCES) { | 197 | if (err == -EACCES) { |
diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c index 5c1e4cc1c049..ad66df17d9d7 100644 --- a/arch/um/kernel/tt/exec_kern.c +++ b/arch/um/kernel/tt/exec_kern.c | |||
@@ -21,7 +21,7 @@ | |||
21 | static int exec_tramp(void *sig_stack) | 21 | static int exec_tramp(void *sig_stack) |
22 | { | 22 | { |
23 | init_new_thread_stack(sig_stack, NULL); | 23 | init_new_thread_stack(sig_stack, NULL); |
24 | init_new_thread_signals(1); | 24 | init_new_thread_signals(); |
25 | os_stop_process(os_getpid()); | 25 | os_stop_process(os_getpid()); |
26 | return(0); | 26 | return(0); |
27 | } | 27 | } |
diff --git a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c index bcb8796c3cb1..84a23b14f770 100644 --- a/arch/um/kernel/tt/mem.c +++ b/arch/um/kernel/tt/mem.c | |||
@@ -24,22 +24,13 @@ void before_mem_tt(unsigned long brk_start) | |||
24 | #define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000) | 24 | #define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000) |
25 | #define START (CONFIG_TOP_ADDR - SIZE) | 25 | #define START (CONFIG_TOP_ADDR - SIZE) |
26 | 26 | ||
27 | unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out, | 27 | unsigned long set_task_sizes_tt(unsigned long *task_size_out) |
28 | unsigned long *task_size_out) | ||
29 | { | 28 | { |
29 | unsigned long host_task_size; | ||
30 | |||
30 | /* Round up to the nearest 4M */ | 31 | /* Round up to the nearest 4M */ |
31 | *host_size_out = ROUND_4M((unsigned long) &arg); | 32 | host_task_size = ROUND_4M((unsigned long) &host_task_size); |
32 | *task_size_out = START; | 33 | *task_size_out = START; |
33 | return(START); | ||
34 | } | ||
35 | 34 | ||
36 | /* | 35 | return host_task_size; |
37 | * Overrides for Emacs so that we follow Linus's tabbing style. | 36 | } |
38 | * Emacs will notice this stuff at the end of the file and automatically | ||
39 | * adjust the settings for this buffer only. This must remain at the end | ||
40 | * of the file. | ||
41 | * --------------------------------------------------------------------------- | ||
42 | * Local variables: | ||
43 | * c-file-style: "linux" | ||
44 | * End: | ||
45 | */ | ||
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c index 8368c2dbe635..1e86f0bfef72 100644 --- a/arch/um/kernel/tt/process_kern.c +++ b/arch/um/kernel/tt/process_kern.c | |||
@@ -142,7 +142,7 @@ static void new_thread_handler(int sig) | |||
142 | schedule_tail(current->thread.prev_sched); | 142 | schedule_tail(current->thread.prev_sched); |
143 | current->thread.prev_sched = NULL; | 143 | current->thread.prev_sched = NULL; |
144 | 144 | ||
145 | init_new_thread_signals(1); | 145 | init_new_thread_signals(); |
146 | enable_timer(); | 146 | enable_timer(); |
147 | free_page(current->thread.temp_stack); | 147 | free_page(current->thread.temp_stack); |
148 | set_cmdline("(kernel thread)"); | 148 | set_cmdline("(kernel thread)"); |
diff --git a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c index 3fda9a03c59a..293caa6d0c2d 100644 --- a/arch/um/kernel/tt/syscall_kern.c +++ b/arch/um/kernel/tt/syscall_kern.c | |||
@@ -21,18 +21,11 @@ void syscall_handler_tt(int sig, struct pt_regs *regs) | |||
21 | void *sc; | 21 | void *sc; |
22 | long result; | 22 | long result; |
23 | int syscall; | 23 | int syscall; |
24 | #ifdef CONFIG_SYSCALL_DEBUG | 24 | |
25 | int index; | ||
26 | #endif | ||
27 | sc = UPT_SC(®s->regs); | 25 | sc = UPT_SC(®s->regs); |
28 | SC_START_SYSCALL(sc); | 26 | SC_START_SYSCALL(sc); |
29 | 27 | ||
30 | syscall = UPT_SYSCALL_NR(®s->regs); | 28 | syscall = UPT_SYSCALL_NR(®s->regs); |
31 | |||
32 | #ifdef CONFIG_SYSCALL_DEBUG | ||
33 | index = record_syscall_start(syscall); | ||
34 | #endif | ||
35 | |||
36 | syscall_trace(®s->regs, 0); | 29 | syscall_trace(®s->regs, 0); |
37 | 30 | ||
38 | current->thread.nsyscalls++; | 31 | current->thread.nsyscalls++; |
@@ -50,7 +43,4 @@ void syscall_handler_tt(int sig, struct pt_regs *regs) | |||
50 | SC_SET_SYSCALL_RETURN(sc, result); | 43 | SC_SET_SYSCALL_RETURN(sc, result); |
51 | 44 | ||
52 | syscall_trace(®s->regs, 1); | 45 | syscall_trace(®s->regs, 1); |
53 | #ifdef CONFIG_SYSCALL_DEBUG | ||
54 | record_syscall_end(index, result); | ||
55 | #endif | ||
56 | } | 46 | } |
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c index 71daae24e48a..9882342206ec 100644 --- a/arch/um/kernel/tt/tracer.c +++ b/arch/um/kernel/tt/tracer.c | |||
@@ -188,10 +188,7 @@ int tracer(int (*init_proc)(void *), void *sp) | |||
188 | int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0; | 188 | int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0; |
189 | int proc_id = 0, n, err, old_tracing = 0, strace = 0; | 189 | int proc_id = 0, n, err, old_tracing = 0, strace = 0; |
190 | int local_using_sysemu = 0; | 190 | int local_using_sysemu = 0; |
191 | #ifdef UML_CONFIG_SYSCALL_DEBUG | 191 | |
192 | unsigned long eip = 0; | ||
193 | int last_index; | ||
194 | #endif | ||
195 | signal(SIGPIPE, SIG_IGN); | 192 | signal(SIGPIPE, SIG_IGN); |
196 | setup_tracer_winch(); | 193 | setup_tracer_winch(); |
197 | tracing_pid = os_getpid(); | 194 | tracing_pid = os_getpid(); |
@@ -282,23 +279,6 @@ int tracer(int (*init_proc)(void *), void *sp) | |||
282 | else if(WIFSTOPPED(status)){ | 279 | else if(WIFSTOPPED(status)){ |
283 | proc_id = pid_to_processor_id(pid); | 280 | proc_id = pid_to_processor_id(pid); |
284 | sig = WSTOPSIG(status); | 281 | sig = WSTOPSIG(status); |
285 | #ifdef UML_CONFIG_SYSCALL_DEBUG | ||
286 | if(signal_index[proc_id] == 1024){ | ||
287 | signal_index[proc_id] = 0; | ||
288 | last_index = 1023; | ||
289 | } | ||
290 | else last_index = signal_index[proc_id] - 1; | ||
291 | if(((sig == SIGPROF) || (sig == SIGVTALRM) || | ||
292 | (sig == SIGALRM)) && | ||
293 | (signal_record[proc_id][last_index].signal == sig)&& | ||
294 | (signal_record[proc_id][last_index].pid == pid)) | ||
295 | signal_index[proc_id] = last_index; | ||
296 | signal_record[proc_id][signal_index[proc_id]].pid = pid; | ||
297 | gettimeofday(&signal_record[proc_id][signal_index[proc_id]].time, NULL); | ||
298 | eip = ptrace(PTRACE_PEEKUSR, pid, PT_IP_OFFSET, 0); | ||
299 | signal_record[proc_id][signal_index[proc_id]].addr = eip; | ||
300 | signal_record[proc_id][signal_index[proc_id]++].signal = sig; | ||
301 | #endif | ||
302 | if(proc_id == -1){ | 282 | if(proc_id == -1){ |
303 | sleeping_process_signal(pid, sig); | 283 | sleeping_process_signal(pid, sig); |
304 | continue; | 284 | continue; |
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 37cfe7701f06..7896cf98232d 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c | |||
@@ -330,6 +330,8 @@ EXPORT_SYMBOL(end_iomem); | |||
330 | 330 | ||
331 | #define MIN_VMALLOC (32 * 1024 * 1024) | 331 | #define MIN_VMALLOC (32 * 1024 * 1024) |
332 | 332 | ||
333 | extern char __binary_start; | ||
334 | |||
333 | int linux_main(int argc, char **argv) | 335 | int linux_main(int argc, char **argv) |
334 | { | 336 | { |
335 | unsigned long avail, diff; | 337 | unsigned long avail, diff; |
@@ -374,8 +376,9 @@ int linux_main(int argc, char **argv) | |||
374 | 376 | ||
375 | printf("UML running in %s mode\n", mode); | 377 | printf("UML running in %s mode\n", mode); |
376 | 378 | ||
377 | uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0, | 379 | uml_start = (unsigned long) &__binary_start; |
378 | &host_task_size, &task_size); | 380 | host_task_size = CHOOSE_MODE_PROC(set_task_sizes_tt, |
381 | set_task_sizes_skas, &task_size); | ||
379 | 382 | ||
380 | /* | 383 | /* |
381 | * Setting up handlers to 'sig_info' struct | 384 | * Setting up handlers to 'sig_info' struct |
@@ -395,7 +398,7 @@ int linux_main(int argc, char **argv) | |||
395 | physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); | 398 | physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); |
396 | } | 399 | } |
397 | 400 | ||
398 | uml_physmem = uml_start; | 401 | uml_physmem = uml_start & PAGE_MASK; |
399 | 402 | ||
400 | /* Reserve up to 4M after the current brk */ | 403 | /* Reserve up to 4M after the current brk */ |
401 | uml_reserved = ROUND_4M(brk_start) + (1 << 22); | 404 | uml_reserved = ROUND_4M(brk_start) + (1 << 22); |
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index af11915ce0a8..8eca47a6ff08 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S | |||
@@ -7,13 +7,16 @@ jiffies = jiffies_64; | |||
7 | 7 | ||
8 | SECTIONS | 8 | SECTIONS |
9 | { | 9 | { |
10 | /*This must contain the right address - not quite the default ELF one.*/ | 10 | /* This must contain the right address - not quite the default ELF one.*/ |
11 | PROVIDE (__executable_start = START); | 11 | PROVIDE (__executable_start = START); |
12 | . = START + SIZEOF_HEADERS; | 12 | /* Static binaries stick stuff here, like the sigreturn trampoline, |
13 | * invisibly to objdump. So, just make __binary_start equal to the very | ||
14 | * beginning of the executable, and if there are unmapped pages after this, | ||
15 | * they are forever unusable. | ||
16 | */ | ||
17 | __binary_start = START; | ||
13 | 18 | ||
14 | /* Used in arch/um/kernel/mem.c. Any memory between START and __binary_start | 19 | . = START + SIZEOF_HEADERS; |
15 | * is remapped.*/ | ||
16 | __binary_start = .; | ||
17 | 20 | ||
18 | #ifdef MODE_TT | 21 | #ifdef MODE_TT |
19 | .remap_data : { UNMAP_PATH (.data .bss) } | 22 | .remap_data : { UNMAP_PATH (.data .bss) } |
diff --git a/arch/um/kernel/vmlinux.lds.S b/arch/um/kernel/vmlinux.lds.S index 72acdce205e0..f8aeb448aab6 100644 --- a/arch/um/kernel/vmlinux.lds.S +++ b/arch/um/kernel/vmlinux.lds.S | |||
@@ -1,5 +1,3 @@ | |||
1 | /* in case the preprocessor is a 32bit one */ | ||
2 | #undef i386 | ||
3 | #ifdef CONFIG_LD_SCRIPT_STATIC | 1 | #ifdef CONFIG_LD_SCRIPT_STATIC |
4 | #include "uml.lds.S" | 2 | #include "uml.lds.S" |
5 | #else | 3 | #else |