aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel')
-rw-r--r--arch/um/kernel/exec_kern.c16
-rw-r--r--arch/um/kernel/ksyms.c5
-rw-r--r--arch/um/kernel/mem.c2
-rw-r--r--arch/um/kernel/process_kern.c26
-rw-r--r--arch/um/kernel/ptrace.c44
-rw-r--r--arch/um/kernel/skas/process_kern.c11
-rw-r--r--arch/um/kernel/syscall_kern.c4
-rw-r--r--arch/um/kernel/trap_kern.c8
-rw-r--r--arch/um/kernel/tt/process_kern.c10
9 files changed, 74 insertions, 52 deletions
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
index 1ca8431931..c0cb627bf5 100644
--- a/arch/um/kernel/exec_kern.c
+++ b/arch/um/kernel/exec_kern.c
@@ -22,6 +22,7 @@
22 22
23void flush_thread(void) 23void flush_thread(void)
24{ 24{
25 arch_flush_thread(&current->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
61long sys_execve(char *file, char __user *__user *argv, 62long 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/ksyms.c b/arch/um/kernel/ksyms.c
index 7713e7a6f4..432cf0b97a 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -39,7 +39,6 @@ EXPORT_SYMBOL(um_virt_to_phys);
39EXPORT_SYMBOL(mode_tt); 39EXPORT_SYMBOL(mode_tt);
40EXPORT_SYMBOL(handle_page_fault); 40EXPORT_SYMBOL(handle_page_fault);
41EXPORT_SYMBOL(find_iomem); 41EXPORT_SYMBOL(find_iomem);
42EXPORT_SYMBOL(end_iomem);
43 42
44#ifdef CONFIG_MODE_TT 43#ifdef CONFIG_MODE_TT
45EXPORT_SYMBOL(strncpy_from_user_tt); 44EXPORT_SYMBOL(strncpy_from_user_tt);
@@ -89,12 +88,10 @@ EXPORT_SYMBOL(dump_thread);
89EXPORT_SYMBOL(do_gettimeofday); 88EXPORT_SYMBOL(do_gettimeofday);
90EXPORT_SYMBOL(do_settimeofday); 89EXPORT_SYMBOL(do_settimeofday);
91 90
92/* This is here because UML expands open to sys_open, not to a system 91/* This is here because UML expands lseek to sys_lseek, not to a system
93 * call instruction. 92 * call instruction.
94 */ 93 */
95EXPORT_SYMBOL(sys_open);
96EXPORT_SYMBOL(sys_lseek); 94EXPORT_SYMBOL(sys_lseek);
97EXPORT_SYMBOL(sys_read);
98EXPORT_SYMBOL(sys_wait4); 95EXPORT_SYMBOL(sys_wait4);
99 96
100#ifdef CONFIG_SMP 97#ifdef CONFIG_SMP
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 92cce96b5e..44e41a35f0 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -30,7 +30,7 @@ extern char __binary_start;
30unsigned long *empty_zero_page = NULL; 30unsigned long *empty_zero_page = NULL;
31unsigned long *empty_bad_page = NULL; 31unsigned long *empty_bad_page = NULL;
32pgd_t swapper_pg_dir[PTRS_PER_PGD]; 32pgd_t swapper_pg_dir[PTRS_PER_PGD];
33unsigned long highmem; 33unsigned long long highmem;
34int kmalloc_ok = 0; 34int kmalloc_ok = 0;
35 35
36static unsigned long brk_end; 36static unsigned long brk_end;
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index 3113cab867..f6a5a50212 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
176out:
177 return ret;
162} 178}
163 179
164void initial_thread_cb(void (*proc)(void *), void *arg) 180void 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
410static int proc_write_sysemu(struct file *file,const char *buf, unsigned long count,void *data) 422static 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 98e09395c0..60d2eda995 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);
46long arch_ptrace(struct task_struct *child, long request, long addr, long data) 46long 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 3f70a2e12f..2135eaf98a 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(&current->thread.regs.regs); 105 userspace(&current->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(&current->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 8e1a3501ff..37d3978337 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
107long sys_uname(struct old_utsname * name) 107long 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
118long sys_olduname(struct oldold_utsname * name) 118long 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 d56046c2ab..02f6d4d8dc 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 295c1ac817..a9c1443fc5 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, &current->thread.exec_buf)) 153 if(!run_kernel_thread(fn, arg, &current->thread.exec_buf))