aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /arch/um/kernel
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'arch/um/kernel')
-rw-r--r--arch/um/kernel/Makefile11
-rw-r--r--arch/um/kernel/asm-offsets.c2
-rw-r--r--arch/um/kernel/config.c.in2
-rw-r--r--arch/um/kernel/dyn.lds.S2
-rw-r--r--arch/um/kernel/early_printk.c2
-rw-r--r--arch/um/kernel/exec.c72
-rw-r--r--arch/um/kernel/gmon_syms.c17
-rw-r--r--arch/um/kernel/gprof_syms.c2
-rw-r--r--arch/um/kernel/initrd.c16
-rw-r--r--arch/um/kernel/irq.c34
-rw-r--r--arch/um/kernel/ksyms.c40
-rw-r--r--arch/um/kernel/mem.c14
-rw-r--r--arch/um/kernel/physmem.c21
-rw-r--r--arch/um/kernel/process.c76
-rw-r--r--arch/um/kernel/ptrace.c73
-rw-r--r--arch/um/kernel/reboot.c23
-rw-r--r--arch/um/kernel/sigio.c9
-rw-r--r--arch/um/kernel/signal.c82
-rw-r--r--arch/um/kernel/skas/clone.c9
-rw-r--r--arch/um/kernel/skas/mmu.c42
-rw-r--r--arch/um/kernel/skas/process.c14
-rw-r--r--arch/um/kernel/skas/syscall.c16
-rw-r--r--arch/um/kernel/skas/uaccess.c14
-rw-r--r--arch/um/kernel/smp.c41
-rw-r--r--arch/um/kernel/syscall.c60
-rw-r--r--arch/um/kernel/sysrq.c2
-rw-r--r--arch/um/kernel/time.c14
-rw-r--r--arch/um/kernel/tlb.c14
-rw-r--r--arch/um/kernel/trap.c77
-rw-r--r--arch/um/kernel/um_arch.c21
-rw-r--r--arch/um/kernel/umid.c6
-rw-r--r--arch/um/kernel/uml.lds.S2
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
6CPPFLAGS_vmlinux.lds := -DSTART=$(LDS_START) \ 6CPPFLAGS_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)
10extra-y := vmlinux.lds 9extra-y := vmlinux.lds
11clean-files := 10clean-files :=
12 11
13obj-y = config.o exec.o exitcode.o irq.o ksyms.o mem.o \ 12obj-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
18obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o 17obj-$(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
10static __initdata const char *config[] = { 10static __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
14static void early_console_write(struct console *con, const char *s, unsigned int n) 14static 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
20void flush_thread(void) 20void 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(&current->mm->context.id); 36 __switch_mm(&current->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
45static 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, &current->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(&current->thread.regs.regs);
48#endif 57#endif
58 task_unlock(current);
59 }
60 return error;
61}
62
63long 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
73long 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}
50EXPORT_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
8extern void __bb_init_func(void *) __attribute__((weak)); 8extern void __bb_init_func(void *) __attribute__((weak));
9EXPORT_SYMBOL(__bb_init_func); 9EXPORT_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
20extern void __gcov_init(void *) __attribute__((weak));
21EXPORT_SYMBOL(__gcov_init);
22
23extern void __gcov_merge_add(void *) __attribute__((weak));
24EXPORT_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
8extern void mcount(void); 8extern void mcount(void);
9EXPORT_SYMBOL(mcount); 9EXPORT_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 */
14static char *initrd __initdata = NULL; 15static char *initrd __initdata = NULL;
15static int load_initrd(char *filename, void *buf, int size);
16 16
17static int __init read_initrd(void) 17static 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
65static int load_initrd(char *filename, void *buf, int size) 65int 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
31extern void free_irqs(void); 31extern void free_irqs(void);
32 32
33void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) 33void 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}
261EXPORT_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
300void um_free_irq(unsigned int irq, void *dev)
301{
302 free_irq_by_irq_and_dev(irq, dev);
303 free_irq(irq, dev);
304}
305EXPORT_SYMBOL(um_free_irq);
306
307int um_request_irq(unsigned int irq, int fd, int type, 299int 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. */
335static struct irq_chip normal_irq_type = { 327static 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
342static struct irq_chip SIGVTALRM_irq_type = { 335static 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
15EXPORT_SYMBOL(uml_physmem);
9EXPORT_SYMBOL(set_signals); 16EXPORT_SYMBOL(set_signals);
10EXPORT_SYMBOL(get_signals); 17EXPORT_SYMBOL(get_signals);
18EXPORT_SYMBOL(kernel_thread);
19EXPORT_SYMBOL(sys_waitpid);
20EXPORT_SYMBOL(flush_tlb_range);
21
22EXPORT_SYMBOL(high_physmem);
23EXPORT_SYMBOL(empty_zero_page);
24EXPORT_SYMBOL(handle_page_fault);
25EXPORT_SYMBOL(find_iomem);
26
27EXPORT_SYMBOL(strnlen_user);
28EXPORT_SYMBOL(strncpy_from_user);
29EXPORT_SYMBOL(copy_to_user);
30EXPORT_SYMBOL(copy_from_user);
31EXPORT_SYMBOL(clear_user);
32EXPORT_SYMBOL(uml_strdup);
11 33
12EXPORT_SYMBOL(os_stat_fd); 34EXPORT_SYMBOL(os_stat_fd);
13EXPORT_SYMBOL(os_stat_file); 35EXPORT_SYMBOL(os_stat_file);
@@ -35,10 +57,24 @@ EXPORT_SYMBOL(os_connect_socket);
35EXPORT_SYMBOL(os_accept_connection); 57EXPORT_SYMBOL(os_accept_connection);
36EXPORT_SYMBOL(os_rcv_fd); 58EXPORT_SYMBOL(os_rcv_fd);
37EXPORT_SYMBOL(run_helper); 59EXPORT_SYMBOL(run_helper);
60EXPORT_SYMBOL(start_thread);
38EXPORT_SYMBOL(os_major); 61EXPORT_SYMBOL(os_major);
39EXPORT_SYMBOL(os_minor); 62EXPORT_SYMBOL(os_minor);
40EXPORT_SYMBOL(os_makedev); 63EXPORT_SYMBOL(os_makedev);
41 64
42EXPORT_SYMBOL(add_sigio_fd); 65EXPORT_SYMBOL(add_sigio_fd);
43EXPORT_SYMBOL(ignore_sigio_fd); 66EXPORT_SYMBOL(ignore_sigio_fd);
67EXPORT_SYMBOL(deactivate_fd);
44EXPORT_SYMBOL(sigio_broken); 68EXPORT_SYMBOL(sigio_broken);
69
70#ifdef CONFIG_SMP
71
72/* required for SMP */
73
74extern void __write_lock_failed(rwlock_t *rw);
75EXPORT_SYMBOL(__write_lock_failed);
76
77extern void __read_lock_failed(rwlock_t *rw);
78EXPORT_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 */
23unsigned long *empty_zero_page = NULL; 22unsigned long *empty_zero_page = NULL;
24EXPORT_SYMBOL(empty_zero_page);
25/* allocated in paging_init and unchanged thereafter */ 23/* allocated in paging_init and unchanged thereafter */
26static unsigned long *empty_bad_page = NULL; 24static 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
17static int physmem_fd = -1; 16static int physmem_fd = -1;
18 17
19/* Changed during early boot */ 18/* Changed during early boot */
20unsigned long high_physmem; 19unsigned long high_physmem;
21EXPORT_SYMBOL(high_physmem);
22 20
23extern unsigned long long physmem_size; 21extern 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}
189EXPORT_SYMBOL(find_iomem);
190 187
191static int setup_iomem(void) 188static 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
71int 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 &current->thread.regs, 0, NULL, NULL);
79 return pid;
80}
81
72static inline void set_current(struct task_struct *task) 82static 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
78extern void arch_switch_to(struct task_struct *to); 88extern void arch_switch_to(struct task_struct *to);
79 89
80void *__switch_to(struct task_struct *from, struct task_struct *to) 90void *_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
102void interrupt_end(void) 116void 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(&current->thread.regs);
110} 122}
111 123
112void exit_thread(void) 124void exit_thread(void)
113{ 125{
114} 126}
115 127
116int get_current_pid(void) 128void *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, &current->thread.exec_buf);
141 userspace(&current->thread.regs.regs); 154 if (n == 1) {
155 /* Handle any immediate reschedules or signals */
156 interrupt_end();
157 userspace(&current->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(&current->thread.regs.regs); 181 userspace(&current->thread.regs.regs);
161} 182}
162 183
163int copy_thread(unsigned long clone_flags, unsigned long sp, 184int 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, &regs->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(&current->thread.arch, &p->thread.arch); 202 arch_copy_thread(&current->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}
270EXPORT_SYMBOL(uml_strdup);
271 289
272int copy_to_user_proc(void __user *to, void *from, int size) 290int 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 */
166void syscall_trace_enter(struct pt_regs *regs) 165void 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(&regs->regs), 168 int tracesysgood;
170 UPT_SYSCALL_ARG1(&regs->regs), 169
171 UPT_SYSCALL_ARG2(&regs->regs), 170 if (unlikely(current->audit_context)) {
172 UPT_SYSCALL_ARG3(&regs->regs), 171 if (!entryexit)
173 UPT_SYSCALL_ARG4(&regs->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));
181void 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, &regs->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
14void (*pm_power_off)(void); 12void (*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 */
12static int sigio_irq_fd = -1; 12static 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
15EXPORT_SYMBOL(block_signals); 16EXPORT_SYMBOL(block_signals);
16EXPORT_SYMBOL(unblock_signals); 17EXPORT_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 */
21static void handle_signal(struct pt_regs *regs, unsigned long signr, 26static 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(&current->sighand->siglock);
71 current->blocked = *oldset;
72 recalc_sigpending();
73 spin_unlock_irq(&current->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(&current->sighand->siglock);
77 sigorsets(&current->blocked, &current->blocked,
78 &ka->sa.sa_mask);
79 if (!(ka->sa.sa_flags & SA_NODEFER))
80 sigaddset(&current->blocked, signr);
81 recalc_sigpending();
82 spin_unlock_irq(&current->sighand->siglock);
83 }
84
85 return err;
69} 86}
70 87
71static int kern_do_signal(struct pt_regs *regs) 88static 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 = &current->saved_sigmask;
97 else
98 oldset = &current->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, &current->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 */
129long sys_sigsuspend(int history0, int history1, old_sigset_t mask) 164long 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(&current->sighand->siglock);
133 return sigsuspend(&blocked); 168 current->saved_sigmask = current->blocked;
169 siginitset(&current->blocked, mask);
170 recalc_sigpending();
171 spin_unlock_irq(&current->sighand->siglock);
172
173 current->state = TASK_INTERRUPTIBLE;
174 schedule();
175 set_thread_flag(TIF_RESTORE_SIGMASK);
176 return -ERESTARTNOHAND;
177}
178
179long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
180{
181 return do_sigaltstack(uss, uoss, PT_REGS_SP(&current->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
15extern int __syscall_stub_start; 15extern 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
104void uml_setup_stubs(struct mm_struct *mm) 106void 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
144out_free:
145 kfree(pages);
134out: 146out:
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
13int new_mm(unsigned long stack) 13int 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
12extern int syscall_table_size; 12extern 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
17pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr) 16pte_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}
153EXPORT_SYMBOL(copy_from_user);
154 152
155static int copy_chunk_to_user(unsigned long to, int len, void *arg) 153static 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}
175EXPORT_SYMBOL(copy_to_user);
176 173
177static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) 174static 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}
210EXPORT_SYMBOL(strncpy_from_user);
211 207
212static int clear_chunk(unsigned long addr, int len, void *unused) 208static 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}
233EXPORT_SYMBOL(clear_user);
234 229
235static int strnlen_chunk(unsigned long str, int len, void *arg) 230static 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}
259EXPORT_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
138void smp_prepare_boot_cpu(void) 139void 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
143int __cpu_up(unsigned int cpu, struct task_struct *tidle) 144int __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
18long sys_fork(void)
19{
20 long ret;
21
22 current->thread.forking = 1;
23 ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
24 &current->thread.regs, 0, NULL, NULL);
25 current->thread.forking = 0;
26 return ret;
27}
28
29long 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(&current->thread.regs.regs),
36 &current->thread.regs, 0, NULL, NULL);
37 current->thread.forking = 0;
38 return ret;
39}
16 40
17long old_mmap(unsigned long addr, unsigned long len, 41long 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
54int 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
16void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) 16void 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
16struct host_vm_change { 16struct 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
291static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) 290int 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}
503EXPORT_SYMBOL(flush_tlb_range);
504 502
505void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, 503void 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
45retry:
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}
130EXPORT_SYMBOL(handle_page_fault);
131 115
132static void show_segv_info(struct uml_pt_regs *regs) 116static 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
176void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) 160void 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
262void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs) 246void 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
301void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs) 261void 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
309void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) 268void 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
51union thread_union cpu0_irqstack
52 __attribute__((__section__(".data..init_irqstack"))) =
53 { INIT_THREAD_INFO(init_task) };
54
55unsigned long thread_saved_pc(struct task_struct *task) 50unsigned 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 */
109unsigned long uml_physmem; 104unsigned long uml_physmem;
110EXPORT_SYMBOL(uml_physmem);
111
112unsigned long uml_reserved; /* Also modified in mem_init */ 105unsigned long uml_reserved; /* Also modified in mem_init */
113unsigned long start_vm; 106unsigned long start_vm;
114unsigned long end_vm; 107unsigned 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 */
12static int umid_inited = 0; 12static 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 :