aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k/kernel
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /arch/m68k/kernel
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'arch/m68k/kernel')
-rw-r--r--arch/m68k/kernel/dma.c1
-rw-r--r--arch/m68k/kernel/entry.S14
-rw-r--r--arch/m68k/kernel/head.S2
-rw-r--r--arch/m68k/kernel/process.c11
-rw-r--r--arch/m68k/kernel/ptrace.c117
-rw-r--r--arch/m68k/kernel/signal.c7
-rw-r--r--arch/m68k/kernel/sys_m68k.c289
-rw-r--r--arch/m68k/kernel/vmlinux-std.lds61
-rw-r--r--arch/m68k/kernel/vmlinux-sun3.lds54
9 files changed, 183 insertions, 373 deletions
diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c
index 2bb4245404d8..4bbb3c2a8880 100644
--- a/arch/m68k/kernel/dma.c
+++ b/arch/m68k/kernel/dma.c
@@ -10,6 +10,7 @@
10#include <linux/device.h> 10#include <linux/device.h>
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/scatterlist.h> 12#include <linux/scatterlist.h>
13#include <linux/slab.h>
13#include <linux/vmalloc.h> 14#include <linux/vmalloc.h>
14 15
15#include <asm/pgalloc.h> 16#include <asm/pgalloc.h>
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index c5b33634c980..2391bdff0996 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -179,7 +179,11 @@ do_signal_return:
179 addql #8,%sp 179 addql #8,%sp
180 RESTORE_SWITCH_STACK 180 RESTORE_SWITCH_STACK
181 addql #4,%sp 181 addql #4,%sp
182 jbra resume_userspace 182 tstl %d0
183 jeq resume_userspace
184 | when single stepping into handler stop at the first insn
185 btst #6,%curptr@(TASK_INFO+TINFO_FLAGS+2)
186 jeq resume_userspace
183 187
184do_delayed_trace: 188do_delayed_trace:
185 bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR 189 bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR
@@ -506,7 +510,7 @@ sys_call_table:
506 .long sys_settimeofday 510 .long sys_settimeofday
507 .long sys_getgroups16 /* 80 */ 511 .long sys_getgroups16 /* 80 */
508 .long sys_setgroups16 512 .long sys_setgroups16
509 .long old_select 513 .long sys_old_select
510 .long sys_symlink 514 .long sys_symlink
511 .long sys_lstat 515 .long sys_lstat
512 .long sys_readlink /* 85 */ 516 .long sys_readlink /* 85 */
@@ -514,7 +518,7 @@ sys_call_table:
514 .long sys_swapon 518 .long sys_swapon
515 .long sys_reboot 519 .long sys_reboot
516 .long sys_old_readdir 520 .long sys_old_readdir
517 .long old_mmap /* 90 */ 521 .long sys_old_mmap /* 90 */
518 .long sys_munmap 522 .long sys_munmap
519 .long sys_truncate 523 .long sys_truncate
520 .long sys_ftruncate 524 .long sys_ftruncate
@@ -757,4 +761,8 @@ sys_call_table:
757 .long sys_pwritev /* 330 */ 761 .long sys_pwritev /* 330 */
758 .long sys_rt_tgsigqueueinfo 762 .long sys_rt_tgsigqueueinfo
759 .long sys_perf_event_open 763 .long sys_perf_event_open
764 .long sys_get_thread_area
765 .long sys_set_thread_area
766 .long sys_atomic_cmpxchg_32 /* 335 */
767 .long sys_atomic_barrier
760 768
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
index 86edb5fbcfc3..ef54128baa0b 100644
--- a/arch/m68k/kernel/head.S
+++ b/arch/m68k/kernel/head.S
@@ -196,7 +196,7 @@
196 * for them and trying to understand what they mean. 196 * for them and trying to understand what they mean.
197 * 197 *
198 * CONFIG_xxx: These are the obvious machine configuration defines created 198 * CONFIG_xxx: These are the obvious machine configuration defines created
199 * during configuration. These are defined in include/linux/autoconf.h. 199 * during configuration. These are defined in autoconf.h.
200 * 200 *
201 * CONSOLE: There is support for head.S console in this file. This 201 * CONSOLE: There is support for head.S console in this file. This
202 * console can talk to a Mac frame buffer, but could easily be extrapolated 202 * console can talk to a Mac frame buffer, but could easily be extrapolated
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index 41230c595a8e..1a6be27cf165 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -15,13 +15,13 @@
15#include <linux/sched.h> 15#include <linux/sched.h>
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/mm.h> 17#include <linux/mm.h>
18#include <linux/slab.h>
18#include <linux/fs.h> 19#include <linux/fs.h>
19#include <linux/smp.h> 20#include <linux/smp.h>
20#include <linux/smp_lock.h> 21#include <linux/smp_lock.h>
21#include <linux/stddef.h> 22#include <linux/stddef.h>
22#include <linux/unistd.h> 23#include <linux/unistd.h>
23#include <linux/ptrace.h> 24#include <linux/ptrace.h>
24#include <linux/slab.h>
25#include <linux/user.h> 25#include <linux/user.h>
26#include <linux/reboot.h> 26#include <linux/reboot.h>
27#include <linux/init_task.h> 27#include <linux/init_task.h>
@@ -251,6 +251,10 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
251 251
252 p->thread.usp = usp; 252 p->thread.usp = usp;
253 p->thread.ksp = (unsigned long)childstack; 253 p->thread.ksp = (unsigned long)childstack;
254
255 if (clone_flags & CLONE_SETTLS)
256 task_thread_info(p)->tp_value = regs->d5;
257
254 /* 258 /*
255 * Must save the current SFC/DFC value, NOT the value when 259 * Must save the current SFC/DFC value, NOT the value when
256 * the parent was last descheduled - RGH 10-08-96 260 * the parent was last descheduled - RGH 10-08-96
@@ -317,15 +321,12 @@ asmlinkage int sys_execve(char __user *name, char __user * __user *argv, char __
317 char * filename; 321 char * filename;
318 struct pt_regs *regs = (struct pt_regs *) &name; 322 struct pt_regs *regs = (struct pt_regs *) &name;
319 323
320 lock_kernel();
321 filename = getname(name); 324 filename = getname(name);
322 error = PTR_ERR(filename); 325 error = PTR_ERR(filename);
323 if (IS_ERR(filename)) 326 if (IS_ERR(filename))
324 goto out; 327 return error;
325 error = do_execve(filename, argv, envp, regs); 328 error = do_execve(filename, argv, envp, regs);
326 putname(filename); 329 putname(filename);
327out:
328 unlock_kernel();
329 return error; 330 return error;
330} 331}
331 332
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index 2075543c2d92..616e59752c29 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -35,7 +35,9 @@
35#define SR_MASK 0x001f 35#define SR_MASK 0x001f
36 36
37/* sets the trace bits. */ 37/* sets the trace bits. */
38#define TRACE_BITS 0x8000 38#define TRACE_BITS 0xC000
39#define T1_BIT 0x8000
40#define T0_BIT 0x4000
39 41
40/* Find the stack offset for a register, relative to thread.esp0. */ 42/* Find the stack offset for a register, relative to thread.esp0. */
41#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg) 43#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg)
@@ -44,7 +46,7 @@
44/* Mapping from PT_xxx to the stack offset at which the register is 46/* Mapping from PT_xxx to the stack offset at which the register is
45 saved. Notice that usp has no stack-slot and needs to be treated 47 saved. Notice that usp has no stack-slot and needs to be treated
46 specially (see get_reg/put_reg below). */ 48 specially (see get_reg/put_reg below). */
47static int regoff[] = { 49static const int regoff[] = {
48 [0] = PT_REG(d1), 50 [0] = PT_REG(d1),
49 [1] = PT_REG(d2), 51 [1] = PT_REG(d2),
50 [2] = PT_REG(d3), 52 [2] = PT_REG(d3),
@@ -79,6 +81,14 @@ static inline long get_reg(struct task_struct *task, int regno)
79 addr = (unsigned long *)(task->thread.esp0 + regoff[regno]); 81 addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
80 else 82 else
81 return 0; 83 return 0;
84 /* Need to take stkadj into account. */
85 if (regno == PT_SR || regno == PT_PC) {
86 long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj));
87 addr = (unsigned long *) ((unsigned long)addr + stkadj);
88 /* The sr is actually a 16 bit register. */
89 if (regno == PT_SR)
90 return *(unsigned short *)addr;
91 }
82 return *addr; 92 return *addr;
83} 93}
84 94
@@ -96,6 +106,16 @@ static inline int put_reg(struct task_struct *task, int regno,
96 addr = (unsigned long *)(task->thread.esp0 + regoff[regno]); 106 addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
97 else 107 else
98 return -1; 108 return -1;
109 /* Need to take stkadj into account. */
110 if (regno == PT_SR || regno == PT_PC) {
111 long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj));
112 addr = (unsigned long *) ((unsigned long)addr + stkadj);
113 /* The sr is actually a 16 bit register. */
114 if (regno == PT_SR) {
115 *(unsigned short *)addr = data;
116 return 0;
117 }
118 }
99 *addr = data; 119 *addr = data;
100 return 0; 120 return 0;
101} 121}
@@ -105,7 +125,7 @@ static inline int put_reg(struct task_struct *task, int regno,
105 */ 125 */
106static inline void singlestep_disable(struct task_struct *child) 126static inline void singlestep_disable(struct task_struct *child)
107{ 127{
108 unsigned long tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); 128 unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
109 put_reg(child, PT_SR, tmp); 129 put_reg(child, PT_SR, tmp);
110 clear_tsk_thread_flag(child, TIF_DELAYED_TRACE); 130 clear_tsk_thread_flag(child, TIF_DELAYED_TRACE);
111} 131}
@@ -118,18 +138,30 @@ void ptrace_disable(struct task_struct *child)
118 singlestep_disable(child); 138 singlestep_disable(child);
119} 139}
120 140
141void user_enable_single_step(struct task_struct *child)
142{
143 unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
144 put_reg(child, PT_SR, tmp | T1_BIT);
145 set_tsk_thread_flag(child, TIF_DELAYED_TRACE);
146}
147
148void user_enable_block_step(struct task_struct *child)
149{
150 unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
151 put_reg(child, PT_SR, tmp | T0_BIT);
152}
153
154void user_disable_single_step(struct task_struct *child)
155{
156 singlestep_disable(child);
157}
158
121long arch_ptrace(struct task_struct *child, long request, long addr, long data) 159long arch_ptrace(struct task_struct *child, long request, long addr, long data)
122{ 160{
123 unsigned long tmp; 161 unsigned long tmp;
124 int i, ret = 0; 162 int i, ret = 0;
125 163
126 switch (request) { 164 switch (request) {
127 /* when I and D space are separate, these will need to be fixed. */
128 case PTRACE_PEEKTEXT: /* read word at location addr. */
129 case PTRACE_PEEKDATA:
130 ret = generic_ptrace_peekdata(child, addr, data);
131 break;
132
133 /* read the word at location addr in the USER area. */ 165 /* read the word at location addr in the USER area. */
134 case PTRACE_PEEKUSR: 166 case PTRACE_PEEKUSR:
135 if (addr & 3) 167 if (addr & 3)
@@ -138,8 +170,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
138 170
139 if (addr >= 0 && addr < 19) { 171 if (addr >= 0 && addr < 19) {
140 tmp = get_reg(child, addr); 172 tmp = get_reg(child, addr);
141 if (addr == PT_SR)
142 tmp >>= 16;
143 } else if (addr >= 21 && addr < 49) { 173 } else if (addr >= 21 && addr < 49) {
144 tmp = child->thread.fp[addr - 21]; 174 tmp = child->thread.fp[addr - 21];
145 /* Convert internal fpu reg representation 175 /* Convert internal fpu reg representation
@@ -149,16 +179,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
149 tmp = ((tmp & 0xffff0000) << 15) | 179 tmp = ((tmp & 0xffff0000) << 15) |
150 ((tmp & 0x0000ffff) << 16); 180 ((tmp & 0x0000ffff) << 16);
151 } else 181 } else
152 break; 182 goto out_eio;
153 ret = put_user(tmp, (unsigned long *)data); 183 ret = put_user(tmp, (unsigned long *)data);
154 break; 184 break;
155 185
156 /* when I and D space are separate, this will have to be fixed. */
157 case PTRACE_POKETEXT: /* write the word at location addr. */
158 case PTRACE_POKEDATA:
159 ret = generic_ptrace_pokedata(child, addr, data);
160 break;
161
162 case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ 186 case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
163 if (addr & 3) 187 if (addr & 3)
164 goto out_eio; 188 goto out_eio;
@@ -166,9 +190,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
166 190
167 if (addr == PT_SR) { 191 if (addr == PT_SR) {
168 data &= SR_MASK; 192 data &= SR_MASK;
169 data <<= 16; 193 data |= get_reg(child, PT_SR) & ~SR_MASK;
170 data |= get_reg(child, PT_SR) & ~(SR_MASK << 16); 194 }
171 } else if (addr >= 0 && addr < 19) { 195 if (addr >= 0 && addr < 19) {
172 if (put_reg(child, addr, data)) 196 if (put_reg(child, addr, data))
173 goto out_eio; 197 goto out_eio;
174 } else if (addr >= 21 && addr < 48) { 198 } else if (addr >= 21 && addr < 48) {
@@ -185,52 +209,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
185 goto out_eio; 209 goto out_eio;
186 break; 210 break;
187 211
188 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
189 case PTRACE_CONT: /* restart after signal. */
190 if (!valid_signal(data))
191 goto out_eio;
192
193 if (request == PTRACE_SYSCALL)
194 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
195 else
196 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
197 child->exit_code = data;
198 singlestep_disable(child);
199 wake_up_process(child);
200 break;
201
202 /*
203 * make the child exit. Best I can do is send it a sigkill.
204 * perhaps it should be put in the status that it wants to
205 * exit.
206 */
207 case PTRACE_KILL:
208 if (child->exit_state == EXIT_ZOMBIE) /* already dead */
209 break;
210 child->exit_code = SIGKILL;
211 singlestep_disable(child);
212 wake_up_process(child);
213 break;
214
215 case PTRACE_SINGLESTEP: /* set the trap flag. */
216 if (!valid_signal(data))
217 goto out_eio;
218
219 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
220 tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
221 put_reg(child, PT_SR, tmp);
222 set_tsk_thread_flag(child, TIF_DELAYED_TRACE);
223
224 child->exit_code = data;
225 /* give it a chance to run. */
226 wake_up_process(child);
227 break;
228
229 case PTRACE_GETREGS: /* Get all gp regs from the child. */ 212 case PTRACE_GETREGS: /* Get all gp regs from the child. */
230 for (i = 0; i < 19; i++) { 213 for (i = 0; i < 19; i++) {
231 tmp = get_reg(child, i); 214 tmp = get_reg(child, i);
232 if (i == PT_SR)
233 tmp >>= 16;
234 ret = put_user(tmp, (unsigned long *)data); 215 ret = put_user(tmp, (unsigned long *)data);
235 if (ret) 216 if (ret)
236 break; 217 break;
@@ -245,8 +226,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
245 break; 226 break;
246 if (i == PT_SR) { 227 if (i == PT_SR) {
247 tmp &= SR_MASK; 228 tmp &= SR_MASK;
248 tmp <<= 16; 229 tmp |= get_reg(child, PT_SR) & ~SR_MASK;
249 tmp |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
250 } 230 }
251 put_reg(child, i, tmp); 231 put_reg(child, i, tmp);
252 data += sizeof(long); 232 data += sizeof(long);
@@ -265,6 +245,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
265 ret = -EFAULT; 245 ret = -EFAULT;
266 break; 246 break;
267 247
248 case PTRACE_GET_THREAD_AREA:
249 ret = put_user(task_thread_info(child)->tp_value,
250 (unsigned long __user *)data);
251 break;
252
268 default: 253 default:
269 ret = ptrace_request(child, request, addr, data); 254 ret = ptrace_request(child, request, addr, data);
270 break; 255 break;
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index de2d05ddd86d..4b387538706f 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -897,10 +897,17 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
897 897
898 /* Set up to return from userspace. */ 898 /* Set up to return from userspace. */
899 err |= __put_user(frame->retcode, &frame->pretcode); 899 err |= __put_user(frame->retcode, &frame->pretcode);
900#ifdef __mcoldfire__
901 /* movel #__NR_rt_sigreturn,d0; trap #0 */
902 err |= __put_user(0x203c0000, (long __user *)(frame->retcode + 0));
903 err |= __put_user(0x00004e40 + (__NR_rt_sigreturn << 16),
904 (long __user *)(frame->retcode + 4));
905#else
900 /* moveq #,d0; notb d0; trap #0 */ 906 /* moveq #,d0; notb d0; trap #0 */
901 err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16), 907 err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
902 (long __user *)(frame->retcode + 0)); 908 (long __user *)(frame->retcode + 0));
903 err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4)); 909 err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4));
910#endif
904 911
905 if (err) 912 if (err)
906 goto give_sigsegv; 913 goto give_sigsegv;
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 7deb402bfc75..77896692eb0a 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -28,215 +28,22 @@
28#include <asm/traps.h> 28#include <asm/traps.h>
29#include <asm/page.h> 29#include <asm/page.h>
30#include <asm/unistd.h> 30#include <asm/unistd.h>
31#include <linux/elf.h>
32#include <asm/tlb.h>
31 33
32/* common code for old and new mmaps */ 34asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
33static inline long do_mmap2( 35 unsigned long error_code);
34 unsigned long addr, unsigned long len,
35 unsigned long prot, unsigned long flags,
36 unsigned long fd, unsigned long pgoff)
37{
38 int error = -EBADF;
39 struct file * file = NULL;
40
41 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
42 if (!(flags & MAP_ANONYMOUS)) {
43 file = fget(fd);
44 if (!file)
45 goto out;
46 }
47
48 down_write(&current->mm->mmap_sem);
49 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
50 up_write(&current->mm->mmap_sem);
51
52 if (file)
53 fput(file);
54out:
55 return error;
56}
57 36
58asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, 37asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
59 unsigned long prot, unsigned long flags, 38 unsigned long prot, unsigned long flags,
60 unsigned long fd, unsigned long pgoff) 39 unsigned long fd, unsigned long pgoff)
61{ 40{
62 return do_mmap2(addr, len, prot, flags, fd, pgoff); 41 /*
63} 42 * This is wrong for sun3 - there PAGE_SIZE is 8Kb,
64 43 * so we need to shift the argument down by 1; m68k mmap64(3)
65/* 44 * (in libc) expects the last argument of mmap2 in 4Kb units.
66 * Perform the select(nd, in, out, ex, tv) and mmap() system 45 */
67 * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to 46 return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
68 * handle more than 4 system call parameters, so these system calls
69 * used a memory block for parameter passing..
70 */
71
72struct mmap_arg_struct {
73 unsigned long addr;
74 unsigned long len;
75 unsigned long prot;
76 unsigned long flags;
77 unsigned long fd;
78 unsigned long offset;
79};
80
81asmlinkage int old_mmap(struct mmap_arg_struct __user *arg)
82{
83 struct mmap_arg_struct a;
84 int error = -EFAULT;
85
86 if (copy_from_user(&a, arg, sizeof(a)))
87 goto out;
88
89 error = -EINVAL;
90 if (a.offset & ~PAGE_MASK)
91 goto out;
92
93 a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
94
95 error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
96out:
97 return error;
98}
99
100#if 0
101struct mmap_arg_struct64 {
102 __u32 addr;
103 __u32 len;
104 __u32 prot;
105 __u32 flags;
106 __u64 offset; /* 64 bits */
107 __u32 fd;
108};
109
110asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg)
111{
112 int error = -EFAULT;
113 struct file * file = NULL;
114 struct mmap_arg_struct64 a;
115 unsigned long pgoff;
116
117 if (copy_from_user(&a, arg, sizeof(a)))
118 return -EFAULT;
119
120 if ((long)a.offset & ~PAGE_MASK)
121 return -EINVAL;
122
123 pgoff = a.offset >> PAGE_SHIFT;
124 if ((a.offset >> PAGE_SHIFT) != pgoff)
125 return -EINVAL;
126
127 if (!(a.flags & MAP_ANONYMOUS)) {
128 error = -EBADF;
129 file = fget(a.fd);
130 if (!file)
131 goto out;
132 }
133 a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
134
135 down_write(&current->mm->mmap_sem);
136 error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff);
137 up_write(&current->mm->mmap_sem);
138 if (file)
139 fput(file);
140out:
141 return error;
142}
143#endif
144
145struct sel_arg_struct {
146 unsigned long n;
147 fd_set __user *inp, *outp, *exp;
148 struct timeval __user *tvp;
149};
150
151asmlinkage int old_select(struct sel_arg_struct __user *arg)
152{
153 struct sel_arg_struct a;
154
155 if (copy_from_user(&a, arg, sizeof(a)))
156 return -EFAULT;
157 /* sys_select() does the appropriate kernel locking */
158 return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
159}
160
161/*
162 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
163 *
164 * This is really horribly ugly.
165 */
166asmlinkage int sys_ipc (uint call, int first, int second,
167 int third, void __user *ptr, long fifth)
168{
169 int version, ret;
170
171 version = call >> 16; /* hack for backward compatibility */
172 call &= 0xffff;
173
174 if (call <= SEMCTL)
175 switch (call) {
176 case SEMOP:
177 return sys_semop (first, ptr, second);
178 case SEMGET:
179 return sys_semget (first, second, third);
180 case SEMCTL: {
181 union semun fourth;
182 if (!ptr)
183 return -EINVAL;
184 if (get_user(fourth.__pad, (void __user *__user *) ptr))
185 return -EFAULT;
186 return sys_semctl (first, second, third, fourth);
187 }
188 default:
189 return -ENOSYS;
190 }
191 if (call <= MSGCTL)
192 switch (call) {
193 case MSGSND:
194 return sys_msgsnd (first, ptr, second, third);
195 case MSGRCV:
196 switch (version) {
197 case 0: {
198 struct ipc_kludge tmp;
199 if (!ptr)
200 return -EINVAL;
201 if (copy_from_user (&tmp, ptr, sizeof (tmp)))
202 return -EFAULT;
203 return sys_msgrcv (first, tmp.msgp, second,
204 tmp.msgtyp, third);
205 }
206 default:
207 return sys_msgrcv (first, ptr,
208 second, fifth, third);
209 }
210 case MSGGET:
211 return sys_msgget ((key_t) first, second);
212 case MSGCTL:
213 return sys_msgctl (first, second, ptr);
214 default:
215 return -ENOSYS;
216 }
217 if (call <= SHMCTL)
218 switch (call) {
219 case SHMAT:
220 switch (version) {
221 default: {
222 ulong raddr;
223 ret = do_shmat (first, ptr, second, &raddr);
224 if (ret)
225 return ret;
226 return put_user (raddr, (ulong __user *) third);
227 }
228 }
229 case SHMDT:
230 return sys_shmdt (ptr);
231 case SHMGET:
232 return sys_shmget (first, second, third);
233 case SHMCTL:
234 return sys_shmctl (first, second, ptr);
235 default:
236 return -ENOSYS;
237 }
238
239 return -EINVAL;
240} 47}
241 48
242/* Convert virtual (user) address VADDR to physical address PADDR */ 49/* Convert virtual (user) address VADDR to physical address PADDR */
@@ -662,3 +469,79 @@ int kernel_execve(const char *filename, char *const argv[], char *const envp[])
662 : "d" (__a), "d" (__b), "d" (__c)); 469 : "d" (__a), "d" (__b), "d" (__c));
663 return __res; 470 return __res;
664} 471}
472
473asmlinkage unsigned long sys_get_thread_area(void)
474{
475 return current_thread_info()->tp_value;
476}
477
478asmlinkage int sys_set_thread_area(unsigned long tp)
479{
480 current_thread_info()->tp_value = tp;
481 return 0;
482}
483
484/* This syscall gets its arguments in A0 (mem), D2 (oldval) and
485 D1 (newval). */
486asmlinkage int
487sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
488 unsigned long __user * mem)
489{
490 /* This was borrowed from ARM's implementation. */
491 for (;;) {
492 struct mm_struct *mm = current->mm;
493 pgd_t *pgd;
494 pmd_t *pmd;
495 pte_t *pte;
496 spinlock_t *ptl;
497 unsigned long mem_value;
498
499 down_read(&mm->mmap_sem);
500 pgd = pgd_offset(mm, (unsigned long)mem);
501 if (!pgd_present(*pgd))
502 goto bad_access;
503 pmd = pmd_offset(pgd, (unsigned long)mem);
504 if (!pmd_present(*pmd))
505 goto bad_access;
506 pte = pte_offset_map_lock(mm, pmd, (unsigned long)mem, &ptl);
507 if (!pte_present(*pte) || !pte_dirty(*pte)
508 || !pte_write(*pte)) {
509 pte_unmap_unlock(pte, ptl);
510 goto bad_access;
511 }
512
513 mem_value = *mem;
514 if (mem_value == oldval)
515 *mem = newval;
516
517 pte_unmap_unlock(pte, ptl);
518 up_read(&mm->mmap_sem);
519 return mem_value;
520
521 bad_access:
522 up_read(&mm->mmap_sem);
523 /* This is not necessarily a bad access, we can get here if
524 a memory we're trying to write to should be copied-on-write.
525 Make the kernel do the necessary page stuff, then re-iterate.
526 Simulate a write access fault to do that. */
527 {
528 /* The first argument of the function corresponds to
529 D1, which is the first field of struct pt_regs. */
530 struct pt_regs *fp = (struct pt_regs *)&newval;
531
532 /* '3' is an RMW flag. */
533 if (do_page_fault(fp, (unsigned long)mem, 3))
534 /* If the do_page_fault() failed, we don't
535 have anything meaningful to return.
536 There should be a SIGSEGV pending for
537 the process. */
538 return 0xdeadbeef;
539 }
540 }
541}
542
543asmlinkage int sys_atomic_barrier(void)
544{
545 /* no code needed for uniprocs */
546 return 0;
547}
diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds
index 47eac19e8f61..878be5f38cad 100644
--- a/arch/m68k/kernel/vmlinux-std.lds
+++ b/arch/m68k/kernel/vmlinux-std.lds
@@ -2,6 +2,7 @@
2 2
3#include <asm-generic/vmlinux.lds.h> 3#include <asm-generic/vmlinux.lds.h>
4#include <asm/page.h> 4#include <asm/page.h>
5#include <asm/thread_info.h>
5 6
6OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k") 7OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k")
7OUTPUT_ARCH(m68k) 8OUTPUT_ARCH(m68k)
@@ -22,73 +23,37 @@ SECTIONS
22 23
23 _etext = .; /* End of text section */ 24 _etext = .; /* End of text section */
24 25
25 . = ALIGN(16); /* Exception table */ 26 EXCEPTION_TABLE(16)
26 __start___ex_table = .;
27 __ex_table : { *(__ex_table) }
28 __stop___ex_table = .;
29 27
30 RODATA 28 RODATA
31 29
32 .data : { /* Data */ 30 RW_DATA_SECTION(16, PAGE_SIZE, THREAD_SIZE)
33 DATA_DATA
34 CONSTRUCTORS
35 }
36 31
37 . = ALIGN(16); 32 BSS_SECTION(0, 0, 0)
38 .data.cacheline_aligned : { *(.data.cacheline_aligned) }
39
40 .bss : { *(.bss) } /* BSS */
41 33
42 _edata = .; /* End of data section */ 34 _edata = .; /* End of data section */
43 35
44 /* will be freed after init */ 36 /* will be freed after init */
45 . = ALIGN(PAGE_SIZE); /* Init code and data */ 37 . = ALIGN(PAGE_SIZE); /* Init code and data */
46 __init_begin = .; 38 __init_begin = .;
47 .init.text : { 39 INIT_TEXT_SECTION(PAGE_SIZE) :data
48 _sinittext = .; 40 INIT_DATA_SECTION(16)
49 INIT_TEXT
50 _einittext = .;
51 } :data
52 .init.data : { INIT_DATA }
53 . = ALIGN(16);
54 __setup_start = .;
55 .init.setup : { *(.init.setup) }
56 __setup_end = .;
57 __initcall_start = .;
58 .initcall.init : {
59 INITCALLS
60 }
61 __initcall_end = .;
62 __con_initcall_start = .;
63 .con_initcall.init : { *(.con_initcall.init) }
64 __con_initcall_end = .;
65 .m68k_fixup : { 41 .m68k_fixup : {
66 __start_fixup = .; 42 __start_fixup = .;
67 *(.m68k_fixup) 43 *(.m68k_fixup)
68 __stop_fixup = .; 44 __stop_fixup = .;
69 } 45 }
70 SECURITY_INIT
71#ifdef CONFIG_BLK_DEV_INITRD
72 . = ALIGN(8192);
73 __initramfs_start = .;
74 .init.ramfs : { *(.init.ramfs) }
75 __initramfs_end = .;
76#endif
77 NOTES 46 NOTES
78 . = ALIGN(8192); 47 .init_end : {
79 __init_end = .; 48 /* This ALIGN be in a section so that _end is at the end of the
80 49 load segment. */
81 .data.init_task : { *(.data.init_task) } /* The initial task and kernel stack */ 50 . = ALIGN(PAGE_SIZE);
51 __init_end = .;
52 }
82 53
83 _end = . ; 54 _end = . ;
84 55
85 /* Stabs debugging sections. */ 56 STABS_DEBUG
86 .stab 0 : { *(.stab) }
87 .stabstr 0 : { *(.stabstr) }
88 .stab.excl 0 : { *(.stab.excl) }
89 .stab.exclstr 0 : { *(.stab.exclstr) }
90 .stab.index 0 : { *(.stab.index) }
91 .stab.indexstr 0 : { *(.stab.indexstr) }
92 .comment 0 : { *(.comment) } 57 .comment 0 : { *(.comment) }
93 58
94 /* Sections to be discarded */ 59 /* Sections to be discarded */
diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds
index 03efaf04d7d7..1ad6b7ad2c17 100644
--- a/arch/m68k/kernel/vmlinux-sun3.lds
+++ b/arch/m68k/kernel/vmlinux-sun3.lds
@@ -2,6 +2,7 @@
2 2
3#include <asm-generic/vmlinux.lds.h> 3#include <asm-generic/vmlinux.lds.h>
4#include <asm/page.h> 4#include <asm/page.h>
5#include <asm/thread_info.h>
5 6
6OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k") 7OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k")
7OUTPUT_ARCH(m68k) 8OUTPUT_ARCH(m68k)
@@ -23,14 +24,8 @@ SECTIONS
23 24
24 _etext = .; /* End of text section */ 25 _etext = .; /* End of text section */
25 26
26 .data : { /* Data */ 27 EXCEPTION_TABLE(16) :data
27 DATA_DATA 28 RW_DATA_SECTION(16, PAGE_SIZE, THREAD_SIZE) :data
28 CONSTRUCTORS
29 . = ALIGN(16); /* Exception table */
30 __start___ex_table = .;
31 *(__ex_table)
32 __stop___ex_table = .;
33 } :data
34 /* End of data goes *here* so that freeing init code works properly. */ 29 /* End of data goes *here* so that freeing init code works properly. */
35 _edata = .; 30 _edata = .;
36 NOTES 31 NOTES
@@ -38,56 +33,21 @@ SECTIONS
38 /* will be freed after init */ 33 /* will be freed after init */
39 . = ALIGN(PAGE_SIZE); /* Init code and data */ 34 . = ALIGN(PAGE_SIZE); /* Init code and data */
40__init_begin = .; 35__init_begin = .;
41 .init.text : { 36 INIT_TEXT_SECTION(PAGE_SIZE)
42 _sinittext = .; 37 INIT_DATA_SECTION(16)
43 INIT_TEXT
44 _einittext = .;
45 }
46 .init.data : { INIT_DATA }
47 . = ALIGN(16);
48 __setup_start = .;
49 .init.setup : { *(.init.setup) }
50 __setup_end = .;
51 __initcall_start = .;
52 .initcall.init : {
53 INITCALLS
54 }
55 __initcall_end = .;
56 __con_initcall_start = .;
57 .con_initcall.init : { *(.con_initcall.init) }
58 __con_initcall_end = .;
59 .m68k_fixup : { 38 .m68k_fixup : {
60 __start_fixup = .; 39 __start_fixup = .;
61 *(.m68k_fixup) 40 *(.m68k_fixup)
62 __stop_fixup = .; 41 __stop_fixup = .;
63 } 42 }
64 SECURITY_INIT
65#ifdef CONFIG_BLK_DEV_INITRD
66 . = ALIGN(PAGE_SIZE);
67 __initramfs_start = .;
68 .init.ramfs : { *(.init.ramfs) }
69 __initramfs_end = .;
70#endif
71 . = ALIGN(PAGE_SIZE); 43 . = ALIGN(PAGE_SIZE);
72 __init_end = .; 44 __init_end = .;
73 .data.init.task : { *(.data.init_task) }
74
75 45
76 .bss : { *(.bss) } /* BSS */ 46 BSS_SECTION(0, 0, 0)
77 47
78 _end = . ; 48 _end = . ;
79 49
80 .crap : { 50 STABS_DEBUG
81 /* Stabs debugging sections. */
82 *(.stab)
83 *(.stabstr)
84 *(.stab.excl)
85 *(.stab.exclstr)
86 *(.stab.index)
87 *(.stab.indexstr)
88 *(.comment)
89 *(.note)
90 }
91 51
92 /* Sections to be discarded */ 52 /* Sections to be discarded */
93 DISCARDS 53 DISCARDS