diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/arm/kernel/head.S | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (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.S | 526 |
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 ) |
120 | 1: b __enable_mmu | ||
104 | ENDPROC(stext) | 121 | ENDPROC(stext) |
122 | .ltorg | ||
123 | #ifndef CONFIG_XIP_KERNEL | ||
124 | 2: .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 | ||
148 | 1: 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 | |||
169 | 1: 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 | ||
187 | 1: 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 | ||
203 | 1: 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 | ||
242 | 1: 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 | ||
275 | ENDPROC(__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 | ||
107 | ENTRY(secondary_startup) | 285 | ENTRY(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 |
144 | ENDPROC(__secondary_switched) | 325 | ENDPROC(__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: | ||
203 | ENDPROC(__turn_mmu_on) | 397 | ENDPROC(__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? |
228 | 1: 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 | 427 | ENDPROC(__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 | 430 | 1: .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 | ||
257 | 1: 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. | 436 | smp_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 | ||
275 | 1: 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 | ||
456 | ENDPROC(__do_fixup_smp_on_up) | ||
290 | 457 | ||
291 | #ifdef CONFIG_DEBUG_LL | 458 | ENTRY(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] | 465 | ENDPROC(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'. |
306 | 1: 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 | 490 | THUMB( 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. | 494 | ENDPROC(__fixup_pv_table) |
324 | */ | 495 | |
325 | add r0, r4, #0x02000000 >> 18 | 496 | .align |
326 | orr r3, r7, #0x02000000 | 497 | 1: .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] | 500 | 2: .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 |
517 | 1: 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 | ||
528 | 2: @ 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 | ||
538 | 3: 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] | ||
543 | 4: 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 | ||
555 | 2: 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] | ||
561 | 3: cmp r4, r5 | ||
562 | ldrcc r7, [r4], #4 @ use branch for delay slot | ||
563 | bcc 2b | ||
332 | mov pc, lr | 564 | mov pc, lr |
333 | ENDPROC(__create_page_tables) | 565 | #endif |
334 | .ltorg | 566 | ENDPROC(__fixup_a_pv_table) |
567 | |||
568 | ENTRY(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} | ||
577 | ENDPROC(fixup_pv_table) | ||
578 | |||
579 | .align | ||
580 | 2: .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" |