diff options
Diffstat (limited to 'arch/um')
| -rw-r--r-- | arch/um/include/os.h | 17 | ||||
| -rw-r--r-- | arch/um/include/skas/skas.h | 14 | ||||
| -rw-r--r-- | arch/um/kernel/skas/Makefile | 4 | ||||
| -rw-r--r-- | arch/um/os-Linux/skas/Makefile | 4 | ||||
| -rw-r--r-- | arch/um/os-Linux/skas/mem.c (renamed from arch/um/kernel/skas/mem_user.c) | 202 |
5 files changed, 123 insertions, 118 deletions
diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 624938ad9e14..8006e085b675 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "../os/include/file.h" | 11 | #include "../os/include/file.h" |
| 12 | #include "sysdep/ptrace.h" | 12 | #include "sysdep/ptrace.h" |
| 13 | #include "kern_util.h" | 13 | #include "kern_util.h" |
| 14 | #include "skas/mm_id.h" | ||
| 14 | 15 | ||
| 15 | #define OS_TYPE_FILE 1 | 16 | #define OS_TYPE_FILE 1 |
| 16 | #define OS_TYPE_DIR 2 | 17 | #define OS_TYPE_DIR 2 |
| @@ -255,4 +256,20 @@ extern void user_time_init(void); | |||
| 255 | extern void uml_idle_timer(void); | 256 | extern void uml_idle_timer(void); |
| 256 | extern unsigned long long os_nsecs(void); | 257 | extern unsigned long long os_nsecs(void); |
| 257 | 258 | ||
| 259 | /* skas/mem.c */ | ||
| 260 | extern long run_syscall_stub(struct mm_id * mm_idp, | ||
| 261 | int syscall, unsigned long *args, long expected, | ||
| 262 | void **addr, int done); | ||
| 263 | extern long syscall_stub_data(struct mm_id * mm_idp, | ||
| 264 | unsigned long *data, int data_count, | ||
| 265 | void **addr, void **stub_addr); | ||
| 266 | extern int map(struct mm_id * mm_idp, unsigned long virt, | ||
| 267 | unsigned long len, int r, int w, int x, int phys_fd, | ||
| 268 | unsigned long long offset, int done, void **data); | ||
| 269 | extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, | ||
| 270 | int done, void **data); | ||
| 271 | extern int protect(struct mm_id * mm_idp, unsigned long addr, | ||
| 272 | unsigned long len, int r, int w, int x, int done, | ||
| 273 | void **data); | ||
| 274 | |||
| 258 | #endif | 275 | #endif |
diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h index 158f322248e3..7418f2addda2 100644 --- a/arch/um/include/skas/skas.h +++ b/arch/um/include/skas/skas.h | |||
| @@ -24,14 +24,6 @@ extern void userspace(union uml_pt_regs *regs); | |||
| 24 | extern void new_thread_proc(void *stack, void (*handler)(int sig)); | 24 | extern void new_thread_proc(void *stack, void (*handler)(int sig)); |
| 25 | extern void new_thread_handler(int sig); | 25 | extern void new_thread_handler(int sig); |
| 26 | extern void handle_syscall(union uml_pt_regs *regs); | 26 | extern void handle_syscall(union uml_pt_regs *regs); |
| 27 | extern int map(struct mm_id * mm_idp, unsigned long virt, | ||
| 28 | unsigned long len, int r, int w, int x, int phys_fd, | ||
| 29 | unsigned long long offset, int done, void **data); | ||
| 30 | extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, | ||
| 31 | int done, void **data); | ||
| 32 | extern int protect(struct mm_id * mm_idp, unsigned long addr, | ||
| 33 | unsigned long len, int r, int w, int x, int done, | ||
| 34 | void **data); | ||
| 35 | extern void user_signal(int sig, union uml_pt_regs *regs, int pid); | 27 | extern void user_signal(int sig, union uml_pt_regs *regs, int pid); |
| 36 | extern int new_mm(unsigned long stack); | 28 | extern int new_mm(unsigned long stack); |
| 37 | extern int start_userspace(unsigned long stub_stack); | 29 | extern int start_userspace(unsigned long stub_stack); |
| @@ -39,11 +31,5 @@ extern int copy_context_skas0(unsigned long stack, int pid); | |||
| 39 | extern void get_skas_faultinfo(int pid, struct faultinfo * fi); | 31 | extern void get_skas_faultinfo(int pid, struct faultinfo * fi); |
| 40 | extern long execute_syscall_skas(void *r); | 32 | extern long execute_syscall_skas(void *r); |
| 41 | extern unsigned long current_stub_stack(void); | 33 | extern unsigned long current_stub_stack(void); |
| 42 | extern long run_syscall_stub(struct mm_id * mm_idp, | ||
| 43 | int syscall, unsigned long *args, long expected, | ||
| 44 | void **addr, int done); | ||
| 45 | extern long syscall_stub_data(struct mm_id * mm_idp, | ||
| 46 | unsigned long *data, int data_count, | ||
| 47 | void **addr, void **stub_addr); | ||
| 48 | 34 | ||
| 49 | #endif | 35 | #endif |
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile index 7a9fc16d71d4..eb664c67c3f4 100644 --- a/arch/um/kernel/skas/Makefile +++ b/arch/um/kernel/skas/Makefile | |||
| @@ -1,9 +1,9 @@ | |||
| 1 | # | 1 | # |
| 2 | # Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.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 | ||
| 6 | obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \ | 6 | obj-y := clone.o exec_kern.o mem.o mmu.o process.o process_kern.o \ |
| 7 | syscall.o tlb.o uaccess.o | 7 | syscall.o tlb.o uaccess.o |
| 8 | 8 | ||
| 9 | USER_OBJS := process.o clone.o | 9 | USER_OBJS := process.o clone.o |
diff --git a/arch/um/os-Linux/skas/Makefile b/arch/um/os-Linux/skas/Makefile index eab5386d60a7..79cc6c72aa92 100644 --- a/arch/um/os-Linux/skas/Makefile +++ b/arch/um/os-Linux/skas/Makefile | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | # Licensed under the GPL | 3 | # Licensed under the GPL |
| 4 | # | 4 | # |
| 5 | 5 | ||
| 6 | obj-y := trap.o | 6 | obj-y := mem.o trap.o |
| 7 | 7 | ||
| 8 | USER_OBJS := trap.o | 8 | USER_OBJS := mem.o trap.o |
| 9 | 9 | ||
| 10 | include arch/um/scripts/Makefile.rules | 10 | include arch/um/scripts/Makefile.rules |
diff --git a/arch/um/kernel/skas/mem_user.c b/arch/um/os-Linux/skas/mem.c index 1d89640bd502..9890e9090f58 100644 --- a/arch/um/kernel/skas/mem_user.c +++ b/arch/um/os-Linux/skas/mem.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) |
| 3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
| 4 | */ | 4 | */ |
| @@ -32,7 +32,7 @@ extern void wait_stub_done(int pid, int sig, char * fname); | |||
| 32 | static inline unsigned long *check_init_stack(struct mm_id * mm_idp, | 32 | static inline unsigned long *check_init_stack(struct mm_id * mm_idp, |
| 33 | unsigned long *stack) | 33 | unsigned long *stack) |
| 34 | { | 34 | { |
| 35 | if(stack == NULL){ | 35 | if(stack == NULL) { |
| 36 | stack = (unsigned long *) mm_idp->stack + 2; | 36 | stack = (unsigned long *) mm_idp->stack + 2; |
| 37 | *stack = 0; | 37 | *stack = 0; |
| 38 | } | 38 | } |
| @@ -45,13 +45,14 @@ int single_count = 0; | |||
| 45 | int multi_count = 0; | 45 | int multi_count = 0; |
| 46 | int multi_op_count = 0; | 46 | int multi_op_count = 0; |
| 47 | 47 | ||
| 48 | static long do_syscall_stub(struct mm_id *mm_idp, void **addr) | 48 | static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) |
| 49 | { | 49 | { |
| 50 | unsigned long regs[MAX_REG_NR]; | 50 | unsigned long regs[MAX_REG_NR]; |
| 51 | unsigned long *data; | 51 | int n; |
| 52 | unsigned long *syscall; | ||
| 53 | long ret, offset; | 52 | long ret, offset; |
| 54 | int n, pid = mm_idp->u.pid; | 53 | unsigned long * data; |
| 54 | unsigned long * syscall; | ||
| 55 | int pid = mm_idp->u.pid; | ||
| 55 | 56 | ||
| 56 | if(proc_mm) | 57 | if(proc_mm) |
| 57 | #warning Need to look up userspace_pid by cpu | 58 | #warning Need to look up userspace_pid by cpu |
| @@ -59,10 +60,11 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr) | |||
| 59 | 60 | ||
| 60 | multi_count++; | 61 | multi_count++; |
| 61 | 62 | ||
| 62 | get_safe_registers(regs); | 63 | get_safe_registers(regs); |
| 63 | regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + | 64 | regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + |
| 64 | ((unsigned long) &batch_syscall_stub - | 65 | ((unsigned long) &batch_syscall_stub - |
| 65 | (unsigned long) &__syscall_stub_start); | 66 | (unsigned long) &__syscall_stub_start); |
| 67 | |||
| 66 | n = ptrace_setregs(pid, regs); | 68 | n = ptrace_setregs(pid, regs); |
| 67 | if(n < 0) | 69 | if(n < 0) |
| 68 | panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", | 70 | panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", |
| @@ -80,6 +82,8 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr) | |||
| 80 | if (offset) { | 82 | if (offset) { |
| 81 | data = (unsigned long *)(mm_idp->stack + | 83 | data = (unsigned long *)(mm_idp->stack + |
| 82 | offset - UML_CONFIG_STUB_DATA); | 84 | offset - UML_CONFIG_STUB_DATA); |
| 85 | printk("do_syscall_stub : ret = %d, offset = %d, " | ||
| 86 | "data = 0x%x\n", ret, offset, data); | ||
| 83 | syscall = (unsigned long *)((unsigned long)data + data[0]); | 87 | syscall = (unsigned long *)((unsigned long)data + data[0]); |
| 84 | printk("do_syscall_stub: syscall %ld failed, return value = " | 88 | printk("do_syscall_stub: syscall %ld failed, return value = " |
| 85 | "0x%lx, expected return value = 0x%lx\n", | 89 | "0x%lx, expected return value = 0x%lx\n", |
| @@ -107,32 +111,32 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr) | |||
| 107 | 111 | ||
| 108 | long run_syscall_stub(struct mm_id * mm_idp, int syscall, | 112 | long run_syscall_stub(struct mm_id * mm_idp, int syscall, |
| 109 | unsigned long *args, long expected, void **addr, | 113 | unsigned long *args, long expected, void **addr, |
| 110 | int done) | 114 | int done) |
| 111 | { | 115 | { |
| 112 | unsigned long *stack = check_init_stack(mm_idp, *addr); | 116 | unsigned long *stack = check_init_stack(mm_idp, *addr); |
| 113 | 117 | ||
| 114 | if(done && *addr == NULL) | 118 | if(done && *addr == NULL) |
| 115 | single_count++; | 119 | single_count++; |
| 116 | 120 | ||
| 117 | *stack += sizeof(long); | 121 | *stack += sizeof(long); |
| 118 | stack += *stack / sizeof(long); | 122 | stack += *stack / sizeof(long); |
| 119 | 123 | ||
| 120 | *stack++ = syscall; | 124 | *stack++ = syscall; |
| 121 | *stack++ = args[0]; | 125 | *stack++ = args[0]; |
| 122 | *stack++ = args[1]; | 126 | *stack++ = args[1]; |
| 123 | *stack++ = args[2]; | 127 | *stack++ = args[2]; |
| 124 | *stack++ = args[3]; | 128 | *stack++ = args[3]; |
| 125 | *stack++ = args[4]; | 129 | *stack++ = args[4]; |
| 126 | *stack++ = args[5]; | 130 | *stack++ = args[5]; |
| 127 | *stack++ = expected; | 131 | *stack++ = expected; |
| 128 | *stack = 0; | 132 | *stack = 0; |
| 129 | multi_op_count++; | 133 | multi_op_count++; |
| 130 | 134 | ||
| 131 | if(!done && ((((unsigned long) stack) & ~PAGE_MASK) < | 135 | if(!done && ((((unsigned long) stack) & ~PAGE_MASK) < |
| 132 | PAGE_SIZE - 10 * sizeof(long))){ | 136 | PAGE_SIZE - 10 * sizeof(long))){ |
| 133 | *addr = stack; | 137 | *addr = stack; |
| 134 | return 0; | 138 | return 0; |
| 135 | } | 139 | } |
| 136 | 140 | ||
| 137 | return do_syscall_stub(mm_idp, addr); | 141 | return do_syscall_stub(mm_idp, addr); |
| 138 | } | 142 | } |
| @@ -150,7 +154,7 @@ long syscall_stub_data(struct mm_id * mm_idp, | |||
| 150 | if((((unsigned long) *addr) & ~PAGE_MASK) >= | 154 | if((((unsigned long) *addr) & ~PAGE_MASK) >= |
| 151 | PAGE_SIZE - (10 + data_count) * sizeof(long)) { | 155 | PAGE_SIZE - (10 + data_count) * sizeof(long)) { |
| 152 | ret = do_syscall_stub(mm_idp, addr); | 156 | ret = do_syscall_stub(mm_idp, addr); |
| 153 | /* in case of error, don't overwrite data on stack */ | 157 | /* in case of error, don't overwrite data on stack */ |
| 154 | if(ret) | 158 | if(ret) |
| 155 | return ret; | 159 | return ret; |
| 156 | } | 160 | } |
| @@ -172,39 +176,39 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, | |||
| 172 | int r, int w, int x, int phys_fd, unsigned long long offset, | 176 | int r, int w, int x, int phys_fd, unsigned long long offset, |
| 173 | int done, void **data) | 177 | int done, void **data) |
| 174 | { | 178 | { |
| 175 | int prot, ret; | 179 | int prot, ret; |
| 176 | 180 | ||
| 177 | prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | | 181 | prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | |
| 178 | (x ? PROT_EXEC : 0); | 182 | (x ? PROT_EXEC : 0); |
| 179 | 183 | ||
| 180 | if(proc_mm){ | 184 | if(proc_mm){ |
| 181 | struct proc_mm_op map; | 185 | struct proc_mm_op map; |
| 182 | int fd = mm_idp->u.mm_fd; | 186 | int fd = mm_idp->u.mm_fd; |
| 183 | 187 | ||
| 184 | map = ((struct proc_mm_op) { .op = MM_MMAP, | 188 | map = ((struct proc_mm_op) { .op = MM_MMAP, |
| 185 | .u = | 189 | .u = |
| 186 | { .mmap = | 190 | { .mmap = |
| 187 | { .addr = virt, | 191 | { .addr = virt, |
| 188 | .len = len, | 192 | .len = len, |
| 189 | .prot = prot, | 193 | .prot = prot, |
| 190 | .flags = MAP_SHARED | | 194 | .flags = MAP_SHARED | |
| 191 | MAP_FIXED, | 195 | MAP_FIXED, |
| 192 | .fd = phys_fd, | 196 | .fd = phys_fd, |
| 193 | .offset= offset | 197 | .offset= offset |
| 194 | } } } ); | 198 | } } } ); |
| 195 | ret = os_write_file(fd, &map, sizeof(map)); | 199 | ret = os_write_file(fd, &map, sizeof(map)); |
| 196 | if(ret != sizeof(map)) | 200 | if(ret != sizeof(map)) |
| 197 | printk("map : /proc/mm map failed, err = %d\n", -ret); | 201 | printk("map : /proc/mm map failed, err = %d\n", -ret); |
| 198 | else ret = 0; | 202 | else ret = 0; |
| 199 | } | 203 | } |
| 200 | else { | 204 | else { |
| 201 | unsigned long args[] = { virt, len, prot, | 205 | unsigned long args[] = { virt, len, prot, |
| 202 | MAP_SHARED | MAP_FIXED, phys_fd, | 206 | MAP_SHARED | MAP_FIXED, phys_fd, |
| 203 | MMAP_OFFSET(offset) }; | 207 | MMAP_OFFSET(offset) }; |
| 204 | 208 | ||
| 205 | ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt, | 209 | ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt, |
| 206 | data, done); | 210 | data, done); |
| 207 | } | 211 | } |
| 208 | 212 | ||
| 209 | return ret; | 213 | return ret; |
| 210 | } | 214 | } |
| @@ -212,68 +216,66 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, | |||
| 212 | int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done, | 216 | int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done, |
| 213 | void **data) | 217 | void **data) |
| 214 | { | 218 | { |
| 215 | int ret; | 219 | int ret; |
| 216 | 220 | ||
| 217 | if(proc_mm){ | 221 | if(proc_mm){ |
| 218 | struct proc_mm_op unmap; | 222 | struct proc_mm_op unmap; |
| 219 | int fd = mm_idp->u.mm_fd; | 223 | int fd = mm_idp->u.mm_fd; |
| 220 | 224 | ||
| 221 | unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, | 225 | unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, |
| 222 | .u = | 226 | .u = |
| 223 | { .munmap = | 227 | { .munmap = |
| 224 | { .addr = | 228 | { .addr = |
| 225 | (unsigned long) addr, | 229 | (unsigned long) addr, |
| 226 | .len = len } } } ); | 230 | .len = len } } } ); |
| 227 | ret = os_write_file(fd, &unmap, sizeof(unmap)); | 231 | ret = os_write_file(fd, &unmap, sizeof(unmap)); |
| 228 | if(ret != sizeof(unmap)) | 232 | if(ret != sizeof(unmap)) |
| 229 | printk("unmap - proc_mm write returned %d\n", ret); | 233 | printk("unmap - proc_mm write returned %d\n", ret); |
| 230 | else ret = 0; | 234 | else ret = 0; |
| 231 | } | 235 | } |
| 232 | else { | 236 | else { |
| 233 | unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0, | 237 | unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0, |
| 234 | 0 }; | 238 | 0 }; |
| 235 | 239 | ||
| 236 | ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0, | 240 | ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0, |
| 237 | data, done); | 241 | data, done); |
| 238 | if(ret < 0) | 242 | } |
| 239 | printk("munmap stub failed, errno = %d\n", ret); | ||
| 240 | } | ||
| 241 | 243 | ||
| 242 | return ret; | 244 | return ret; |
| 243 | } | 245 | } |
| 244 | 246 | ||
| 245 | int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, | 247 | int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, |
| 246 | int r, int w, int x, int done, void **data) | 248 | int r, int w, int x, int done, void **data) |
| 247 | { | 249 | { |
| 248 | struct proc_mm_op protect; | 250 | struct proc_mm_op protect; |
| 249 | int prot, ret; | 251 | int prot, ret; |
| 250 | 252 | ||
| 251 | prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | | 253 | prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | |
| 252 | (x ? PROT_EXEC : 0); | 254 | (x ? PROT_EXEC : 0); |
| 253 | 255 | if(proc_mm){ | |
| 254 | if(proc_mm){ | 256 | int fd = mm_idp->u.mm_fd; |
| 255 | int fd = mm_idp->u.mm_fd; | 257 | |
| 256 | protect = ((struct proc_mm_op) { .op = MM_MPROTECT, | 258 | protect = ((struct proc_mm_op) { .op = MM_MPROTECT, |
| 257 | .u = | 259 | .u = |
| 258 | { .mprotect = | 260 | { .mprotect = |
| 259 | { .addr = | 261 | { .addr = |
| 260 | (unsigned long) addr, | 262 | (unsigned long) addr, |
| 261 | .len = len, | 263 | .len = len, |
| 262 | .prot = prot } } } ); | 264 | .prot = prot } } } ); |
| 263 | 265 | ||
| 264 | ret = os_write_file(fd, &protect, sizeof(protect)); | 266 | ret = os_write_file(fd, &protect, sizeof(protect)); |
| 265 | if(ret != sizeof(protect)) | 267 | if(ret != sizeof(protect)) |
| 266 | printk("protect failed, err = %d", -ret); | 268 | printk("protect failed, err = %d", -ret); |
| 267 | else ret = 0; | 269 | else ret = 0; |
| 268 | } | 270 | } |
| 269 | else { | 271 | else { |
| 270 | unsigned long args[] = { addr, len, prot, 0, 0, 0 }; | 272 | unsigned long args[] = { addr, len, prot, 0, 0, 0 }; |
| 271 | 273 | ||
| 272 | ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0, | 274 | ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0, |
| 273 | data, done); | 275 | data, done); |
| 274 | } | 276 | } |
| 275 | 277 | ||
| 276 | return ret; | 278 | return ret; |
| 277 | } | 279 | } |
| 278 | 280 | ||
| 279 | void before_mem_skas(unsigned long unused) | 281 | void before_mem_skas(unsigned long unused) |
