aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel/skas
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel/skas')
-rw-r--r--arch/um/kernel/skas/exec_kern.c2
-rw-r--r--arch/um/kernel/skas/include/mm_id.h17
-rw-r--r--arch/um/kernel/skas/include/mmu-skas.h7
-rw-r--r--arch/um/kernel/skas/include/skas.h15
-rw-r--r--arch/um/kernel/skas/mem.c6
-rw-r--r--arch/um/kernel/skas/mem_user.c225
-rw-r--r--arch/um/kernel/skas/mmu.c136
-rw-r--r--arch/um/kernel/skas/process.c153
-rw-r--r--arch/um/kernel/skas/process_kern.c33
-rw-r--r--arch/um/kernel/skas/tlb.c28
10 files changed, 470 insertions, 152 deletions
diff --git a/arch/um/kernel/skas/exec_kern.c b/arch/um/kernel/skas/exec_kern.c
index c6b4d5dba789..77ed7bbab219 100644
--- a/arch/um/kernel/skas/exec_kern.c
+++ b/arch/um/kernel/skas/exec_kern.c
@@ -18,7 +18,7 @@
18void flush_thread_skas(void) 18void flush_thread_skas(void)
19{ 19{
20 force_flush_all(); 20 force_flush_all();
21 switch_mm_skas(current->mm->context.skas.mm_fd); 21 switch_mm_skas(&current->mm->context.skas.id);
22} 22}
23 23
24void start_thread_skas(struct pt_regs *regs, unsigned long eip, 24void start_thread_skas(struct pt_regs *regs, unsigned long eip,
diff --git a/arch/um/kernel/skas/include/mm_id.h b/arch/um/kernel/skas/include/mm_id.h
new file mode 100644
index 000000000000..48dd0989ddaa
--- /dev/null
+++ b/arch/um/kernel/skas/include/mm_id.h
@@ -0,0 +1,17 @@
1/*
2 * Copyright (C) 2005 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __MM_ID_H
7#define __MM_ID_H
8
9struct mm_id {
10 union {
11 int mm_fd;
12 int pid;
13 } u;
14 unsigned long stack;
15};
16
17#endif
diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h
index 4cd60d7213f3..278b72f1d9ad 100644
--- a/arch/um/kernel/skas/include/mmu-skas.h
+++ b/arch/um/kernel/skas/include/mmu-skas.h
@@ -6,10 +6,15 @@
6#ifndef __SKAS_MMU_H 6#ifndef __SKAS_MMU_H
7#define __SKAS_MMU_H 7#define __SKAS_MMU_H
8 8
9#include "mm_id.h"
10
9struct mmu_context_skas { 11struct mmu_context_skas {
10 int mm_fd; 12 struct mm_id id;
13 unsigned long last_page_table;
11}; 14};
12 15
16extern void switch_mm_skas(struct mm_id * mm_idp);
17
13#endif 18#endif
14 19
15/* 20/*
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
index 96b51dba3471..d91a60f3830a 100644
--- a/arch/um/kernel/skas/include/skas.h
+++ b/arch/um/kernel/skas/include/skas.h
@@ -6,9 +6,11 @@
6#ifndef __SKAS_H 6#ifndef __SKAS_H
7#define __SKAS_H 7#define __SKAS_H
8 8
9#include "mm_id.h"
9#include "sysdep/ptrace.h" 10#include "sysdep/ptrace.h"
10 11
11extern int userspace_pid[]; 12extern int userspace_pid[];
13extern int proc_mm, ptrace_faultinfo;
12 14
13extern void switch_threads(void *me, void *next); 15extern void switch_threads(void *me, void *next);
14extern void thread_wait(void *sw, void *fb); 16extern void thread_wait(void *sw, void *fb);
@@ -22,16 +24,17 @@ extern void new_thread_proc(void *stack, void (*handler)(int sig));
22extern void remove_sigstack(void); 24extern void remove_sigstack(void);
23extern void new_thread_handler(int sig); 25extern void new_thread_handler(int sig);
24extern void handle_syscall(union uml_pt_regs *regs); 26extern void handle_syscall(union uml_pt_regs *regs);
25extern void map(int fd, unsigned long virt, unsigned long len, int r, int w, 27extern int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len,
26 int x, int phys_fd, unsigned long long offset); 28 int r, int w, int x, int phys_fd, unsigned long long offset);
27extern int unmap(int fd, void *addr, unsigned long len); 29extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len);
28extern int protect(int fd, unsigned long addr, unsigned long len, 30extern int protect(struct mm_id * mm_idp, unsigned long addr,
29 int r, int w, int x); 31 unsigned long len, int r, int w, int x);
30extern void user_signal(int sig, union uml_pt_regs *regs, int pid); 32extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
31extern int new_mm(int from); 33extern int new_mm(int from);
32extern void start_userspace(int cpu); 34extern int start_userspace(unsigned long stub_stack);
33extern void get_skas_faultinfo(int pid, struct faultinfo * fi); 35extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
34extern long execute_syscall_skas(void *r); 36extern long execute_syscall_skas(void *r);
37extern unsigned long current_stub_stack(void);
35 38
36#endif 39#endif
37 40
diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c
index 438db2f43456..147466d7ff4f 100644
--- a/arch/um/kernel/skas/mem.c
+++ b/arch/um/kernel/skas/mem.c
@@ -5,7 +5,9 @@
5 5
6#include "linux/config.h" 6#include "linux/config.h"
7#include "linux/mm.h" 7#include "linux/mm.h"
8#include "asm/pgtable.h"
8#include "mem_user.h" 9#include "mem_user.h"
10#include "skas.h"
9 11
10unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, 12unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
11 unsigned long *task_size_out) 13 unsigned long *task_size_out)
@@ -18,7 +20,9 @@ unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
18 *task_size_out = CONFIG_HOST_TASK_SIZE; 20 *task_size_out = CONFIG_HOST_TASK_SIZE;
19#else 21#else
20 *host_size_out = top; 22 *host_size_out = top;
21 *task_size_out = top; 23 if (proc_mm && ptrace_faultinfo)
24 *task_size_out = top;
25 else *task_size_out = CONFIG_STUB_START & PGDIR_MASK;
22#endif 26#endif
23 return(((unsigned long) set_task_sizes_skas) & ~0xffffff); 27 return(((unsigned long) set_task_sizes_skas) & ~0xffffff);
24} 28}
diff --git a/arch/um/kernel/skas/mem_user.c b/arch/um/kernel/skas/mem_user.c
index 1310bf1e88d1..b0980ff3bd95 100644
--- a/arch/um/kernel/skas/mem_user.c
+++ b/arch/um/kernel/skas/mem_user.c
@@ -3,100 +3,171 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <signal.h>
6#include <errno.h> 7#include <errno.h>
7#include <sys/mman.h> 8#include <sys/mman.h>
9#include <sys/wait.h>
10#include <asm/page.h>
11#include <asm/unistd.h>
8#include "mem_user.h" 12#include "mem_user.h"
9#include "mem.h" 13#include "mem.h"
14#include "mm_id.h"
10#include "user.h" 15#include "user.h"
11#include "os.h" 16#include "os.h"
12#include "proc_mm.h" 17#include "proc_mm.h"
13 18#include "ptrace_user.h"
14void map(int fd, unsigned long virt, unsigned long len, int r, int w, 19#include "user_util.h"
15 int x, int phys_fd, unsigned long long offset) 20#include "kern_util.h"
21#include "task.h"
22#include "registers.h"
23#include "uml-config.h"
24#include "sysdep/ptrace.h"
25#include "sysdep/stub.h"
26#include "skas.h"
27
28extern unsigned long syscall_stub, __syscall_stub_start;
29
30extern void wait_stub_done(int pid, int sig, char * fname);
31
32static long run_syscall_stub(struct mm_id * mm_idp, int syscall,
33 unsigned long *args)
16{ 34{
17 struct proc_mm_op map; 35 int n, pid = mm_idp->u.pid;
18 int prot, n; 36 unsigned long regs[MAX_REG_NR];
19 37
20 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 38 get_safe_registers(regs);
21 (x ? PROT_EXEC : 0); 39 regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
22 40 ((unsigned long) &syscall_stub -
23 map = ((struct proc_mm_op) { .op = MM_MMAP, 41 (unsigned long) &__syscall_stub_start);
24 .u = 42 /* XXX Don't have a define for starting a syscall */
25 { .mmap = 43 regs[REGS_SYSCALL_NR] = syscall;
26 { .addr = virt, 44 regs[REGS_SYSCALL_ARG1] = args[0];
27 .len = len, 45 regs[REGS_SYSCALL_ARG2] = args[1];
28 .prot = prot, 46 regs[REGS_SYSCALL_ARG3] = args[2];
29 .flags = MAP_SHARED | 47 regs[REGS_SYSCALL_ARG4] = args[3];
30 MAP_FIXED, 48 regs[REGS_SYSCALL_ARG5] = args[4];
31 .fd = phys_fd, 49 regs[REGS_SYSCALL_ARG6] = args[5];
32 .offset = offset 50 n = ptrace_setregs(pid, regs);
33 } } } ); 51 if(n < 0){
34 n = os_write_file(fd, &map, sizeof(map)); 52 printk("run_syscall_stub : PTRACE_SETREGS failed, "
35 if(n != sizeof(map)) 53 "errno = %d\n", n);
36 printk("map : /proc/mm map failed, err = %d\n", -n); 54 return(n);
55 }
56
57 wait_stub_done(pid, 0, "run_syscall_stub");
58
59 return(*((unsigned long *) mm_idp->stack));
37} 60}
38 61
39int unmap(int fd, void *addr, unsigned long len) 62int map(struct mm_id *mm_idp, unsigned long virt, unsigned long len,
63 int r, int w, int x, int phys_fd, unsigned long long offset)
40{ 64{
41 struct proc_mm_op unmap; 65 int prot, n;
42 int n; 66
43 67 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
44 unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, 68 (x ? PROT_EXEC : 0);
45 .u = 69
46 { .munmap = 70 if(proc_mm){
47 { .addr = (unsigned long) addr, 71 struct proc_mm_op map;
48 .len = len } } } ); 72 int fd = mm_idp->u.mm_fd;
49 n = os_write_file(fd, &unmap, sizeof(unmap)); 73 map = ((struct proc_mm_op) { .op = MM_MMAP,
50 if(n != sizeof(unmap)) { 74 .u =
51 if(n < 0) 75 { .mmap =
52 return(n); 76 { .addr = virt,
53 else if(n > 0) 77 .len = len,
54 return(-EIO); 78 .prot = prot,
55 } 79 .flags = MAP_SHARED |
56 80 MAP_FIXED,
57 return(0); 81 .fd = phys_fd,
82 .offset= offset
83 } } } );
84 n = os_write_file(fd, &map, sizeof(map));
85 if(n != sizeof(map))
86 printk("map : /proc/mm map failed, err = %d\n", -n);
87 }
88 else {
89 long res;
90 unsigned long args[] = { virt, len, prot,
91 MAP_SHARED | MAP_FIXED, phys_fd,
92 MMAP_OFFSET(offset) };
93
94 res = run_syscall_stub(mm_idp, STUB_MMAP_NR, args);
95 if((void *) res == MAP_FAILED)
96 printk("mmap stub failed, errno = %d\n", res);
97 }
98
99 return 0;
58} 100}
59 101
60int protect(int fd, unsigned long addr, unsigned long len, int r, int w, 102int unmap(struct mm_id *mm_idp, void *addr, unsigned long len)
61 int x, int must_succeed)
62{ 103{
63 struct proc_mm_op protect; 104 int n;
64 int prot, n; 105
65 106 if(proc_mm){
66 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 107 struct proc_mm_op unmap;
67 (x ? PROT_EXEC : 0); 108 int fd = mm_idp->u.mm_fd;
68 109 unmap = ((struct proc_mm_op) { .op = MM_MUNMAP,
69 protect = ((struct proc_mm_op) { .op = MM_MPROTECT, 110 .u =
70 .u = 111 { .munmap =
71 { .mprotect = 112 { .addr =
72 { .addr = (unsigned long) addr, 113 (unsigned long) addr,
73 .len = len, 114 .len = len } } } );
74 .prot = prot } } } ); 115 n = os_write_file(fd, &unmap, sizeof(unmap));
75 116 if(n != sizeof(unmap)) {
76 n = os_write_file(fd, &protect, sizeof(protect)); 117 if(n < 0)
77 if(n != sizeof(protect)) { 118 return(n);
78 if(n == 0) return(0); 119 else if(n > 0)
79 120 return(-EIO);
80 if(must_succeed) 121 }
81 panic("protect failed, err = %d", -n); 122 }
82 123 else {
83 return(-EIO); 124 int res;
84 } 125 unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0,
126 0 };
127
128 res = run_syscall_stub(mm_idp, __NR_munmap, args);
129 if(res < 0)
130 printk("munmap stub failed, errno = %d\n", res);
131 }
132
133 return(0);
134}
85 135
86 return(0); 136int protect(struct mm_id *mm_idp, unsigned long addr, unsigned long len,
137 int r, int w, int x)
138{
139 struct proc_mm_op protect;
140 int prot, n;
141
142 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
143 (x ? PROT_EXEC : 0);
144
145 if(proc_mm){
146 int fd = mm_idp->u.mm_fd;
147 protect = ((struct proc_mm_op) { .op = MM_MPROTECT,
148 .u =
149 { .mprotect =
150 { .addr =
151 (unsigned long) addr,
152 .len = len,
153 .prot = prot } } } );
154
155 n = os_write_file(fd, &protect, sizeof(protect));
156 if(n != sizeof(protect))
157 panic("protect failed, err = %d", -n);
158 }
159 else {
160 int res;
161 unsigned long args[] = { addr, len, prot, 0, 0, 0 };
162
163 res = run_syscall_stub(mm_idp, __NR_mprotect, args);
164 if(res < 0)
165 panic("mprotect stub failed, errno = %d\n", res);
166 }
167
168 return(0);
87} 169}
88 170
89void before_mem_skas(unsigned long unused) 171void before_mem_skas(unsigned long unused)
90{ 172{
91} 173}
92
93/*
94 * Overrides for Emacs so that we follow Linus's tabbing style.
95 * Emacs will notice this stuff at the end of the file and automatically
96 * adjust the settings for this buffer only. This must remain at the end
97 * of the file.
98 * ---------------------------------------------------------------------------
99 * Local variables:
100 * c-file-style: "linux"
101 * End:
102 */
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 6cb9a6d028a9..511a855c9ec0 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -3,46 +3,138 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include "linux/config.h"
6#include "linux/sched.h" 7#include "linux/sched.h"
7#include "linux/list.h" 8#include "linux/list.h"
8#include "linux/spinlock.h" 9#include "linux/spinlock.h"
9#include "linux/slab.h" 10#include "linux/slab.h"
11#include "linux/errno.h"
12#include "linux/mm.h"
10#include "asm/current.h" 13#include "asm/current.h"
11#include "asm/segment.h" 14#include "asm/segment.h"
12#include "asm/mmu.h" 15#include "asm/mmu.h"
16#include "asm/pgalloc.h"
17#include "asm/pgtable.h"
13#include "os.h" 18#include "os.h"
14#include "skas.h" 19#include "skas.h"
15 20
21extern int __syscall_stub_start;
22
23static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
24 unsigned long kernel)
25{
26 pgd_t *pgd;
27 pud_t *pud;
28 pmd_t *pmd;
29 pte_t *pte;
30
31 spin_lock(&mm->page_table_lock);
32 pgd = pgd_offset(mm, proc);
33 pud = pud_alloc(mm, pgd, proc);
34 if (!pud)
35 goto out;
36
37 pmd = pmd_alloc(mm, pud, proc);
38 if (!pmd)
39 goto out_pmd;
40
41 pte = pte_alloc_map(mm, pmd, proc);
42 if (!pte)
43 goto out_pte;
44
45 /* There's an interaction between the skas0 stub pages, stack
46 * randomization, and the BUG at the end of exit_mmap. exit_mmap
47 * checks that the number of page tables freed is the same as had
48 * been allocated. If the stack is on the last page table page,
49 * then the stack pte page will be freed, and if not, it won't. To
50 * avoid having to know where the stack is, or if the process mapped
51 * something at the top of its address space for some other reason,
52 * we set TASK_SIZE to end at the start of the last page table.
53 * This keeps exit_mmap off the last page, but introduces a leak
54 * of that page. So, we hang onto it here and free it in
55 * destroy_context_skas.
56 */
57
58 mm->context.skas.last_page_table = pmd_page_kernel(*pmd);
59
60 *pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
61 *pte = pte_mkexec(*pte);
62 *pte = pte_wrprotect(*pte);
63 spin_unlock(&mm->page_table_lock);
64 return(0);
65
66 out_pmd:
67 pud_free(pud);
68 out_pte:
69 pmd_free(pmd);
70 out:
71 spin_unlock(&mm->page_table_lock);
72 return(-ENOMEM);
73}
74
16int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) 75int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
17{ 76{
18 int from; 77 struct mm_struct *cur_mm = current->mm;
78 struct mm_id *mm_id = &mm->context.skas.id;
79 unsigned long stack;
80 int from, ret;
19 81
20 if((current->mm != NULL) && (current->mm != &init_mm)) 82 if(proc_mm){
21 from = current->mm->context.skas.mm_fd; 83 if((cur_mm != NULL) && (cur_mm != &init_mm))
22 else from = -1; 84 from = cur_mm->context.skas.id.u.mm_fd;
85 else from = -1;
23 86
24 mm->context.skas.mm_fd = new_mm(from); 87 ret = new_mm(from);
25 if(mm->context.skas.mm_fd < 0){ 88 if(ret < 0){
26 printk("init_new_context_skas - new_mm failed, errno = %d\n", 89 printk("init_new_context_skas - new_mm failed, "
27 mm->context.skas.mm_fd); 90 "errno = %d\n", ret);
28 return(mm->context.skas.mm_fd); 91 return ret;
92 }
93 mm_id->u.mm_fd = ret;
29 } 94 }
95 else {
96 /* This zeros the entry that pgd_alloc didn't, needed since
97 * we are about to reinitialize it, and want mm.nr_ptes to
98 * be accurate.
99 */
100 mm->pgd[USER_PTRS_PER_PGD] = __pgd(0);
30 101
31 return(0); 102 ret = init_stub_pte(mm, CONFIG_STUB_CODE,
103 (unsigned long) &__syscall_stub_start);
104 if(ret)
105 goto out;
106
107 ret = -ENOMEM;
108 stack = get_zeroed_page(GFP_KERNEL);
109 if(stack == 0)
110 goto out;
111 mm_id->stack = stack;
112
113 ret = init_stub_pte(mm, CONFIG_STUB_DATA, stack);
114 if(ret)
115 goto out_free;
116
117 mm->nr_ptes--;
118 mm_id->u.pid = start_userspace(stack);
119 }
120
121 return 0;
122
123 out_free:
124 free_page(mm_id->stack);
125 out:
126 return ret;
32} 127}
33 128
34void destroy_context_skas(struct mm_struct *mm) 129void destroy_context_skas(struct mm_struct *mm)
35{ 130{
36 os_close_file(mm->context.skas.mm_fd); 131 struct mmu_context_skas *mmu = &mm->context.skas;
37}
38 132
39/* 133 if(proc_mm)
40 * Overrides for Emacs so that we follow Linus's tabbing style. 134 os_close_file(mmu->id.u.mm_fd);
41 * Emacs will notice this stuff at the end of the file and automatically 135 else {
42 * adjust the settings for this buffer only. This must remain at the end 136 os_kill_ptraced_process(mmu->id.u.pid, 1);
43 * of the file. 137 free_page(mmu->id.stack);
44 * --------------------------------------------------------------------------- 138 free_page(mmu->last_page_table);
45 * Local variables: 139 }
46 * c-file-style: "linux" 140}
47 * End:
48 */
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 773cd2b525fc..1647abb0d1aa 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
@@ -14,6 +14,7 @@
14#include <sys/mman.h> 14#include <sys/mman.h>
15#include <sys/user.h> 15#include <sys/user.h>
16#include <asm/unistd.h> 16#include <asm/unistd.h>
17#include <asm/types.h>
17#include "user.h" 18#include "user.h"
18#include "ptrace_user.h" 19#include "ptrace_user.h"
19#include "time_user.h" 20#include "time_user.h"
@@ -21,13 +22,17 @@
21#include "user_util.h" 22#include "user_util.h"
22#include "kern_util.h" 23#include "kern_util.h"
23#include "skas.h" 24#include "skas.h"
25#include "mm_id.h"
24#include "sysdep/sigcontext.h" 26#include "sysdep/sigcontext.h"
27#include "sysdep/stub.h"
25#include "os.h" 28#include "os.h"
26#include "proc_mm.h" 29#include "proc_mm.h"
27#include "skas_ptrace.h" 30#include "skas_ptrace.h"
28#include "chan_user.h" 31#include "chan_user.h"
29#include "signal_user.h" 32#include "signal_user.h"
30#include "registers.h" 33#include "registers.h"
34#include "mem.h"
35#include "uml-config.h"
31#include "process.h" 36#include "process.h"
32 37
33int is_skas_winch(int pid, int fd, void *data) 38int is_skas_winch(int pid, int fd, void *data)
@@ -39,20 +44,55 @@ int is_skas_winch(int pid, int fd, void *data)
39 return(1); 44 return(1);
40} 45}
41 46
42void get_skas_faultinfo(int pid, struct faultinfo * fi) 47void wait_stub_done(int pid, int sig, char * fname)
43{ 48{
44 int err; 49 int n, status, err;
45 50
46 err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); 51 do {
47 if(err) 52 if ( sig != -1 ) {
48 panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " 53 err = ptrace(PTRACE_CONT, pid, 0, sig);
49 "errno = %d\n", errno); 54 if(err)
55 panic("%s : continue failed, errno = %d\n",
56 fname, errno);
57 }
58 sig = 0;
59
60 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
61 } while((n >= 0) && WIFSTOPPED(status) &&
62 (WSTOPSIG(status) == SIGVTALRM));
63
64 if((n < 0) || !WIFSTOPPED(status) ||
65 (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status != SIGTRAP))){
66 panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
67 "pid = %d, n = %d, errno = %d, status = 0x%x\n",
68 fname, pid, n, errno, status);
69 }
70}
50 71
51 /* Special handling for i386, which has different structs */ 72void get_skas_faultinfo(int pid, struct faultinfo * fi)
52 if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo)) 73{
53 memset((char *)fi + sizeof(struct ptrace_faultinfo), 0, 74 int err;
54 sizeof(struct faultinfo) - 75
55 sizeof(struct ptrace_faultinfo)); 76 if(ptrace_faultinfo){
77 err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
78 if(err)
79 panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
80 "errno = %d\n", errno);
81
82 /* Special handling for i386, which has different structs */
83 if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
84 memset((char *)fi + sizeof(struct ptrace_faultinfo), 0,
85 sizeof(struct faultinfo) -
86 sizeof(struct ptrace_faultinfo));
87 }
88 else {
89 wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo");
90
91 /* faultinfo is prepared by the stub-segv-handler at start of
92 * the stub stack page. We just have to copy it.
93 */
94 memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
95 }
56} 96}
57 97
58static void handle_segv(int pid, union uml_pt_regs * regs) 98static void handle_segv(int pid, union uml_pt_regs * regs)
@@ -91,11 +131,56 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu
91 handle_syscall(regs); 131 handle_syscall(regs);
92} 132}
93 133
94static int userspace_tramp(void *arg) 134extern int __syscall_stub_start;
135
136static int userspace_tramp(void *stack)
95{ 137{
96 init_new_thread_signals(0); 138 void *addr;
97 enable_timer(); 139
98 ptrace(PTRACE_TRACEME, 0, 0, 0); 140 ptrace(PTRACE_TRACEME, 0, 0, 0);
141
142 init_new_thread_signals(1);
143 enable_timer();
144
145 if(!proc_mm){
146 /* This has a pte, but it can't be mapped in with the usual
147 * tlb_flush mechanism because this is part of that mechanism
148 */
149 int fd;
150 __u64 offset;
151
152 fd = phys_mapping(to_phys(&__syscall_stub_start), &offset);
153 addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(),
154 PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
155 if(addr == MAP_FAILED){
156 printk("mapping mmap stub failed, errno = %d\n",
157 errno);
158 exit(1);
159 }
160
161 if(stack != NULL){
162 fd = phys_mapping(to_phys(stack), &offset);
163 addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(),
164 PROT_READ | PROT_WRITE,
165 MAP_FIXED | MAP_SHARED, fd, offset);
166 if(addr == MAP_FAILED){
167 printk("mapping segfault stack failed, "
168 "errno = %d\n", errno);
169 exit(1);
170 }
171 }
172 }
173 if(!ptrace_faultinfo && (stack != NULL)){
174 unsigned long v = UML_CONFIG_STUB_CODE +
175 (unsigned long) stub_segv_handler -
176 (unsigned long) &__syscall_stub_start;
177
178 set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size());
179 set_handler(SIGSEGV, (void *) v, SA_ONSTACK,
180 SIGIO, SIGWINCH, SIGALRM, SIGVTALRM,
181 SIGUSR1, -1);
182 }
183
99 os_stop_process(os_getpid()); 184 os_stop_process(os_getpid());
100 return(0); 185 return(0);
101} 186}
@@ -105,11 +190,11 @@ static int userspace_tramp(void *arg)
105#define NR_CPUS 1 190#define NR_CPUS 1
106int userspace_pid[NR_CPUS]; 191int userspace_pid[NR_CPUS];
107 192
108void start_userspace(int cpu) 193int start_userspace(unsigned long stub_stack)
109{ 194{
110 void *stack; 195 void *stack;
111 unsigned long sp; 196 unsigned long sp;
112 int pid, status, n; 197 int pid, status, n, flags;
113 198
114 stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, 199 stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
115 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 200 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
@@ -117,8 +202,9 @@ void start_userspace(int cpu)
117 panic("start_userspace : mmap failed, errno = %d", errno); 202 panic("start_userspace : mmap failed, errno = %d", errno);
118 sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); 203 sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
119 204
120 pid = clone(userspace_tramp, (void *) sp, 205 flags = CLONE_FILES | SIGCHLD;
121 CLONE_FILES | CLONE_VM | SIGCHLD, NULL); 206 if(proc_mm) flags |= CLONE_VM;
207 pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
122 if(pid < 0) 208 if(pid < 0)
123 panic("start_userspace : clone failed, errno = %d", errno); 209 panic("start_userspace : clone failed, errno = %d", errno);
124 210
@@ -140,7 +226,7 @@ void start_userspace(int cpu)
140 if(munmap(stack, PAGE_SIZE) < 0) 226 if(munmap(stack, PAGE_SIZE) < 0)
141 panic("start_userspace : munmap failed, errno = %d\n", errno); 227 panic("start_userspace : munmap failed, errno = %d\n", errno);
142 228
143 userspace_pid[cpu] = pid; 229 return(pid);
144} 230}
145 231
146void userspace(union uml_pt_regs *regs) 232void userspace(union uml_pt_regs *regs)
@@ -174,7 +260,9 @@ void userspace(union uml_pt_regs *regs)
174 if(WIFSTOPPED(status)){ 260 if(WIFSTOPPED(status)){
175 switch(WSTOPSIG(status)){ 261 switch(WSTOPSIG(status)){
176 case SIGSEGV: 262 case SIGSEGV:
177 handle_segv(pid, regs); 263 if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo)
264 user_signal(SIGSEGV, regs, pid);
265 else handle_segv(pid, regs);
178 break; 266 break;
179 case SIGTRAP + 0x80: 267 case SIGTRAP + 0x80:
180 handle_trap(pid, regs, local_using_sysemu); 268 handle_trap(pid, regs, local_using_sysemu);
@@ -194,6 +282,7 @@ void userspace(union uml_pt_regs *regs)
194 printk("userspace - child stopped with signal " 282 printk("userspace - child stopped with signal "
195 "%d\n", WSTOPSIG(status)); 283 "%d\n", WSTOPSIG(status));
196 } 284 }
285 pid = userspace_pid[0];
197 interrupt_end(); 286 interrupt_end();
198 287
199 /* Avoid -ERESTARTSYS handling in host */ 288 /* Avoid -ERESTARTSYS handling in host */
@@ -334,21 +423,19 @@ void reboot_skas(void)
334 siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT); 423 siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT);
335} 424}
336 425
337void switch_mm_skas(int mm_fd) 426void switch_mm_skas(struct mm_id *mm_idp)
338{ 427{
339 int err; 428 int err;
340 429
341#warning need cpu pid in switch_mm_skas 430#warning need cpu pid in switch_mm_skas
342 err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_fd); 431 if(proc_mm){
343 if(err) 432 err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
344 panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n", 433 mm_idp->u.mm_fd);
345 errno); 434 if(err)
346} 435 panic("switch_mm_skas - PTRACE_SWITCH_MM failed, "
347 436 "errno = %d\n", errno);
348void kill_off_processes_skas(void) 437 }
349{ 438 else userspace_pid[0] = mm_idp->u.pid;
350#warning need to loop over userspace_pids in kill_off_processes_skas
351 os_kill_ptraced_process(userspace_pid[0], 1);
352} 439}
353 440
354/* 441/*
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index 0a7b8aa55db8..cbabab104ac3 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -175,9 +175,12 @@ static int start_kernel_proc(void *unused)
175 return(0); 175 return(0);
176} 176}
177 177
178extern int userspace_pid[];
179
178int start_uml_skas(void) 180int start_uml_skas(void)
179{ 181{
180 start_userspace(0); 182 if(proc_mm)
183 userspace_pid[0] = start_userspace(0);
181 184
182 init_new_thread_signals(1); 185 init_new_thread_signals(1);
183 186
@@ -199,3 +202,31 @@ int thread_pid_skas(struct task_struct *task)
199#warning Need to look up userspace_pid by cpu 202#warning Need to look up userspace_pid by cpu
200 return(userspace_pid[0]); 203 return(userspace_pid[0]);
201} 204}
205
206void kill_off_processes_skas(void)
207{
208 if(proc_mm)
209#warning need to loop over userspace_pids in kill_off_processes_skas
210 os_kill_ptraced_process(userspace_pid[0], 1);
211 else {
212 struct task_struct *p;
213 int pid, me;
214
215 me = os_getpid();
216 for_each_process(p){
217 if(p->mm == NULL)
218 continue;
219
220 pid = p->mm->context.skas.id.u.pid;
221 os_kill_ptraced_process(pid, 1);
222 }
223 }
224}
225
226unsigned long current_stub_stack(void)
227{
228 if(current->mm == NULL)
229 return(0);
230
231 return(current->mm->context.skas.id.stack);
232}
diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c
index 18f9a7711de1..6230999c672c 100644
--- a/arch/um/kernel/skas/tlb.c
+++ b/arch/um/kernel/skas/tlb.c
@@ -6,6 +6,7 @@
6 6
7#include "linux/stddef.h" 7#include "linux/stddef.h"
8#include "linux/sched.h" 8#include "linux/sched.h"
9#include "linux/config.h"
9#include "linux/mm.h" 10#include "linux/mm.h"
10#include "asm/page.h" 11#include "asm/page.h"
11#include "asm/pgtable.h" 12#include "asm/pgtable.h"
@@ -17,7 +18,7 @@
17#include "os.h" 18#include "os.h"
18#include "tlb.h" 19#include "tlb.h"
19 20
20static void do_ops(int fd, struct host_vm_op *ops, int last) 21static void do_ops(union mm_context *mmu, struct host_vm_op *ops, int last)
21{ 22{
22 struct host_vm_op *op; 23 struct host_vm_op *op;
23 int i; 24 int i;
@@ -26,18 +27,18 @@ static void do_ops(int fd, struct host_vm_op *ops, int last)
26 op = &ops[i]; 27 op = &ops[i];
27 switch(op->type){ 28 switch(op->type){
28 case MMAP: 29 case MMAP:
29 map(fd, op->u.mmap.addr, op->u.mmap.len, 30 map(&mmu->skas.id, op->u.mmap.addr, op->u.mmap.len,
30 op->u.mmap.r, op->u.mmap.w, op->u.mmap.x, 31 op->u.mmap.r, op->u.mmap.w, op->u.mmap.x,
31 op->u.mmap.fd, op->u.mmap.offset); 32 op->u.mmap.fd, op->u.mmap.offset);
32 break; 33 break;
33 case MUNMAP: 34 case MUNMAP:
34 unmap(fd, (void *) op->u.munmap.addr, 35 unmap(&mmu->skas.id, (void *) op->u.munmap.addr,
35 op->u.munmap.len); 36 op->u.munmap.len);
36 break; 37 break;
37 case MPROTECT: 38 case MPROTECT:
38 protect(fd, op->u.mprotect.addr, op->u.mprotect.len, 39 protect(&mmu->skas.id, op->u.mprotect.addr,
39 op->u.mprotect.r, op->u.mprotect.w, 40 op->u.mprotect.len, op->u.mprotect.r,
40 op->u.mprotect.x); 41 op->u.mprotect.w, op->u.mprotect.x);
41 break; 42 break;
42 default: 43 default:
43 printk("Unknown op type %d in do_ops\n", op->type); 44 printk("Unknown op type %d in do_ops\n", op->type);
@@ -46,12 +47,15 @@ static void do_ops(int fd, struct host_vm_op *ops, int last)
46 } 47 }
47} 48}
48 49
50extern int proc_mm;
51
49static void fix_range(struct mm_struct *mm, unsigned long start_addr, 52static void fix_range(struct mm_struct *mm, unsigned long start_addr,
50 unsigned long end_addr, int force) 53 unsigned long end_addr, int force)
51{ 54{
52 int fd = mm->context.skas.mm_fd; 55 if(!proc_mm && (end_addr > CONFIG_STUB_START))
56 end_addr = CONFIG_STUB_START;
53 57
54 fix_range_common(mm, start_addr, end_addr, force, fd, do_ops); 58 fix_range_common(mm, start_addr, end_addr, force, do_ops);
55} 59}
56 60
57void __flush_tlb_one_skas(unsigned long addr) 61void __flush_tlb_one_skas(unsigned long addr)
@@ -69,16 +73,20 @@ void flush_tlb_range_skas(struct vm_area_struct *vma, unsigned long start,
69 73
70void flush_tlb_mm_skas(struct mm_struct *mm) 74void flush_tlb_mm_skas(struct mm_struct *mm)
71{ 75{
76 unsigned long end;
77
72 /* Don't bother flushing if this address space is about to be 78 /* Don't bother flushing if this address space is about to be
73 * destroyed. 79 * destroyed.
74 */ 80 */
75 if(atomic_read(&mm->mm_users) == 0) 81 if(atomic_read(&mm->mm_users) == 0)
76 return; 82 return;
77 83
78 fix_range(mm, 0, host_task_size, 0); 84 end = proc_mm ? task_size : CONFIG_STUB_START;
85 fix_range(mm, 0, end, 0);
79} 86}
80 87
81void force_flush_all_skas(void) 88void force_flush_all_skas(void)
82{ 89{
83 fix_range(current->mm, 0, host_task_size, 1); 90 unsigned long end = proc_mm ? task_size : CONFIG_STUB_START;
91 fix_range(current->mm, 0, end, 1);
84} 92}