diff options
Diffstat (limited to 'arch/um/kernel')
| -rw-r--r-- | arch/um/kernel/exec_kern.c | 16 | ||||
| -rw-r--r-- | arch/um/kernel/mem.c | 2 | ||||
| -rw-r--r-- | arch/um/kernel/process_kern.c | 26 | ||||
| -rw-r--r-- | arch/um/kernel/ptrace.c | 44 | ||||
| -rw-r--r-- | arch/um/kernel/skas/process_kern.c | 11 | ||||
| -rw-r--r-- | arch/um/kernel/syscall_kern.c | 4 | ||||
| -rw-r--r-- | arch/um/kernel/trap_kern.c | 8 | ||||
| -rw-r--r-- | arch/um/kernel/tt/process_kern.c | 10 |
8 files changed, 73 insertions, 48 deletions
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c index 1ca84319317d..c0cb627bf594 100644 --- a/arch/um/kernel/exec_kern.c +++ b/arch/um/kernel/exec_kern.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | 22 | ||
| 23 | void flush_thread(void) | 23 | void flush_thread(void) |
| 24 | { | 24 | { |
| 25 | arch_flush_thread(¤t->thread.arch); | ||
| 25 | CHOOSE_MODE(flush_thread_tt(), flush_thread_skas()); | 26 | CHOOSE_MODE(flush_thread_tt(), flush_thread_skas()); |
| 26 | } | 27 | } |
| 27 | 28 | ||
| @@ -58,14 +59,14 @@ long um_execve(char *file, char __user *__user *argv, char __user *__user *env) | |||
| 58 | return(err); | 59 | return(err); |
| 59 | } | 60 | } |
| 60 | 61 | ||
| 61 | long sys_execve(char *file, char __user *__user *argv, | 62 | long sys_execve(char __user *file, char __user *__user *argv, |
| 62 | char __user *__user *env) | 63 | char __user *__user *env) |
| 63 | { | 64 | { |
| 64 | long error; | 65 | long error; |
| 65 | char *filename; | 66 | char *filename; |
| 66 | 67 | ||
| 67 | lock_kernel(); | 68 | lock_kernel(); |
| 68 | filename = getname((char __user *) file); | 69 | filename = getname(file); |
| 69 | error = PTR_ERR(filename); | 70 | error = PTR_ERR(filename); |
| 70 | if (IS_ERR(filename)) goto out; | 71 | if (IS_ERR(filename)) goto out; |
| 71 | error = execve1(filename, argv, env); | 72 | error = execve1(filename, argv, env); |
| @@ -74,14 +75,3 @@ long sys_execve(char *file, char __user *__user *argv, | |||
| 74 | unlock_kernel(); | 75 | unlock_kernel(); |
| 75 | return(error); | 76 | return(error); |
| 76 | } | 77 | } |
| 77 | |||
| 78 | /* | ||
| 79 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
| 80 | * Emacs will notice this stuff at the end of the file and automatically | ||
| 81 | * adjust the settings for this buffer only. This must remain at the end | ||
| 82 | * of the file. | ||
| 83 | * --------------------------------------------------------------------------- | ||
| 84 | * Local variables: | ||
| 85 | * c-file-style: "linux" | ||
| 86 | * End: | ||
| 87 | */ | ||
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 92cce96b5e24..44e41a35f000 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c | |||
| @@ -30,7 +30,7 @@ extern char __binary_start; | |||
| 30 | unsigned long *empty_zero_page = NULL; | 30 | unsigned long *empty_zero_page = NULL; |
| 31 | unsigned long *empty_bad_page = NULL; | 31 | unsigned long *empty_bad_page = NULL; |
| 32 | pgd_t swapper_pg_dir[PTRS_PER_PGD]; | 32 | pgd_t swapper_pg_dir[PTRS_PER_PGD]; |
| 33 | unsigned long highmem; | 33 | unsigned long long highmem; |
| 34 | int kmalloc_ok = 0; | 34 | int kmalloc_ok = 0; |
| 35 | 35 | ||
| 36 | static unsigned long brk_end; | 36 | static unsigned long brk_end; |
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index 3113cab8675e..f6a5a502120b 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c | |||
| @@ -156,9 +156,25 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, | |||
| 156 | unsigned long stack_top, struct task_struct * p, | 156 | unsigned long stack_top, struct task_struct * p, |
| 157 | struct pt_regs *regs) | 157 | struct pt_regs *regs) |
| 158 | { | 158 | { |
| 159 | int ret; | ||
| 160 | |||
| 159 | p->thread = (struct thread_struct) INIT_THREAD; | 161 | p->thread = (struct thread_struct) INIT_THREAD; |
| 160 | return(CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr, | 162 | ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr, |
| 161 | clone_flags, sp, stack_top, p, regs)); | 163 | clone_flags, sp, stack_top, p, regs); |
| 164 | |||
| 165 | if (ret || !current->thread.forking) | ||
| 166 | goto out; | ||
| 167 | |||
| 168 | clear_flushed_tls(p); | ||
| 169 | |||
| 170 | /* | ||
| 171 | * Set a new TLS for the child thread? | ||
| 172 | */ | ||
| 173 | if (clone_flags & CLONE_SETTLS) | ||
| 174 | ret = arch_copy_tls(p); | ||
| 175 | |||
| 176 | out: | ||
| 177 | return ret; | ||
| 162 | } | 178 | } |
| 163 | 179 | ||
| 164 | void initial_thread_cb(void (*proc)(void *), void *arg) | 180 | void initial_thread_cb(void (*proc)(void *), void *arg) |
| @@ -185,10 +201,6 @@ void default_idle(void) | |||
| 185 | { | 201 | { |
| 186 | CHOOSE_MODE(uml_idle_timer(), (void) 0); | 202 | CHOOSE_MODE(uml_idle_timer(), (void) 0); |
| 187 | 203 | ||
| 188 | atomic_inc(&init_mm.mm_count); | ||
| 189 | current->mm = &init_mm; | ||
| 190 | current->active_mm = &init_mm; | ||
| 191 | |||
| 192 | while(1){ | 204 | while(1){ |
| 193 | /* endless idle loop with no priority at all */ | 205 | /* endless idle loop with no priority at all */ |
| 194 | 206 | ||
| @@ -407,7 +419,7 @@ static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int | |||
| 407 | return strlen(buf); | 419 | return strlen(buf); |
| 408 | } | 420 | } |
| 409 | 421 | ||
| 410 | static int proc_write_sysemu(struct file *file,const char *buf, unsigned long count,void *data) | 422 | static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned long count,void *data) |
| 411 | { | 423 | { |
| 412 | char tmp[2]; | 424 | char tmp[2]; |
| 413 | 425 | ||
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 98e09395c093..60d2eda995c1 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c | |||
| @@ -46,6 +46,7 @@ extern int poke_user(struct task_struct * child, long addr, long data); | |||
| 46 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 46 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
| 47 | { | 47 | { |
| 48 | int i, ret; | 48 | int i, ret; |
| 49 | unsigned long __user *p = (void __user *)(unsigned long)data; | ||
| 49 | 50 | ||
| 50 | switch (request) { | 51 | switch (request) { |
| 51 | /* when I and D space are separate, these will need to be fixed. */ | 52 | /* when I and D space are separate, these will need to be fixed. */ |
| @@ -58,7 +59,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 58 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | 59 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); |
| 59 | if (copied != sizeof(tmp)) | 60 | if (copied != sizeof(tmp)) |
| 60 | break; | 61 | break; |
| 61 | ret = put_user(tmp, (unsigned long __user *) data); | 62 | ret = put_user(tmp, p); |
| 62 | break; | 63 | break; |
| 63 | } | 64 | } |
| 64 | 65 | ||
| @@ -136,15 +137,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 136 | 137 | ||
| 137 | #ifdef PTRACE_GETREGS | 138 | #ifdef PTRACE_GETREGS |
| 138 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ | 139 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ |
| 139 | if (!access_ok(VERIFY_WRITE, (unsigned long *)data, | 140 | if (!access_ok(VERIFY_WRITE, p, MAX_REG_OFFSET)) { |
| 140 | MAX_REG_OFFSET)) { | ||
| 141 | ret = -EIO; | 141 | ret = -EIO; |
| 142 | break; | 142 | break; |
| 143 | } | 143 | } |
| 144 | for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) { | 144 | for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) { |
| 145 | __put_user(getreg(child, i), | 145 | __put_user(getreg(child, i), p); |
| 146 | (unsigned long __user *) data); | 146 | p++; |
| 147 | data += sizeof(long); | ||
| 148 | } | 147 | } |
| 149 | ret = 0; | 148 | ret = 0; |
| 150 | break; | 149 | break; |
| @@ -153,15 +152,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 153 | #ifdef PTRACE_SETREGS | 152 | #ifdef PTRACE_SETREGS |
| 154 | case PTRACE_SETREGS: { /* Set all gp regs in the child. */ | 153 | case PTRACE_SETREGS: { /* Set all gp regs in the child. */ |
| 155 | unsigned long tmp = 0; | 154 | unsigned long tmp = 0; |
| 156 | if (!access_ok(VERIFY_READ, (unsigned *)data, | 155 | if (!access_ok(VERIFY_READ, p, MAX_REG_OFFSET)) { |
| 157 | MAX_REG_OFFSET)) { | ||
| 158 | ret = -EIO; | 156 | ret = -EIO; |
| 159 | break; | 157 | break; |
| 160 | } | 158 | } |
| 161 | for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) { | 159 | for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) { |
| 162 | __get_user(tmp, (unsigned long __user *) data); | 160 | __get_user(tmp, p); |
| 163 | putreg(child, i, tmp); | 161 | putreg(child, i, tmp); |
| 164 | data += sizeof(long); | 162 | p++; |
| 165 | } | 163 | } |
| 166 | ret = 0; | 164 | ret = 0; |
| 167 | break; | 165 | break; |
| @@ -187,14 +185,23 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 187 | ret = set_fpxregs(data, child); | 185 | ret = set_fpxregs(data, child); |
| 188 | break; | 186 | break; |
| 189 | #endif | 187 | #endif |
| 188 | case PTRACE_GET_THREAD_AREA: | ||
| 189 | ret = ptrace_get_thread_area(child, addr, | ||
| 190 | (struct user_desc __user *) data); | ||
| 191 | break; | ||
| 192 | |||
| 193 | case PTRACE_SET_THREAD_AREA: | ||
| 194 | ret = ptrace_set_thread_area(child, addr, | ||
| 195 | (struct user_desc __user *) data); | ||
| 196 | break; | ||
| 197 | |||
| 190 | case PTRACE_FAULTINFO: { | 198 | case PTRACE_FAULTINFO: { |
| 191 | /* Take the info from thread->arch->faultinfo, | 199 | /* Take the info from thread->arch->faultinfo, |
| 192 | * but transfer max. sizeof(struct ptrace_faultinfo). | 200 | * but transfer max. sizeof(struct ptrace_faultinfo). |
| 193 | * On i386, ptrace_faultinfo is smaller! | 201 | * On i386, ptrace_faultinfo is smaller! |
| 194 | */ | 202 | */ |
| 195 | ret = copy_to_user((unsigned long __user *) data, | 203 | ret = copy_to_user(p, &child->thread.arch.faultinfo, |
| 196 | &child->thread.arch.faultinfo, | 204 | sizeof(struct ptrace_faultinfo)); |
| 197 | sizeof(struct ptrace_faultinfo)); | ||
| 198 | if(ret) | 205 | if(ret) |
| 199 | break; | 206 | break; |
| 200 | break; | 207 | break; |
| @@ -204,8 +211,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 204 | case PTRACE_LDT: { | 211 | case PTRACE_LDT: { |
| 205 | struct ptrace_ldt ldt; | 212 | struct ptrace_ldt ldt; |
| 206 | 213 | ||
| 207 | if(copy_from_user(&ldt, (unsigned long __user *) data, | 214 | if(copy_from_user(&ldt, p, sizeof(ldt))){ |
| 208 | sizeof(ldt))){ | ||
| 209 | ret = -EIO; | 215 | ret = -EIO; |
| 210 | break; | 216 | break; |
| 211 | } | 217 | } |
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index 3f70a2e12f06..2135eaf98a93 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c | |||
| @@ -35,6 +35,8 @@ void switch_to_skas(void *prev, void *next) | |||
| 35 | switch_threads(&from->thread.mode.skas.switch_buf, | 35 | switch_threads(&from->thread.mode.skas.switch_buf, |
| 36 | to->thread.mode.skas.switch_buf); | 36 | to->thread.mode.skas.switch_buf); |
| 37 | 37 | ||
| 38 | arch_switch_to_skas(current->thread.prev_sched, current); | ||
| 39 | |||
| 38 | if(current->pid == 0) | 40 | if(current->pid == 0) |
| 39 | switch_timers(1); | 41 | switch_timers(1); |
| 40 | } | 42 | } |
| @@ -89,10 +91,17 @@ void fork_handler(int sig) | |||
| 89 | panic("blech"); | 91 | panic("blech"); |
| 90 | 92 | ||
| 91 | schedule_tail(current->thread.prev_sched); | 93 | schedule_tail(current->thread.prev_sched); |
| 94 | |||
| 95 | /* XXX: if interrupt_end() calls schedule, this call to | ||
| 96 | * arch_switch_to_skas isn't needed. We could want to apply this to | ||
| 97 | * improve performance. -bb */ | ||
| 98 | arch_switch_to_skas(current->thread.prev_sched, current); | ||
| 99 | |||
| 92 | current->thread.prev_sched = NULL; | 100 | current->thread.prev_sched = NULL; |
| 93 | 101 | ||
| 94 | /* Handle any immediate reschedules or signals */ | 102 | /* Handle any immediate reschedules or signals */ |
| 95 | interrupt_end(); | 103 | interrupt_end(); |
| 104 | |||
| 96 | userspace(¤t->thread.regs.regs); | 105 | userspace(¤t->thread.regs.regs); |
| 97 | } | 106 | } |
| 98 | 107 | ||
| @@ -109,6 +118,8 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, | |||
| 109 | if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp; | 118 | if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp; |
| 110 | 119 | ||
| 111 | handler = fork_handler; | 120 | handler = fork_handler; |
| 121 | |||
| 122 | arch_copy_thread(¤t->thread.arch, &p->thread.arch); | ||
| 112 | } | 123 | } |
| 113 | else { | 124 | else { |
| 114 | init_thread_registers(&p->thread.regs.regs); | 125 | init_thread_registers(&p->thread.regs.regs); |
diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c index 8e1a3501ff46..37d3978337d8 100644 --- a/arch/um/kernel/syscall_kern.c +++ b/arch/um/kernel/syscall_kern.c | |||
| @@ -104,7 +104,7 @@ long sys_pipe(unsigned long __user * fildes) | |||
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | 106 | ||
| 107 | long sys_uname(struct old_utsname * name) | 107 | long sys_uname(struct old_utsname __user * name) |
| 108 | { | 108 | { |
| 109 | long err; | 109 | long err; |
| 110 | if (!name) | 110 | if (!name) |
| @@ -115,7 +115,7 @@ long sys_uname(struct old_utsname * name) | |||
| 115 | return err?-EFAULT:0; | 115 | return err?-EFAULT:0; |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | long sys_olduname(struct oldold_utsname * name) | 118 | long sys_olduname(struct oldold_utsname __user * name) |
| 119 | { | 119 | { |
| 120 | long error; | 120 | long error; |
| 121 | 121 | ||
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index d56046c2aba2..02f6d4d8dc3a 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c | |||
| @@ -198,7 +198,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) | |||
| 198 | si.si_signo = SIGBUS; | 198 | si.si_signo = SIGBUS; |
| 199 | si.si_errno = 0; | 199 | si.si_errno = 0; |
| 200 | si.si_code = BUS_ADRERR; | 200 | si.si_code = BUS_ADRERR; |
| 201 | si.si_addr = (void *)address; | 201 | si.si_addr = (void __user *)address; |
| 202 | current->thread.arch.faultinfo = fi; | 202 | current->thread.arch.faultinfo = fi; |
| 203 | force_sig_info(SIGBUS, &si, current); | 203 | force_sig_info(SIGBUS, &si, current); |
| 204 | } else if (err == -ENOMEM) { | 204 | } else if (err == -ENOMEM) { |
| @@ -207,7 +207,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) | |||
| 207 | } else { | 207 | } else { |
| 208 | BUG_ON(err != -EFAULT); | 208 | BUG_ON(err != -EFAULT); |
| 209 | si.si_signo = SIGSEGV; | 209 | si.si_signo = SIGSEGV; |
| 210 | si.si_addr = (void *) address; | 210 | si.si_addr = (void __user *) address; |
| 211 | current->thread.arch.faultinfo = fi; | 211 | current->thread.arch.faultinfo = fi; |
| 212 | force_sig_info(SIGSEGV, &si, current); | 212 | force_sig_info(SIGSEGV, &si, current); |
| 213 | } | 213 | } |
| @@ -220,8 +220,8 @@ void bad_segv(struct faultinfo fi, unsigned long ip) | |||
| 220 | 220 | ||
| 221 | si.si_signo = SIGSEGV; | 221 | si.si_signo = SIGSEGV; |
| 222 | si.si_code = SEGV_ACCERR; | 222 | si.si_code = SEGV_ACCERR; |
| 223 | si.si_addr = (void *) FAULT_ADDRESS(fi); | 223 | si.si_addr = (void __user *) FAULT_ADDRESS(fi); |
| 224 | current->thread.arch.faultinfo = fi; | 224 | current->thread.arch.faultinfo = fi; |
| 225 | force_sig_info(SIGSEGV, &si, current); | 225 | force_sig_info(SIGSEGV, &si, current); |
| 226 | } | 226 | } |
| 227 | 227 | ||
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c index 295c1ac817b3..a9c1443fc548 100644 --- a/arch/um/kernel/tt/process_kern.c +++ b/arch/um/kernel/tt/process_kern.c | |||
| @@ -51,6 +51,13 @@ void switch_to_tt(void *prev, void *next) | |||
| 51 | 51 | ||
| 52 | c = 0; | 52 | c = 0; |
| 53 | 53 | ||
| 54 | /* Notice that here we "up" the semaphore on which "to" is waiting, and | ||
| 55 | * below (the read) we wait on this semaphore (which is implemented by | ||
| 56 | * switch_pipe) and go sleeping. Thus, after that, we have resumed in | ||
| 57 | * "to", and can't use any more the value of "from" (which is outdated), | ||
| 58 | * nor the value in "to" (since it was the task which stole us the CPU, | ||
| 59 | * which we don't care about). */ | ||
| 60 | |||
| 54 | err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c)); | 61 | err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c)); |
| 55 | if(err != sizeof(c)) | 62 | if(err != sizeof(c)) |
| 56 | panic("write of switch_pipe failed, err = %d", -err); | 63 | panic("write of switch_pipe failed, err = %d", -err); |
| @@ -77,7 +84,7 @@ void switch_to_tt(void *prev, void *next) | |||
| 77 | change_sig(SIGALRM, alrm); | 84 | change_sig(SIGALRM, alrm); |
| 78 | change_sig(SIGPROF, prof); | 85 | change_sig(SIGPROF, prof); |
| 79 | 86 | ||
| 80 | arch_switch(); | 87 | arch_switch_to_tt(prev_sched, current); |
| 81 | 88 | ||
| 82 | flush_tlb_all(); | 89 | flush_tlb_all(); |
| 83 | local_irq_restore(flags); | 90 | local_irq_restore(flags); |
| @@ -141,7 +148,6 @@ static void new_thread_handler(int sig) | |||
| 141 | set_cmdline("(kernel thread)"); | 148 | set_cmdline("(kernel thread)"); |
| 142 | 149 | ||
| 143 | change_sig(SIGUSR1, 1); | 150 | change_sig(SIGUSR1, 1); |
| 144 | change_sig(SIGVTALRM, 1); | ||
| 145 | change_sig(SIGPROF, 1); | 151 | change_sig(SIGPROF, 1); |
| 146 | local_irq_enable(); | 152 | local_irq_enable(); |
| 147 | if(!run_kernel_thread(fn, arg, ¤t->thread.exec_buf)) | 153 | if(!run_kernel_thread(fn, arg, ¤t->thread.exec_buf)) |
