diff options
author | Paul Mackerras <paulus@samba.org> | 2005-10-30 21:37:12 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2005-10-30 21:37:12 -0500 |
commit | 23fd07750a789a66fe88cf173d52a18f1a387da4 (patch) | |
tree | 06fdd6df35fdb835abdaa9b754d62f6b84b97250 /arch/arm/kernel | |
parent | bd787d438a59266af3c9f6351644c85ef1dd21fe (diff) | |
parent | ed28f96ac1960f30f818374d65be71d2fdf811b0 (diff) |
Merge ../linux-2.6 by hand
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/kernel/arthur.c | 1 | ||||
-rw-r--r-- | arch/arm/kernel/asm-offsets.c | 1 | ||||
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 3 | ||||
-rw-r--r-- | arch/arm/kernel/head.S | 57 | ||||
-rw-r--r-- | arch/arm/kernel/module.c | 1 | ||||
-rw-r--r-- | arch/arm/kernel/ptrace.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/signal.c | 96 | ||||
-rw-r--r-- | arch/arm/kernel/time.c | 4 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 47 | ||||
-rw-r--r-- | arch/arm/kernel/vmlinux.lds.S | 11 |
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 | ||
5 | AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR) | 5 | AFLAGS_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 | ||
785 | asmlinkage int sys_ptrace(long request, long pid, long addr, long data) | 785 | asmlinkage 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 | ||
142 | static 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 | |||
156 | static 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 | |||
189 | static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame) | 142 | static 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 | ||
209 | static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame) | 155 | static 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 | ||
39 | u64 jiffies_64 = INITIAL_JIFFIES; | ||
40 | |||
41 | EXPORT_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 | ||
201 | DEFINE_SPINLOCK(die_lock); | 201 | static 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 | */ | ||
206 | NORET_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 | |||
220 | DEFINE_SPINLOCK(die_lock); | ||
221 | |||
222 | /* | ||
223 | * This function is protected against re-entrancy. | ||
224 | */ | ||
225 | NORET_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 | ||
10 | OUTPUT_ARCH(arm) | 11 | OUTPUT_ARCH(arm) |
11 | ENTRY(stext) | 12 | ENTRY(stext) |
13 | |||
12 | #ifndef __ARMEB__ | 14 | #ifndef __ARMEB__ |
13 | jiffies = jiffies_64; | 15 | jiffies = jiffies_64; |
14 | #else | 16 | #else |
15 | jiffies = jiffies_64 + 4; | 17 | jiffies = 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 | |||
17 | SECTIONS | 26 | SECTIONS |
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 = .; |