aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/head-common.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/head-common.S')
-rw-r--r--arch/arm/kernel/head-common.S217
1 files changed, 217 insertions, 0 deletions
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
new file mode 100644
index 000000000000..a52da0ddb43d
--- /dev/null
+++ b/arch/arm/kernel/head-common.S
@@ -0,0 +1,217 @@
1/*
2 * linux/arch/arm/kernel/head-common.S
3 *
4 * Copyright (C) 1994-2002 Russell King
5 * Copyright (c) 2003 ARM Limited
6 * All Rights Reserved
7 *
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
10 * published by the Free Software Foundation.
11 *
12 */
13
14 .type __switch_data, %object
15__switch_data:
16 .long __mmap_switched
17 .long __data_loc @ r4
18 .long __data_start @ r5
19 .long __bss_start @ r6
20 .long _end @ r7
21 .long processor_id @ r4
22 .long __machine_arch_type @ r5
23 .long cr_alignment @ r6
24 .long init_thread_union + THREAD_START_SP @ sp
25
26/*
27 * The following fragment of code is executed with the MMU on in MMU mode,
28 * and uses absolute addresses; this is not position independent.
29 *
30 * r0 = cp#15 control register
31 * r1 = machine ID
32 * r9 = processor ID
33 */
34 .type __mmap_switched, %function
35__mmap_switched:
36 adr r3, __switch_data + 4
37
38 ldmia r3!, {r4, r5, r6, r7}
39 cmp r4, r5 @ Copy data segment if needed
401: cmpne r5, r6
41 ldrne fp, [r4], #4
42 strne fp, [r5], #4
43 bne 1b
44
45 mov fp, #0 @ Clear BSS (and zero fp)
461: cmp r6, r7
47 strcc fp, [r6],#4
48 bcc 1b
49
50 ldmia r3, {r4, r5, r6, sp}
51 str r9, [r4] @ Save processor ID
52 str r1, [r5] @ Save machine type
53 bic r4, r0, #CR_A @ Clear 'A' bit
54 stmia r6, {r0, r4} @ Save control register values
55 b start_kernel
56
57/*
58 * Exception handling. Something went wrong and we can't proceed. We
59 * ought to tell the user, but since we don't have any guarantee that
60 * we're even running on the right architecture, we do virtually nothing.
61 *
62 * If CONFIG_DEBUG_LL is set we try to print out something about the error
63 * and hope for the best (useful if bootloader fails to pass a proper
64 * machine ID for example).
65 */
66
67 .type __error_p, %function
68__error_p:
69#ifdef CONFIG_DEBUG_LL
70 adr r0, str_p1
71 bl printascii
72 b __error
73str_p1: .asciz "\nError: unrecognized/unsupported processor variant.\n"
74 .align
75#endif
76
77 .type __error_a, %function
78__error_a:
79#ifdef CONFIG_DEBUG_LL
80 mov r4, r1 @ preserve machine ID
81 adr r0, str_a1
82 bl printascii
83 mov r0, r4
84 bl printhex8
85 adr r0, str_a2
86 bl printascii
87 adr r3, 3f
88 ldmia r3, {r4, r5, r6} @ get machine desc list
89 sub r4, r3, r4 @ get offset between virt&phys
90 add r5, r5, r4 @ convert virt addresses to
91 add r6, r6, r4 @ physical address space
921: ldr r0, [r5, #MACHINFO_TYPE] @ get machine type
93 bl printhex8
94 mov r0, #'\t'
95 bl printch
96 ldr r0, [r5, #MACHINFO_NAME] @ get machine name
97 add r0, r0, r4
98 bl printascii
99 mov r0, #'\n'
100 bl printch
101 add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc
102 cmp r5, r6
103 blo 1b
104 adr r0, str_a3
105 bl printascii
106 b __error
107str_a1: .asciz "\nError: unrecognized/unsupported machine ID (r1 = 0x"
108str_a2: .asciz ").\n\nAvailable machine support:\n\nID (hex)\tNAME\n"
109str_a3: .asciz "\nPlease check your kernel config and/or bootloader.\n"
110 .align
111#endif
112
113 .type __error, %function
114__error:
115#ifdef CONFIG_ARCH_RPC
116/*
117 * Turn the screen red on a error - RiscPC only.
118 */
119 mov r0, #0x02000000
120 mov r3, #0x11
121 orr r3, r3, r3, lsl #8
122 orr r3, r3, r3, lsl #16
123 str r3, [r0], #4
124 str r3, [r0], #4
125 str r3, [r0], #4
126 str r3, [r0], #4
127#endif
1281: mov r0, r0
129 b 1b
130
131
132/*
133 * Read processor ID register (CP#15, CR0), and look up in the linker-built
134 * supported processor list. Note that we can't use the absolute addresses
135 * for the __proc_info lists since we aren't running with the MMU on
136 * (and therefore, we are not in the correct address space). We have to
137 * calculate the offset.
138 *
139 * r9 = cpuid
140 * Returns:
141 * r3, r4, r6 corrupted
142 * r5 = proc_info pointer in physical address space
143 * r9 = cpuid (preserved)
144 */
145 .type __lookup_processor_type, %function
146__lookup_processor_type:
147 adr r3, 3f
148 ldmda r3, {r5 - r7}
149 sub r3, r3, r7 @ get offset between virt&phys
150 add r5, r5, r3 @ convert virt addresses to
151 add r6, r6, r3 @ physical address space
1521: ldmia r5, {r3, r4} @ value, mask
153 and r4, r4, r9 @ mask wanted bits
154 teq r3, r4
155 beq 2f
156 add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list)
157 cmp r5, r6
158 blo 1b
159 mov r5, #0 @ unknown processor
1602: mov pc, lr
161
162/*
163 * This provides a C-API version of the above function.
164 */
165ENTRY(lookup_processor_type)
166 stmfd sp!, {r4 - r7, r9, lr}
167 mov r9, r0
168 bl __lookup_processor_type
169 mov r0, r5
170 ldmfd sp!, {r4 - r7, r9, pc}
171
172/*
173 * Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for
174 * more information about the __proc_info and __arch_info structures.
175 */
176 .long __proc_info_begin
177 .long __proc_info_end
1783: .long .
179 .long __arch_info_begin
180 .long __arch_info_end
181
182/*
183 * Lookup machine architecture in the linker-build list of architectures.
184 * Note that we can't use the absolute addresses for the __arch_info
185 * lists since we aren't running with the MMU on (and therefore, we are
186 * not in the correct address space). We have to calculate the offset.
187 *
188 * r1 = machine architecture number
189 * Returns:
190 * r3, r4, r6 corrupted
191 * r5 = mach_info pointer in physical address space
192 */
193 .type __lookup_machine_type, %function
194__lookup_machine_type:
195 adr r3, 3b
196 ldmia r3, {r4, r5, r6}
197 sub r3, r3, r4 @ get offset between virt&phys
198 add r5, r5, r3 @ convert virt addresses to
199 add r6, r6, r3 @ physical address space
2001: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type
201 teq r3, r1 @ matches loader number?
202 beq 2f @ found
203 add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc
204 cmp r5, r6
205 blo 1b
206 mov r5, #0 @ unknown machine
2072: mov pc, lr
208
209/*
210 * This provides a C-API version of the above function.
211 */
212ENTRY(lookup_machine_type)
213 stmfd sp!, {r4 - r6, lr}
214 mov r1, r0
215 bl __lookup_machine_type
216 mov r0, r5
217 ldmfd sp!, {r4 - r6, pc}