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/Makefile2
-rw-r--r--arch/um/kernel/skas/exec.c40
-rw-r--r--arch/um/kernel/skas/mem.c22
-rw-r--r--arch/um/kernel/skas/mmu.c4
-rw-r--r--arch/um/kernel/skas/process.c158
-rw-r--r--arch/um/kernel/skas/syscall.c4
-rw-r--r--arch/um/kernel/skas/tlb.c164
7 files changed, 13 insertions, 381 deletions
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index 3e3fa7e7e3cf..b2823cdd783e 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -3,7 +3,7 @@
3# Licensed under the GPL 3# Licensed under the GPL
4# 4#
5 5
6obj-y := clone.o exec.o mem.o mmu.o process.o syscall.o tlb.o uaccess.o 6obj-y := clone.o mmu.o process.o syscall.o uaccess.o
7 7
8# clone.o is in the stub, so it can't be built with profiling 8# clone.o is in the stub, so it can't be built with profiling
9# GCC hardened also auto-enables -fpic, but we need %ebx so it can't work -> 9# GCC hardened also auto-enables -fpic, but we need %ebx so it can't work ->
diff --git a/arch/um/kernel/skas/exec.c b/arch/um/kernel/skas/exec.c
deleted file mode 100644
index 580eb6468949..000000000000
--- a/arch/um/kernel/skas/exec.c
+++ /dev/null
@@ -1,40 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include "linux/kernel.h"
7#include "asm/current.h"
8#include "asm/page.h"
9#include "asm/signal.h"
10#include "asm/ptrace.h"
11#include "asm/uaccess.h"
12#include "asm/mmu_context.h"
13#include "tlb.h"
14#include "skas.h"
15#include "um_mmu.h"
16#include "os.h"
17
18void flush_thread_skas(void)
19{
20 void *data = NULL;
21 unsigned long end = proc_mm ? task_size : CONFIG_STUB_START;
22 int ret;
23
24 ret = unmap(&current->mm->context.skas.id, 0, end, 1, &data);
25 if(ret){
26 printk("flush_thread_skas - clearing address space failed, "
27 "err = %d\n", ret);
28 force_sig(SIGKILL, current);
29 }
30
31 switch_mm_skas(&current->mm->context.skas.id);
32}
33
34void start_thread_skas(struct pt_regs *regs, unsigned long eip,
35 unsigned long esp)
36{
37 set_fs(USER_DS);
38 PT_REGS_IP(regs) = eip;
39 PT_REGS_SP(regs) = esp;
40}
diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c
deleted file mode 100644
index 7c18dfcd7d8e..000000000000
--- a/arch/um/kernel/skas/mem.c
+++ /dev/null
@@ -1,22 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include "linux/mm.h"
7#include "asm/pgtable.h"
8#include "mem_user.h"
9#include "skas.h"
10
11unsigned long set_task_sizes_skas(unsigned long *task_size_out)
12{
13 /* Round up to the nearest 4M */
14 unsigned long host_task_size = ROUND_4M((unsigned long)
15 &host_task_size);
16
17 if (!skas_needs_stub)
18 *task_size_out = host_task_size;
19 else *task_size_out = CONFIG_STUB_START & PGDIR_MASK;
20
21 return host_task_size;
22}
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 2c6d090a2e87..902d74138952 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -71,7 +71,7 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
71 return(-ENOMEM); 71 return(-ENOMEM);
72} 72}
73 73
74int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) 74int init_new_context(struct task_struct *task, struct mm_struct *mm)
75{ 75{
76 struct mmu_context_skas *from_mm = NULL; 76 struct mmu_context_skas *from_mm = NULL;
77 struct mmu_context_skas *to_mm = &mm->context.skas; 77 struct mmu_context_skas *to_mm = &mm->context.skas;
@@ -137,7 +137,7 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
137 return ret; 137 return ret;
138} 138}
139 139
140void destroy_context_skas(struct mm_struct *mm) 140void destroy_context(struct mm_struct *mm)
141{ 141{
142 struct mmu_context_skas *mmu = &mm->context.skas; 142 struct mmu_context_skas *mmu = &mm->context.skas;
143 143
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 48051a98525f..dabae62d52be 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -18,129 +18,22 @@
18#include "os.h" 18#include "os.h"
19#include "tlb.h" 19#include "tlb.h"
20#include "kern.h" 20#include "kern.h"
21#include "mode.h"
22#include "registers.h" 21#include "registers.h"
23 22
24void switch_to_skas(void *prev, void *next)
25{
26 struct task_struct *from, *to;
27
28 from = prev;
29 to = next;
30
31 /* XXX need to check runqueues[cpu].idle */
32 if(current->pid == 0)
33 switch_timers(0);
34
35 switch_threads(&from->thread.mode.skas.switch_buf,
36 &to->thread.mode.skas.switch_buf);
37
38 arch_switch_to_skas(current->thread.prev_sched, current);
39
40 if(current->pid == 0)
41 switch_timers(1);
42}
43
44extern void schedule_tail(struct task_struct *prev); 23extern void schedule_tail(struct task_struct *prev);
45 24
46/* This is called magically, by its address being stuffed in a jmp_buf
47 * and being longjmp-d to.
48 */
49void new_thread_handler(void)
50{
51 int (*fn)(void *), n;
52 void *arg;
53
54 if(current->thread.prev_sched != NULL)
55 schedule_tail(current->thread.prev_sched);
56 current->thread.prev_sched = NULL;
57
58 fn = current->thread.request.u.thread.proc;
59 arg = current->thread.request.u.thread.arg;
60
61 /* The return value is 1 if the kernel thread execs a process,
62 * 0 if it just exits
63 */
64 n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
65 if(n == 1){
66 /* Handle any immediate reschedules or signals */
67 interrupt_end();
68 userspace(&current->thread.regs.regs);
69 }
70 else do_exit(0);
71}
72
73void release_thread_skas(struct task_struct *task)
74{
75}
76
77/* Called magically, see new_thread_handler above */
78void fork_handler(void)
79{
80 force_flush_all();
81 if(current->thread.prev_sched == NULL)
82 panic("blech");
83
84 schedule_tail(current->thread.prev_sched);
85
86 /* XXX: if interrupt_end() calls schedule, this call to
87 * arch_switch_to_skas isn't needed. We could want to apply this to
88 * improve performance. -bb */
89 arch_switch_to_skas(current->thread.prev_sched, current);
90
91 current->thread.prev_sched = NULL;
92
93/* Handle any immediate reschedules or signals */
94 interrupt_end();
95
96 userspace(&current->thread.regs.regs);
97}
98
99int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
100 unsigned long stack_top, struct task_struct * p,
101 struct pt_regs *regs)
102{
103 void (*handler)(void);
104
105 if(current->thread.forking){
106 memcpy(&p->thread.regs.regs.skas, &regs->regs.skas,
107 sizeof(p->thread.regs.regs.skas));
108 REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
109 if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
110
111 handler = fork_handler;
112
113 arch_copy_thread(&current->thread.arch, &p->thread.arch);
114 }
115 else {
116 init_thread_registers(&p->thread.regs.regs);
117 p->thread.request.u.thread = current->thread.request.u.thread;
118 handler = new_thread_handler;
119 }
120
121 new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf,
122 handler);
123 return(0);
124}
125
126int new_mm(unsigned long stack) 25int new_mm(unsigned long stack)
127{ 26{
128 int fd; 27 int fd;
129 28
130 fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); 29 fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
131 if(fd < 0) 30 if(fd < 0)
132 return(fd); 31 return fd;
133 32
134 if(skas_needs_stub) 33 if(skas_needs_stub)
135 map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); 34 map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
136 35
137 return(fd); 36 return fd;
138}
139
140void init_idle_skas(void)
141{
142 cpu_tasks[current_thread->cpu].pid = os_getpid();
143 default_idle();
144} 37}
145 38
146extern void start_kernel(void); 39extern void start_kernel(void);
@@ -158,14 +51,14 @@ static int __init start_kernel_proc(void *unused)
158 cpu_online_map = cpumask_of_cpu(0); 51 cpu_online_map = cpumask_of_cpu(0);
159#endif 52#endif
160 start_kernel(); 53 start_kernel();
161 return(0); 54 return 0;
162} 55}
163 56
164extern int userspace_pid[]; 57extern int userspace_pid[];
165 58
166extern char cpu0_irqstack[]; 59extern char cpu0_irqstack[];
167 60
168int __init start_uml_skas(void) 61int __init start_uml(void)
169{ 62{
170 stack_protections((unsigned long) &cpu0_irqstack); 63 stack_protections((unsigned long) &cpu0_irqstack);
171 set_sigstack(cpu0_irqstack, THREAD_SIZE); 64 set_sigstack(cpu0_irqstack, THREAD_SIZE);
@@ -176,49 +69,14 @@ int __init start_uml_skas(void)
176 69
177 init_task.thread.request.u.thread.proc = start_kernel_proc; 70 init_task.thread.request.u.thread.proc = start_kernel_proc;
178 init_task.thread.request.u.thread.arg = NULL; 71 init_task.thread.request.u.thread.arg = NULL;
179 return(start_idle_thread(task_stack_page(&init_task), 72 return start_idle_thread(task_stack_page(&init_task),
180 &init_task.thread.mode.skas.switch_buf)); 73 &init_task.thread.switch_buf);
181}
182
183int external_pid_skas(struct task_struct *task)
184{
185 /* FIXME: Need to look up userspace_pid by cpu */
186 return(userspace_pid[0]);
187}
188
189int thread_pid_skas(struct task_struct *task)
190{
191 /* FIXME: Need to look up userspace_pid by cpu */
192 return(userspace_pid[0]);
193}
194
195void kill_off_processes_skas(void)
196{
197 if(proc_mm)
198 /*
199 * FIXME: need to loop over userspace_pids in
200 * kill_off_processes_skas
201 */
202 os_kill_ptraced_process(userspace_pid[0], 1);
203 else {
204 struct task_struct *p;
205 int pid, me;
206
207 me = os_getpid();
208 for_each_process(p){
209 if(p->mm == NULL)
210 continue;
211
212 pid = p->mm->context.skas.id.u.pid;
213 os_kill_ptraced_process(pid, 1);
214 }
215 }
216} 74}
217 75
218unsigned long current_stub_stack(void) 76unsigned long current_stub_stack(void)
219{ 77{
220 if(current->mm == NULL) 78 if(current->mm == NULL)
221 return(0); 79 return 0;
222 80
223 return(current->mm->context.skas.id.stack); 81 return current->mm->context.skas.id.stack;
224} 82}
diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c
index 0ae4eea21be4..e183da633c89 100644
--- a/arch/um/kernel/skas/syscall.c
+++ b/arch/um/kernel/skas/syscall.c
@@ -13,7 +13,7 @@
13#include "kern_util.h" 13#include "kern_util.h"
14#include "syscall.h" 14#include "syscall.h"
15 15
16void handle_syscall(union uml_pt_regs *r) 16void handle_syscall(struct uml_pt_regs *r)
17{ 17{
18 struct pt_regs *regs = container_of(r, struct pt_regs, regs); 18 struct pt_regs *regs = container_of(r, struct pt_regs, regs);
19 long result; 19 long result;
@@ -37,7 +37,7 @@ void handle_syscall(union uml_pt_regs *r)
37 result = -ENOSYS; 37 result = -ENOSYS;
38 else result = EXECUTE_SYSCALL(syscall, regs); 38 else result = EXECUTE_SYSCALL(syscall, regs);
39 39
40 REGS_SET_SYSCALL_RETURN(r->skas.regs, result); 40 REGS_SET_SYSCALL_RETURN(r->regs, result);
41 41
42 syscall_trace(r, 1); 42 syscall_trace(r, 1);
43} 43}
diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c
deleted file mode 100644
index c0f0693743ba..000000000000
--- a/arch/um/kernel/skas/tlb.c
+++ /dev/null
@@ -1,164 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Copyright 2003 PathScale, Inc.
4 * Licensed under the GPL
5 */
6
7#include "linux/stddef.h"
8#include "linux/sched.h"
9#include "linux/mm.h"
10#include "asm/page.h"
11#include "asm/pgtable.h"
12#include "asm/mmu.h"
13#include "mem_user.h"
14#include "mem.h"
15#include "skas.h"
16#include "os.h"
17#include "tlb.h"
18
19static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last,
20 int finished, void **flush)
21{
22 struct host_vm_op *op;
23 int i, ret = 0;
24
25 for(i = 0; i <= last && !ret; i++){
26 op = &ops[i];
27 switch(op->type){
28 case MMAP:
29 ret = map(&mmu->skas.id, op->u.mmap.addr,
30 op->u.mmap.len, op->u.mmap.prot,
31 op->u.mmap.fd, op->u.mmap.offset, finished,
32 flush);
33 break;
34 case MUNMAP:
35 ret = unmap(&mmu->skas.id, op->u.munmap.addr,
36 op->u.munmap.len, finished, flush);
37 break;
38 case MPROTECT:
39 ret = protect(&mmu->skas.id, op->u.mprotect.addr,
40 op->u.mprotect.len, op->u.mprotect.prot,
41 finished, flush);
42 break;
43 default:
44 printk("Unknown op type %d in do_ops\n", op->type);
45 break;
46 }
47 }
48
49 return ret;
50}
51
52extern int proc_mm;
53
54static void fix_range(struct mm_struct *mm, unsigned long start_addr,
55 unsigned long end_addr, int force)
56{
57 if(!proc_mm && (end_addr > CONFIG_STUB_START))
58 end_addr = CONFIG_STUB_START;
59
60 fix_range_common(mm, start_addr, end_addr, force, do_ops);
61}
62
63void __flush_tlb_one_skas(unsigned long addr)
64{
65 flush_tlb_kernel_range_common(addr, addr + PAGE_SIZE);
66}
67
68void flush_tlb_range_skas(struct vm_area_struct *vma, unsigned long start,
69 unsigned long end)
70{
71 if(vma->vm_mm == NULL)
72 flush_tlb_kernel_range_common(start, end);
73 else fix_range(vma->vm_mm, start, end, 0);
74}
75
76void flush_tlb_mm_skas(struct mm_struct *mm)
77{
78 unsigned long end;
79
80 /* Don't bother flushing if this address space is about to be
81 * destroyed.
82 */
83 if(atomic_read(&mm->mm_users) == 0)
84 return;
85
86 end = proc_mm ? task_size : CONFIG_STUB_START;
87 fix_range(mm, 0, end, 0);
88}
89
90void force_flush_all_skas(void)
91{
92 struct mm_struct *mm = current->mm;
93 struct vm_area_struct *vma = mm->mmap;
94
95 while(vma != NULL) {
96 fix_range(mm, vma->vm_start, vma->vm_end, 1);
97 vma = vma->vm_next;
98 }
99}
100
101void flush_tlb_page_skas(struct vm_area_struct *vma, unsigned long address)
102{
103 pgd_t *pgd;
104 pud_t *pud;
105 pmd_t *pmd;
106 pte_t *pte;
107 struct mm_struct *mm = vma->vm_mm;
108 void *flush = NULL;
109 int r, w, x, prot, err = 0;
110 struct mm_id *mm_id;
111
112 pgd = pgd_offset(mm, address);
113 if(!pgd_present(*pgd))
114 goto kill;
115
116 pud = pud_offset(pgd, address);
117 if(!pud_present(*pud))
118 goto kill;
119
120 pmd = pmd_offset(pud, address);
121 if(!pmd_present(*pmd))
122 goto kill;
123
124 pte = pte_offset_kernel(pmd, address);
125
126 r = pte_read(*pte);
127 w = pte_write(*pte);
128 x = pte_exec(*pte);
129 if (!pte_young(*pte)) {
130 r = 0;
131 w = 0;
132 } else if (!pte_dirty(*pte)) {
133 w = 0;
134 }
135
136 mm_id = &mm->context.skas.id;
137 prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
138 (x ? UM_PROT_EXEC : 0));
139 if(pte_newpage(*pte)){
140 if(pte_present(*pte)){
141 unsigned long long offset;
142 int fd;
143
144 fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset);
145 err = map(mm_id, address, PAGE_SIZE, prot, fd, offset,
146 1, &flush);
147 }
148 else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush);
149 }
150 else if(pte_newprot(*pte))
151 err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush);
152
153 if(err)
154 goto kill;
155
156 *pte = pte_mkuptodate(*pte);
157
158 return;
159
160kill:
161 printk("Failed to flush page for address 0x%lx\n", address);
162 force_sig(SIGKILL, current);
163}
164