aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/head.S
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/arm/kernel/head.S
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'arch/arm/kernel/head.S')
-rw-r--r--arch/arm/kernel/head.S526
1 files changed, 391 insertions, 135 deletions
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index eb62bf947212..278c1b0ebb2e 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -22,14 +22,10 @@
22#include <asm/thread_info.h> 22#include <asm/thread_info.h>
23#include <asm/system.h> 23#include <asm/system.h>
24 24
25#if (PHYS_OFFSET & 0x001fffff) 25#ifdef CONFIG_DEBUG_LL
26#error "PHYS_OFFSET must be at an even 2MiB boundary!" 26#include <mach/debug-macro.S>
27#endif 27#endif
28 28
29#define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET)
30#define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET)
31
32
33/* 29/*
34 * swapper_pg_dir is the virtual address of the initial page table. 30 * swapper_pg_dir is the virtual address of the initial page table.
35 * We place the page tables 16K below KERNEL_RAM_VADDR. Therefore, we must 31 * We place the page tables 16K below KERNEL_RAM_VADDR. Therefore, we must
@@ -37,6 +33,7 @@
37 * the least significant 16 bits to be 0x8000, but we could probably 33 * the least significant 16 bits to be 0x8000, but we could probably
38 * relax this restriction to KERNEL_RAM_VADDR >= PAGE_OFFSET + 0x4000. 34 * relax this restriction to KERNEL_RAM_VADDR >= PAGE_OFFSET + 0x4000.
39 */ 35 */
36#define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET)
40#if (KERNEL_RAM_VADDR & 0xffff) != 0x8000 37#if (KERNEL_RAM_VADDR & 0xffff) != 0x8000
41#error KERNEL_RAM_VADDR must start at 0xXXXX8000 38#error KERNEL_RAM_VADDR must start at 0xXXXX8000
42#endif 39#endif
@@ -44,8 +41,8 @@
44 .globl swapper_pg_dir 41 .globl swapper_pg_dir
45 .equ swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000 42 .equ swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000
46 43
47 .macro pgtbl, rd 44 .macro pgtbl, rd, phys
48 ldr \rd, =(KERNEL_RAM_PADDR - 0x4000) 45 add \rd, \phys, #TEXT_OFFSET - 0x4000
49 .endm 46 .endm
50 47
51#ifdef CONFIG_XIP_KERNEL 48#ifdef CONFIG_XIP_KERNEL
@@ -62,7 +59,7 @@
62 * 59 *
63 * This is normally called from the decompressor code. The requirements 60 * This is normally called from the decompressor code. The requirements
64 * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, 61 * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
65 * r1 = machine nr, r2 = atags pointer. 62 * r1 = machine nr, r2 = atags or dtb pointer.
66 * 63 *
67 * This code is mostly position independent, so if you link the kernel at 64 * This code is mostly position independent, so if you link the kernel at
68 * 0xc0008000, you call this at __pa(0xc0008000). 65 * 0xc0008000, you call this at __pa(0xc0008000).
@@ -81,29 +78,210 @@ ENTRY(stext)
81 mrc p15, 0, r9, c0, c0 @ get processor id 78 mrc p15, 0, r9, c0, c0 @ get processor id
82 bl __lookup_processor_type @ r5=procinfo r9=cpuid 79 bl __lookup_processor_type @ r5=procinfo r9=cpuid
83 movs r10, r5 @ invalid processor (r5=0)? 80 movs r10, r5 @ invalid processor (r5=0)?
81 THUMB( it eq ) @ force fixup-able long branch encoding
84 beq __error_p @ yes, error 'p' 82 beq __error_p @ yes, error 'p'
85 bl __lookup_machine_type @ r5=machinfo 83
86 movs r8, r5 @ invalid machine (r5=0)? 84#ifndef CONFIG_XIP_KERNEL
87 beq __error_a @ yes, error 'a' 85 adr r3, 2f
86 ldmia r3, {r4, r8}
87 sub r4, r3, r4 @ (PHYS_OFFSET - PAGE_OFFSET)
88 add r8, r8, r4 @ PHYS_OFFSET
89#else
90 ldr r8, =PLAT_PHYS_OFFSET
91#endif
92
93 /*
94 * r1 = machine no, r2 = atags or dtb,
95 * r8 = phys_offset, r9 = cpuid, r10 = procinfo
96 */
88 bl __vet_atags 97 bl __vet_atags
98#ifdef CONFIG_SMP_ON_UP
99 bl __fixup_smp
100#endif
101#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
102 bl __fixup_pv_table
103#endif
89 bl __create_page_tables 104 bl __create_page_tables
90 105
91 /* 106 /*
92 * The following calls CPU specific code in a position independent 107 * The following calls CPU specific code in a position independent
93 * manner. See arch/arm/mm/proc-*.S for details. r10 = base of 108 * manner. See arch/arm/mm/proc-*.S for details. r10 = base of
94 * xxx_proc_info structure selected by __lookup_machine_type 109 * xxx_proc_info structure selected by __lookup_processor_type
95 * above. On return, the CPU will be ready for the MMU to be 110 * above. On return, the CPU will be ready for the MMU to be
96 * turned on, and r0 will hold the CPU control register value. 111 * turned on, and r0 will hold the CPU control register value.
97 */ 112 */
98 ldr r13, __switch_data @ address to jump to after 113 ldr r13, =__mmap_switched @ address to jump to after
99 @ mmu has been enabled 114 @ mmu has been enabled
100 adr lr, BSYM(__enable_mmu) @ return (PIC) address 115 adr lr, BSYM(1f) @ return (PIC) address
116 mov r8, r4 @ set TTBR1 to swapper_pg_dir
101 ARM( add pc, r10, #PROCINFO_INITFUNC ) 117 ARM( add pc, r10, #PROCINFO_INITFUNC )
102 THUMB( add r12, r10, #PROCINFO_INITFUNC ) 118 THUMB( add r12, r10, #PROCINFO_INITFUNC )
103 THUMB( mov pc, r12 ) 119 THUMB( mov pc, r12 )
1201: b __enable_mmu
104ENDPROC(stext) 121ENDPROC(stext)
122 .ltorg
123#ifndef CONFIG_XIP_KERNEL
1242: .long .
125 .long PAGE_OFFSET
126#endif
127
128/*
129 * Setup the initial page tables. We only setup the barest
130 * amount which are required to get the kernel running, which
131 * generally means mapping in the kernel code.
132 *
133 * r8 = phys_offset, r9 = cpuid, r10 = procinfo
134 *
135 * Returns:
136 * r0, r3, r5-r7 corrupted
137 * r4 = physical page table address
138 */
139__create_page_tables:
140 pgtbl r4, r8 @ page table address
141
142 /*
143 * Clear the 16K level 1 swapper page table
144 */
145 mov r0, r4
146 mov r3, #0
147 add r6, r0, #0x4000
1481: str r3, [r0], #4
149 str r3, [r0], #4
150 str r3, [r0], #4
151 str r3, [r0], #4
152 teq r0, r6
153 bne 1b
154
155 ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags
156
157 /*
158 * Create identity mapping to cater for __enable_mmu.
159 * This identity mapping will be removed by paging_init().
160 */
161 adr r0, __enable_mmu_loc
162 ldmia r0, {r3, r5, r6}
163 sub r0, r0, r3 @ virt->phys offset
164 add r5, r5, r0 @ phys __enable_mmu
165 add r6, r6, r0 @ phys __enable_mmu_end
166 mov r5, r5, lsr #20
167 mov r6, r6, lsr #20
168
1691: orr r3, r7, r5, lsl #20 @ flags + kernel base
170 str r3, [r4, r5, lsl #2] @ identity mapping
171 teq r5, r6
172 addne r5, r5, #1 @ next section
173 bne 1b
174
175 /*
176 * Now setup the pagetables for our kernel direct
177 * mapped region.
178 */
179 mov r3, pc
180 mov r3, r3, lsr #20
181 orr r3, r7, r3, lsl #20
182 add r0, r4, #(KERNEL_START & 0xff000000) >> 18
183 str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]!
184 ldr r6, =(KERNEL_END - 1)
185 add r0, r0, #4
186 add r6, r4, r6, lsr #18
1871: cmp r0, r6
188 add r3, r3, #1 << 20
189 strls r3, [r0], #4
190 bls 1b
191
192#ifdef CONFIG_XIP_KERNEL
193 /*
194 * Map some ram to cover our .data and .bss areas.
195 */
196 add r3, r8, #TEXT_OFFSET
197 orr r3, r3, r7
198 add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> 18
199 str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]!
200 ldr r6, =(_end - 1)
201 add r0, r0, #4
202 add r6, r4, r6, lsr #18
2031: cmp r0, r6
204 add r3, r3, #1 << 20
205 strls r3, [r0], #4
206 bls 1b
207#endif
208
209 /*
210 * Then map boot params address in r2 or
211 * the first 1MB of ram if boot params address is not specified.
212 */
213 mov r0, r2, lsr #20
214 movs r0, r0, lsl #20
215 moveq r0, r8
216 sub r3, r0, r8
217 add r3, r3, #PAGE_OFFSET
218 add r3, r4, r3, lsr #18
219 orr r6, r7, r0
220 str r6, [r3]
221
222#ifdef CONFIG_DEBUG_LL
223#ifndef CONFIG_DEBUG_ICEDCC
224 /*
225 * Map in IO space for serial debugging.
226 * This allows debug messages to be output
227 * via a serial console before paging_init.
228 */
229 addruart r7, r3
230
231 mov r3, r3, lsr #20
232 mov r3, r3, lsl #2
233
234 add r0, r4, r3
235 rsb r3, r3, #0x4000 @ PTRS_PER_PGD*sizeof(long)
236 cmp r3, #0x0800 @ limit to 512MB
237 movhi r3, #0x0800
238 add r6, r0, r3
239 mov r3, r7, lsr #20
240 ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
241 orr r3, r7, r3, lsl #20
2421: str r3, [r0], #4
243 add r3, r3, #1 << 20
244 teq r0, r6
245 bne 1b
246
247#else /* CONFIG_DEBUG_ICEDCC */
248 /* we don't need any serial debugging mappings for ICEDCC */
249 ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
250#endif /* !CONFIG_DEBUG_ICEDCC */
251
252#if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS)
253 /*
254 * If we're using the NetWinder or CATS, we also need to map
255 * in the 16550-type serial port for the debug messages
256 */
257 add r0, r4, #0xff000000 >> 18
258 orr r3, r7, #0x7c000000
259 str r3, [r0]
260#endif
261#ifdef CONFIG_ARCH_RPC
262 /*
263 * Map in screen at 0x02000000 & SCREEN2_BASE
264 * Similar reasons here - for debug. This is
265 * only for Acorn RiscPC architectures.
266 */
267 add r0, r4, #0x02000000 >> 18
268 orr r3, r7, #0x02000000
269 str r3, [r0]
270 add r0, r4, #0xd8000000 >> 18
271 str r3, [r0]
272#endif
273#endif
274 mov pc, lr
275ENDPROC(__create_page_tables)
276 .ltorg
277 .align
278__enable_mmu_loc:
279 .long .
280 .long __enable_mmu
281 .long __enable_mmu_end
105 282
106#if defined(CONFIG_SMP) 283#if defined(CONFIG_SMP)
284 __CPUINIT
107ENTRY(secondary_startup) 285ENTRY(secondary_startup)
108 /* 286 /*
109 * Common entry point for secondary CPUs. 287 * Common entry point for secondary CPUs.
@@ -117,15 +295,18 @@ ENTRY(secondary_startup)
117 bl __lookup_processor_type 295 bl __lookup_processor_type
118 movs r10, r5 @ invalid processor? 296 movs r10, r5 @ invalid processor?
119 moveq r0, #'p' @ yes, error 'p' 297 moveq r0, #'p' @ yes, error 'p'
120 beq __error 298 THUMB( it eq ) @ force fixup-able long branch encoding
299 beq __error_p
121 300
122 /* 301 /*
123 * Use the page tables supplied from __cpu_up. 302 * Use the page tables supplied from __cpu_up.
124 */ 303 */
125 adr r4, __secondary_data 304 adr r4, __secondary_data
126 ldmia r4, {r5, r7, r12} @ address to jump to after 305 ldmia r4, {r5, r7, r12} @ address to jump to after
127 sub r4, r4, r5 @ mmu has been enabled 306 sub lr, r4, r5 @ mmu has been enabled
128 ldr r4, [r7, r4] @ get secondary_data.pgdir 307 ldr r4, [r7, lr] @ get secondary_data.pgdir
308 add r7, r7, #4
309 ldr r8, [r7, lr] @ get secondary_data.swapper_pg_dir
129 adr lr, BSYM(__enable_mmu) @ return address 310 adr lr, BSYM(__enable_mmu) @ return address
130 mov r13, r12 @ __secondary_switched address 311 mov r13, r12 @ __secondary_switched address
131 ARM( add pc, r10, #PROCINFO_INITFUNC ) @ initialise processor 312 ARM( add pc, r10, #PROCINFO_INITFUNC ) @ initialise processor
@@ -143,6 +324,8 @@ ENTRY(__secondary_switched)
143 b secondary_start_kernel 324 b secondary_start_kernel
144ENDPROC(__secondary_switched) 325ENDPROC(__secondary_switched)
145 326
327 .align
328
146 .type __secondary_data, %object 329 .type __secondary_data, %object
147__secondary_data: 330__secondary_data:
148 .long . 331 .long .
@@ -156,6 +339,13 @@ __secondary_data:
156 * Setup common bits before finally enabling the MMU. Essentially 339 * Setup common bits before finally enabling the MMU. Essentially
157 * this is just loading the page table pointer and domain access 340 * this is just loading the page table pointer and domain access
158 * registers. 341 * registers.
342 *
343 * r0 = cp#15 control register
344 * r1 = machine ID
345 * r2 = atags or dtb pointer
346 * r4 = page table pointer
347 * r9 = processor ID
348 * r13 = *virtual* address to jump to upon completion
159 */ 349 */
160__enable_mmu: 350__enable_mmu:
161#ifdef CONFIG_ALIGNMENT_TRAP 351#ifdef CONFIG_ALIGNMENT_TRAP
@@ -188,6 +378,9 @@ ENDPROC(__enable_mmu)
188 * mailing list archives BEFORE sending another post to the list. 378 * mailing list archives BEFORE sending another post to the list.
189 * 379 *
190 * r0 = cp#15 control register 380 * r0 = cp#15 control register
381 * r1 = machine ID
382 * r2 = atags or dtb pointer
383 * r9 = processor ID
191 * r13 = *virtual* address to jump to upon completion 384 * r13 = *virtual* address to jump to upon completion
192 * 385 *
193 * other registers depend on the function called upon completion 386 * other registers depend on the function called upon completion
@@ -200,137 +393,200 @@ __turn_mmu_on:
200 mov r3, r3 393 mov r3, r3
201 mov r3, r13 394 mov r3, r13
202 mov pc, r3 395 mov pc, r3
396__enable_mmu_end:
203ENDPROC(__turn_mmu_on) 397ENDPROC(__turn_mmu_on)
204 398
205 399
206/* 400#ifdef CONFIG_SMP_ON_UP
207 * Setup the initial page tables. We only setup the barest 401 __INIT
208 * amount which are required to get the kernel running, which 402__fixup_smp:
209 * generally means mapping in the kernel code. 403 and r3, r9, #0x000f0000 @ architecture version
210 * 404 teq r3, #0x000f0000 @ CPU ID supported?
211 * r8 = machinfo 405 bne __fixup_smp_on_up @ no, assume UP
212 * r9 = cpuid
213 * r10 = procinfo
214 *
215 * Returns:
216 * r0, r3, r6, r7 corrupted
217 * r4 = physical page table address
218 */
219__create_page_tables:
220 pgtbl r4 @ page table address
221 406
222 /* 407 bic r3, r9, #0x00ff0000
223 * Clear the 16K level 1 swapper page table 408 bic r3, r3, #0x0000000f @ mask 0xff00fff0
224 */ 409 mov r4, #0x41000000
225 mov r0, r4 410 orr r4, r4, #0x0000b000
226 mov r3, #0 411 orr r4, r4, #0x00000020 @ val 0x4100b020
227 add r6, r0, #0x4000 412 teq r3, r4 @ ARM 11MPCore?
2281: str r3, [r0], #4 413 moveq pc, lr @ yes, assume SMP
229 str r3, [r0], #4
230 str r3, [r0], #4
231 str r3, [r0], #4
232 teq r0, r6
233 bne 1b
234 414
235 ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags 415 mrc p15, 0, r0, c0, c0, 5 @ read MPIDR
416 and r0, r0, #0xc0000000 @ multiprocessing extensions and
417 teq r0, #0x80000000 @ not part of a uniprocessor system?
418 moveq pc, lr @ yes, assume SMP
236 419
237 /* 420__fixup_smp_on_up:
238 * Create identity mapping for first MB of kernel to 421 adr r0, 1f
239 * cater for the MMU enable. This identity mapping 422 ldmia r0, {r3 - r5}
240 * will be removed by paging_init(). We use our current program 423 sub r3, r0, r3
241 * counter to determine corresponding section base address. 424 add r4, r4, r3
242 */ 425 add r5, r5, r3
243 mov r6, pc 426 b __do_fixup_smp_on_up
244 mov r6, r6, lsr #20 @ start of kernel section 427ENDPROC(__fixup_smp)
245 orr r3, r7, r6, lsl #20 @ flags + kernel base
246 str r3, [r4, r6, lsl #2] @ identity mapping
247 428
248 /* 429 .align
249 * Now setup the pagetables for our kernel direct 4301: .word .
250 * mapped region. 431 .word __smpalt_begin
251 */ 432 .word __smpalt_end
252 add r0, r4, #(KERNEL_START & 0xff000000) >> 18
253 str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]!
254 ldr r6, =(KERNEL_END - 1)
255 add r0, r0, #4
256 add r6, r4, r6, lsr #18
2571: cmp r0, r6
258 add r3, r3, #1 << 20
259 strls r3, [r0], #4
260 bls 1b
261 433
262#ifdef CONFIG_XIP_KERNEL 434 .pushsection .data
263 /* 435 .globl smp_on_up
264 * Map some ram to cover our .data and .bss areas. 436smp_on_up:
265 */ 437 ALT_SMP(.long 1)
266 orr r3, r7, #(KERNEL_RAM_PADDR & 0xff000000) 438 ALT_UP(.long 0)
267 .if (KERNEL_RAM_PADDR & 0x00f00000) 439 .popsection
268 orr r3, r3, #(KERNEL_RAM_PADDR & 0x00f00000)
269 .endif
270 add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> 18
271 str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]!
272 ldr r6, =(_end - 1)
273 add r0, r0, #4
274 add r6, r4, r6, lsr #18
2751: cmp r0, r6
276 add r3, r3, #1 << 20
277 strls r3, [r0], #4
278 bls 1b
279#endif 440#endif
280 441
281 /* 442 .text
282 * Then map first 1MB of ram in case it contains our boot params. 443__do_fixup_smp_on_up:
283 */ 444 cmp r4, r5
284 add r0, r4, #PAGE_OFFSET >> 18 445 movhs pc, lr
285 orr r6, r7, #(PHYS_OFFSET & 0xff000000) 446 ldmia r4!, {r0, r6}
286 .if (PHYS_OFFSET & 0x00f00000) 447 ARM( str r6, [r0, r3] )
287 orr r6, r6, #(PHYS_OFFSET & 0x00f00000) 448 THUMB( add r0, r0, r3 )
288 .endif 449#ifdef __ARMEB__
289 str r6, [r0] 450 THUMB( mov r6, r6, ror #16 ) @ Convert word order for big-endian.
451#endif
452 THUMB( strh r6, [r0], #2 ) @ For Thumb-2, store as two halfwords
453 THUMB( mov r6, r6, lsr #16 ) @ to be robust against misaligned r3.
454 THUMB( strh r6, [r0] )
455 b __do_fixup_smp_on_up
456ENDPROC(__do_fixup_smp_on_up)
290 457
291#ifdef CONFIG_DEBUG_LL 458ENTRY(fixup_smp)
292 ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags 459 stmfd sp!, {r4 - r6, lr}
293 /* 460 mov r4, r0
294 * Map in IO space for serial debugging. 461 add r5, r0, r1
295 * This allows debug messages to be output 462 mov r3, #0
296 * via a serial console before paging_init. 463 bl __do_fixup_smp_on_up
297 */ 464 ldmfd sp!, {r4 - r6, pc}
298 ldr r3, [r8, #MACHINFO_PGOFFIO] 465ENDPROC(fixup_smp)
299 add r0, r4, r3 466
300 rsb r3, r3, #0x4000 @ PTRS_PER_PGD*sizeof(long) 467#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
301 cmp r3, #0x0800 @ limit to 512MB 468
302 movhi r3, #0x0800 469/* __fixup_pv_table - patch the stub instructions with the delta between
303 add r6, r0, r3 470 * PHYS_OFFSET and PAGE_OFFSET, which is assumed to be 16MiB aligned and
304 ldr r3, [r8, #MACHINFO_PHYSIO] 471 * can be expressed by an immediate shifter operand. The stub instruction
305 orr r3, r3, r7 472 * has a form of '(add|sub) rd, rn, #imm'.
3061: str r3, [r0], #4 473 */
307 add r3, r3, #1 << 20 474 __HEAD
308 teq r0, r6 475__fixup_pv_table:
309 bne 1b 476 adr r0, 1f
310#if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS) 477 ldmia r0, {r3-r5, r7}
311 /* 478 sub r3, r0, r3 @ PHYS_OFFSET - PAGE_OFFSET
312 * If we're using the NetWinder or CATS, we also need to map 479 add r4, r4, r3 @ adjust table start address
313 * in the 16550-type serial port for the debug messages 480 add r5, r5, r3 @ adjust table end address
314 */ 481 add r7, r7, r3 @ adjust __pv_phys_offset address
315 add r0, r4, #0xff000000 >> 18 482 str r8, [r7] @ save computed PHYS_OFFSET to __pv_phys_offset
316 orr r3, r7, #0x7c000000 483#ifndef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
317 str r3, [r0] 484 mov r6, r3, lsr #24 @ constant for add/sub instructions
485 teq r3, r6, lsl #24 @ must be 16MiB aligned
486#else
487 mov r6, r3, lsr #16 @ constant for add/sub instructions
488 teq r3, r6, lsl #16 @ must be 64kiB aligned
318#endif 489#endif
319#ifdef CONFIG_ARCH_RPC 490THUMB( it ne @ cross section branch )
320 /* 491 bne __error
321 * Map in screen at 0x02000000 & SCREEN2_BASE 492 str r6, [r7, #4] @ save to __pv_offset
322 * Similar reasons here - for debug. This is 493 b __fixup_a_pv_table
323 * only for Acorn RiscPC architectures. 494ENDPROC(__fixup_pv_table)
324 */ 495
325 add r0, r4, #0x02000000 >> 18 496 .align
326 orr r3, r7, #0x02000000 4971: .long .
327 str r3, [r0] 498 .long __pv_table_begin
328 add r0, r4, #0xd8000000 >> 18 499 .long __pv_table_end
329 str r3, [r0] 5002: .long __pv_phys_offset
501
502 .text
503__fixup_a_pv_table:
504#ifdef CONFIG_THUMB2_KERNEL
505#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
506 lsls r0, r6, #24
507 lsr r6, #8
508 beq 1f
509 clz r7, r0
510 lsr r0, #24
511 lsl r0, r7
512 bic r0, 0x0080
513 lsrs r7, #1
514 orrcs r0, #0x0080
515 orr r0, r0, r7, lsl #12
330#endif 516#endif
5171: lsls r6, #24
518 beq 4f
519 clz r7, r6
520 lsr r6, #24
521 lsl r6, r7
522 bic r6, #0x0080
523 lsrs r7, #1
524 orrcs r6, #0x0080
525 orr r6, r6, r7, lsl #12
526 orr r6, #0x4000
527 b 4f
5282: @ at this point the C flag is always clear
529 add r7, r3
530#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
531 ldrh ip, [r7]
532 tst ip, 0x0400 @ the i bit tells us LS or MS byte
533 beq 3f
534 cmp r0, #0 @ set C flag, and ...
535 biceq ip, 0x0400 @ immediate zero value has a special encoding
536 streqh ip, [r7] @ that requires the i bit cleared
537#endif
5383: ldrh ip, [r7, #2]
539 and ip, 0x8f00
540 orrcc ip, r6 @ mask in offset bits 31-24
541 orrcs ip, r0 @ mask in offset bits 23-16
542 strh ip, [r7, #2]
5434: cmp r4, r5
544 ldrcc r7, [r4], #4 @ use branch for delay slot
545 bcc 2b
546 bx lr
547#else
548#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
549 and r0, r6, #255 @ offset bits 23-16
550 mov r6, r6, lsr #8 @ offset bits 31-24
551#else
552 mov r0, #0 @ just in case...
331#endif 553#endif
554 b 3f
5552: ldr ip, [r7, r3]
556 bic ip, ip, #0x000000ff
557 tst ip, #0x400 @ rotate shift tells us LS or MS byte
558 orrne ip, ip, r6 @ mask in offset bits 31-24
559 orreq ip, ip, r0 @ mask in offset bits 23-16
560 str ip, [r7, r3]
5613: cmp r4, r5
562 ldrcc r7, [r4], #4 @ use branch for delay slot
563 bcc 2b
332 mov pc, lr 564 mov pc, lr
333ENDPROC(__create_page_tables) 565#endif
334 .ltorg 566ENDPROC(__fixup_a_pv_table)
567
568ENTRY(fixup_pv_table)
569 stmfd sp!, {r4 - r7, lr}
570 ldr r2, 2f @ get address of __pv_phys_offset
571 mov r3, #0 @ no offset
572 mov r4, r0 @ r0 = table start
573 add r5, r0, r1 @ r1 = table size
574 ldr r6, [r2, #4] @ get __pv_offset
575 bl __fixup_a_pv_table
576 ldmfd sp!, {r4 - r7, pc}
577ENDPROC(fixup_pv_table)
578
579 .align
5802: .long __pv_phys_offset
581
582 .data
583 .globl __pv_phys_offset
584 .type __pv_phys_offset, %object
585__pv_phys_offset:
586 .long 0
587 .size __pv_phys_offset, . - __pv_phys_offset
588__pv_offset:
589 .long 0
590#endif
335 591
336#include "head-common.S" 592#include "head-common.S"