diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /arch/um/kernel | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'arch/um/kernel')
32 files changed, 490 insertions, 340 deletions
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index babe21826e3..c4491c15afb 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile | |||
@@ -3,16 +3,15 @@ | |||
3 | # Licensed under the GPL | 3 | # Licensed under the GPL |
4 | # | 4 | # |
5 | 5 | ||
6 | CPPFLAGS_vmlinux.lds := -DSTART=$(LDS_START) \ | 6 | CPPFLAGS_vmlinux.lds := -U$(SUBARCH) -DSTART=$(LDS_START) \ |
7 | -DELF_ARCH=$(LDS_ELF_ARCH) \ | 7 | -DELF_ARCH=$(LDS_ELF_ARCH) \ |
8 | -DELF_FORMAT=$(LDS_ELF_FORMAT) \ | 8 | -DELF_FORMAT=$(LDS_ELF_FORMAT) |
9 | $(LDS_EXTRA) | ||
10 | extra-y := vmlinux.lds | 9 | extra-y := vmlinux.lds |
11 | clean-files := | 10 | clean-files := |
12 | 11 | ||
13 | obj-y = config.o exec.o exitcode.o irq.o ksyms.o mem.o \ | 12 | obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \ |
14 | physmem.o process.o ptrace.o reboot.o sigio.o \ | 13 | physmem.o process.o ptrace.o reboot.o sigio.o \ |
15 | signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o \ | 14 | signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \ |
16 | um_arch.o umid.o skas/ | 15 | um_arch.o umid.o skas/ |
17 | 16 | ||
18 | obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o | 17 | obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o |
diff --git a/arch/um/kernel/asm-offsets.c b/arch/um/kernel/asm-offsets.c index 1fb12235ab9..91ea538e161 100644 --- a/arch/um/kernel/asm-offsets.c +++ b/arch/um/kernel/asm-offsets.c | |||
@@ -1 +1 @@ | |||
#include <sysdep/kernel-offsets.h> | #include "sysdep/kernel-offsets.h" | ||
diff --git a/arch/um/kernel/config.c.in b/arch/um/kernel/config.c.in index 972bf165956..b7a43feafde 100644 --- a/arch/um/kernel/config.c.in +++ b/arch/um/kernel/config.c.in | |||
@@ -5,7 +5,7 @@ | |||
5 | 5 | ||
6 | #include <stdio.h> | 6 | #include <stdio.h> |
7 | #include <stdlib.h> | 7 | #include <stdlib.h> |
8 | #include <init.h> | 8 | #include "init.h" |
9 | 9 | ||
10 | static __initdata const char *config[] = { | 10 | static __initdata const char *config[] = { |
11 | "CONFIG" | 11 | "CONFIG" |
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index fb8fd6fb656..a3cab6d3ae0 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S | |||
@@ -89,7 +89,7 @@ SECTIONS | |||
89 | 89 | ||
90 | .kstrtab : { *(.kstrtab) } | 90 | .kstrtab : { *(.kstrtab) } |
91 | 91 | ||
92 | #include <asm/common.lds.S> | 92 | #include "asm/common.lds.S" |
93 | 93 | ||
94 | init.data : { INIT_DATA } | 94 | init.data : { INIT_DATA } |
95 | 95 | ||
diff --git a/arch/um/kernel/early_printk.c b/arch/um/kernel/early_printk.c index 49480f09245..ec649bf72f6 100644 --- a/arch/um/kernel/early_printk.c +++ b/arch/um/kernel/early_printk.c | |||
@@ -9,7 +9,7 @@ | |||
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/console.h> | 10 | #include <linux/console.h> |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <os.h> | 12 | #include "os.h" |
13 | 13 | ||
14 | static void early_console_write(struct console *con, const char *s, unsigned int n) | 14 | static void early_console_write(struct console *con, const char *s, unsigned int n) |
15 | { | 15 | { |
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index 0d7103c9eff..939a4a67f0f 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c | |||
@@ -3,19 +3,19 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/stddef.h> | 6 | #include "linux/stddef.h" |
7 | #include <linux/module.h> | 7 | #include "linux/fs.h" |
8 | #include <linux/fs.h> | 8 | #include "linux/ptrace.h" |
9 | #include <linux/ptrace.h> | 9 | #include "linux/sched.h" |
10 | #include <linux/sched.h> | 10 | #include "linux/slab.h" |
11 | #include <linux/slab.h> | 11 | #include "asm/current.h" |
12 | #include <asm/current.h> | 12 | #include "asm/processor.h" |
13 | #include <asm/processor.h> | 13 | #include "asm/uaccess.h" |
14 | #include <asm/uaccess.h> | 14 | #include "as-layout.h" |
15 | #include <as-layout.h> | 15 | #include "mem_user.h" |
16 | #include <mem_user.h> | 16 | #include "skas.h" |
17 | #include <skas.h> | 17 | #include "os.h" |
18 | #include <os.h> | 18 | #include "internal.h" |
19 | 19 | ||
20 | void flush_thread(void) | 20 | void flush_thread(void) |
21 | { | 21 | { |
@@ -32,8 +32,6 @@ void flush_thread(void) | |||
32 | "err = %d\n", ret); | 32 | "err = %d\n", ret); |
33 | force_sig(SIGKILL, current); | 33 | force_sig(SIGKILL, current); |
34 | } | 34 | } |
35 | get_safe_registers(current_pt_regs()->regs.gp, | ||
36 | current_pt_regs()->regs.fp); | ||
37 | 35 | ||
38 | __switch_mm(¤t->mm->context.id); | 36 | __switch_mm(¤t->mm->context.id); |
39 | } | 37 | } |
@@ -42,9 +40,47 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) | |||
42 | { | 40 | { |
43 | PT_REGS_IP(regs) = eip; | 41 | PT_REGS_IP(regs) = eip; |
44 | PT_REGS_SP(regs) = esp; | 42 | PT_REGS_SP(regs) = esp; |
45 | current->ptrace &= ~PT_DTRACE; | 43 | } |
44 | |||
45 | static long execve1(const char *file, | ||
46 | const char __user *const __user *argv, | ||
47 | const char __user *const __user *env) | ||
48 | { | ||
49 | long error; | ||
50 | |||
51 | error = do_execve(file, argv, env, ¤t->thread.regs); | ||
52 | if (error == 0) { | ||
53 | task_lock(current); | ||
54 | current->ptrace &= ~PT_DTRACE; | ||
46 | #ifdef SUBARCH_EXECVE1 | 55 | #ifdef SUBARCH_EXECVE1 |
47 | SUBARCH_EXECVE1(regs->regs); | 56 | SUBARCH_EXECVE1(¤t->thread.regs.regs); |
48 | #endif | 57 | #endif |
58 | task_unlock(current); | ||
59 | } | ||
60 | return error; | ||
61 | } | ||
62 | |||
63 | long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env) | ||
64 | { | ||
65 | long err; | ||
66 | |||
67 | err = execve1(file, argv, env); | ||
68 | if (!err) | ||
69 | UML_LONGJMP(current->thread.exec_buf, 1); | ||
70 | return err; | ||
71 | } | ||
72 | |||
73 | long sys_execve(const char __user *file, const char __user *const __user *argv, | ||
74 | const char __user *const __user *env) | ||
75 | { | ||
76 | long error; | ||
77 | char *filename; | ||
78 | |||
79 | filename = getname(file); | ||
80 | error = PTR_ERR(filename); | ||
81 | if (IS_ERR(filename)) goto out; | ||
82 | error = execve1(filename, argv, env); | ||
83 | putname(filename); | ||
84 | out: | ||
85 | return error; | ||
49 | } | 86 | } |
50 | EXPORT_SYMBOL(start_thread); | ||
diff --git a/arch/um/kernel/gmon_syms.c b/arch/um/kernel/gmon_syms.c index 1bf61266da8..72eccd2a411 100644 --- a/arch/um/kernel/gmon_syms.c +++ b/arch/um/kernel/gmon_syms.c | |||
@@ -3,7 +3,22 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/module.h> | 6 | #include "linux/module.h" |
7 | 7 | ||
8 | extern void __bb_init_func(void *) __attribute__((weak)); | 8 | extern void __bb_init_func(void *) __attribute__((weak)); |
9 | EXPORT_SYMBOL(__bb_init_func); | 9 | EXPORT_SYMBOL(__bb_init_func); |
10 | |||
11 | /* | ||
12 | * This is defined (and referred to in profiling stub code) only by some GCC | ||
13 | * versions in libgcov. | ||
14 | * | ||
15 | * Since SuSE backported the fix, we cannot handle it depending on GCC version. | ||
16 | * So, unconditionally export it. But also give it a weak declaration, which | ||
17 | * will be overridden by any other one. | ||
18 | */ | ||
19 | |||
20 | extern void __gcov_init(void *) __attribute__((weak)); | ||
21 | EXPORT_SYMBOL(__gcov_init); | ||
22 | |||
23 | extern void __gcov_merge_add(void *) __attribute__((weak)); | ||
24 | EXPORT_SYMBOL(__gcov_merge_add); | ||
diff --git a/arch/um/kernel/gprof_syms.c b/arch/um/kernel/gprof_syms.c index 74ddb44288a..e2f043d0de6 100644 --- a/arch/um/kernel/gprof_syms.c +++ b/arch/um/kernel/gprof_syms.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/module.h> | 6 | #include "linux/module.h" |
7 | 7 | ||
8 | extern void mcount(void); | 8 | extern void mcount(void); |
9 | EXPORT_SYMBOL(mcount); | 9 | EXPORT_SYMBOL(mcount); |
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c index 55cead809b1..d386c75c88e 100644 --- a/arch/um/kernel/initrd.c +++ b/arch/um/kernel/initrd.c | |||
@@ -3,16 +3,16 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/init.h> | 6 | #include "linux/init.h" |
7 | #include <linux/bootmem.h> | 7 | #include "linux/bootmem.h" |
8 | #include <linux/initrd.h> | 8 | #include "linux/initrd.h" |
9 | #include <asm/types.h> | 9 | #include "asm/types.h" |
10 | #include <init.h> | 10 | #include "initrd.h" |
11 | #include <os.h> | 11 | #include "init.h" |
12 | #include "os.h" | ||
12 | 13 | ||
13 | /* Changed by uml_initrd_setup, which is a setup */ | 14 | /* Changed by uml_initrd_setup, which is a setup */ |
14 | static char *initrd __initdata = NULL; | 15 | static char *initrd __initdata = NULL; |
15 | static int load_initrd(char *filename, void *buf, int size); | ||
16 | 16 | ||
17 | static int __init read_initrd(void) | 17 | static int __init read_initrd(void) |
18 | { | 18 | { |
@@ -62,7 +62,7 @@ __uml_setup("initrd=", uml_initrd_setup, | |||
62 | " name of the file containing the image.\n\n" | 62 | " name of the file containing the image.\n\n" |
63 | ); | 63 | ); |
64 | 64 | ||
65 | static int load_initrd(char *filename, void *buf, int size) | 65 | int load_initrd(char *filename, void *buf, int size) |
66 | { | 66 | { |
67 | int fd, n; | 67 | int fd, n; |
68 | 68 | ||
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index 36e12f0cefd..9e485c77030 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c | |||
@@ -5,17 +5,17 @@ | |||
5 | * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar | 5 | * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/cpumask.h> | 8 | #include "linux/cpumask.h" |
9 | #include <linux/hardirq.h> | 9 | #include "linux/hardirq.h" |
10 | #include <linux/interrupt.h> | 10 | #include "linux/interrupt.h" |
11 | #include <linux/kernel_stat.h> | 11 | #include "linux/kernel_stat.h" |
12 | #include <linux/module.h> | 12 | #include "linux/module.h" |
13 | #include <linux/sched.h> | 13 | #include "linux/sched.h" |
14 | #include <linux/seq_file.h> | 14 | #include "linux/seq_file.h" |
15 | #include <linux/slab.h> | 15 | #include "linux/slab.h" |
16 | #include <as-layout.h> | 16 | #include "as-layout.h" |
17 | #include <kern_util.h> | 17 | #include "kern_util.h" |
18 | #include <os.h> | 18 | #include "os.h" |
19 | 19 | ||
20 | /* | 20 | /* |
21 | * This list is accessed under irq_lock, except in sigio_handler, | 21 | * This list is accessed under irq_lock, except in sigio_handler, |
@@ -30,7 +30,7 @@ static struct irq_fd **last_irq_ptr = &active_fds; | |||
30 | 30 | ||
31 | extern void free_irqs(void); | 31 | extern void free_irqs(void); |
32 | 32 | ||
33 | void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) | 33 | void sigio_handler(int sig, struct uml_pt_regs *regs) |
34 | { | 34 | { |
35 | struct irq_fd *irq_fd; | 35 | struct irq_fd *irq_fd; |
36 | int n; | 36 | int n; |
@@ -258,7 +258,6 @@ void deactivate_fd(int fd, int irqnum) | |||
258 | 258 | ||
259 | ignore_sigio_fd(fd); | 259 | ignore_sigio_fd(fd); |
260 | } | 260 | } |
261 | EXPORT_SYMBOL(deactivate_fd); | ||
262 | 261 | ||
263 | /* | 262 | /* |
264 | * Called just before shutdown in order to provide a clean exec | 263 | * Called just before shutdown in order to provide a clean exec |
@@ -297,13 +296,6 @@ unsigned int do_IRQ(int irq, struct uml_pt_regs *regs) | |||
297 | return 1; | 296 | return 1; |
298 | } | 297 | } |
299 | 298 | ||
300 | void um_free_irq(unsigned int irq, void *dev) | ||
301 | { | ||
302 | free_irq_by_irq_and_dev(irq, dev); | ||
303 | free_irq(irq, dev); | ||
304 | } | ||
305 | EXPORT_SYMBOL(um_free_irq); | ||
306 | |||
307 | int um_request_irq(unsigned int irq, int fd, int type, | 299 | int um_request_irq(unsigned int irq, int fd, int type, |
308 | irq_handler_t handler, | 300 | irq_handler_t handler, |
309 | unsigned long irqflags, const char * devname, | 301 | unsigned long irqflags, const char * devname, |
@@ -334,6 +326,7 @@ static void dummy(struct irq_data *d) | |||
334 | /* This is used for everything else than the timer. */ | 326 | /* This is used for everything else than the timer. */ |
335 | static struct irq_chip normal_irq_type = { | 327 | static struct irq_chip normal_irq_type = { |
336 | .name = "SIGIO", | 328 | .name = "SIGIO", |
329 | .release = free_irq_by_irq_and_dev, | ||
337 | .irq_disable = dummy, | 330 | .irq_disable = dummy, |
338 | .irq_enable = dummy, | 331 | .irq_enable = dummy, |
339 | .irq_ack = dummy, | 332 | .irq_ack = dummy, |
@@ -341,6 +334,7 @@ static struct irq_chip normal_irq_type = { | |||
341 | 334 | ||
342 | static struct irq_chip SIGVTALRM_irq_type = { | 335 | static struct irq_chip SIGVTALRM_irq_type = { |
343 | .name = "SIGVTALRM", | 336 | .name = "SIGVTALRM", |
337 | .release = free_irq_by_irq_and_dev, | ||
344 | .irq_disable = dummy, | 338 | .irq_disable = dummy, |
345 | .irq_enable = dummy, | 339 | .irq_enable = dummy, |
346 | .irq_ack = dummy, | 340 | .irq_ack = dummy, |
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index 543c0475693..0ae0dfcfbff 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c | |||
@@ -3,11 +3,33 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/module.h> | 6 | #include "linux/module.h" |
7 | #include <os.h> | 7 | #include "linux/syscalls.h" |
8 | #include "asm/tlbflush.h" | ||
9 | #include "asm/uaccess.h" | ||
10 | #include "as-layout.h" | ||
11 | #include "kern_util.h" | ||
12 | #include "mem_user.h" | ||
13 | #include "os.h" | ||
8 | 14 | ||
15 | EXPORT_SYMBOL(uml_physmem); | ||
9 | EXPORT_SYMBOL(set_signals); | 16 | EXPORT_SYMBOL(set_signals); |
10 | EXPORT_SYMBOL(get_signals); | 17 | EXPORT_SYMBOL(get_signals); |
18 | EXPORT_SYMBOL(kernel_thread); | ||
19 | EXPORT_SYMBOL(sys_waitpid); | ||
20 | EXPORT_SYMBOL(flush_tlb_range); | ||
21 | |||
22 | EXPORT_SYMBOL(high_physmem); | ||
23 | EXPORT_SYMBOL(empty_zero_page); | ||
24 | EXPORT_SYMBOL(handle_page_fault); | ||
25 | EXPORT_SYMBOL(find_iomem); | ||
26 | |||
27 | EXPORT_SYMBOL(strnlen_user); | ||
28 | EXPORT_SYMBOL(strncpy_from_user); | ||
29 | EXPORT_SYMBOL(copy_to_user); | ||
30 | EXPORT_SYMBOL(copy_from_user); | ||
31 | EXPORT_SYMBOL(clear_user); | ||
32 | EXPORT_SYMBOL(uml_strdup); | ||
11 | 33 | ||
12 | EXPORT_SYMBOL(os_stat_fd); | 34 | EXPORT_SYMBOL(os_stat_fd); |
13 | EXPORT_SYMBOL(os_stat_file); | 35 | EXPORT_SYMBOL(os_stat_file); |
@@ -35,10 +57,24 @@ EXPORT_SYMBOL(os_connect_socket); | |||
35 | EXPORT_SYMBOL(os_accept_connection); | 57 | EXPORT_SYMBOL(os_accept_connection); |
36 | EXPORT_SYMBOL(os_rcv_fd); | 58 | EXPORT_SYMBOL(os_rcv_fd); |
37 | EXPORT_SYMBOL(run_helper); | 59 | EXPORT_SYMBOL(run_helper); |
60 | EXPORT_SYMBOL(start_thread); | ||
38 | EXPORT_SYMBOL(os_major); | 61 | EXPORT_SYMBOL(os_major); |
39 | EXPORT_SYMBOL(os_minor); | 62 | EXPORT_SYMBOL(os_minor); |
40 | EXPORT_SYMBOL(os_makedev); | 63 | EXPORT_SYMBOL(os_makedev); |
41 | 64 | ||
42 | EXPORT_SYMBOL(add_sigio_fd); | 65 | EXPORT_SYMBOL(add_sigio_fd); |
43 | EXPORT_SYMBOL(ignore_sigio_fd); | 66 | EXPORT_SYMBOL(ignore_sigio_fd); |
67 | EXPORT_SYMBOL(deactivate_fd); | ||
44 | EXPORT_SYMBOL(sigio_broken); | 68 | EXPORT_SYMBOL(sigio_broken); |
69 | |||
70 | #ifdef CONFIG_SMP | ||
71 | |||
72 | /* required for SMP */ | ||
73 | |||
74 | extern void __write_lock_failed(rwlock_t *rw); | ||
75 | EXPORT_SYMBOL(__write_lock_failed); | ||
76 | |||
77 | extern void __read_lock_failed(rwlock_t *rw); | ||
78 | EXPORT_SYMBOL(__read_lock_failed); | ||
79 | |||
80 | #endif | ||
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 5abcbfbe7e2..8137ccc9635 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c | |||
@@ -4,7 +4,6 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/stddef.h> | 6 | #include <linux/stddef.h> |
7 | #include <linux/module.h> | ||
8 | #include <linux/bootmem.h> | 7 | #include <linux/bootmem.h> |
9 | #include <linux/highmem.h> | 8 | #include <linux/highmem.h> |
10 | #include <linux/mm.h> | 9 | #include <linux/mm.h> |
@@ -12,16 +11,15 @@ | |||
12 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
13 | #include <asm/fixmap.h> | 12 | #include <asm/fixmap.h> |
14 | #include <asm/page.h> | 13 | #include <asm/page.h> |
15 | #include <as-layout.h> | 14 | #include "as-layout.h" |
16 | #include <init.h> | 15 | #include "init.h" |
17 | #include <kern.h> | 16 | #include "kern.h" |
18 | #include <kern_util.h> | 17 | #include "kern_util.h" |
19 | #include <mem_user.h> | 18 | #include "mem_user.h" |
20 | #include <os.h> | 19 | #include "os.h" |
21 | 20 | ||
22 | /* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */ | 21 | /* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */ |
23 | unsigned long *empty_zero_page = NULL; | 22 | unsigned long *empty_zero_page = NULL; |
24 | EXPORT_SYMBOL(empty_zero_page); | ||
25 | /* allocated in paging_init and unchanged thereafter */ | 23 | /* allocated in paging_init and unchanged thereafter */ |
26 | static unsigned long *empty_bad_page = NULL; | 24 | static unsigned long *empty_bad_page = NULL; |
27 | 25 | ||
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index f116db15d40..a1a9090254c 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c | |||
@@ -3,22 +3,20 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/module.h> | 6 | #include "linux/bootmem.h" |
7 | #include <linux/bootmem.h> | 7 | #include "linux/mm.h" |
8 | #include <linux/mm.h> | 8 | #include "linux/pfn.h" |
9 | #include <linux/pfn.h> | 9 | #include "asm/page.h" |
10 | #include <asm/page.h> | 10 | #include "as-layout.h" |
11 | #include <as-layout.h> | 11 | #include "init.h" |
12 | #include <init.h> | 12 | #include "kern.h" |
13 | #include <kern.h> | 13 | #include "mem_user.h" |
14 | #include <mem_user.h> | 14 | #include "os.h" |
15 | #include <os.h> | ||
16 | 15 | ||
17 | static int physmem_fd = -1; | 16 | static int physmem_fd = -1; |
18 | 17 | ||
19 | /* Changed during early boot */ | 18 | /* Changed during early boot */ |
20 | unsigned long high_physmem; | 19 | unsigned long high_physmem; |
21 | EXPORT_SYMBOL(high_physmem); | ||
22 | 20 | ||
23 | extern unsigned long long physmem_size; | 21 | extern unsigned long long physmem_size; |
24 | 22 | ||
@@ -186,7 +184,6 @@ unsigned long find_iomem(char *driver, unsigned long *len_out) | |||
186 | 184 | ||
187 | return 0; | 185 | return 0; |
188 | } | 186 | } |
189 | EXPORT_SYMBOL(find_iomem); | ||
190 | 187 | ||
191 | static int setup_iomem(void) | 188 | static int setup_iomem(void) |
192 | { | 189 | { |
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index b462b13c5ba..21c1ae7c3d7 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c | |||
@@ -18,15 +18,14 @@ | |||
18 | #include <linux/seq_file.h> | 18 | #include <linux/seq_file.h> |
19 | #include <linux/tick.h> | 19 | #include <linux/tick.h> |
20 | #include <linux/threads.h> | 20 | #include <linux/threads.h> |
21 | #include <linux/tracehook.h> | ||
22 | #include <asm/current.h> | 21 | #include <asm/current.h> |
23 | #include <asm/pgtable.h> | 22 | #include <asm/pgtable.h> |
24 | #include <asm/mmu_context.h> | ||
25 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
26 | #include <as-layout.h> | 24 | #include "as-layout.h" |
27 | #include <kern_util.h> | 25 | #include "kern_util.h" |
28 | #include <os.h> | 26 | #include "os.h" |
29 | #include <skas.h> | 27 | #include "skas.h" |
28 | #include "tlb.h" | ||
30 | 29 | ||
31 | /* | 30 | /* |
32 | * This is a per-cpu array. A processor only modifies its entry and it only | 31 | * This is a per-cpu array. A processor only modifies its entry and it only |
@@ -69,6 +68,17 @@ unsigned long alloc_stack(int order, int atomic) | |||
69 | return page; | 68 | return page; |
70 | } | 69 | } |
71 | 70 | ||
71 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
72 | { | ||
73 | int pid; | ||
74 | |||
75 | current->thread.request.u.thread.proc = fn; | ||
76 | current->thread.request.u.thread.arg = arg; | ||
77 | pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, | ||
78 | ¤t->thread.regs, 0, NULL, NULL); | ||
79 | return pid; | ||
80 | } | ||
81 | |||
72 | static inline void set_current(struct task_struct *task) | 82 | static inline void set_current(struct task_struct *task) |
73 | { | 83 | { |
74 | cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) | 84 | cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) |
@@ -77,8 +87,11 @@ static inline void set_current(struct task_struct *task) | |||
77 | 87 | ||
78 | extern void arch_switch_to(struct task_struct *to); | 88 | extern void arch_switch_to(struct task_struct *to); |
79 | 89 | ||
80 | void *__switch_to(struct task_struct *from, struct task_struct *to) | 90 | void *_switch_to(void *prev, void *next, void *last) |
81 | { | 91 | { |
92 | struct task_struct *from = prev; | ||
93 | struct task_struct *to = next; | ||
94 | |||
82 | to->thread.prev_sched = from; | 95 | to->thread.prev_sched = from; |
83 | set_current(to); | 96 | set_current(to); |
84 | 97 | ||
@@ -97,25 +110,24 @@ void *__switch_to(struct task_struct *from, struct task_struct *to) | |||
97 | } while (current->thread.saved_task); | 110 | } while (current->thread.saved_task); |
98 | 111 | ||
99 | return current->thread.prev_sched; | 112 | return current->thread.prev_sched; |
113 | |||
100 | } | 114 | } |
101 | 115 | ||
102 | void interrupt_end(void) | 116 | void interrupt_end(void) |
103 | { | 117 | { |
104 | if (need_resched()) | 118 | if (need_resched()) |
105 | schedule(); | 119 | schedule(); |
106 | if (test_thread_flag(TIF_SIGPENDING)) | 120 | if (test_tsk_thread_flag(current, TIF_SIGPENDING)) |
107 | do_signal(); | 121 | do_signal(); |
108 | if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) | ||
109 | tracehook_notify_resume(¤t->thread.regs); | ||
110 | } | 122 | } |
111 | 123 | ||
112 | void exit_thread(void) | 124 | void exit_thread(void) |
113 | { | 125 | { |
114 | } | 126 | } |
115 | 127 | ||
116 | int get_current_pid(void) | 128 | void *get_current(void) |
117 | { | 129 | { |
118 | return task_pid_nr(current); | 130 | return current; |
119 | } | 131 | } |
120 | 132 | ||
121 | /* | 133 | /* |
@@ -135,10 +147,16 @@ void new_thread_handler(void) | |||
135 | arg = current->thread.request.u.thread.arg; | 147 | arg = current->thread.request.u.thread.arg; |
136 | 148 | ||
137 | /* | 149 | /* |
138 | * callback returns only if the kernel thread execs a process | 150 | * The return value is 1 if the kernel thread execs a process, |
151 | * 0 if it just exits | ||
139 | */ | 152 | */ |
140 | n = fn(arg); | 153 | n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); |
141 | userspace(¤t->thread.regs.regs); | 154 | if (n == 1) { |
155 | /* Handle any immediate reschedules or signals */ | ||
156 | interrupt_end(); | ||
157 | userspace(¤t->thread.regs.regs); | ||
158 | } | ||
159 | else do_exit(0); | ||
142 | } | 160 | } |
143 | 161 | ||
144 | /* Called magically, see new_thread_handler above */ | 162 | /* Called magically, see new_thread_handler above */ |
@@ -157,38 +175,41 @@ void fork_handler(void) | |||
157 | 175 | ||
158 | current->thread.prev_sched = NULL; | 176 | current->thread.prev_sched = NULL; |
159 | 177 | ||
178 | /* Handle any immediate reschedules or signals */ | ||
179 | interrupt_end(); | ||
180 | |||
160 | userspace(¤t->thread.regs.regs); | 181 | userspace(¤t->thread.regs.regs); |
161 | } | 182 | } |
162 | 183 | ||
163 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 184 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
164 | unsigned long arg, struct task_struct * p) | 185 | unsigned long stack_top, struct task_struct * p, |
186 | struct pt_regs *regs) | ||
165 | { | 187 | { |
166 | void (*handler)(void); | 188 | void (*handler)(void); |
167 | int kthread = current->flags & PF_KTHREAD; | ||
168 | int ret = 0; | 189 | int ret = 0; |
169 | 190 | ||
170 | p->thread = (struct thread_struct) INIT_THREAD; | 191 | p->thread = (struct thread_struct) INIT_THREAD; |
171 | 192 | ||
172 | if (!kthread) { | 193 | if (current->thread.forking) { |
173 | memcpy(&p->thread.regs.regs, current_pt_regs(), | 194 | memcpy(&p->thread.regs.regs, ®s->regs, |
174 | sizeof(p->thread.regs.regs)); | 195 | sizeof(p->thread.regs.regs)); |
175 | PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0); | 196 | REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.gp, 0); |
176 | if (sp != 0) | 197 | if (sp != 0) |
177 | REGS_SP(p->thread.regs.regs.gp) = sp; | 198 | REGS_SP(p->thread.regs.regs.gp) = sp; |
178 | 199 | ||
179 | handler = fork_handler; | 200 | handler = fork_handler; |
180 | 201 | ||
181 | arch_copy_thread(¤t->thread.arch, &p->thread.arch); | 202 | arch_copy_thread(¤t->thread.arch, &p->thread.arch); |
182 | } else { | 203 | } |
204 | else { | ||
183 | get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp); | 205 | get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp); |
184 | p->thread.request.u.thread.proc = (int (*)(void *))sp; | 206 | p->thread.request.u.thread = current->thread.request.u.thread; |
185 | p->thread.request.u.thread.arg = (void *)arg; | ||
186 | handler = new_thread_handler; | 207 | handler = new_thread_handler; |
187 | } | 208 | } |
188 | 209 | ||
189 | new_thread(task_stack_page(p), &p->thread.switch_buf, handler); | 210 | new_thread(task_stack_page(p), &p->thread.switch_buf, handler); |
190 | 211 | ||
191 | if (!kthread) { | 212 | if (current->thread.forking) { |
192 | clear_flushed_tls(p); | 213 | clear_flushed_tls(p); |
193 | 214 | ||
194 | /* | 215 | /* |
@@ -224,12 +245,10 @@ void default_idle(void) | |||
224 | if (need_resched()) | 245 | if (need_resched()) |
225 | schedule(); | 246 | schedule(); |
226 | 247 | ||
227 | tick_nohz_idle_enter(); | 248 | tick_nohz_stop_sched_tick(1); |
228 | rcu_idle_enter(); | ||
229 | nsecs = disable_timer(); | 249 | nsecs = disable_timer(); |
230 | idle_sleep(nsecs); | 250 | idle_sleep(nsecs); |
231 | rcu_idle_exit(); | 251 | tick_nohz_restart_sched_tick(); |
232 | tick_nohz_idle_exit(); | ||
233 | } | 252 | } |
234 | } | 253 | } |
235 | 254 | ||
@@ -267,7 +286,6 @@ char *uml_strdup(const char *string) | |||
267 | { | 286 | { |
268 | return kstrdup(string, GFP_KERNEL); | 287 | return kstrdup(string, GFP_KERNEL); |
269 | } | 288 | } |
270 | EXPORT_SYMBOL(uml_strdup); | ||
271 | 289 | ||
272 | int copy_to_user_proc(void __user *to, void *from, int size) | 290 | int copy_to_user_proc(void __user *to, void *from, int size) |
273 | { | 291 | { |
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 694d551c889..c9da32b0c70 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c | |||
@@ -3,12 +3,11 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/audit.h> | 6 | #include "linux/audit.h" |
7 | #include <linux/ptrace.h> | 7 | #include "linux/ptrace.h" |
8 | #include <linux/sched.h> | 8 | #include "linux/sched.h" |
9 | #include <linux/tracehook.h> | 9 | #include "asm/uaccess.h" |
10 | #include <asm/uaccess.h> | 10 | #include "skas_ptrace.h" |
11 | #include <skas_ptrace.h> | ||
12 | 11 | ||
13 | 12 | ||
14 | 13 | ||
@@ -163,36 +162,50 @@ static void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs, | |||
163 | * XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and | 162 | * XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and |
164 | * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check | 163 | * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check |
165 | */ | 164 | */ |
166 | void syscall_trace_enter(struct pt_regs *regs) | 165 | void syscall_trace(struct uml_pt_regs *regs, int entryexit) |
167 | { | 166 | { |
168 | audit_syscall_entry(HOST_AUDIT_ARCH, | 167 | int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit; |
169 | UPT_SYSCALL_NR(®s->regs), | 168 | int tracesysgood; |
170 | UPT_SYSCALL_ARG1(®s->regs), | 169 | |
171 | UPT_SYSCALL_ARG2(®s->regs), | 170 | if (unlikely(current->audit_context)) { |
172 | UPT_SYSCALL_ARG3(®s->regs), | 171 | if (!entryexit) |
173 | UPT_SYSCALL_ARG4(®s->regs)); | 172 | audit_syscall_entry(HOST_AUDIT_ARCH, |
174 | 173 | UPT_SYSCALL_NR(regs), | |
175 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) | 174 | UPT_SYSCALL_ARG1(regs), |
176 | return; | 175 | UPT_SYSCALL_ARG2(regs), |
177 | 176 | UPT_SYSCALL_ARG3(regs), | |
178 | tracehook_report_syscall_entry(regs); | 177 | UPT_SYSCALL_ARG4(regs)); |
179 | } | 178 | else audit_syscall_exit(AUDITSC_RESULT(UPT_SYSCALL_RET(regs)), |
180 | 179 | UPT_SYSCALL_RET(regs)); | |
181 | void syscall_trace_leave(struct pt_regs *regs) | 180 | } |
182 | { | ||
183 | int ptraced = current->ptrace; | ||
184 | |||
185 | audit_syscall_exit(regs); | ||
186 | 181 | ||
187 | /* Fake a debug trap */ | 182 | /* Fake a debug trap */ |
188 | if (ptraced & PT_DTRACE) | 183 | if (is_singlestep) |
189 | send_sigtrap(current, ®s->regs, 0); | 184 | send_sigtrap(current, regs, 0); |
190 | 185 | ||
191 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) | 186 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) |
192 | return; | 187 | return; |
193 | 188 | ||
194 | tracehook_report_syscall_exit(regs, 0); | 189 | if (!(current->ptrace & PT_PTRACED)) |
195 | /* force do_signal() --> is_syscall() */ | 190 | return; |
196 | if (ptraced & PT_PTRACED) | 191 | |
192 | /* | ||
193 | * the 0x80 provides a way for the tracing parent to distinguish | ||
194 | * between a syscall stop and SIGTRAP delivery | ||
195 | */ | ||
196 | tracesysgood = (current->ptrace & PT_TRACESYSGOOD); | ||
197 | ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0)); | ||
198 | |||
199 | if (entryexit) /* force do_signal() --> is_syscall() */ | ||
197 | set_thread_flag(TIF_SIGPENDING); | 200 | set_thread_flag(TIF_SIGPENDING); |
201 | |||
202 | /* | ||
203 | * this isn't the same as continuing with a signal, but it will do | ||
204 | * for normal use. strace only continues with a signal if the | ||
205 | * stopping signal is not SIGTRAP. -brl | ||
206 | */ | ||
207 | if (current->exit_code) { | ||
208 | send_sig(current->exit_code, current, 1); | ||
209 | current->exit_code = 0; | ||
210 | } | ||
198 | } | 211 | } |
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index ced8903921a..4d93dff6b37 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c | |||
@@ -3,13 +3,11 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/sched.h> | 6 | #include "linux/sched.h" |
7 | #include <linux/spinlock.h> | 7 | #include "linux/slab.h" |
8 | #include <linux/slab.h> | 8 | #include "kern_util.h" |
9 | #include <linux/oom.h> | 9 | #include "os.h" |
10 | #include <kern_util.h> | 10 | #include "skas.h" |
11 | #include <os.h> | ||
12 | #include <skas.h> | ||
13 | 11 | ||
14 | void (*pm_power_off)(void); | 12 | void (*pm_power_off)(void); |
15 | 13 | ||
@@ -24,18 +22,13 @@ static void kill_off_processes(void) | |||
24 | struct task_struct *p; | 22 | struct task_struct *p; |
25 | int pid; | 23 | int pid; |
26 | 24 | ||
27 | read_lock(&tasklist_lock); | ||
28 | for_each_process(p) { | 25 | for_each_process(p) { |
29 | struct task_struct *t; | 26 | if (p->mm == NULL) |
30 | |||
31 | t = find_lock_task_mm(p); | ||
32 | if (!t) | ||
33 | continue; | 27 | continue; |
34 | pid = t->mm->context.id.u.pid; | 28 | |
35 | task_unlock(t); | 29 | pid = p->mm->context.id.u.pid; |
36 | os_kill_ptraced_process(pid, 1); | 30 | os_kill_ptraced_process(pid, 1); |
37 | } | 31 | } |
38 | read_unlock(&tasklist_lock); | ||
39 | } | 32 | } |
40 | } | 33 | } |
41 | 34 | ||
diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c index b5e0cbb3438..2b272b63b51 100644 --- a/arch/um/kernel/sigio.c +++ b/arch/um/kernel/sigio.c | |||
@@ -4,9 +4,9 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/interrupt.h> | 6 | #include <linux/interrupt.h> |
7 | #include <irq_kern.h> | 7 | #include "irq_kern.h" |
8 | #include <os.h> | 8 | #include "os.h" |
9 | #include <sigio.h> | 9 | #include "sigio.h" |
10 | 10 | ||
11 | /* Protected by sigio_lock() called from write_sigio_workaround */ | 11 | /* Protected by sigio_lock() called from write_sigio_workaround */ |
12 | static int sigio_irq_fd = -1; | 12 | static int sigio_irq_fd = -1; |
@@ -25,7 +25,8 @@ int write_sigio_irq(int fd) | |||
25 | int err; | 25 | int err; |
26 | 26 | ||
27 | err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, | 27 | err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, |
28 | 0, "write sigio", NULL); | 28 | IRQF_DISABLED|IRQF_SAMPLE_RANDOM, "write sigio", |
29 | NULL); | ||
29 | if (err) { | 30 | if (err) { |
30 | printk(KERN_ERR "write_sigio_irq : um_request_irq failed, " | 31 | printk(KERN_ERR "write_sigio_irq : um_request_irq failed, " |
31 | "err = %d\n", err); | 32 | "err = %d\n", err); |
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c index 48ccf718e29..b5c094c4ade 100644 --- a/arch/um/kernel/signal.c +++ b/arch/um/kernel/signal.c | |||
@@ -9,25 +9,29 @@ | |||
9 | #include <asm/siginfo.h> | 9 | #include <asm/siginfo.h> |
10 | #include <asm/signal.h> | 10 | #include <asm/signal.h> |
11 | #include <asm/unistd.h> | 11 | #include <asm/unistd.h> |
12 | #include <frame_kern.h> | 12 | #include "frame_kern.h" |
13 | #include <kern_util.h> | 13 | #include "kern_util.h" |
14 | #include <sysdep/sigcontext.h> | ||
14 | 15 | ||
15 | EXPORT_SYMBOL(block_signals); | 16 | EXPORT_SYMBOL(block_signals); |
16 | EXPORT_SYMBOL(unblock_signals); | 17 | EXPORT_SYMBOL(unblock_signals); |
17 | 18 | ||
19 | #define _S(nr) (1<<((nr)-1)) | ||
20 | |||
21 | #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) | ||
22 | |||
18 | /* | 23 | /* |
19 | * OK, we're invoking a handler | 24 | * OK, we're invoking a handler |
20 | */ | 25 | */ |
21 | static void handle_signal(struct pt_regs *regs, unsigned long signr, | 26 | static int handle_signal(struct pt_regs *regs, unsigned long signr, |
22 | struct k_sigaction *ka, siginfo_t *info) | 27 | struct k_sigaction *ka, siginfo_t *info, |
28 | sigset_t *oldset) | ||
23 | { | 29 | { |
24 | sigset_t *oldset = sigmask_to_save(); | ||
25 | int singlestep = 0; | ||
26 | unsigned long sp; | 30 | unsigned long sp; |
27 | int err; | 31 | int err; |
28 | 32 | ||
29 | if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) | 33 | /* Always make any pending restarted system calls return -EINTR */ |
30 | singlestep = 1; | 34 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
31 | 35 | ||
32 | /* Did we come from a system call? */ | 36 | /* Did we come from a system call? */ |
33 | if (PT_REGS_SYSCALL_NR(regs) >= 0) { | 37 | if (PT_REGS_SYSCALL_NR(regs) >= 0) { |
@@ -62,22 +66,51 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr, | |||
62 | #endif | 66 | #endif |
63 | err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset); | 67 | err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset); |
64 | 68 | ||
65 | if (err) | 69 | if (err) { |
70 | spin_lock_irq(¤t->sighand->siglock); | ||
71 | current->blocked = *oldset; | ||
72 | recalc_sigpending(); | ||
73 | spin_unlock_irq(¤t->sighand->siglock); | ||
66 | force_sigsegv(signr, current); | 74 | force_sigsegv(signr, current); |
67 | else | 75 | } else { |
68 | signal_delivered(signr, info, ka, regs, singlestep); | 76 | spin_lock_irq(¤t->sighand->siglock); |
77 | sigorsets(¤t->blocked, ¤t->blocked, | ||
78 | &ka->sa.sa_mask); | ||
79 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
80 | sigaddset(¤t->blocked, signr); | ||
81 | recalc_sigpending(); | ||
82 | spin_unlock_irq(¤t->sighand->siglock); | ||
83 | } | ||
84 | |||
85 | return err; | ||
69 | } | 86 | } |
70 | 87 | ||
71 | static int kern_do_signal(struct pt_regs *regs) | 88 | static int kern_do_signal(struct pt_regs *regs) |
72 | { | 89 | { |
73 | struct k_sigaction ka_copy; | 90 | struct k_sigaction ka_copy; |
74 | siginfo_t info; | 91 | siginfo_t info; |
92 | sigset_t *oldset; | ||
75 | int sig, handled_sig = 0; | 93 | int sig, handled_sig = 0; |
76 | 94 | ||
95 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
96 | oldset = ¤t->saved_sigmask; | ||
97 | else | ||
98 | oldset = ¤t->blocked; | ||
99 | |||
77 | while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) { | 100 | while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) { |
78 | handled_sig = 1; | 101 | handled_sig = 1; |
79 | /* Whee! Actually deliver the signal. */ | 102 | /* Whee! Actually deliver the signal. */ |
80 | handle_signal(regs, sig, &ka_copy, &info); | 103 | if (!handle_signal(regs, sig, &ka_copy, &info, oldset)) { |
104 | /* | ||
105 | * a signal was successfully delivered; the saved | ||
106 | * sigmask will have been stored in the signal frame, | ||
107 | * and will be restored by sigreturn, so we can simply | ||
108 | * clear the TIF_RESTORE_SIGMASK flag | ||
109 | */ | ||
110 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
111 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
112 | break; | ||
113 | } | ||
81 | } | 114 | } |
82 | 115 | ||
83 | /* Did we come from a system call? */ | 116 | /* Did we come from a system call? */ |
@@ -113,8 +146,10 @@ static int kern_do_signal(struct pt_regs *regs) | |||
113 | * if there's no signal to deliver, we just put the saved sigmask | 146 | * if there's no signal to deliver, we just put the saved sigmask |
114 | * back | 147 | * back |
115 | */ | 148 | */ |
116 | if (!handled_sig) | 149 | if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) { |
117 | restore_saved_sigmask(); | 150 | clear_thread_flag(TIF_RESTORE_SIGMASK); |
151 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
152 | } | ||
118 | return handled_sig; | 153 | return handled_sig; |
119 | } | 154 | } |
120 | 155 | ||
@@ -128,7 +163,20 @@ int do_signal(void) | |||
128 | */ | 163 | */ |
129 | long sys_sigsuspend(int history0, int history1, old_sigset_t mask) | 164 | long sys_sigsuspend(int history0, int history1, old_sigset_t mask) |
130 | { | 165 | { |
131 | sigset_t blocked; | 166 | mask &= _BLOCKABLE; |
132 | siginitset(&blocked, mask); | 167 | spin_lock_irq(¤t->sighand->siglock); |
133 | return sigsuspend(&blocked); | 168 | current->saved_sigmask = current->blocked; |
169 | siginitset(¤t->blocked, mask); | ||
170 | recalc_sigpending(); | ||
171 | spin_unlock_irq(¤t->sighand->siglock); | ||
172 | |||
173 | current->state = TASK_INTERRUPTIBLE; | ||
174 | schedule(); | ||
175 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
176 | return -ERESTARTNOHAND; | ||
177 | } | ||
178 | |||
179 | long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) | ||
180 | { | ||
181 | return do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs)); | ||
134 | } | 182 | } |
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c index 289771dadf8..2c8583c1a34 100644 --- a/arch/um/kernel/skas/clone.c +++ b/arch/um/kernel/skas/clone.c | |||
@@ -7,10 +7,11 @@ | |||
7 | #include <sched.h> | 7 | #include <sched.h> |
8 | #include <asm/unistd.h> | 8 | #include <asm/unistd.h> |
9 | #include <sys/time.h> | 9 | #include <sys/time.h> |
10 | #include <as-layout.h> | 10 | #include "as-layout.h" |
11 | #include <ptrace_user.h> | 11 | #include "kern_constants.h" |
12 | #include <stub-data.h> | 12 | #include "ptrace_user.h" |
13 | #include <sysdep/stub.h> | 13 | #include "stub-data.h" |
14 | #include "sysdep/stub.h" | ||
14 | 15 | ||
15 | /* | 16 | /* |
16 | * This is in a separate file because it needs to be compiled with any | 17 | * This is in a separate file because it needs to be compiled with any |
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index ff03067a3b1..1aee587e9c5 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c | |||
@@ -3,14 +3,14 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/mm.h> | 6 | #include "linux/mm.h" |
7 | #include <linux/sched.h> | 7 | #include "linux/sched.h" |
8 | #include <linux/slab.h> | 8 | #include "linux/slab.h" |
9 | #include <asm/pgalloc.h> | 9 | #include "asm/pgalloc.h" |
10 | #include <asm/pgtable.h> | 10 | #include "asm/pgtable.h" |
11 | #include <as-layout.h> | 11 | #include "as-layout.h" |
12 | #include <os.h> | 12 | #include "os.h" |
13 | #include <skas.h> | 13 | #include "skas.h" |
14 | 14 | ||
15 | extern int __syscall_stub_start; | 15 | extern int __syscall_stub_start; |
16 | 16 | ||
@@ -92,6 +92,8 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm) | |||
92 | goto out_free; | 92 | goto out_free; |
93 | } | 93 | } |
94 | 94 | ||
95 | to_mm->stub_pages = NULL; | ||
96 | |||
95 | return 0; | 97 | return 0; |
96 | 98 | ||
97 | out_free: | 99 | out_free: |
@@ -101,8 +103,9 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm) | |||
101 | return ret; | 103 | return ret; |
102 | } | 104 | } |
103 | 105 | ||
104 | void uml_setup_stubs(struct mm_struct *mm) | 106 | void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm) |
105 | { | 107 | { |
108 | struct page **pages; | ||
106 | int err, ret; | 109 | int err, ret; |
107 | 110 | ||
108 | if (!skas_needs_stub) | 111 | if (!skas_needs_stub) |
@@ -117,20 +120,29 @@ void uml_setup_stubs(struct mm_struct *mm) | |||
117 | if (ret) | 120 | if (ret) |
118 | goto out; | 121 | goto out; |
119 | 122 | ||
120 | mm->context.stub_pages[0] = virt_to_page(&__syscall_stub_start); | 123 | pages = kmalloc(2 * sizeof(struct page *), GFP_KERNEL); |
121 | mm->context.stub_pages[1] = virt_to_page(mm->context.id.stack); | 124 | if (pages == NULL) { |
125 | printk(KERN_ERR "arch_dup_mmap failed to allocate 2 page " | ||
126 | "pointers\n"); | ||
127 | goto out; | ||
128 | } | ||
129 | |||
130 | pages[0] = virt_to_page(&__syscall_stub_start); | ||
131 | pages[1] = virt_to_page(mm->context.id.stack); | ||
132 | mm->context.stub_pages = pages; | ||
122 | 133 | ||
123 | /* dup_mmap already holds mmap_sem */ | 134 | /* dup_mmap already holds mmap_sem */ |
124 | err = install_special_mapping(mm, STUB_START, STUB_END - STUB_START, | 135 | err = install_special_mapping(mm, STUB_START, STUB_END - STUB_START, |
125 | VM_READ | VM_MAYREAD | VM_EXEC | | 136 | VM_READ | VM_MAYREAD | VM_EXEC | |
126 | VM_MAYEXEC | VM_DONTCOPY, | 137 | VM_MAYEXEC | VM_DONTCOPY, pages); |
127 | mm->context.stub_pages); | ||
128 | if (err) { | 138 | if (err) { |
129 | printk(KERN_ERR "install_special_mapping returned %d\n", err); | 139 | printk(KERN_ERR "install_special_mapping returned %d\n", err); |
130 | goto out; | 140 | goto out_free; |
131 | } | 141 | } |
132 | return; | 142 | return; |
133 | 143 | ||
144 | out_free: | ||
145 | kfree(pages); | ||
134 | out: | 146 | out: |
135 | force_sigsegv(SIGSEGV, current); | 147 | force_sigsegv(SIGSEGV, current); |
136 | } | 148 | } |
@@ -139,6 +151,8 @@ void arch_exit_mmap(struct mm_struct *mm) | |||
139 | { | 151 | { |
140 | pte_t *pte; | 152 | pte_t *pte; |
141 | 153 | ||
154 | if (mm->context.stub_pages != NULL) | ||
155 | kfree(mm->context.stub_pages); | ||
142 | pte = virt_to_pte(mm, STUB_CODE); | 156 | pte = virt_to_pte(mm, STUB_CODE); |
143 | if (pte != NULL) | 157 | if (pte != NULL) |
144 | pte_clear(mm, STUB_CODE, pte); | 158 | pte_clear(mm, STUB_CODE, pte); |
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 4da11b3c8dd..2e9852c0d48 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c | |||
@@ -3,12 +3,12 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/init.h> | 6 | #include "linux/init.h" |
7 | #include <linux/sched.h> | 7 | #include "linux/sched.h" |
8 | #include <as-layout.h> | 8 | #include "as-layout.h" |
9 | #include <kern.h> | 9 | #include "kern.h" |
10 | #include <os.h> | 10 | #include "os.h" |
11 | #include <skas.h> | 11 | #include "skas.h" |
12 | 12 | ||
13 | int new_mm(unsigned long stack) | 13 | int new_mm(unsigned long stack) |
14 | { | 14 | { |
@@ -41,7 +41,7 @@ static int __init start_kernel_proc(void *unused) | |||
41 | cpu_tasks[0].pid = pid; | 41 | cpu_tasks[0].pid = pid; |
42 | cpu_tasks[0].task = current; | 42 | cpu_tasks[0].task = current; |
43 | #ifdef CONFIG_SMP | 43 | #ifdef CONFIG_SMP |
44 | init_cpu_online(get_cpu_mask(0)); | 44 | cpu_online_map = cpumask_of_cpu(0); |
45 | #endif | 45 | #endif |
46 | start_kernel(); | 46 | start_kernel(); |
47 | return 0; | 47 | return 0; |
diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c index c0681e09743..f5173e1ec3a 100644 --- a/arch/um/kernel/skas/syscall.c +++ b/arch/um/kernel/skas/syscall.c | |||
@@ -3,11 +3,11 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/kernel.h> | 6 | #include "linux/kernel.h" |
7 | #include <linux/ptrace.h> | 7 | #include "linux/ptrace.h" |
8 | #include <kern_util.h> | 8 | #include "kern_util.h" |
9 | #include <sysdep/ptrace.h> | 9 | #include "sysdep/ptrace.h" |
10 | #include <sysdep/syscalls.h> | 10 | #include "sysdep/syscalls.h" |
11 | 11 | ||
12 | extern int syscall_table_size; | 12 | extern int syscall_table_size; |
13 | #define NR_SYSCALLS (syscall_table_size / sizeof(void *)) | 13 | #define NR_SYSCALLS (syscall_table_size / sizeof(void *)) |
@@ -18,7 +18,7 @@ void handle_syscall(struct uml_pt_regs *r) | |||
18 | long result; | 18 | long result; |
19 | int syscall; | 19 | int syscall; |
20 | 20 | ||
21 | syscall_trace_enter(regs); | 21 | syscall_trace(r, 0); |
22 | 22 | ||
23 | /* | 23 | /* |
24 | * This should go in the declaration of syscall, but when I do that, | 24 | * This should go in the declaration of syscall, but when I do that, |
@@ -34,7 +34,7 @@ void handle_syscall(struct uml_pt_regs *r) | |||
34 | result = -ENOSYS; | 34 | result = -ENOSYS; |
35 | else result = EXECUTE_SYSCALL(syscall, regs); | 35 | else result = EXECUTE_SYSCALL(syscall, regs); |
36 | 36 | ||
37 | PT_REGS_SET_SYSCALL_RETURN(regs, result); | 37 | REGS_SET_SYSCALL_RETURN(r->gp, result); |
38 | 38 | ||
39 | syscall_trace_leave(regs); | 39 | syscall_trace(r, 1); |
40 | } | 40 | } |
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index 1d3e0c17340..696634214dc 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c | |||
@@ -6,13 +6,12 @@ | |||
6 | #include <linux/err.h> | 6 | #include <linux/err.h> |
7 | #include <linux/highmem.h> | 7 | #include <linux/highmem.h> |
8 | #include <linux/mm.h> | 8 | #include <linux/mm.h> |
9 | #include <linux/module.h> | ||
10 | #include <linux/sched.h> | 9 | #include <linux/sched.h> |
11 | #include <asm/current.h> | 10 | #include <asm/current.h> |
12 | #include <asm/page.h> | 11 | #include <asm/page.h> |
13 | #include <asm/pgtable.h> | 12 | #include <asm/pgtable.h> |
14 | #include <kern_util.h> | 13 | #include "kern_util.h" |
15 | #include <os.h> | 14 | #include "os.h" |
16 | 15 | ||
17 | pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr) | 16 | pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr) |
18 | { | 17 | { |
@@ -69,7 +68,7 @@ static int do_op_one_page(unsigned long addr, int len, int is_write, | |||
69 | return -1; | 68 | return -1; |
70 | 69 | ||
71 | page = pte_page(*pte); | 70 | page = pte_page(*pte); |
72 | addr = (unsigned long) kmap_atomic(page) + | 71 | addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) + |
73 | (addr & ~PAGE_MASK); | 72 | (addr & ~PAGE_MASK); |
74 | 73 | ||
75 | current->thread.fault_catcher = &buf; | 74 | current->thread.fault_catcher = &buf; |
@@ -82,7 +81,7 @@ static int do_op_one_page(unsigned long addr, int len, int is_write, | |||
82 | 81 | ||
83 | current->thread.fault_catcher = NULL; | 82 | current->thread.fault_catcher = NULL; |
84 | 83 | ||
85 | kunmap_atomic((void *)addr); | 84 | kunmap_atomic((void *)addr, KM_UML_USERCOPY); |
86 | 85 | ||
87 | return n; | 86 | return n; |
88 | } | 87 | } |
@@ -150,7 +149,6 @@ int copy_from_user(void *to, const void __user *from, int n) | |||
150 | buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): | 149 | buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): |
151 | n; | 150 | n; |
152 | } | 151 | } |
153 | EXPORT_SYMBOL(copy_from_user); | ||
154 | 152 | ||
155 | static int copy_chunk_to_user(unsigned long to, int len, void *arg) | 153 | static int copy_chunk_to_user(unsigned long to, int len, void *arg) |
156 | { | 154 | { |
@@ -172,7 +170,6 @@ int copy_to_user(void __user *to, const void *from, int n) | |||
172 | buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : | 170 | buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : |
173 | n; | 171 | n; |
174 | } | 172 | } |
175 | EXPORT_SYMBOL(copy_to_user); | ||
176 | 173 | ||
177 | static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) | 174 | static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) |
178 | { | 175 | { |
@@ -207,7 +204,6 @@ int strncpy_from_user(char *dst, const char __user *src, int count) | |||
207 | return -EFAULT; | 204 | return -EFAULT; |
208 | return strnlen(dst, count); | 205 | return strnlen(dst, count); |
209 | } | 206 | } |
210 | EXPORT_SYMBOL(strncpy_from_user); | ||
211 | 207 | ||
212 | static int clear_chunk(unsigned long addr, int len, void *unused) | 208 | static int clear_chunk(unsigned long addr, int len, void *unused) |
213 | { | 209 | { |
@@ -230,7 +226,6 @@ int clear_user(void __user *mem, int len) | |||
230 | return access_ok(VERIFY_WRITE, mem, len) ? | 226 | return access_ok(VERIFY_WRITE, mem, len) ? |
231 | buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len; | 227 | buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len; |
232 | } | 228 | } |
233 | EXPORT_SYMBOL(clear_user); | ||
234 | 229 | ||
235 | static int strnlen_chunk(unsigned long str, int len, void *arg) | 230 | static int strnlen_chunk(unsigned long str, int len, void *arg) |
236 | { | 231 | { |
@@ -256,4 +251,3 @@ int strnlen_user(const void __user *str, int len) | |||
256 | return count + 1; | 251 | return count + 1; |
257 | return -EFAULT; | 252 | return -EFAULT; |
258 | } | 253 | } |
259 | EXPORT_SYMBOL(strnlen_user); | ||
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c index 5c8c3ea7db7..155206a6690 100644 --- a/arch/um/kernel/smp.c +++ b/arch/um/kernel/smp.c | |||
@@ -3,24 +3,24 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/percpu.h> | 6 | #include "linux/percpu.h" |
7 | #include <asm/pgalloc.h> | 7 | #include "asm/pgalloc.h" |
8 | #include <asm/tlb.h> | 8 | #include "asm/tlb.h" |
9 | 9 | ||
10 | #ifdef CONFIG_SMP | 10 | #ifdef CONFIG_SMP |
11 | 11 | ||
12 | #include <linux/sched.h> | 12 | #include "linux/sched.h" |
13 | #include <linux/module.h> | 13 | #include "linux/module.h" |
14 | #include <linux/threads.h> | 14 | #include "linux/threads.h" |
15 | #include <linux/interrupt.h> | 15 | #include "linux/interrupt.h" |
16 | #include <linux/err.h> | 16 | #include "linux/err.h" |
17 | #include <linux/hardirq.h> | 17 | #include "linux/hardirq.h" |
18 | #include <asm/smp.h> | 18 | #include "asm/smp.h" |
19 | #include <asm/processor.h> | 19 | #include "asm/processor.h" |
20 | #include <asm/spinlock.h> | 20 | #include "asm/spinlock.h" |
21 | #include <kern.h> | 21 | #include "kern.h" |
22 | #include <irq_user.h> | 22 | #include "irq_user.h" |
23 | #include <os.h> | 23 | #include "os.h" |
24 | 24 | ||
25 | /* Per CPU bogomips and other parameters | 25 | /* Per CPU bogomips and other parameters |
26 | * The only piece used here is the ipi pipe, which is set before SMP is | 26 | * The only piece used here is the ipi pipe, which is set before SMP is |
@@ -76,7 +76,7 @@ static int idle_proc(void *cpup) | |||
76 | cpu_relax(); | 76 | cpu_relax(); |
77 | 77 | ||
78 | notify_cpu_starting(cpu); | 78 | notify_cpu_starting(cpu); |
79 | set_cpu_online(cpu, true); | 79 | cpu_set(cpu, cpu_online_map); |
80 | default_idle(); | 80 | default_idle(); |
81 | return 0; | 81 | return 0; |
82 | } | 82 | } |
@@ -110,7 +110,8 @@ void smp_prepare_cpus(unsigned int maxcpus) | |||
110 | for (i = 0; i < ncpus; ++i) | 110 | for (i = 0; i < ncpus; ++i) |
111 | set_cpu_possible(i, true); | 111 | set_cpu_possible(i, true); |
112 | 112 | ||
113 | set_cpu_online(me, true); | 113 | cpu_clear(me, cpu_online_map); |
114 | cpu_set(me, cpu_online_map); | ||
114 | cpu_set(me, cpu_callin_map); | 115 | cpu_set(me, cpu_callin_map); |
115 | 116 | ||
116 | err = os_pipe(cpu_data[me].ipi_pipe, 1, 1); | 117 | err = os_pipe(cpu_data[me].ipi_pipe, 1, 1); |
@@ -137,13 +138,13 @@ void smp_prepare_cpus(unsigned int maxcpus) | |||
137 | 138 | ||
138 | void smp_prepare_boot_cpu(void) | 139 | void smp_prepare_boot_cpu(void) |
139 | { | 140 | { |
140 | set_cpu_online(smp_processor_id(), true); | 141 | cpu_set(smp_processor_id(), cpu_online_map); |
141 | } | 142 | } |
142 | 143 | ||
143 | int __cpu_up(unsigned int cpu, struct task_struct *tidle) | 144 | int __cpu_up(unsigned int cpu) |
144 | { | 145 | { |
145 | cpu_set(cpu, smp_commenced_mask); | 146 | cpu_set(cpu, smp_commenced_mask); |
146 | while (!cpu_online(cpu)) | 147 | while (!cpu_isset(cpu, cpu_online_map)) |
147 | mb(); | 148 | mb(); |
148 | return 0; | 149 | return 0; |
149 | } | 150 | } |
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index c1d0ae069b5..f958cb876ee 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c | |||
@@ -3,16 +3,40 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/file.h> | 6 | #include "linux/file.h" |
7 | #include <linux/fs.h> | 7 | #include "linux/fs.h" |
8 | #include <linux/mm.h> | 8 | #include "linux/mm.h" |
9 | #include <linux/sched.h> | 9 | #include "linux/sched.h" |
10 | #include <linux/utsname.h> | 10 | #include "linux/utsname.h" |
11 | #include <linux/syscalls.h> | 11 | #include "linux/syscalls.h" |
12 | #include <asm/current.h> | 12 | #include "asm/current.h" |
13 | #include <asm/mman.h> | 13 | #include "asm/mman.h" |
14 | #include <asm/uaccess.h> | 14 | #include "asm/uaccess.h" |
15 | #include <asm/unistd.h> | 15 | #include "asm/unistd.h" |
16 | #include "internal.h" | ||
17 | |||
18 | long sys_fork(void) | ||
19 | { | ||
20 | long ret; | ||
21 | |||
22 | current->thread.forking = 1; | ||
23 | ret = do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), | ||
24 | ¤t->thread.regs, 0, NULL, NULL); | ||
25 | current->thread.forking = 0; | ||
26 | return ret; | ||
27 | } | ||
28 | |||
29 | long sys_vfork(void) | ||
30 | { | ||
31 | long ret; | ||
32 | |||
33 | current->thread.forking = 1; | ||
34 | ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, | ||
35 | UPT_SP(¤t->thread.regs.regs), | ||
36 | ¤t->thread.regs, 0, NULL, NULL); | ||
37 | current->thread.forking = 0; | ||
38 | return ret; | ||
39 | } | ||
16 | 40 | ||
17 | long old_mmap(unsigned long addr, unsigned long len, | 41 | long old_mmap(unsigned long addr, unsigned long len, |
18 | unsigned long prot, unsigned long flags, | 42 | unsigned long prot, unsigned long flags, |
@@ -26,3 +50,19 @@ long old_mmap(unsigned long addr, unsigned long len, | |||
26 | out: | 50 | out: |
27 | return err; | 51 | return err; |
28 | } | 52 | } |
53 | |||
54 | int kernel_execve(const char *filename, | ||
55 | const char *const argv[], | ||
56 | const char *const envp[]) | ||
57 | { | ||
58 | mm_segment_t fs; | ||
59 | int ret; | ||
60 | |||
61 | fs = get_fs(); | ||
62 | set_fs(KERNEL_DS); | ||
63 | ret = um_execve(filename, (const char __user *const __user *)argv, | ||
64 | (const char __user *const __user *) envp); | ||
65 | set_fs(fs); | ||
66 | |||
67 | return ret; | ||
68 | } | ||
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index e562ff80409..0960de54495 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c | |||
@@ -7,7 +7,7 @@ | |||
7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <linux/sched.h> | 9 | #include <linux/sched.h> |
10 | #include <asm/sysrq.h> | 10 | #include "sysrq.h" |
11 | 11 | ||
12 | /* Catch non-i386 SUBARCH's. */ | 12 | /* Catch non-i386 SUBARCH's. */ |
13 | #if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT) | 13 | #if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT) |
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index 117568d4f64..a08d9fab81f 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c | |||
@@ -10,10 +10,10 @@ | |||
10 | #include <linux/threads.h> | 10 | #include <linux/threads.h> |
11 | #include <asm/irq.h> | 11 | #include <asm/irq.h> |
12 | #include <asm/param.h> | 12 | #include <asm/param.h> |
13 | #include <kern_util.h> | 13 | #include "kern_util.h" |
14 | #include <os.h> | 14 | #include "os.h" |
15 | 15 | ||
16 | void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) | 16 | void timer_handler(int sig, struct uml_pt_regs *regs) |
17 | { | 17 | { |
18 | unsigned long flags; | 18 | unsigned long flags; |
19 | 19 | ||
@@ -75,6 +75,8 @@ static struct clocksource itimer_clocksource = { | |||
75 | .rating = 300, | 75 | .rating = 300, |
76 | .read = itimer_read, | 76 | .read = itimer_read, |
77 | .mask = CLOCKSOURCE_MASK(64), | 77 | .mask = CLOCKSOURCE_MASK(64), |
78 | .mult = 1000, | ||
79 | .shift = 0, | ||
78 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 80 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
79 | }; | 81 | }; |
80 | 82 | ||
@@ -82,7 +84,7 @@ static void __init setup_itimer(void) | |||
82 | { | 84 | { |
83 | int err; | 85 | int err; |
84 | 86 | ||
85 | err = request_irq(TIMER_IRQ, um_timer, 0, "timer", NULL); | 87 | err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL); |
86 | if (err != 0) | 88 | if (err != 0) |
87 | printk(KERN_ERR "register_timer : request_irq failed - " | 89 | printk(KERN_ERR "register_timer : request_irq failed - " |
88 | "errno = %d\n", -err); | 90 | "errno = %d\n", -err); |
@@ -92,9 +94,9 @@ static void __init setup_itimer(void) | |||
92 | clockevent_delta2ns(60 * HZ, &itimer_clockevent); | 94 | clockevent_delta2ns(60 * HZ, &itimer_clockevent); |
93 | itimer_clockevent.min_delta_ns = | 95 | itimer_clockevent.min_delta_ns = |
94 | clockevent_delta2ns(1, &itimer_clockevent); | 96 | clockevent_delta2ns(1, &itimer_clockevent); |
95 | err = clocksource_register_hz(&itimer_clocksource, USEC_PER_SEC); | 97 | err = clocksource_register(&itimer_clocksource); |
96 | if (err) { | 98 | if (err) { |
97 | printk(KERN_ERR "clocksource_register_hz returned %d\n", err); | 99 | printk(KERN_ERR "clocksource_register returned %d\n", err); |
98 | return; | 100 | return; |
99 | } | 101 | } |
100 | clockevents_register_device(&itimer_clockevent); | 102 | clockevents_register_device(&itimer_clockevent); |
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index 9472079471b..d175d0566af 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c | |||
@@ -4,14 +4,14 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/mm.h> | 6 | #include <linux/mm.h> |
7 | #include <linux/module.h> | ||
8 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
9 | #include <asm/pgtable.h> | 8 | #include <asm/pgtable.h> |
10 | #include <asm/tlbflush.h> | 9 | #include <asm/tlbflush.h> |
11 | #include <as-layout.h> | 10 | #include "as-layout.h" |
12 | #include <mem_user.h> | 11 | #include "mem_user.h" |
13 | #include <os.h> | 12 | #include "os.h" |
14 | #include <skas.h> | 13 | #include "skas.h" |
14 | #include "tlb.h" | ||
15 | 15 | ||
16 | struct host_vm_change { | 16 | struct host_vm_change { |
17 | struct host_vm_op { | 17 | struct host_vm_op { |
@@ -75,7 +75,6 @@ static int do_ops(struct host_vm_change *hvc, int end, | |||
75 | default: | 75 | default: |
76 | printk(KERN_ERR "Unknown op type %d in do_ops\n", | 76 | printk(KERN_ERR "Unknown op type %d in do_ops\n", |
77 | op->type); | 77 | op->type); |
78 | BUG(); | ||
79 | break; | 78 | break; |
80 | } | 79 | } |
81 | } | 80 | } |
@@ -288,7 +287,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr, | |||
288 | } | 287 | } |
289 | } | 288 | } |
290 | 289 | ||
291 | static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) | 290 | int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) |
292 | { | 291 | { |
293 | struct mm_struct *mm; | 292 | struct mm_struct *mm; |
294 | pgd_t *pgd; | 293 | pgd_t *pgd; |
@@ -500,7 +499,6 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | |||
500 | flush_tlb_kernel_range_common(start, end); | 499 | flush_tlb_kernel_range_common(start, end); |
501 | else fix_range(vma->vm_mm, start, end, 0); | 500 | else fix_range(vma->vm_mm, start, end, 0); |
502 | } | 501 | } |
503 | EXPORT_SYMBOL(flush_tlb_range); | ||
504 | 502 | ||
505 | void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, | 503 | void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, |
506 | unsigned long end) | 504 | unsigned long end) |
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index 089f3987e27..8c7b8823d1f 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c | |||
@@ -6,15 +6,15 @@ | |||
6 | #include <linux/mm.h> | 6 | #include <linux/mm.h> |
7 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
8 | #include <linux/hardirq.h> | 8 | #include <linux/hardirq.h> |
9 | #include <linux/module.h> | ||
10 | #include <asm/current.h> | 9 | #include <asm/current.h> |
11 | #include <asm/pgtable.h> | 10 | #include <asm/pgtable.h> |
12 | #include <asm/tlbflush.h> | 11 | #include <asm/tlbflush.h> |
13 | #include <arch.h> | 12 | #include "arch.h" |
14 | #include <as-layout.h> | 13 | #include "as-layout.h" |
15 | #include <kern_util.h> | 14 | #include "kern_util.h" |
16 | #include <os.h> | 15 | #include "os.h" |
17 | #include <skas.h> | 16 | #include "skas.h" |
17 | #include "sysdep/sigcontext.h" | ||
18 | 18 | ||
19 | /* | 19 | /* |
20 | * Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by | 20 | * Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by |
@@ -30,8 +30,6 @@ int handle_page_fault(unsigned long address, unsigned long ip, | |||
30 | pmd_t *pmd; | 30 | pmd_t *pmd; |
31 | pte_t *pte; | 31 | pte_t *pte; |
32 | int err = -EFAULT; | 32 | int err = -EFAULT; |
33 | unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | | ||
34 | (is_write ? FAULT_FLAG_WRITE : 0); | ||
35 | 33 | ||
36 | *code_out = SEGV_MAPERR; | 34 | *code_out = SEGV_MAPERR; |
37 | 35 | ||
@@ -42,7 +40,6 @@ int handle_page_fault(unsigned long address, unsigned long ip, | |||
42 | if (in_atomic()) | 40 | if (in_atomic()) |
43 | goto out_nosemaphore; | 41 | goto out_nosemaphore; |
44 | 42 | ||
45 | retry: | ||
46 | down_read(&mm->mmap_sem); | 43 | down_read(&mm->mmap_sem); |
47 | vma = find_vma(mm, address); | 44 | vma = find_vma(mm, address); |
48 | if (!vma) | 45 | if (!vma) |
@@ -68,11 +65,7 @@ good_area: | |||
68 | do { | 65 | do { |
69 | int fault; | 66 | int fault; |
70 | 67 | ||
71 | fault = handle_mm_fault(mm, vma, address, flags); | 68 | fault = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0); |
72 | |||
73 | if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) | ||
74 | goto out_nosemaphore; | ||
75 | |||
76 | if (unlikely(fault & VM_FAULT_ERROR)) { | 69 | if (unlikely(fault & VM_FAULT_ERROR)) { |
77 | if (fault & VM_FAULT_OOM) { | 70 | if (fault & VM_FAULT_OOM) { |
78 | goto out_of_memory; | 71 | goto out_of_memory; |
@@ -82,18 +75,10 @@ good_area: | |||
82 | } | 75 | } |
83 | BUG(); | 76 | BUG(); |
84 | } | 77 | } |
85 | if (flags & FAULT_FLAG_ALLOW_RETRY) { | 78 | if (fault & VM_FAULT_MAJOR) |
86 | if (fault & VM_FAULT_MAJOR) | 79 | current->maj_flt++; |
87 | current->maj_flt++; | 80 | else |
88 | else | 81 | current->min_flt++; |
89 | current->min_flt++; | ||
90 | if (fault & VM_FAULT_RETRY) { | ||
91 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | ||
92 | flags |= FAULT_FLAG_TRIED; | ||
93 | |||
94 | goto retry; | ||
95 | } | ||
96 | } | ||
97 | 82 | ||
98 | pgd = pgd_offset(mm, address); | 83 | pgd = pgd_offset(mm, address); |
99 | pud = pud_offset(pgd, address); | 84 | pud = pud_offset(pgd, address); |
@@ -127,7 +112,6 @@ out_of_memory: | |||
127 | pagefault_out_of_memory(); | 112 | pagefault_out_of_memory(); |
128 | return 0; | 113 | return 0; |
129 | } | 114 | } |
130 | EXPORT_SYMBOL(handle_page_fault); | ||
131 | 115 | ||
132 | static void show_segv_info(struct uml_pt_regs *regs) | 116 | static void show_segv_info(struct uml_pt_regs *regs) |
133 | { | 117 | { |
@@ -173,7 +157,7 @@ void fatal_sigsegv(void) | |||
173 | os_dump_core(); | 157 | os_dump_core(); |
174 | } | 158 | } |
175 | 159 | ||
176 | void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) | 160 | void segv_handler(int sig, struct uml_pt_regs *regs) |
177 | { | 161 | { |
178 | struct faultinfo * fi = UPT_FAULTINFO(regs); | 162 | struct faultinfo * fi = UPT_FAULTINFO(regs); |
179 | 163 | ||
@@ -259,11 +243,8 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, | |||
259 | return 0; | 243 | return 0; |
260 | } | 244 | } |
261 | 245 | ||
262 | void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs) | 246 | void relay_signal(int sig, struct uml_pt_regs *regs) |
263 | { | 247 | { |
264 | struct faultinfo *fi; | ||
265 | struct siginfo clean_si; | ||
266 | |||
267 | if (!UPT_IS_USER(regs)) { | 248 | if (!UPT_IS_USER(regs)) { |
268 | if (sig == SIGBUS) | 249 | if (sig == SIGBUS) |
269 | printk(KERN_ERR "Bus error - the host /dev/shm or /tmp " | 250 | printk(KERN_ERR "Bus error - the host /dev/shm or /tmp " |
@@ -273,40 +254,18 @@ void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs) | |||
273 | 254 | ||
274 | arch_examine_signal(sig, regs); | 255 | arch_examine_signal(sig, regs); |
275 | 256 | ||
276 | memset(&clean_si, 0, sizeof(clean_si)); | 257 | current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); |
277 | clean_si.si_signo = si->si_signo; | 258 | force_sig(sig, current); |
278 | clean_si.si_errno = si->si_errno; | ||
279 | clean_si.si_code = si->si_code; | ||
280 | switch (sig) { | ||
281 | case SIGILL: | ||
282 | case SIGFPE: | ||
283 | case SIGSEGV: | ||
284 | case SIGBUS: | ||
285 | case SIGTRAP: | ||
286 | fi = UPT_FAULTINFO(regs); | ||
287 | clean_si.si_addr = (void __user *) FAULT_ADDRESS(*fi); | ||
288 | current->thread.arch.faultinfo = *fi; | ||
289 | #ifdef __ARCH_SI_TRAPNO | ||
290 | clean_si.si_trapno = si->si_trapno; | ||
291 | #endif | ||
292 | break; | ||
293 | default: | ||
294 | printk(KERN_ERR "Attempted to relay unknown signal %d (si_code = %d)\n", | ||
295 | sig, si->si_code); | ||
296 | } | ||
297 | |||
298 | force_sig_info(sig, &clean_si, current); | ||
299 | } | 259 | } |
300 | 260 | ||
301 | void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs) | 261 | void bus_handler(int sig, struct uml_pt_regs *regs) |
302 | { | 262 | { |
303 | if (current->thread.fault_catcher != NULL) | 263 | if (current->thread.fault_catcher != NULL) |
304 | UML_LONGJMP(current->thread.fault_catcher, 1); | 264 | UML_LONGJMP(current->thread.fault_catcher, 1); |
305 | else | 265 | else relay_signal(sig, regs); |
306 | relay_signal(sig, si, regs); | ||
307 | } | 266 | } |
308 | 267 | ||
309 | void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) | 268 | void winch(int sig, struct uml_pt_regs *regs) |
310 | { | 269 | { |
311 | do_IRQ(WINCH_IRQ, regs); | 270 | do_IRQ(WINCH_IRQ, regs); |
312 | } | 271 | } |
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 87df5e3acc2..8d84250324b 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c | |||
@@ -10,17 +10,16 @@ | |||
10 | #include <linux/seq_file.h> | 10 | #include <linux/seq_file.h> |
11 | #include <linux/string.h> | 11 | #include <linux/string.h> |
12 | #include <linux/utsname.h> | 12 | #include <linux/utsname.h> |
13 | #include <linux/sched.h> | ||
14 | #include <asm/pgtable.h> | 13 | #include <asm/pgtable.h> |
15 | #include <asm/processor.h> | 14 | #include <asm/processor.h> |
16 | #include <asm/setup.h> | 15 | #include <asm/setup.h> |
17 | #include <as-layout.h> | 16 | #include "as-layout.h" |
18 | #include <arch.h> | 17 | #include "arch.h" |
19 | #include <init.h> | 18 | #include "init.h" |
20 | #include <kern.h> | 19 | #include "kern.h" |
21 | #include <kern_util.h> | 20 | #include "kern_util.h" |
22 | #include <mem_user.h> | 21 | #include "mem_user.h" |
23 | #include <os.h> | 22 | #include "os.h" |
24 | 23 | ||
25 | #define DEFAULT_COMMAND_LINE "root=98:0" | 24 | #define DEFAULT_COMMAND_LINE "root=98:0" |
26 | 25 | ||
@@ -48,10 +47,6 @@ struct cpuinfo_um boot_cpu_data = { | |||
48 | .ipi_pipe = { -1, -1 } | 47 | .ipi_pipe = { -1, -1 } |
49 | }; | 48 | }; |
50 | 49 | ||
51 | union thread_union cpu0_irqstack | ||
52 | __attribute__((__section__(".data..init_irqstack"))) = | ||
53 | { INIT_THREAD_INFO(init_task) }; | ||
54 | |||
55 | unsigned long thread_saved_pc(struct task_struct *task) | 50 | unsigned long thread_saved_pc(struct task_struct *task) |
56 | { | 51 | { |
57 | /* FIXME: Need to look up userspace_pid by cpu */ | 52 | /* FIXME: Need to look up userspace_pid by cpu */ |
@@ -107,8 +102,6 @@ const struct seq_operations cpuinfo_op = { | |||
107 | 102 | ||
108 | /* Set in linux_main */ | 103 | /* Set in linux_main */ |
109 | unsigned long uml_physmem; | 104 | unsigned long uml_physmem; |
110 | EXPORT_SYMBOL(uml_physmem); | ||
111 | |||
112 | unsigned long uml_reserved; /* Also modified in mem_init */ | 105 | unsigned long uml_reserved; /* Also modified in mem_init */ |
113 | unsigned long start_vm; | 106 | unsigned long start_vm; |
114 | unsigned long end_vm; | 107 | unsigned long end_vm; |
diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c index f6cc3bd6178..81e07e2be3a 100644 --- a/arch/um/kernel/umid.c +++ b/arch/um/kernel/umid.c | |||
@@ -4,9 +4,9 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <asm/errno.h> | 6 | #include <asm/errno.h> |
7 | #include <init.h> | 7 | #include "init.h" |
8 | #include <kern.h> | 8 | #include "kern.h" |
9 | #include <os.h> | 9 | #include "os.h" |
10 | 10 | ||
11 | /* Changed by set_umid_arg */ | 11 | /* Changed by set_umid_arg */ |
12 | static int umid_inited = 0; | 12 | static int umid_inited = 0; |
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index ff65fb4f1a9..fbd99402d4d 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S | |||
@@ -60,7 +60,7 @@ SECTIONS | |||
60 | PROVIDE_HIDDEN(__rela_iplt_end = .); | 60 | PROVIDE_HIDDEN(__rela_iplt_end = .); |
61 | } | 61 | } |
62 | 62 | ||
63 | #include <asm/common.lds.S> | 63 | #include "asm/common.lds.S" |
64 | 64 | ||
65 | init.data : { INIT_DATA } | 65 | init.data : { INIT_DATA } |
66 | .data : | 66 | .data : |