diff options
| author | Anton Altaparmakov <aia21@cantab.net> | 2006-02-24 04:06:36 -0500 |
|---|---|---|
| committer | Anton Altaparmakov <aia21@cantab.net> | 2006-02-24 04:06:36 -0500 |
| commit | fab8d6ddf6dee2608869005d45fe97f70e4f5bdd (patch) | |
| tree | fecf566e03a87b2a44c7f3363ddb5c0d4bebdca7 /arch/um/kernel | |
| parent | 64419d93a5906600af5817ad0cae3c6ecf7fb389 (diff) | |
| parent | f52ee1410d563cd409b08822492273a5bc235821 (diff) | |
Merge branch 'master' of /home/src/linux-2.6/
Diffstat (limited to 'arch/um/kernel')
| -rw-r--r-- | arch/um/kernel/exec_kern.c | 2 | ||||
| -rw-r--r-- | arch/um/kernel/physmem.c | 2 | ||||
| -rw-r--r-- | arch/um/kernel/reboot.c | 1 | ||||
| -rw-r--r-- | arch/um/kernel/skas/process.c | 569 | ||||
| -rw-r--r-- | arch/um/kernel/tt/syscall_kern.c | 8 | ||||
| -rw-r--r-- | arch/um/kernel/um_arch.c | 18 |
6 files changed, 27 insertions, 573 deletions
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c index 569fe8b9b053..c264e1c05ab3 100644 --- a/arch/um/kernel/exec_kern.c +++ b/arch/um/kernel/exec_kern.c | |||
| @@ -33,7 +33,7 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) | |||
| 33 | extern void log_exec(char **argv, void *tty); | 33 | extern void log_exec(char **argv, void *tty); |
| 34 | 34 | ||
| 35 | static long execve1(char *file, char __user * __user *argv, | 35 | static long execve1(char *file, char __user * __user *argv, |
| 36 | char *__user __user *env) | 36 | char __user *__user *env) |
| 37 | { | 37 | { |
| 38 | long error; | 38 | long error; |
| 39 | 39 | ||
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index f3b583a878a6..544665e04513 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c | |||
| @@ -265,7 +265,7 @@ int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem) | |||
| 265 | highmem_len = highmem_pages * sizeof(struct page); | 265 | highmem_len = highmem_pages * sizeof(struct page); |
| 266 | 266 | ||
| 267 | total_pages = phys_pages + iomem_pages + highmem_pages; | 267 | total_pages = phys_pages + iomem_pages + highmem_pages; |
| 268 | total_len = phys_len + iomem_pages + highmem_len; | 268 | total_len = phys_len + iomem_len + highmem_len; |
| 269 | 269 | ||
| 270 | if(kmalloc_ok){ | 270 | if(kmalloc_ok){ |
| 271 | map = kmalloc(total_len, GFP_KERNEL); | 271 | map = kmalloc(total_len, GFP_KERNEL); |
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index 6f1a3a288117..3ef73bf2e781 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include "linux/module.h" | 6 | #include "linux/module.h" |
| 7 | #include "linux/sched.h" | 7 | #include "linux/sched.h" |
| 8 | #include "asm/smp.h" | ||
| 8 | #include "user_util.h" | 9 | #include "user_util.h" |
| 9 | #include "kern_util.h" | 10 | #include "kern_util.h" |
| 10 | #include "kern.h" | 11 | #include "kern.h" |
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c deleted file mode 100644 index eea1c9c4bb0f..000000000000 --- a/arch/um/kernel/skas/process.c +++ /dev/null | |||
| @@ -1,569 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com) | ||
| 3 | * Licensed under the GPL | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <stdlib.h> | ||
| 7 | #include <string.h> | ||
| 8 | #include <unistd.h> | ||
| 9 | #include <errno.h> | ||
| 10 | #include <signal.h> | ||
| 11 | #include <setjmp.h> | ||
| 12 | #include <sched.h> | ||
| 13 | #include <sys/wait.h> | ||
| 14 | #include <sys/mman.h> | ||
| 15 | #include <sys/user.h> | ||
| 16 | #include <sys/time.h> | ||
| 17 | #include <asm/unistd.h> | ||
| 18 | #include <asm/types.h> | ||
| 19 | #include "user.h" | ||
| 20 | #include "ptrace_user.h" | ||
| 21 | #include "sysdep/ptrace.h" | ||
| 22 | #include "user_util.h" | ||
| 23 | #include "kern_util.h" | ||
| 24 | #include "skas.h" | ||
| 25 | #include "stub-data.h" | ||
| 26 | #include "mm_id.h" | ||
| 27 | #include "sysdep/sigcontext.h" | ||
| 28 | #include "sysdep/stub.h" | ||
| 29 | #include "os.h" | ||
| 30 | #include "proc_mm.h" | ||
| 31 | #include "skas_ptrace.h" | ||
| 32 | #include "chan_user.h" | ||
| 33 | #include "registers.h" | ||
| 34 | #include "mem.h" | ||
| 35 | #include "uml-config.h" | ||
| 36 | #include "process.h" | ||
| 37 | |||
| 38 | int is_skas_winch(int pid, int fd, void *data) | ||
| 39 | { | ||
| 40 | if(pid != os_getpgrp()) | ||
| 41 | return(0); | ||
| 42 | |||
| 43 | register_winch_irq(-1, fd, -1, data); | ||
| 44 | return(1); | ||
| 45 | } | ||
| 46 | |||
| 47 | void wait_stub_done(int pid, int sig, char * fname) | ||
| 48 | { | ||
| 49 | int n, status, err; | ||
| 50 | |||
| 51 | do { | ||
| 52 | if ( sig != -1 ) { | ||
| 53 | err = ptrace(PTRACE_CONT, pid, 0, sig); | ||
| 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 | /* running UML inside a detached screen can cause | ||
| 64 | * SIGWINCHes | ||
| 65 | */ | ||
| 66 | (WSTOPSIG(status) == SIGWINCH))); | ||
| 67 | |||
| 68 | if((n < 0) || !WIFSTOPPED(status) || | ||
| 69 | (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ | ||
| 70 | unsigned long regs[HOST_FRAME_SIZE]; | ||
| 71 | if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) | ||
| 72 | printk("Failed to get registers from stub, " | ||
| 73 | "errno = %d\n", errno); | ||
| 74 | else { | ||
| 75 | int i; | ||
| 76 | |||
| 77 | printk("Stub registers -\n"); | ||
| 78 | for(i = 0; i < HOST_FRAME_SIZE; i++) | ||
| 79 | printk("\t%d - %lx\n", i, regs[i]); | ||
| 80 | } | ||
| 81 | panic("%s : failed to wait for SIGUSR1/SIGTRAP, " | ||
| 82 | "pid = %d, n = %d, errno = %d, status = 0x%x\n", | ||
| 83 | fname, pid, n, errno, status); | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | void get_skas_faultinfo(int pid, struct faultinfo * fi) | ||
| 88 | { | ||
| 89 | int err; | ||
| 90 | |||
| 91 | if(ptrace_faultinfo){ | ||
| 92 | err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); | ||
| 93 | if(err) | ||
| 94 | panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " | ||
| 95 | "errno = %d\n", errno); | ||
| 96 | |||
| 97 | /* Special handling for i386, which has different structs */ | ||
| 98 | if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo)) | ||
| 99 | memset((char *)fi + sizeof(struct ptrace_faultinfo), 0, | ||
| 100 | sizeof(struct faultinfo) - | ||
| 101 | sizeof(struct ptrace_faultinfo)); | ||
| 102 | } | ||
| 103 | else { | ||
| 104 | wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo"); | ||
| 105 | |||
| 106 | /* faultinfo is prepared by the stub-segv-handler at start of | ||
| 107 | * the stub stack page. We just have to copy it. | ||
| 108 | */ | ||
| 109 | memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | static void handle_segv(int pid, union uml_pt_regs * regs) | ||
| 114 | { | ||
| 115 | get_skas_faultinfo(pid, ®s->skas.faultinfo); | ||
| 116 | segv(regs->skas.faultinfo, 0, 1, NULL); | ||
| 117 | } | ||
| 118 | |||
| 119 | /*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/ | ||
| 120 | static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu) | ||
| 121 | { | ||
| 122 | int err, status; | ||
| 123 | |||
| 124 | /* Mark this as a syscall */ | ||
| 125 | UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs); | ||
| 126 | |||
| 127 | if (!local_using_sysemu) | ||
| 128 | { | ||
| 129 | err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid); | ||
| 130 | if(err < 0) | ||
| 131 | panic("handle_trap - nullifying syscall failed errno = %d\n", | ||
| 132 | errno); | ||
| 133 | |||
| 134 | err = ptrace(PTRACE_SYSCALL, pid, 0, 0); | ||
| 135 | if(err < 0) | ||
| 136 | panic("handle_trap - continuing to end of syscall failed, " | ||
| 137 | "errno = %d\n", errno); | ||
| 138 | |||
| 139 | CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); | ||
| 140 | if((err < 0) || !WIFSTOPPED(status) || | ||
| 141 | (WSTOPSIG(status) != SIGTRAP + 0x80)) | ||
| 142 | panic("handle_trap - failed to wait at end of syscall, " | ||
| 143 | "errno = %d, status = %d\n", errno, status); | ||
| 144 | } | ||
| 145 | |||
| 146 | handle_syscall(regs); | ||
| 147 | } | ||
| 148 | |||
| 149 | extern int __syscall_stub_start; | ||
| 150 | int stub_code_fd = -1; | ||
| 151 | __u64 stub_code_offset; | ||
| 152 | |||
| 153 | static int userspace_tramp(void *stack) | ||
| 154 | { | ||
| 155 | void *addr; | ||
| 156 | |||
| 157 | ptrace(PTRACE_TRACEME, 0, 0, 0); | ||
| 158 | |||
| 159 | init_new_thread_signals(1); | ||
| 160 | enable_timer(); | ||
| 161 | |||
| 162 | if(!proc_mm){ | ||
| 163 | /* This has a pte, but it can't be mapped in with the usual | ||
| 164 | * tlb_flush mechanism because this is part of that mechanism | ||
| 165 | */ | ||
| 166 | addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(), | ||
| 167 | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, | ||
| 168 | stub_code_fd, stub_code_offset); | ||
| 169 | if(addr == MAP_FAILED){ | ||
| 170 | printk("mapping stub code failed, errno = %d\n", | ||
| 171 | errno); | ||
| 172 | exit(1); | ||
| 173 | } | ||
| 174 | |||
| 175 | if(stack != NULL){ | ||
| 176 | int fd; | ||
| 177 | __u64 offset; | ||
| 178 | |||
| 179 | fd = phys_mapping(to_phys(stack), &offset); | ||
| 180 | addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(), | ||
| 181 | PROT_READ | PROT_WRITE, | ||
| 182 | MAP_FIXED | MAP_SHARED, fd, offset); | ||
| 183 | if(addr == MAP_FAILED){ | ||
| 184 | printk("mapping stub stack failed, " | ||
| 185 | "errno = %d\n", errno); | ||
| 186 | exit(1); | ||
| 187 | } | ||
| 188 | } | ||
| 189 | } | ||
| 190 | if(!ptrace_faultinfo){ | ||
| 191 | unsigned long v = UML_CONFIG_STUB_CODE + | ||
| 192 | (unsigned long) stub_segv_handler - | ||
| 193 | (unsigned long) &__syscall_stub_start; | ||
| 194 | |||
| 195 | set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size()); | ||
| 196 | set_handler(SIGSEGV, (void *) v, SA_ONSTACK, | ||
| 197 | SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, | ||
| 198 | SIGUSR1, -1); | ||
| 199 | } | ||
| 200 | |||
| 201 | os_stop_process(os_getpid()); | ||
| 202 | return(0); | ||
| 203 | } | ||
| 204 | |||
| 205 | /* Each element set once, and only accessed by a single processor anyway */ | ||
| 206 | #undef NR_CPUS | ||
| 207 | #define NR_CPUS 1 | ||
| 208 | int userspace_pid[NR_CPUS]; | ||
| 209 | |||
| 210 | int start_userspace(unsigned long stub_stack) | ||
| 211 | { | ||
| 212 | void *stack; | ||
| 213 | unsigned long sp; | ||
| 214 | int pid, status, n, flags; | ||
| 215 | |||
| 216 | if ( stub_code_fd == -1 ) | ||
| 217 | stub_code_fd = phys_mapping(to_phys(&__syscall_stub_start), | ||
| 218 | &stub_code_offset); | ||
| 219 | |||
| 220 | stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, | ||
| 221 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | ||
| 222 | if(stack == MAP_FAILED) | ||
| 223 | panic("start_userspace : mmap failed, errno = %d", errno); | ||
| 224 | sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); | ||
| 225 | |||
| 226 | flags = CLONE_FILES | SIGCHLD; | ||
| 227 | if(proc_mm) flags |= CLONE_VM; | ||
| 228 | pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); | ||
| 229 | if(pid < 0) | ||
| 230 | panic("start_userspace : clone failed, errno = %d", errno); | ||
| 231 | |||
| 232 | do { | ||
| 233 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | ||
| 234 | if(n < 0) | ||
| 235 | panic("start_userspace : wait failed, errno = %d", | ||
| 236 | errno); | ||
| 237 | } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); | ||
| 238 | |||
| 239 | if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) | ||
| 240 | panic("start_userspace : expected SIGSTOP, got status = %d", | ||
| 241 | status); | ||
| 242 | |||
| 243 | if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0) | ||
| 244 | panic("start_userspace : PTRACE_SETOPTIONS failed, errno=%d\n", | ||
| 245 | errno); | ||
| 246 | |||
| 247 | if(munmap(stack, PAGE_SIZE) < 0) | ||
| 248 | panic("start_userspace : munmap failed, errno = %d\n", errno); | ||
| 249 | |||
| 250 | return(pid); | ||
| 251 | } | ||
| 252 | |||
| 253 | void userspace(union uml_pt_regs *regs) | ||
| 254 | { | ||
| 255 | int err, status, op, pid = userspace_pid[0]; | ||
| 256 | int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/ | ||
| 257 | |||
| 258 | while(1){ | ||
| 259 | restore_registers(pid, regs); | ||
| 260 | |||
| 261 | /* Now we set local_using_sysemu to be used for one loop */ | ||
| 262 | local_using_sysemu = get_using_sysemu(); | ||
| 263 | |||
| 264 | op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL)); | ||
| 265 | |||
| 266 | err = ptrace(op, pid, 0, 0); | ||
| 267 | if(err) | ||
| 268 | panic("userspace - could not resume userspace process, " | ||
| 269 | "pid=%d, ptrace operation = %d, errno = %d\n", | ||
| 270 | op, errno); | ||
| 271 | |||
| 272 | CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); | ||
| 273 | if(err < 0) | ||
| 274 | panic("userspace - waitpid failed, errno = %d\n", | ||
| 275 | errno); | ||
| 276 | |||
| 277 | regs->skas.is_user = 1; | ||
| 278 | save_registers(pid, regs); | ||
| 279 | UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ | ||
| 280 | |||
| 281 | if(WIFSTOPPED(status)){ | ||
| 282 | switch(WSTOPSIG(status)){ | ||
| 283 | case SIGSEGV: | ||
| 284 | if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) | ||
| 285 | user_signal(SIGSEGV, regs, pid); | ||
| 286 | else handle_segv(pid, regs); | ||
| 287 | break; | ||
| 288 | case SIGTRAP + 0x80: | ||
| 289 | handle_trap(pid, regs, local_using_sysemu); | ||
| 290 | break; | ||
| 291 | case SIGTRAP: | ||
| 292 | relay_signal(SIGTRAP, regs); | ||
| 293 | break; | ||
| 294 | case SIGIO: | ||
| 295 | case SIGVTALRM: | ||
| 296 | case SIGILL: | ||
| 297 | case SIGBUS: | ||
| 298 | case SIGFPE: | ||
| 299 | case SIGWINCH: | ||
| 300 | user_signal(WSTOPSIG(status), regs, pid); | ||
| 301 | break; | ||
| 302 | default: | ||
| 303 | printk("userspace - child stopped with signal " | ||
| 304 | "%d\n", WSTOPSIG(status)); | ||
| 305 | } | ||
| 306 | pid = userspace_pid[0]; | ||
| 307 | interrupt_end(); | ||
| 308 | |||
| 309 | /* Avoid -ERESTARTSYS handling in host */ | ||
| 310 | PT_SYSCALL_NR(regs->skas.regs) = -1; | ||
| 311 | } | ||
| 312 | } | ||
| 313 | } | ||
| 314 | #define INIT_JMP_NEW_THREAD 0 | ||
| 315 | #define INIT_JMP_REMOVE_SIGSTACK 1 | ||
| 316 | #define INIT_JMP_CALLBACK 2 | ||
| 317 | #define INIT_JMP_HALT 3 | ||
| 318 | #define INIT_JMP_REBOOT 4 | ||
| 319 | |||
| 320 | |||
| 321 | int copy_context_skas0(unsigned long new_stack, int pid) | ||
| 322 | { | ||
| 323 | int err; | ||
| 324 | unsigned long regs[MAX_REG_NR]; | ||
| 325 | unsigned long current_stack = current_stub_stack(); | ||
| 326 | struct stub_data *data = (struct stub_data *) current_stack; | ||
| 327 | struct stub_data *child_data = (struct stub_data *) new_stack; | ||
| 328 | __u64 new_offset; | ||
| 329 | int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset); | ||
| 330 | |||
| 331 | /* prepare offset and fd of child's stack as argument for parent's | ||
| 332 | * and child's mmap2 calls | ||
| 333 | */ | ||
| 334 | *data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset), | ||
| 335 | .fd = new_fd, | ||
| 336 | .timer = ((struct itimerval) | ||
| 337 | { { 0, 1000000 / hz() }, | ||
| 338 | { 0, 1000000 / hz() }})}); | ||
| 339 | get_safe_registers(regs); | ||
| 340 | |||
| 341 | /* Set parent's instruction pointer to start of clone-stub */ | ||
| 342 | regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + | ||
| 343 | (unsigned long) stub_clone_handler - | ||
| 344 | (unsigned long) &__syscall_stub_start; | ||
| 345 | regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE - | ||
| 346 | sizeof(void *); | ||
| 347 | err = ptrace_setregs(pid, regs); | ||
| 348 | if(err < 0) | ||
| 349 | panic("copy_context_skas0 : PTRACE_SETREGS failed, " | ||
| 350 | "pid = %d, errno = %d\n", pid, errno); | ||
| 351 | |||
| 352 | /* set a well known return code for detection of child write failure */ | ||
| 353 | child_data->err = 12345678; | ||
| 354 | |||
| 355 | /* Wait, until parent has finished its work: read child's pid from | ||
| 356 | * parent's stack, and check, if bad result. | ||
| 357 | */ | ||
| 358 | wait_stub_done(pid, 0, "copy_context_skas0"); | ||
| 359 | |||
| 360 | pid = data->err; | ||
| 361 | if(pid < 0) | ||
| 362 | panic("copy_context_skas0 - stub-parent reports error %d\n", | ||
| 363 | pid); | ||
| 364 | |||
| 365 | /* Wait, until child has finished too: read child's result from | ||
| 366 | * child's stack and check it. | ||
| 367 | */ | ||
| 368 | wait_stub_done(pid, -1, "copy_context_skas0"); | ||
| 369 | if (child_data->err != UML_CONFIG_STUB_DATA) | ||
| 370 | panic("copy_context_skas0 - stub-child reports error %d\n", | ||
| 371 | child_data->err); | ||
| 372 | |||
| 373 | if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, | ||
| 374 | (void *)PTRACE_O_TRACESYSGOOD) < 0) | ||
| 375 | panic("copy_context_skas0 : PTRACE_SETOPTIONS failed, " | ||
| 376 | "errno = %d\n", errno); | ||
| 377 | |||
| 378 | return pid; | ||
| 379 | } | ||
| 380 | |||
| 381 | /* | ||
| 382 | * This is used only, if stub pages are needed, while proc_mm is | ||
| 383 | * availabl. Opening /proc/mm creates a new mm_context, which lacks | ||
| 384 | * the stub-pages. Thus, we map them using /proc/mm-fd | ||
| 385 | */ | ||
| 386 | void map_stub_pages(int fd, unsigned long code, | ||
| 387 | unsigned long data, unsigned long stack) | ||
| 388 | { | ||
| 389 | struct proc_mm_op mmop; | ||
| 390 | int n; | ||
| 391 | |||
| 392 | mmop = ((struct proc_mm_op) { .op = MM_MMAP, | ||
| 393 | .u = | ||
| 394 | { .mmap = | ||
| 395 | { .addr = code, | ||
| 396 | .len = PAGE_SIZE, | ||
| 397 | .prot = PROT_EXEC, | ||
| 398 | .flags = MAP_FIXED | MAP_PRIVATE, | ||
| 399 | .fd = stub_code_fd, | ||
| 400 | .offset = stub_code_offset | ||
| 401 | } } }); | ||
| 402 | n = os_write_file(fd, &mmop, sizeof(mmop)); | ||
| 403 | if(n != sizeof(mmop)) | ||
| 404 | panic("map_stub_pages : /proc/mm map for code failed, " | ||
| 405 | "err = %d\n", -n); | ||
| 406 | |||
| 407 | if ( stack ) { | ||
| 408 | __u64 map_offset; | ||
| 409 | int map_fd = phys_mapping(to_phys((void *)stack), &map_offset); | ||
| 410 | mmop = ((struct proc_mm_op) | ||
| 411 | { .op = MM_MMAP, | ||
| 412 | .u = | ||
| 413 | { .mmap = | ||
| 414 | { .addr = data, | ||
| 415 | .len = PAGE_SIZE, | ||
| 416 | .prot = PROT_READ | PROT_WRITE, | ||
| 417 | .flags = MAP_FIXED | MAP_SHARED, | ||
| 418 | .fd = map_fd, | ||
| 419 | .offset = map_offset | ||
| 420 | } } }); | ||
| 421 | n = os_write_file(fd, &mmop, sizeof(mmop)); | ||
| 422 | if(n != sizeof(mmop)) | ||
| 423 | panic("map_stub_pages : /proc/mm map for data failed, " | ||
| 424 | "err = %d\n", -n); | ||
| 425 | } | ||
| 426 | } | ||
| 427 | |||
| 428 | void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, | ||
| 429 | void (*handler)(int)) | ||
| 430 | { | ||
| 431 | unsigned long flags; | ||
| 432 | sigjmp_buf switch_buf, fork_buf; | ||
| 433 | |||
| 434 | *switch_buf_ptr = &switch_buf; | ||
| 435 | *fork_buf_ptr = &fork_buf; | ||
| 436 | |||
| 437 | /* Somewhat subtle - siglongjmp restores the signal mask before doing | ||
| 438 | * the longjmp. This means that when jumping from one stack to another | ||
| 439 | * when the target stack has interrupts enabled, an interrupt may occur | ||
| 440 | * on the source stack. This is bad when starting up a process because | ||
| 441 | * it's not supposed to get timer ticks until it has been scheduled. | ||
| 442 | * So, we disable interrupts around the sigsetjmp to ensure that | ||
| 443 | * they can't happen until we get back here where they are safe. | ||
| 444 | */ | ||
| 445 | flags = get_signals(); | ||
| 446 | block_signals(); | ||
| 447 | if(sigsetjmp(fork_buf, 1) == 0) | ||
| 448 | new_thread_proc(stack, handler); | ||
| 449 | |||
| 450 | remove_sigstack(); | ||
| 451 | |||
| 452 | set_signals(flags); | ||
| 453 | } | ||
| 454 | |||
| 455 | void thread_wait(void *sw, void *fb) | ||
| 456 | { | ||
| 457 | sigjmp_buf buf, **switch_buf = sw, *fork_buf; | ||
| 458 | |||
| 459 | *switch_buf = &buf; | ||
| 460 | fork_buf = fb; | ||
| 461 | if(sigsetjmp(buf, 1) == 0) | ||
| 462 | siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK); | ||
| 463 | } | ||
| 464 | |||
| 465 | void switch_threads(void *me, void *next) | ||
| 466 | { | ||
| 467 | sigjmp_buf my_buf, **me_ptr = me, *next_buf = next; | ||
| 468 | |||
| 469 | *me_ptr = &my_buf; | ||
| 470 | if(sigsetjmp(my_buf, 1) == 0) | ||
| 471 | siglongjmp(*next_buf, 1); | ||
| 472 | } | ||
| 473 | |||
| 474 | static sigjmp_buf initial_jmpbuf; | ||
| 475 | |||
| 476 | /* XXX Make these percpu */ | ||
| 477 | static void (*cb_proc)(void *arg); | ||
| 478 | static void *cb_arg; | ||
| 479 | static sigjmp_buf *cb_back; | ||
| 480 | |||
| 481 | int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) | ||
| 482 | { | ||
| 483 | sigjmp_buf **switch_buf = switch_buf_ptr; | ||
| 484 | int n; | ||
| 485 | |||
| 486 | set_handler(SIGWINCH, (__sighandler_t) sig_handler, | ||
| 487 | SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, | ||
| 488 | SIGVTALRM, -1); | ||
| 489 | |||
| 490 | *fork_buf_ptr = &initial_jmpbuf; | ||
| 491 | n = sigsetjmp(initial_jmpbuf, 1); | ||
| 492 | switch(n){ | ||
| 493 | case INIT_JMP_NEW_THREAD: | ||
| 494 | new_thread_proc((void *) stack, new_thread_handler); | ||
| 495 | break; | ||
| 496 | case INIT_JMP_REMOVE_SIGSTACK: | ||
| 497 | remove_sigstack(); | ||
| 498 | break; | ||
| 499 | case INIT_JMP_CALLBACK: | ||
| 500 | (*cb_proc)(cb_arg); | ||
| 501 | siglongjmp(*cb_back, 1); | ||
| 502 | break; | ||
| 503 | case INIT_JMP_HALT: | ||
| 504 | kmalloc_ok = 0; | ||
| 505 | return(0); | ||
| 506 | case INIT_JMP_REBOOT: | ||
| 507 | kmalloc_ok = 0; | ||
| 508 | return(1); | ||
| 509 | default: | ||
| 510 | panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); | ||
| 511 | } | ||
| 512 | siglongjmp(**switch_buf, 1); | ||
| 513 | } | ||
| 514 | |||
| 515 | void initial_thread_cb_skas(void (*proc)(void *), void *arg) | ||
| 516 | { | ||
| 517 | sigjmp_buf here; | ||
| 518 | |||
| 519 | cb_proc = proc; | ||
| 520 | cb_arg = arg; | ||
| 521 | cb_back = &here; | ||
| 522 | |||
| 523 | block_signals(); | ||
| 524 | if(sigsetjmp(here, 1) == 0) | ||
| 525 | siglongjmp(initial_jmpbuf, INIT_JMP_CALLBACK); | ||
| 526 | unblock_signals(); | ||
| 527 | |||
| 528 | cb_proc = NULL; | ||
| 529 | cb_arg = NULL; | ||
| 530 | cb_back = NULL; | ||
| 531 | } | ||
| 532 | |||
| 533 | void halt_skas(void) | ||
| 534 | { | ||
| 535 | block_signals(); | ||
| 536 | siglongjmp(initial_jmpbuf, INIT_JMP_HALT); | ||
| 537 | } | ||
| 538 | |||
| 539 | void reboot_skas(void) | ||
| 540 | { | ||
| 541 | block_signals(); | ||
| 542 | siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT); | ||
| 543 | } | ||
| 544 | |||
| 545 | void switch_mm_skas(struct mm_id *mm_idp) | ||
| 546 | { | ||
| 547 | int err; | ||
| 548 | |||
| 549 | #warning need cpu pid in switch_mm_skas | ||
| 550 | if(proc_mm){ | ||
| 551 | err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, | ||
| 552 | mm_idp->u.mm_fd); | ||
| 553 | if(err) | ||
| 554 | panic("switch_mm_skas - PTRACE_SWITCH_MM failed, " | ||
| 555 | "errno = %d\n", errno); | ||
| 556 | } | ||
| 557 | else userspace_pid[0] = mm_idp->u.pid; | ||
| 558 | } | ||
| 559 | |||
| 560 | /* | ||
| 561 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
| 562 | * Emacs will notice this stuff at the end of the file and automatically | ||
| 563 | * adjust the settings for this buffer only. This must remain at the end | ||
| 564 | * of the file. | ||
| 565 | * --------------------------------------------------------------------------- | ||
| 566 | * Local variables: | ||
| 567 | * c-file-style: "linux" | ||
| 568 | * End: | ||
| 569 | */ | ||
diff --git a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c index 3d29c90514cc..3fda9a03c59a 100644 --- a/arch/um/kernel/tt/syscall_kern.c +++ b/arch/um/kernel/tt/syscall_kern.c | |||
| @@ -23,16 +23,20 @@ void syscall_handler_tt(int sig, struct pt_regs *regs) | |||
| 23 | int syscall; | 23 | int syscall; |
| 24 | #ifdef CONFIG_SYSCALL_DEBUG | 24 | #ifdef CONFIG_SYSCALL_DEBUG |
| 25 | int index; | 25 | int index; |
| 26 | index = record_syscall_start(syscall); | ||
| 27 | #endif | 26 | #endif |
| 28 | sc = UPT_SC(®s->regs); | 27 | sc = UPT_SC(®s->regs); |
| 29 | SC_START_SYSCALL(sc); | 28 | SC_START_SYSCALL(sc); |
| 30 | 29 | ||
| 30 | syscall = UPT_SYSCALL_NR(®s->regs); | ||
| 31 | |||
| 32 | #ifdef CONFIG_SYSCALL_DEBUG | ||
| 33 | index = record_syscall_start(syscall); | ||
| 34 | #endif | ||
| 35 | |||
| 31 | syscall_trace(®s->regs, 0); | 36 | syscall_trace(®s->regs, 0); |
| 32 | 37 | ||
| 33 | current->thread.nsyscalls++; | 38 | current->thread.nsyscalls++; |
| 34 | nsyscalls++; | 39 | nsyscalls++; |
| 35 | syscall = UPT_SYSCALL_NR(®s->regs); | ||
| 36 | 40 | ||
| 37 | if((syscall >= NR_syscalls) || (syscall < 0)) | 41 | if((syscall >= NR_syscalls) || (syscall < 0)) |
| 38 | result = -ENOSYS; | 42 | result = -ENOSYS; |
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index e2d3ca445ef5..27cdf9164422 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c | |||
| @@ -193,6 +193,24 @@ __uml_setup("root=", uml_root_setup, | |||
| 193 | " root=/dev/ubd5\n\n" | 193 | " root=/dev/ubd5\n\n" |
| 194 | ); | 194 | ); |
| 195 | 195 | ||
| 196 | #ifndef CONFIG_MODE_TT | ||
| 197 | |||
| 198 | static int __init no_skas_debug_setup(char *line, int *add) | ||
| 199 | { | ||
| 200 | printf("'debug' is not necessary to gdb UML in skas mode - run \n"); | ||
| 201 | printf("'gdb linux' and disable CONFIG_CMDLINE_ON_HOST if gdb \n"); | ||
| 202 | printf("doesn't work as expected\n"); | ||
| 203 | |||
| 204 | return 0; | ||
| 205 | } | ||
| 206 | |||
| 207 | __uml_setup("debug", no_skas_debug_setup, | ||
| 208 | "debug\n" | ||
| 209 | " this flag is not needed to run gdb on UML in skas mode\n\n" | ||
| 210 | ); | ||
| 211 | |||
| 212 | #endif | ||
| 213 | |||
| 196 | #ifdef CONFIG_SMP | 214 | #ifdef CONFIG_SMP |
| 197 | static int __init uml_ncpus_setup(char *line, int *add) | 215 | static int __init uml_ncpus_setup(char *line, int *add) |
| 198 | { | 216 | { |
