Commit 865a4fae7793b80e2b8bca76e279d6dfecbeac17
1 parent
00945010c0
Exists in
master
and in
7 other branches
ARM: add register documentation for __enable_mmu
Add some additional documentation on register usage in __enable_mmu to help complete the overall picture. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Showing 1 changed file with 10 additions and 0 deletions Inline Diff
arch/arm/kernel/head.S
1 | /* | 1 | /* |
2 | * linux/arch/arm/kernel/head.S | 2 | * linux/arch/arm/kernel/head.S |
3 | * | 3 | * |
4 | * Copyright (C) 1994-2002 Russell King | 4 | * Copyright (C) 1994-2002 Russell King |
5 | * Copyright (c) 2003 ARM Limited | 5 | * Copyright (c) 2003 ARM Limited |
6 | * All Rights Reserved | 6 | * All Rights Reserved |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | * | 11 | * |
12 | * Kernel startup code for all 32-bit CPUs | 12 | * Kernel startup code for all 32-bit CPUs |
13 | */ | 13 | */ |
14 | #include <linux/linkage.h> | 14 | #include <linux/linkage.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | 16 | ||
17 | #include <asm/assembler.h> | 17 | #include <asm/assembler.h> |
18 | #include <asm/domain.h> | 18 | #include <asm/domain.h> |
19 | #include <asm/ptrace.h> | 19 | #include <asm/ptrace.h> |
20 | #include <asm/asm-offsets.h> | 20 | #include <asm/asm-offsets.h> |
21 | #include <asm/memory.h> | 21 | #include <asm/memory.h> |
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 | #if (PHYS_OFFSET & 0x001fffff) |
26 | #error "PHYS_OFFSET must be at an even 2MiB boundary!" | 26 | #error "PHYS_OFFSET must be at an even 2MiB boundary!" |
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | #define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) | 29 | #define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) |
30 | #define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET) | 30 | #define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET) |
31 | 31 | ||
32 | 32 | ||
33 | /* | 33 | /* |
34 | * swapper_pg_dir is the virtual address of the initial page table. | 34 | * 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 | 35 | * We place the page tables 16K below KERNEL_RAM_VADDR. Therefore, we must |
36 | * make sure that KERNEL_RAM_VADDR is correctly set. Currently, we expect | 36 | * make sure that KERNEL_RAM_VADDR is correctly set. Currently, we expect |
37 | * the least significant 16 bits to be 0x8000, but we could probably | 37 | * the least significant 16 bits to be 0x8000, but we could probably |
38 | * relax this restriction to KERNEL_RAM_VADDR >= PAGE_OFFSET + 0x4000. | 38 | * relax this restriction to KERNEL_RAM_VADDR >= PAGE_OFFSET + 0x4000. |
39 | */ | 39 | */ |
40 | #if (KERNEL_RAM_VADDR & 0xffff) != 0x8000 | 40 | #if (KERNEL_RAM_VADDR & 0xffff) != 0x8000 |
41 | #error KERNEL_RAM_VADDR must start at 0xXXXX8000 | 41 | #error KERNEL_RAM_VADDR must start at 0xXXXX8000 |
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | .globl swapper_pg_dir | 44 | .globl swapper_pg_dir |
45 | .equ swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000 | 45 | .equ swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000 |
46 | 46 | ||
47 | .macro pgtbl, rd | 47 | .macro pgtbl, rd |
48 | ldr \rd, =(KERNEL_RAM_PADDR - 0x4000) | 48 | ldr \rd, =(KERNEL_RAM_PADDR - 0x4000) |
49 | .endm | 49 | .endm |
50 | 50 | ||
51 | #ifdef CONFIG_XIP_KERNEL | 51 | #ifdef CONFIG_XIP_KERNEL |
52 | #define KERNEL_START XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) | 52 | #define KERNEL_START XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) |
53 | #define KERNEL_END _edata_loc | 53 | #define KERNEL_END _edata_loc |
54 | #else | 54 | #else |
55 | #define KERNEL_START KERNEL_RAM_VADDR | 55 | #define KERNEL_START KERNEL_RAM_VADDR |
56 | #define KERNEL_END _end | 56 | #define KERNEL_END _end |
57 | #endif | 57 | #endif |
58 | 58 | ||
59 | /* | 59 | /* |
60 | * Kernel startup entry point. | 60 | * Kernel startup entry point. |
61 | * --------------------------- | 61 | * --------------------------- |
62 | * | 62 | * |
63 | * This is normally called from the decompressor code. The requirements | 63 | * This is normally called from the decompressor code. The requirements |
64 | * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, | 64 | * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, |
65 | * r1 = machine nr, r2 = atags pointer. | 65 | * r1 = machine nr, r2 = atags pointer. |
66 | * | 66 | * |
67 | * This code is mostly position independent, so if you link the kernel at | 67 | * This code is mostly position independent, so if you link the kernel at |
68 | * 0xc0008000, you call this at __pa(0xc0008000). | 68 | * 0xc0008000, you call this at __pa(0xc0008000). |
69 | * | 69 | * |
70 | * See linux/arch/arm/tools/mach-types for the complete list of machine | 70 | * See linux/arch/arm/tools/mach-types for the complete list of machine |
71 | * numbers for r1. | 71 | * numbers for r1. |
72 | * | 72 | * |
73 | * We're trying to keep crap to a minimum; DO NOT add any machine specific | 73 | * We're trying to keep crap to a minimum; DO NOT add any machine specific |
74 | * crap here - that's what the boot loader (or in extreme, well justified | 74 | * crap here - that's what the boot loader (or in extreme, well justified |
75 | * circumstances, zImage) is for. | 75 | * circumstances, zImage) is for. |
76 | */ | 76 | */ |
77 | __HEAD | 77 | __HEAD |
78 | ENTRY(stext) | 78 | ENTRY(stext) |
79 | setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode | 79 | setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode |
80 | @ and irqs disabled | 80 | @ and irqs disabled |
81 | mrc p15, 0, r9, c0, c0 @ get processor id | 81 | mrc p15, 0, r9, c0, c0 @ get processor id |
82 | bl __lookup_processor_type @ r5=procinfo r9=cpuid | 82 | bl __lookup_processor_type @ r5=procinfo r9=cpuid |
83 | movs r10, r5 @ invalid processor (r5=0)? | 83 | movs r10, r5 @ invalid processor (r5=0)? |
84 | beq __error_p @ yes, error 'p' | 84 | beq __error_p @ yes, error 'p' |
85 | bl __lookup_machine_type @ r5=machinfo | 85 | bl __lookup_machine_type @ r5=machinfo |
86 | movs r8, r5 @ invalid machine (r5=0)? | 86 | movs r8, r5 @ invalid machine (r5=0)? |
87 | beq __error_a @ yes, error 'a' | 87 | beq __error_a @ yes, error 'a' |
88 | bl __vet_atags | 88 | bl __vet_atags |
89 | bl __create_page_tables | 89 | bl __create_page_tables |
90 | 90 | ||
91 | /* | 91 | /* |
92 | * The following calls CPU specific code in a position independent | 92 | * The following calls CPU specific code in a position independent |
93 | * manner. See arch/arm/mm/proc-*.S for details. r10 = base of | 93 | * manner. See arch/arm/mm/proc-*.S for details. r10 = base of |
94 | * xxx_proc_info structure selected by __lookup_machine_type | 94 | * xxx_proc_info structure selected by __lookup_machine_type |
95 | * above. On return, the CPU will be ready for the MMU to be | 95 | * 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. | 96 | * turned on, and r0 will hold the CPU control register value. |
97 | */ | 97 | */ |
98 | ldr r13, =__mmap_switched @ address to jump to after | 98 | ldr r13, =__mmap_switched @ address to jump to after |
99 | @ mmu has been enabled | 99 | @ mmu has been enabled |
100 | adr lr, BSYM(1f) @ return (PIC) address | 100 | adr lr, BSYM(1f) @ return (PIC) address |
101 | ARM( add pc, r10, #PROCINFO_INITFUNC ) | 101 | ARM( add pc, r10, #PROCINFO_INITFUNC ) |
102 | THUMB( add r12, r10, #PROCINFO_INITFUNC ) | 102 | THUMB( add r12, r10, #PROCINFO_INITFUNC ) |
103 | THUMB( mov pc, r12 ) | 103 | THUMB( mov pc, r12 ) |
104 | 1: b __enable_mmu | 104 | 1: b __enable_mmu |
105 | ENDPROC(stext) | 105 | ENDPROC(stext) |
106 | .ltorg | 106 | .ltorg |
107 | 107 | ||
108 | /* | 108 | /* |
109 | * Setup the initial page tables. We only setup the barest | 109 | * Setup the initial page tables. We only setup the barest |
110 | * amount which are required to get the kernel running, which | 110 | * amount which are required to get the kernel running, which |
111 | * generally means mapping in the kernel code. | 111 | * generally means mapping in the kernel code. |
112 | * | 112 | * |
113 | * r8 = machinfo | 113 | * r8 = machinfo |
114 | * r9 = cpuid | 114 | * r9 = cpuid |
115 | * r10 = procinfo | 115 | * r10 = procinfo |
116 | * | 116 | * |
117 | * Returns: | 117 | * Returns: |
118 | * r0, r3, r5-r7 corrupted | 118 | * r0, r3, r5-r7 corrupted |
119 | * r4 = physical page table address | 119 | * r4 = physical page table address |
120 | */ | 120 | */ |
121 | __create_page_tables: | 121 | __create_page_tables: |
122 | pgtbl r4 @ page table address | 122 | pgtbl r4 @ page table address |
123 | 123 | ||
124 | /* | 124 | /* |
125 | * Clear the 16K level 1 swapper page table | 125 | * Clear the 16K level 1 swapper page table |
126 | */ | 126 | */ |
127 | mov r0, r4 | 127 | mov r0, r4 |
128 | mov r3, #0 | 128 | mov r3, #0 |
129 | add r6, r0, #0x4000 | 129 | add r6, r0, #0x4000 |
130 | 1: str r3, [r0], #4 | 130 | 1: str r3, [r0], #4 |
131 | str r3, [r0], #4 | 131 | str r3, [r0], #4 |
132 | str r3, [r0], #4 | 132 | str r3, [r0], #4 |
133 | str r3, [r0], #4 | 133 | str r3, [r0], #4 |
134 | teq r0, r6 | 134 | teq r0, r6 |
135 | bne 1b | 135 | bne 1b |
136 | 136 | ||
137 | ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags | 137 | ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags |
138 | 138 | ||
139 | /* | 139 | /* |
140 | * Create identity mapping to cater for __enable_mmu. | 140 | * Create identity mapping to cater for __enable_mmu. |
141 | * This identity mapping will be removed by paging_init(). | 141 | * This identity mapping will be removed by paging_init(). |
142 | */ | 142 | */ |
143 | adr r0, __enable_mmu_loc | 143 | adr r0, __enable_mmu_loc |
144 | ldmia r0, {r3, r5, r6} | 144 | ldmia r0, {r3, r5, r6} |
145 | sub r0, r0, r3 @ virt->phys offset | 145 | sub r0, r0, r3 @ virt->phys offset |
146 | add r5, r5, r0 @ phys __enable_mmu | 146 | add r5, r5, r0 @ phys __enable_mmu |
147 | add r6, r6, r0 @ phys __enable_mmu_end | 147 | add r6, r6, r0 @ phys __enable_mmu_end |
148 | mov r5, r5, lsr #20 | 148 | mov r5, r5, lsr #20 |
149 | mov r6, r6, lsr #20 | 149 | mov r6, r6, lsr #20 |
150 | 150 | ||
151 | 1: orr r3, r7, r5, lsl #20 @ flags + kernel base | 151 | 1: orr r3, r7, r5, lsl #20 @ flags + kernel base |
152 | str r3, [r4, r5, lsl #2] @ identity mapping | 152 | str r3, [r4, r5, lsl #2] @ identity mapping |
153 | teq r5, r6 | 153 | teq r5, r6 |
154 | addne r5, r5, #1 @ next section | 154 | addne r5, r5, #1 @ next section |
155 | bne 1b | 155 | bne 1b |
156 | 156 | ||
157 | /* | 157 | /* |
158 | * Now setup the pagetables for our kernel direct | 158 | * Now setup the pagetables for our kernel direct |
159 | * mapped region. | 159 | * mapped region. |
160 | */ | 160 | */ |
161 | mov r3, pc | 161 | mov r3, pc |
162 | mov r3, r3, lsr #20 | 162 | mov r3, r3, lsr #20 |
163 | orr r3, r7, r3, lsl #20 | 163 | orr r3, r7, r3, lsl #20 |
164 | add r0, r4, #(KERNEL_START & 0xff000000) >> 18 | 164 | add r0, r4, #(KERNEL_START & 0xff000000) >> 18 |
165 | str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]! | 165 | str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]! |
166 | ldr r6, =(KERNEL_END - 1) | 166 | ldr r6, =(KERNEL_END - 1) |
167 | add r0, r0, #4 | 167 | add r0, r0, #4 |
168 | add r6, r4, r6, lsr #18 | 168 | add r6, r4, r6, lsr #18 |
169 | 1: cmp r0, r6 | 169 | 1: cmp r0, r6 |
170 | add r3, r3, #1 << 20 | 170 | add r3, r3, #1 << 20 |
171 | strls r3, [r0], #4 | 171 | strls r3, [r0], #4 |
172 | bls 1b | 172 | bls 1b |
173 | 173 | ||
174 | #ifdef CONFIG_XIP_KERNEL | 174 | #ifdef CONFIG_XIP_KERNEL |
175 | /* | 175 | /* |
176 | * Map some ram to cover our .data and .bss areas. | 176 | * Map some ram to cover our .data and .bss areas. |
177 | */ | 177 | */ |
178 | orr r3, r7, #(KERNEL_RAM_PADDR & 0xff000000) | 178 | orr r3, r7, #(KERNEL_RAM_PADDR & 0xff000000) |
179 | .if (KERNEL_RAM_PADDR & 0x00f00000) | 179 | .if (KERNEL_RAM_PADDR & 0x00f00000) |
180 | orr r3, r3, #(KERNEL_RAM_PADDR & 0x00f00000) | 180 | orr r3, r3, #(KERNEL_RAM_PADDR & 0x00f00000) |
181 | .endif | 181 | .endif |
182 | add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> 18 | 182 | add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> 18 |
183 | str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]! | 183 | str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]! |
184 | ldr r6, =(_end - 1) | 184 | ldr r6, =(_end - 1) |
185 | add r0, r0, #4 | 185 | add r0, r0, #4 |
186 | add r6, r4, r6, lsr #18 | 186 | add r6, r4, r6, lsr #18 |
187 | 1: cmp r0, r6 | 187 | 1: cmp r0, r6 |
188 | add r3, r3, #1 << 20 | 188 | add r3, r3, #1 << 20 |
189 | strls r3, [r0], #4 | 189 | strls r3, [r0], #4 |
190 | bls 1b | 190 | bls 1b |
191 | #endif | 191 | #endif |
192 | 192 | ||
193 | /* | 193 | /* |
194 | * Then map first 1MB of ram in case it contains our boot params. | 194 | * Then map first 1MB of ram in case it contains our boot params. |
195 | */ | 195 | */ |
196 | add r0, r4, #PAGE_OFFSET >> 18 | 196 | add r0, r4, #PAGE_OFFSET >> 18 |
197 | orr r6, r7, #(PHYS_OFFSET & 0xff000000) | 197 | orr r6, r7, #(PHYS_OFFSET & 0xff000000) |
198 | .if (PHYS_OFFSET & 0x00f00000) | 198 | .if (PHYS_OFFSET & 0x00f00000) |
199 | orr r6, r6, #(PHYS_OFFSET & 0x00f00000) | 199 | orr r6, r6, #(PHYS_OFFSET & 0x00f00000) |
200 | .endif | 200 | .endif |
201 | str r6, [r0] | 201 | str r6, [r0] |
202 | 202 | ||
203 | #ifdef CONFIG_DEBUG_LL | 203 | #ifdef CONFIG_DEBUG_LL |
204 | ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags | 204 | ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags |
205 | /* | 205 | /* |
206 | * Map in IO space for serial debugging. | 206 | * Map in IO space for serial debugging. |
207 | * This allows debug messages to be output | 207 | * This allows debug messages to be output |
208 | * via a serial console before paging_init. | 208 | * via a serial console before paging_init. |
209 | */ | 209 | */ |
210 | ldr r3, [r8, #MACHINFO_PGOFFIO] | 210 | ldr r3, [r8, #MACHINFO_PGOFFIO] |
211 | add r0, r4, r3 | 211 | add r0, r4, r3 |
212 | rsb r3, r3, #0x4000 @ PTRS_PER_PGD*sizeof(long) | 212 | rsb r3, r3, #0x4000 @ PTRS_PER_PGD*sizeof(long) |
213 | cmp r3, #0x0800 @ limit to 512MB | 213 | cmp r3, #0x0800 @ limit to 512MB |
214 | movhi r3, #0x0800 | 214 | movhi r3, #0x0800 |
215 | add r6, r0, r3 | 215 | add r6, r0, r3 |
216 | ldr r3, [r8, #MACHINFO_PHYSIO] | 216 | ldr r3, [r8, #MACHINFO_PHYSIO] |
217 | orr r3, r3, r7 | 217 | orr r3, r3, r7 |
218 | 1: str r3, [r0], #4 | 218 | 1: str r3, [r0], #4 |
219 | add r3, r3, #1 << 20 | 219 | add r3, r3, #1 << 20 |
220 | teq r0, r6 | 220 | teq r0, r6 |
221 | bne 1b | 221 | bne 1b |
222 | #if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS) | 222 | #if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS) |
223 | /* | 223 | /* |
224 | * If we're using the NetWinder or CATS, we also need to map | 224 | * If we're using the NetWinder or CATS, we also need to map |
225 | * in the 16550-type serial port for the debug messages | 225 | * in the 16550-type serial port for the debug messages |
226 | */ | 226 | */ |
227 | add r0, r4, #0xff000000 >> 18 | 227 | add r0, r4, #0xff000000 >> 18 |
228 | orr r3, r7, #0x7c000000 | 228 | orr r3, r7, #0x7c000000 |
229 | str r3, [r0] | 229 | str r3, [r0] |
230 | #endif | 230 | #endif |
231 | #ifdef CONFIG_ARCH_RPC | 231 | #ifdef CONFIG_ARCH_RPC |
232 | /* | 232 | /* |
233 | * Map in screen at 0x02000000 & SCREEN2_BASE | 233 | * Map in screen at 0x02000000 & SCREEN2_BASE |
234 | * Similar reasons here - for debug. This is | 234 | * Similar reasons here - for debug. This is |
235 | * only for Acorn RiscPC architectures. | 235 | * only for Acorn RiscPC architectures. |
236 | */ | 236 | */ |
237 | add r0, r4, #0x02000000 >> 18 | 237 | add r0, r4, #0x02000000 >> 18 |
238 | orr r3, r7, #0x02000000 | 238 | orr r3, r7, #0x02000000 |
239 | str r3, [r0] | 239 | str r3, [r0] |
240 | add r0, r4, #0xd8000000 >> 18 | 240 | add r0, r4, #0xd8000000 >> 18 |
241 | str r3, [r0] | 241 | str r3, [r0] |
242 | #endif | 242 | #endif |
243 | #endif | 243 | #endif |
244 | mov pc, lr | 244 | mov pc, lr |
245 | ENDPROC(__create_page_tables) | 245 | ENDPROC(__create_page_tables) |
246 | .ltorg | 246 | .ltorg |
247 | __enable_mmu_loc: | 247 | __enable_mmu_loc: |
248 | .long . | 248 | .long . |
249 | .long __enable_mmu | 249 | .long __enable_mmu |
250 | .long __enable_mmu_end | 250 | .long __enable_mmu_end |
251 | 251 | ||
252 | #if defined(CONFIG_SMP) | 252 | #if defined(CONFIG_SMP) |
253 | __CPUINIT | 253 | __CPUINIT |
254 | ENTRY(secondary_startup) | 254 | ENTRY(secondary_startup) |
255 | /* | 255 | /* |
256 | * Common entry point for secondary CPUs. | 256 | * Common entry point for secondary CPUs. |
257 | * | 257 | * |
258 | * Ensure that we're in SVC mode, and IRQs are disabled. Lookup | 258 | * Ensure that we're in SVC mode, and IRQs are disabled. Lookup |
259 | * the processor type - there is no need to check the machine type | 259 | * the processor type - there is no need to check the machine type |
260 | * as it has already been validated by the primary processor. | 260 | * as it has already been validated by the primary processor. |
261 | */ | 261 | */ |
262 | setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 | 262 | setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 |
263 | mrc p15, 0, r9, c0, c0 @ get processor id | 263 | mrc p15, 0, r9, c0, c0 @ get processor id |
264 | bl __lookup_processor_type | 264 | bl __lookup_processor_type |
265 | movs r10, r5 @ invalid processor? | 265 | movs r10, r5 @ invalid processor? |
266 | moveq r0, #'p' @ yes, error 'p' | 266 | moveq r0, #'p' @ yes, error 'p' |
267 | beq __error_p | 267 | beq __error_p |
268 | 268 | ||
269 | /* | 269 | /* |
270 | * Use the page tables supplied from __cpu_up. | 270 | * Use the page tables supplied from __cpu_up. |
271 | */ | 271 | */ |
272 | adr r4, __secondary_data | 272 | adr r4, __secondary_data |
273 | ldmia r4, {r5, r7, r12} @ address to jump to after | 273 | ldmia r4, {r5, r7, r12} @ address to jump to after |
274 | sub r4, r4, r5 @ mmu has been enabled | 274 | sub r4, r4, r5 @ mmu has been enabled |
275 | ldr r4, [r7, r4] @ get secondary_data.pgdir | 275 | ldr r4, [r7, r4] @ get secondary_data.pgdir |
276 | adr lr, BSYM(__enable_mmu) @ return address | 276 | adr lr, BSYM(__enable_mmu) @ return address |
277 | mov r13, r12 @ __secondary_switched address | 277 | mov r13, r12 @ __secondary_switched address |
278 | ARM( add pc, r10, #PROCINFO_INITFUNC ) @ initialise processor | 278 | ARM( add pc, r10, #PROCINFO_INITFUNC ) @ initialise processor |
279 | @ (return control reg) | 279 | @ (return control reg) |
280 | THUMB( add r12, r10, #PROCINFO_INITFUNC ) | 280 | THUMB( add r12, r10, #PROCINFO_INITFUNC ) |
281 | THUMB( mov pc, r12 ) | 281 | THUMB( mov pc, r12 ) |
282 | ENDPROC(secondary_startup) | 282 | ENDPROC(secondary_startup) |
283 | 283 | ||
284 | /* | 284 | /* |
285 | * r6 = &secondary_data | 285 | * r6 = &secondary_data |
286 | */ | 286 | */ |
287 | ENTRY(__secondary_switched) | 287 | ENTRY(__secondary_switched) |
288 | ldr sp, [r7, #4] @ get secondary_data.stack | 288 | ldr sp, [r7, #4] @ get secondary_data.stack |
289 | mov fp, #0 | 289 | mov fp, #0 |
290 | b secondary_start_kernel | 290 | b secondary_start_kernel |
291 | ENDPROC(__secondary_switched) | 291 | ENDPROC(__secondary_switched) |
292 | 292 | ||
293 | .type __secondary_data, %object | 293 | .type __secondary_data, %object |
294 | __secondary_data: | 294 | __secondary_data: |
295 | .long . | 295 | .long . |
296 | .long secondary_data | 296 | .long secondary_data |
297 | .long __secondary_switched | 297 | .long __secondary_switched |
298 | #endif /* defined(CONFIG_SMP) */ | 298 | #endif /* defined(CONFIG_SMP) */ |
299 | 299 | ||
300 | 300 | ||
301 | 301 | ||
302 | /* | 302 | /* |
303 | * Setup common bits before finally enabling the MMU. Essentially | 303 | * Setup common bits before finally enabling the MMU. Essentially |
304 | * this is just loading the page table pointer and domain access | 304 | * this is just loading the page table pointer and domain access |
305 | * registers. | 305 | * registers. |
306 | * | ||
307 | * r0 = cp#15 control register | ||
308 | * r1 = machine ID | ||
309 | * r2 = atags pointer | ||
310 | * r4 = page table pointer | ||
311 | * r9 = processor ID | ||
312 | * r13 = *virtual* address to jump to upon completion | ||
306 | */ | 313 | */ |
307 | __enable_mmu: | 314 | __enable_mmu: |
308 | #ifdef CONFIG_ALIGNMENT_TRAP | 315 | #ifdef CONFIG_ALIGNMENT_TRAP |
309 | orr r0, r0, #CR_A | 316 | orr r0, r0, #CR_A |
310 | #else | 317 | #else |
311 | bic r0, r0, #CR_A | 318 | bic r0, r0, #CR_A |
312 | #endif | 319 | #endif |
313 | #ifdef CONFIG_CPU_DCACHE_DISABLE | 320 | #ifdef CONFIG_CPU_DCACHE_DISABLE |
314 | bic r0, r0, #CR_C | 321 | bic r0, r0, #CR_C |
315 | #endif | 322 | #endif |
316 | #ifdef CONFIG_CPU_BPREDICT_DISABLE | 323 | #ifdef CONFIG_CPU_BPREDICT_DISABLE |
317 | bic r0, r0, #CR_Z | 324 | bic r0, r0, #CR_Z |
318 | #endif | 325 | #endif |
319 | #ifdef CONFIG_CPU_ICACHE_DISABLE | 326 | #ifdef CONFIG_CPU_ICACHE_DISABLE |
320 | bic r0, r0, #CR_I | 327 | bic r0, r0, #CR_I |
321 | #endif | 328 | #endif |
322 | mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ | 329 | mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ |
323 | domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ | 330 | domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ |
324 | domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \ | 331 | domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \ |
325 | domain_val(DOMAIN_IO, DOMAIN_CLIENT)) | 332 | domain_val(DOMAIN_IO, DOMAIN_CLIENT)) |
326 | mcr p15, 0, r5, c3, c0, 0 @ load domain access register | 333 | mcr p15, 0, r5, c3, c0, 0 @ load domain access register |
327 | mcr p15, 0, r4, c2, c0, 0 @ load page table pointer | 334 | mcr p15, 0, r4, c2, c0, 0 @ load page table pointer |
328 | b __turn_mmu_on | 335 | b __turn_mmu_on |
329 | ENDPROC(__enable_mmu) | 336 | ENDPROC(__enable_mmu) |
330 | 337 | ||
331 | /* | 338 | /* |
332 | * Enable the MMU. This completely changes the structure of the visible | 339 | * Enable the MMU. This completely changes the structure of the visible |
333 | * memory space. You will not be able to trace execution through this. | 340 | * memory space. You will not be able to trace execution through this. |
334 | * If you have an enquiry about this, *please* check the linux-arm-kernel | 341 | * If you have an enquiry about this, *please* check the linux-arm-kernel |
335 | * mailing list archives BEFORE sending another post to the list. | 342 | * mailing list archives BEFORE sending another post to the list. |
336 | * | 343 | * |
337 | * r0 = cp#15 control register | 344 | * r0 = cp#15 control register |
345 | * r1 = machine ID | ||
346 | * r2 = atags pointer | ||
347 | * r9 = processor ID | ||
338 | * r13 = *virtual* address to jump to upon completion | 348 | * r13 = *virtual* address to jump to upon completion |
339 | * | 349 | * |
340 | * other registers depend on the function called upon completion | 350 | * other registers depend on the function called upon completion |
341 | */ | 351 | */ |
342 | .align 5 | 352 | .align 5 |
343 | __turn_mmu_on: | 353 | __turn_mmu_on: |
344 | mov r0, r0 | 354 | mov r0, r0 |
345 | mcr p15, 0, r0, c1, c0, 0 @ write control reg | 355 | mcr p15, 0, r0, c1, c0, 0 @ write control reg |
346 | mrc p15, 0, r3, c0, c0, 0 @ read id reg | 356 | mrc p15, 0, r3, c0, c0, 0 @ read id reg |
347 | mov r3, r3 | 357 | mov r3, r3 |
348 | mov r3, r13 | 358 | mov r3, r13 |
349 | mov pc, r3 | 359 | mov pc, r3 |
350 | __enable_mmu_end: | 360 | __enable_mmu_end: |
351 | ENDPROC(__turn_mmu_on) | 361 | ENDPROC(__turn_mmu_on) |
352 | 362 | ||
353 | 363 | ||
354 | #include "head-common.S" | 364 | #include "head-common.S" |
355 | 365 |