aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-10-30 21:37:12 -0500
committerPaul Mackerras <paulus@samba.org>2005-10-30 21:37:12 -0500
commit23fd07750a789a66fe88cf173d52a18f1a387da4 (patch)
tree06fdd6df35fdb835abdaa9b754d62f6b84b97250 /arch/arm/kernel
parentbd787d438a59266af3c9f6351644c85ef1dd21fe (diff)
parented28f96ac1960f30f818374d65be71d2fdf811b0 (diff)
Merge ../linux-2.6 by hand
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/Makefile2
-rw-r--r--arch/arm/kernel/arthur.c1
-rw-r--r--arch/arm/kernel/asm-offsets.c1
-rw-r--r--arch/arm/kernel/entry-armv.S3
-rw-r--r--arch/arm/kernel/head.S57
-rw-r--r--arch/arm/kernel/module.c1
-rw-r--r--arch/arm/kernel/ptrace.c2
-rw-r--r--arch/arm/kernel/signal.c96
-rw-r--r--arch/arm/kernel/time.c4
-rw-r--r--arch/arm/kernel/traps.c47
-rw-r--r--arch/arm/kernel/vmlinux.lds.S11
11 files changed, 80 insertions, 145 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 3e1b0327e4d7..c11169b5ed9a 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -2,7 +2,7 @@
2# Makefile for the linux kernel. 2# Makefile for the linux kernel.
3# 3#
4 4
5AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR) 5AFLAGS_head.o := -DKERNEL_RAM_ADDR=$(TEXTADDR)
6 6
7# Object file lists. 7# Object file lists.
8 8
diff --git a/arch/arm/kernel/arthur.c b/arch/arm/kernel/arthur.c
index a418dad6692c..0ee2e9819631 100644
--- a/arch/arm/kernel/arthur.c
+++ b/arch/arm/kernel/arthur.c
@@ -18,6 +18,7 @@
18#include <linux/stddef.h> 18#include <linux/stddef.h>
19#include <linux/signal.h> 19#include <linux/signal.h>
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/sched.h>
21 22
22#include <asm/ptrace.h> 23#include <asm/ptrace.h>
23 24
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index c1ff4d1f1bfd..04d3082a7b94 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -94,7 +94,6 @@ int main(void)
94 DEFINE(VM_EXEC, VM_EXEC); 94 DEFINE(VM_EXEC, VM_EXEC);
95 BLANK(); 95 BLANK();
96 DEFINE(PAGE_SZ, PAGE_SIZE); 96 DEFINE(PAGE_SZ, PAGE_SIZE);
97 DEFINE(VIRT_OFFSET, PAGE_OFFSET);
98 BLANK(); 97 BLANK();
99 DEFINE(SYS_ERROR0, 0x9f0000); 98 DEFINE(SYS_ERROR0, 0x9f0000);
100 BLANK(); 99 BLANK();
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 93b5e8e5292e..be439cab92c6 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -15,6 +15,7 @@
15 */ 15 */
16#include <linux/config.h> 16#include <linux/config.h>
17 17
18#include <asm/memory.h>
18#include <asm/glue.h> 19#include <asm/glue.h>
19#include <asm/vfpmacros.h> 20#include <asm/vfpmacros.h>
20#include <asm/hardware.h> /* should be moved into entry-macro.S */ 21#include <asm/hardware.h> /* should be moved into entry-macro.S */
@@ -310,7 +311,7 @@ __pabt_svc:
310 311
311#if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) 312#if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
312 @ make sure our user space atomic helper is aborted 313 @ make sure our user space atomic helper is aborted
313 cmp r2, #VIRT_OFFSET 314 cmp r2, #TASK_SIZE
314 bichs r3, r3, #PSR_Z_BIT 315 bichs r3, r3, #PSR_Z_BIT
315#endif 316#endif
316 317
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 539626351348..8d8748407cbe 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -21,6 +21,7 @@
21#include <asm/procinfo.h> 21#include <asm/procinfo.h>
22#include <asm/ptrace.h> 22#include <asm/ptrace.h>
23#include <asm/asm-offsets.h> 23#include <asm/asm-offsets.h>
24#include <asm/memory.h>
24#include <asm/thread_info.h> 25#include <asm/thread_info.h>
25#include <asm/system.h> 26#include <asm/system.h>
26 27
@@ -33,52 +34,28 @@
33#define MACHINFO_PGOFFIO 12 34#define MACHINFO_PGOFFIO 12
34#define MACHINFO_NAME 16 35#define MACHINFO_NAME 16
35 36
36#ifndef CONFIG_XIP_KERNEL
37/* 37/*
38 * We place the page tables 16K below TEXTADDR. Therefore, we must make sure 38 * swapper_pg_dir is the virtual address of the initial page table.
39 * that TEXTADDR is correctly set. Currently, we expect the least significant 39 * We place the page tables 16K below KERNEL_RAM_ADDR. Therefore, we must
40 * 16 bits to be 0x8000, but we could probably relax this restriction to 40 * make sure that KERNEL_RAM_ADDR is correctly set. Currently, we expect
41 * TEXTADDR >= PAGE_OFFSET + 0x4000 41 * the least significant 16 bits to be 0x8000, but we could probably
42 * 42 * relax this restriction to KERNEL_RAM_ADDR >= PAGE_OFFSET + 0x4000.
43 * Note that swapper_pg_dir is the virtual address of the page tables, and
44 * pgtbl gives us a position-independent reference to these tables. We can
45 * do this because stext == TEXTADDR
46 */ 43 */
47#if (TEXTADDR & 0xffff) != 0x8000 44#if (KERNEL_RAM_ADDR & 0xffff) != 0x8000
48#error TEXTADDR must start at 0xXXXX8000 45#error KERNEL_RAM_ADDR must start at 0xXXXX8000
49#endif 46#endif
50 47
51 .globl swapper_pg_dir 48 .globl swapper_pg_dir
52 .equ swapper_pg_dir, TEXTADDR - 0x4000 49 .equ swapper_pg_dir, KERNEL_RAM_ADDR - 0x4000
53 50
54 .macro pgtbl, rd, phys 51 .macro pgtbl, rd
55 adr \rd, stext 52 ldr \rd, =(__virt_to_phys(KERNEL_RAM_ADDR - 0x4000))
56 sub \rd, \rd, #0x4000
57 .endm 53 .endm
58#else
59/*
60 * XIP Kernel:
61 *
62 * We place the page tables 16K below DATAADDR. Therefore, we must make sure
63 * that DATAADDR is correctly set. Currently, we expect the least significant
64 * 16 bits to be 0x8000, but we could probably relax this restriction to
65 * DATAADDR >= PAGE_OFFSET + 0x4000
66 *
67 * Note that pgtbl is meant to return the physical address of swapper_pg_dir.
68 * We can't make it relative to the kernel position in this case since
69 * the kernel can physically be anywhere.
70 */
71#if (DATAADDR & 0xffff) != 0x8000
72#error DATAADDR must start at 0xXXXX8000
73#endif
74
75 .globl swapper_pg_dir
76 .equ swapper_pg_dir, DATAADDR - 0x4000
77 54
78 .macro pgtbl, rd, phys 55#ifdef CONFIG_XIP_KERNEL
79 ldr \rd, =((DATAADDR - 0x4000) - VIRT_OFFSET) 56#define TEXTADDR XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
80 add \rd, \rd, \phys 57#else
81 .endm 58#define TEXTADDR KERNEL_RAM_ADDR
82#endif 59#endif
83 60
84/* 61/*
@@ -279,7 +256,7 @@ __turn_mmu_on:
279 .type __create_page_tables, %function 256 .type __create_page_tables, %function
280__create_page_tables: 257__create_page_tables:
281 ldr r5, [r8, #MACHINFO_PHYSRAM] @ physram 258 ldr r5, [r8, #MACHINFO_PHYSRAM] @ physram
282 pgtbl r4, r5 @ page table address 259 pgtbl r4 @ page table address
283 260
284 /* 261 /*
285 * Clear the 16K level 1 swapper page table 262 * Clear the 16K level 1 swapper page table
@@ -324,7 +301,7 @@ __create_page_tables:
324 /* 301 /*
325 * Then map first 1MB of ram in case it contains our boot params. 302 * Then map first 1MB of ram in case it contains our boot params.
326 */ 303 */
327 add r0, r4, #VIRT_OFFSET >> 18 304 add r0, r4, #PAGE_OFFSET >> 18
328 orr r6, r5, r7 305 orr r6, r5, r7
329 str r6, [r0] 306 str r6, [r0]
330 307
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 1a85cfdad5ac..6055e1427ba3 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -11,6 +11,7 @@
11 */ 11 */
12#include <linux/config.h> 12#include <linux/config.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/moduleloader.h>
14#include <linux/kernel.h> 15#include <linux/kernel.h>
15#include <linux/elf.h> 16#include <linux/elf.h>
16#include <linux/vmalloc.h> 17#include <linux/vmalloc.h>
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index cd99b83f14c2..9bd8609a2926 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -782,7 +782,7 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
782 return ret; 782 return ret;
783} 783}
784 784
785asmlinkage int sys_ptrace(long request, long pid, long addr, long data) 785asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
786{ 786{
787 struct task_struct *child; 787 struct task_struct *child;
788 int ret; 788 int ret;
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index a94d75fef598..a917e3dd3666 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -139,93 +139,33 @@ struct iwmmxt_sigframe {
139 unsigned long storage[0x98/4]; 139 unsigned long storage[0x98/4];
140}; 140};
141 141
142static int page_present(struct mm_struct *mm, void __user *uptr, int wr)
143{
144 unsigned long addr = (unsigned long)uptr;
145 pgd_t *pgd = pgd_offset(mm, addr);
146 if (pgd_present(*pgd)) {
147 pmd_t *pmd = pmd_offset(pgd, addr);
148 if (pmd_present(*pmd)) {
149 pte_t *pte = pte_offset_map(pmd, addr);
150 return (pte_present(*pte) && (!wr || pte_write(*pte)));
151 }
152 }
153 return 0;
154}
155
156static int copy_locked(void __user *uptr, void *kptr, size_t size, int write,
157 void (*copyfn)(void *, void __user *))
158{
159 unsigned char v, __user *userptr = uptr;
160 int err = 0;
161
162 do {
163 struct mm_struct *mm;
164
165 if (write) {
166 __put_user_error(0, userptr, err);
167 __put_user_error(0, userptr + size - 1, err);
168 } else {
169 __get_user_error(v, userptr, err);
170 __get_user_error(v, userptr + size - 1, err);
171 }
172
173 if (err)
174 break;
175
176 mm = current->mm;
177 spin_lock(&mm->page_table_lock);
178 if (page_present(mm, userptr, write) &&
179 page_present(mm, userptr + size - 1, write)) {
180 copyfn(kptr, uptr);
181 } else
182 err = 1;
183 spin_unlock(&mm->page_table_lock);
184 } while (err);
185
186 return err;
187}
188
189static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame) 142static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame)
190{ 143{
191 int err = 0; 144 char kbuf[sizeof(*frame) + 8];
145 struct iwmmxt_sigframe *kframe;
192 146
193 /* the iWMMXt context must be 64 bit aligned */ 147 /* the iWMMXt context must be 64 bit aligned */
194 WARN_ON((unsigned long)frame & 7); 148 kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
195 149 kframe->magic0 = IWMMXT_MAGIC0;
196 __put_user_error(IWMMXT_MAGIC0, &frame->magic0, err); 150 kframe->magic1 = IWMMXT_MAGIC1;
197 __put_user_error(IWMMXT_MAGIC1, &frame->magic1, err); 151 iwmmxt_task_copy(current_thread_info(), &kframe->storage);
198 152 return __copy_to_user(frame, kframe, sizeof(*frame));
199 /*
200 * iwmmxt_task_copy() doesn't check user permissions.
201 * Let's do a dummy write on the upper boundary to ensure
202 * access to user mem is OK all way up.
203 */
204 err |= copy_locked(&frame->storage, current_thread_info(),
205 sizeof(frame->storage), 1, iwmmxt_task_copy);
206 return err;
207} 153}
208 154
209static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame) 155static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
210{ 156{
211 unsigned long magic0, magic1; 157 char kbuf[sizeof(*frame) + 8];
212 int err = 0; 158 struct iwmmxt_sigframe *kframe;
213 159
214 /* the iWMMXt context is 64 bit aligned */ 160 /* the iWMMXt context must be 64 bit aligned */
215 WARN_ON((unsigned long)frame & 7); 161 kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
216 162 if (__copy_from_user(kframe, frame, sizeof(*frame)))
217 /* 163 return -1;
218 * Validate iWMMXt context signature. 164 if (kframe->magic0 != IWMMXT_MAGIC0 ||
219 * Also, iwmmxt_task_restore() doesn't check user permissions. 165 kframe->magic1 != IWMMXT_MAGIC1)
220 * Let's do a dummy write on the upper boundary to ensure 166 return -1;
221 * access to user mem is OK all way up. 167 iwmmxt_task_restore(current_thread_info(), &kframe->storage);
222 */ 168 return 0;
223 __get_user_error(magic0, &frame->magic0, err);
224 __get_user_error(magic1, &frame->magic1, err);
225 if (!err && magic0 == IWMMXT_MAGIC0 && magic1 == IWMMXT_MAGIC1)
226 err = copy_locked(&frame->storage, current_thread_info(),
227 sizeof(frame->storage), 0, iwmmxt_task_restore);
228 return err;
229} 169}
230 170
231#endif 171#endif
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 69449a818dcc..fc4729106a32 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -36,10 +36,6 @@
36#include <asm/thread_info.h> 36#include <asm/thread_info.h>
37#include <asm/mach/time.h> 37#include <asm/mach/time.h>
38 38
39u64 jiffies_64 = INITIAL_JIFFIES;
40
41EXPORT_SYMBOL(jiffies_64);
42
43/* 39/*
44 * Our system timer. 40 * Our system timer.
45 */ 41 */
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index f6de76e0a45d..45e9ea6cd2a5 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -198,25 +198,16 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
198 barrier(); 198 barrier();
199} 199}
200 200
201DEFINE_SPINLOCK(die_lock); 201static void __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs)
202
203/*
204 * This function is protected against re-entrancy.
205 */
206NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
207{ 202{
208 struct task_struct *tsk = current; 203 struct task_struct *tsk = thread->task;
209 static int die_counter; 204 static int die_counter;
210 205
211 console_verbose();
212 spin_lock_irq(&die_lock);
213 bust_spinlocks(1);
214
215 printk("Internal error: %s: %x [#%d]\n", str, err, ++die_counter); 206 printk("Internal error: %s: %x [#%d]\n", str, err, ++die_counter);
216 print_modules(); 207 print_modules();
217 __show_regs(regs); 208 __show_regs(regs);
218 printk("Process %s (pid: %d, stack limit = 0x%p)\n", 209 printk("Process %s (pid: %d, stack limit = 0x%p)\n",
219 tsk->comm, tsk->pid, tsk->thread_info + 1); 210 tsk->comm, tsk->pid, thread + 1);
220 211
221 if (!user_mode(regs) || in_interrupt()) { 212 if (!user_mode(regs) || in_interrupt()) {
222 dump_mem("Stack: ", regs->ARM_sp, 213 dump_mem("Stack: ", regs->ARM_sp,
@@ -224,7 +215,21 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
224 dump_backtrace(regs, tsk); 215 dump_backtrace(regs, tsk);
225 dump_instr(regs); 216 dump_instr(regs);
226 } 217 }
218}
219
220DEFINE_SPINLOCK(die_lock);
221
222/*
223 * This function is protected against re-entrancy.
224 */
225NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
226{
227 struct thread_info *thread = current_thread_info();
227 228
229 console_verbose();
230 spin_lock_irq(&die_lock);
231 bust_spinlocks(1);
232 __die(str, err, thread, regs);
228 bust_spinlocks(0); 233 bust_spinlocks(0);
229 spin_unlock_irq(&die_lock); 234 spin_unlock_irq(&die_lock);
230 do_exit(SIGSEGV); 235 do_exit(SIGSEGV);
@@ -345,7 +350,9 @@ static int bad_syscall(int n, struct pt_regs *regs)
345 struct thread_info *thread = current_thread_info(); 350 struct thread_info *thread = current_thread_info();
346 siginfo_t info; 351 siginfo_t info;
347 352
348 if (current->personality != PER_LINUX && thread->exec_domain->handler) { 353 if (current->personality != PER_LINUX &&
354 current->personality != PER_LINUX_32BIT &&
355 thread->exec_domain->handler) {
349 thread->exec_domain->handler(n, regs); 356 thread->exec_domain->handler(n, regs);
350 return regs->ARM_r0; 357 return regs->ARM_r0;
351 } 358 }
@@ -481,29 +488,33 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
481 unsigned long addr = regs->ARM_r2; 488 unsigned long addr = regs->ARM_r2;
482 struct mm_struct *mm = current->mm; 489 struct mm_struct *mm = current->mm;
483 pgd_t *pgd; pmd_t *pmd; pte_t *pte; 490 pgd_t *pgd; pmd_t *pmd; pte_t *pte;
491 spinlock_t *ptl;
484 492
485 regs->ARM_cpsr &= ~PSR_C_BIT; 493 regs->ARM_cpsr &= ~PSR_C_BIT;
486 spin_lock(&mm->page_table_lock); 494 down_read(&mm->mmap_sem);
487 pgd = pgd_offset(mm, addr); 495 pgd = pgd_offset(mm, addr);
488 if (!pgd_present(*pgd)) 496 if (!pgd_present(*pgd))
489 goto bad_access; 497 goto bad_access;
490 pmd = pmd_offset(pgd, addr); 498 pmd = pmd_offset(pgd, addr);
491 if (!pmd_present(*pmd)) 499 if (!pmd_present(*pmd))
492 goto bad_access; 500 goto bad_access;
493 pte = pte_offset_map(pmd, addr); 501 pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
494 if (!pte_present(*pte) || !pte_write(*pte)) 502 if (!pte_present(*pte) || !pte_write(*pte)) {
503 pte_unmap_unlock(pte, ptl);
495 goto bad_access; 504 goto bad_access;
505 }
496 val = *(unsigned long *)addr; 506 val = *(unsigned long *)addr;
497 val -= regs->ARM_r0; 507 val -= regs->ARM_r0;
498 if (val == 0) { 508 if (val == 0) {
499 *(unsigned long *)addr = regs->ARM_r1; 509 *(unsigned long *)addr = regs->ARM_r1;
500 regs->ARM_cpsr |= PSR_C_BIT; 510 regs->ARM_cpsr |= PSR_C_BIT;
501 } 511 }
502 spin_unlock(&mm->page_table_lock); 512 pte_unmap_unlock(pte, ptl);
513 up_read(&mm->mmap_sem);
503 return val; 514 return val;
504 515
505 bad_access: 516 bad_access:
506 spin_unlock(&mm->page_table_lock); 517 up_read(&mm->mmap_sem);
507 /* simulate a write access fault */ 518 /* simulate a write access fault */
508 do_DataAbort(addr, 15 + (1 << 11), regs); 519 do_DataAbort(addr, 15 + (1 << 11), regs);
509 return -1; 520 return -1;
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 0d5db5279c5c..80c8e4c8cefa 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -6,14 +6,23 @@
6#include <asm-generic/vmlinux.lds.h> 6#include <asm-generic/vmlinux.lds.h>
7#include <linux/config.h> 7#include <linux/config.h>
8#include <asm/thread_info.h> 8#include <asm/thread_info.h>
9#include <asm/memory.h>
9 10
10OUTPUT_ARCH(arm) 11OUTPUT_ARCH(arm)
11ENTRY(stext) 12ENTRY(stext)
13
12#ifndef __ARMEB__ 14#ifndef __ARMEB__
13jiffies = jiffies_64; 15jiffies = jiffies_64;
14#else 16#else
15jiffies = jiffies_64 + 4; 17jiffies = jiffies_64 + 4;
16#endif 18#endif
19
20#ifdef CONFIG_XIP_KERNEL
21#define TEXTADDR XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
22#else
23#define TEXTADDR KERNEL_RAM_ADDR
24#endif
25
17SECTIONS 26SECTIONS
18{ 27{
19 . = TEXTADDR; 28 . = TEXTADDR;
@@ -95,7 +104,7 @@ SECTIONS
95 104
96#ifdef CONFIG_XIP_KERNEL 105#ifdef CONFIG_XIP_KERNEL
97 __data_loc = ALIGN(4); /* location in binary */ 106 __data_loc = ALIGN(4); /* location in binary */
98 . = DATAADDR; 107 . = KERNEL_RAM_ADDR;
99#else 108#else
100 . = ALIGN(THREAD_SIZE); 109 . = ALIGN(THREAD_SIZE);
101 __data_loc = .; 110 __data_loc = .;