xref: /linux/arch/arm/kernel/head.S (revision de2fe5e07d58424bc286fff3fd3c1b0bf933cd58)
1/*
2 *  linux/arch/arm/kernel/head.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 *  Kernel startup code for all 32-bit CPUs
13 */
14#include <linux/config.h>
15#include <linux/linkage.h>
16#include <linux/init.h>
17
18#include <asm/assembler.h>
19#include <asm/domain.h>
20#include <asm/procinfo.h>
21#include <asm/ptrace.h>
22#include <asm/asm-offsets.h>
23#include <asm/memory.h>
24#include <asm/thread_info.h>
25#include <asm/system.h>
26
27#define PROCINFO_MMUFLAGS	8
28#define PROCINFO_INITFUNC	12
29
30#define MACHINFO_TYPE		0
31#define MACHINFO_PHYSIO		4
32#define MACHINFO_PGOFFIO	8
33#define MACHINFO_NAME		12
34
35#define KERNEL_RAM_ADDR	(PAGE_OFFSET + TEXT_OFFSET)
36
37/*
38 * swapper_pg_dir is the virtual address of the initial page table.
39 * We place the page tables 16K below KERNEL_RAM_ADDR.  Therefore, we must
40 * make sure that KERNEL_RAM_ADDR is correctly set.  Currently, we expect
41 * the least significant 16 bits to be 0x8000, but we could probably
42 * relax this restriction to KERNEL_RAM_ADDR >= PAGE_OFFSET + 0x4000.
43 */
44#if (KERNEL_RAM_ADDR & 0xffff) != 0x8000
45#error KERNEL_RAM_ADDR must start at 0xXXXX8000
46#endif
47
48	.globl	swapper_pg_dir
49	.equ	swapper_pg_dir, KERNEL_RAM_ADDR - 0x4000
50
51	.macro	pgtbl, rd
52	ldr	\rd, =(__virt_to_phys(KERNEL_RAM_ADDR - 0x4000))
53	.endm
54
55#ifdef CONFIG_XIP_KERNEL
56#define TEXTADDR  XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
57#else
58#define TEXTADDR  KERNEL_RAM_ADDR
59#endif
60
61/*
62 * Kernel startup entry point.
63 * ---------------------------
64 *
65 * This is normally called from the decompressor code.  The requirements
66 * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
67 * r1 = machine nr.
68 *
69 * This code is mostly position independent, so if you link the kernel at
70 * 0xc0008000, you call this at __pa(0xc0008000).
71 *
72 * See linux/arch/arm/tools/mach-types for the complete list of machine
73 * numbers for r1.
74 *
75 * We're trying to keep crap to a minimum; DO NOT add any machine specific
76 * crap here - that's what the boot loader (or in extreme, well justified
77 * circumstances, zImage) is for.
78 */
79	__INIT
80	.type	stext, %function
81ENTRY(stext)
82	msr	cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC @ ensure svc mode
83						@ and irqs disabled
84	mrc	p15, 0, r9, c0, c0		@ get processor id
85	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
86	movs	r10, r5				@ invalid processor (r5=0)?
87	beq	__error_p			@ yes, error 'p'
88	bl	__lookup_machine_type		@ r5=machinfo
89	movs	r8, r5				@ invalid machine (r5=0)?
90	beq	__error_a			@ yes, error 'a'
91	bl	__create_page_tables
92
93	/*
94	 * The following calls CPU specific code in a position independent
95	 * manner.  See arch/arm/mm/proc-*.S for details.  r10 = base of
96	 * xxx_proc_info structure selected by __lookup_machine_type
97	 * above.  On return, the CPU will be ready for the MMU to be
98	 * turned on, and r0 will hold the CPU control register value.
99	 */
100	ldr	r13, __switch_data		@ address to jump to after
101						@ mmu has been enabled
102	adr	lr, __enable_mmu		@ return (PIC) address
103	add	pc, r10, #PROCINFO_INITFUNC
104
105	.type	__switch_data, %object
106__switch_data:
107	.long	__mmap_switched
108	.long	__data_loc			@ r4
109	.long	__data_start			@ r5
110	.long	__bss_start			@ r6
111	.long	_end				@ r7
112	.long	processor_id			@ r4
113	.long	__machine_arch_type		@ r5
114	.long	cr_alignment			@ r6
115	.long	init_thread_union + THREAD_START_SP @ sp
116
117/*
118 * The following fragment of code is executed with the MMU on, and uses
119 * absolute addresses; this is not position independent.
120 *
121 *  r0  = cp#15 control register
122 *  r1  = machine ID
123 *  r9  = processor ID
124 */
125	.type	__mmap_switched, %function
126__mmap_switched:
127	adr	r3, __switch_data + 4
128
129	ldmia	r3!, {r4, r5, r6, r7}
130	cmp	r4, r5				@ Copy data segment if needed
1311:	cmpne	r5, r6
132	ldrne	fp, [r4], #4
133	strne	fp, [r5], #4
134	bne	1b
135
136	mov	fp, #0				@ Clear BSS (and zero fp)
1371:	cmp	r6, r7
138	strcc	fp, [r6],#4
139	bcc	1b
140
141	ldmia	r3, {r4, r5, r6, sp}
142	str	r9, [r4]			@ Save processor ID
143	str	r1, [r5]			@ Save machine type
144	bic	r4, r0, #CR_A			@ Clear 'A' bit
145	stmia	r6, {r0, r4}			@ Save control register values
146	b	start_kernel
147
148#if defined(CONFIG_SMP)
149	.type   secondary_startup, #function
150ENTRY(secondary_startup)
151	/*
152	 * Common entry point for secondary CPUs.
153	 *
154	 * Ensure that we're in SVC mode, and IRQs are disabled.  Lookup
155	 * the processor type - there is no need to check the machine type
156	 * as it has already been validated by the primary processor.
157	 */
158	msr	cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC
159	mrc	p15, 0, r9, c0, c0		@ get processor id
160	bl	__lookup_processor_type
161	movs	r10, r5				@ invalid processor?
162	moveq	r0, #'p'			@ yes, error 'p'
163	beq	__error
164
165	/*
166	 * Use the page tables supplied from  __cpu_up.
167	 */
168	adr	r4, __secondary_data
169	ldmia	r4, {r5, r6, r13}		@ address to jump to after
170	sub	r4, r4, r5			@ mmu has been enabled
171	ldr	r4, [r6, r4]			@ get secondary_data.pgdir
172	adr	lr, __enable_mmu		@ return address
173	add	pc, r10, #12			@ initialise processor
174						@ (return control reg)
175
176	/*
177	 * r6  = &secondary_data
178	 */
179ENTRY(__secondary_switched)
180	ldr	sp, [r6, #4]			@ get secondary_data.stack
181	mov	fp, #0
182	b	secondary_start_kernel
183
184	.type	__secondary_data, %object
185__secondary_data:
186	.long	.
187	.long	secondary_data
188	.long	__secondary_switched
189#endif /* defined(CONFIG_SMP) */
190
191
192
193/*
194 * Setup common bits before finally enabling the MMU.  Essentially
195 * this is just loading the page table pointer and domain access
196 * registers.
197 */
198	.type	__enable_mmu, %function
199__enable_mmu:
200#ifdef CONFIG_ALIGNMENT_TRAP
201	orr	r0, r0, #CR_A
202#else
203	bic	r0, r0, #CR_A
204#endif
205#ifdef CONFIG_CPU_DCACHE_DISABLE
206	bic	r0, r0, #CR_C
207#endif
208#ifdef CONFIG_CPU_BPREDICT_DISABLE
209	bic	r0, r0, #CR_Z
210#endif
211#ifdef CONFIG_CPU_ICACHE_DISABLE
212	bic	r0, r0, #CR_I
213#endif
214	mov	r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
215		      domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
216		      domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \
217		      domain_val(DOMAIN_IO, DOMAIN_CLIENT))
218	mcr	p15, 0, r5, c3, c0, 0		@ load domain access register
219	mcr	p15, 0, r4, c2, c0, 0		@ load page table pointer
220	b	__turn_mmu_on
221
222/*
223 * Enable the MMU.  This completely changes the structure of the visible
224 * memory space.  You will not be able to trace execution through this.
225 * If you have an enquiry about this, *please* check the linux-arm-kernel
226 * mailing list archives BEFORE sending another post to the list.
227 *
228 *  r0  = cp#15 control register
229 *  r13 = *virtual* address to jump to upon completion
230 *
231 * other registers depend on the function called upon completion
232 */
233	.align	5
234	.type	__turn_mmu_on, %function
235__turn_mmu_on:
236	mov	r0, r0
237	mcr	p15, 0, r0, c1, c0, 0		@ write control reg
238	mrc	p15, 0, r3, c0, c0, 0		@ read id reg
239	mov	r3, r3
240	mov	r3, r3
241	mov	pc, r13
242
243
244
245/*
246 * Setup the initial page tables.  We only setup the barest
247 * amount which are required to get the kernel running, which
248 * generally means mapping in the kernel code.
249 *
250 * r8  = machinfo
251 * r9  = cpuid
252 * r10 = procinfo
253 *
254 * Returns:
255 *  r0, r3, r6, r7 corrupted
256 *  r4 = physical page table address
257 */
258	.type	__create_page_tables, %function
259__create_page_tables:
260	pgtbl	r4				@ page table address
261
262	/*
263	 * Clear the 16K level 1 swapper page table
264	 */
265	mov	r0, r4
266	mov	r3, #0
267	add	r6, r0, #0x4000
2681:	str	r3, [r0], #4
269	str	r3, [r0], #4
270	str	r3, [r0], #4
271	str	r3, [r0], #4
272	teq	r0, r6
273	bne	1b
274
275	ldr	r7, [r10, #PROCINFO_MMUFLAGS]	@ mmuflags
276
277	/*
278	 * Create identity mapping for first MB of kernel to
279	 * cater for the MMU enable.  This identity mapping
280	 * will be removed by paging_init().  We use our current program
281	 * counter to determine corresponding section base address.
282	 */
283	mov	r6, pc, lsr #20			@ start of kernel section
284	orr	r3, r7, r6, lsl #20		@ flags + kernel base
285	str	r3, [r4, r6, lsl #2]		@ identity mapping
286
287	/*
288	 * Now setup the pagetables for our kernel direct
289	 * mapped region.  We round TEXTADDR down to the
290	 * nearest megabyte boundary.  It is assumed that
291	 * the kernel fits within 4 contigous 1MB sections.
292	 */
293	add	r0, r4,  #(TEXTADDR & 0xff000000) >> 18	@ start of kernel
294	str	r3, [r0, #(TEXTADDR & 0x00f00000) >> 18]!
295	add	r3, r3, #1 << 20
296	str	r3, [r0, #4]!			@ KERNEL + 1MB
297	add	r3, r3, #1 << 20
298	str	r3, [r0, #4]!			@ KERNEL + 2MB
299	add	r3, r3, #1 << 20
300	str	r3, [r0, #4]			@ KERNEL + 3MB
301
302	/*
303	 * Then map first 1MB of ram in case it contains our boot params.
304	 */
305	add	r0, r4, #PAGE_OFFSET >> 18
306	orr	r6, r7, #PHYS_OFFSET
307	str	r6, [r0]
308
309#ifdef CONFIG_XIP_KERNEL
310	/*
311	 * Map some ram to cover our .data and .bss areas.
312	 * Mapping 3MB should be plenty.
313	 */
314	sub	r3, r4, #PHYS_OFFSET
315	mov	r3, r3, lsr #20
316	add	r0, r0, r3, lsl #2
317	add	r6, r6, r3, lsl #20
318	str	r6, [r0], #4
319	add	r6, r6, #(1 << 20)
320	str	r6, [r0], #4
321	add	r6, r6, #(1 << 20)
322	str	r6, [r0]
323#endif
324
325#ifdef CONFIG_DEBUG_LL
326	bic	r7, r7, #0x0c			@ turn off cacheable
327						@ and bufferable bits
328	/*
329	 * Map in IO space for serial debugging.
330	 * This allows debug messages to be output
331	 * via a serial console before paging_init.
332	 */
333	ldr	r3, [r8, #MACHINFO_PGOFFIO]
334	add	r0, r4, r3
335	rsb	r3, r3, #0x4000			@ PTRS_PER_PGD*sizeof(long)
336	cmp	r3, #0x0800			@ limit to 512MB
337	movhi	r3, #0x0800
338	add	r6, r0, r3
339	ldr	r3, [r8, #MACHINFO_PHYSIO]
340	orr	r3, r3, r7
3411:	str	r3, [r0], #4
342	add	r3, r3, #1 << 20
343	teq	r0, r6
344	bne	1b
345#if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS)
346	/*
347	 * If we're using the NetWinder or CATS, we also need to map
348	 * in the 16550-type serial port for the debug messages
349	 */
350	add	r0, r4, #0xff000000 >> 18
351	orr	r3, r7, #0x7c000000
352	str	r3, [r0]
353#endif
354#ifdef CONFIG_ARCH_RPC
355	/*
356	 * Map in screen at 0x02000000 & SCREEN2_BASE
357	 * Similar reasons here - for debug.  This is
358	 * only for Acorn RiscPC architectures.
359	 */
360	add	r0, r4, #0x02000000 >> 18
361	orr	r3, r7, #0x02000000
362	str	r3, [r0]
363	add	r0, r4, #0xd8000000 >> 18
364	str	r3, [r0]
365#endif
366#endif
367	mov	pc, lr
368	.ltorg
369
370
371
372/*
373 * Exception handling.  Something went wrong and we can't proceed.  We
374 * ought to tell the user, but since we don't have any guarantee that
375 * we're even running on the right architecture, we do virtually nothing.
376 *
377 * If CONFIG_DEBUG_LL is set we try to print out something about the error
378 * and hope for the best (useful if bootloader fails to pass a proper
379 * machine ID for example).
380 */
381
382	.type	__error_p, %function
383__error_p:
384#ifdef CONFIG_DEBUG_LL
385	adr	r0, str_p1
386	bl	printascii
387	b	__error
388str_p1:	.asciz	"\nError: unrecognized/unsupported processor variant.\n"
389	.align
390#endif
391
392	.type	__error_a, %function
393__error_a:
394#ifdef CONFIG_DEBUG_LL
395	mov	r4, r1				@ preserve machine ID
396	adr	r0, str_a1
397	bl	printascii
398	mov	r0, r4
399	bl	printhex8
400	adr	r0, str_a2
401	bl	printascii
402	adr	r3, 3f
403	ldmia	r3, {r4, r5, r6}		@ get machine desc list
404	sub	r4, r3, r4			@ get offset between virt&phys
405	add	r5, r5, r4			@ convert virt addresses to
406	add	r6, r6, r4			@ physical address space
4071:	ldr	r0, [r5, #MACHINFO_TYPE]	@ get machine type
408	bl	printhex8
409	mov	r0, #'\t'
410	bl	printch
411	ldr     r0, [r5, #MACHINFO_NAME]	@ get machine name
412	add	r0, r0, r4
413	bl	printascii
414	mov	r0, #'\n'
415	bl	printch
416	add	r5, r5, #SIZEOF_MACHINE_DESC	@ next machine_desc
417	cmp	r5, r6
418	blo	1b
419	adr	r0, str_a3
420	bl	printascii
421	b	__error
422str_a1:	.asciz	"\nError: unrecognized/unsupported machine ID (r1 = 0x"
423str_a2:	.asciz	").\n\nAvailable machine support:\n\nID (hex)\tNAME\n"
424str_a3:	.asciz	"\nPlease check your kernel config and/or bootloader.\n"
425	.align
426#endif
427
428	.type	__error, %function
429__error:
430#ifdef CONFIG_ARCH_RPC
431/*
432 * Turn the screen red on a error - RiscPC only.
433 */
434	mov	r0, #0x02000000
435	mov	r3, #0x11
436	orr	r3, r3, r3, lsl #8
437	orr	r3, r3, r3, lsl #16
438	str	r3, [r0], #4
439	str	r3, [r0], #4
440	str	r3, [r0], #4
441	str	r3, [r0], #4
442#endif
4431:	mov	r0, r0
444	b	1b
445
446
447/*
448 * Read processor ID register (CP#15, CR0), and look up in the linker-built
449 * supported processor list.  Note that we can't use the absolute addresses
450 * for the __proc_info lists since we aren't running with the MMU on
451 * (and therefore, we are not in the correct address space).  We have to
452 * calculate the offset.
453 *
454 *	r9 = cpuid
455 * Returns:
456 *	r3, r4, r6 corrupted
457 *	r5 = proc_info pointer in physical address space
458 *	r9 = cpuid (preserved)
459 */
460	.type	__lookup_processor_type, %function
461__lookup_processor_type:
462	adr	r3, 3f
463	ldmda	r3, {r5 - r7}
464	sub	r3, r3, r7			@ get offset between virt&phys
465	add	r5, r5, r3			@ convert virt addresses to
466	add	r6, r6, r3			@ physical address space
4671:	ldmia	r5, {r3, r4}			@ value, mask
468	and	r4, r4, r9			@ mask wanted bits
469	teq	r3, r4
470	beq	2f
471	add	r5, r5, #PROC_INFO_SZ		@ sizeof(proc_info_list)
472	cmp	r5, r6
473	blo	1b
474	mov	r5, #0				@ unknown processor
4752:	mov	pc, lr
476
477/*
478 * This provides a C-API version of the above function.
479 */
480ENTRY(lookup_processor_type)
481	stmfd	sp!, {r4 - r7, r9, lr}
482	mov	r9, r0
483	bl	__lookup_processor_type
484	mov	r0, r5
485	ldmfd	sp!, {r4 - r7, r9, pc}
486
487/*
488 * Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for
489 * more information about the __proc_info and __arch_info structures.
490 */
491	.long	__proc_info_begin
492	.long	__proc_info_end
4933:	.long	.
494	.long	__arch_info_begin
495	.long	__arch_info_end
496
497/*
498 * Lookup machine architecture in the linker-build list of architectures.
499 * Note that we can't use the absolute addresses for the __arch_info
500 * lists since we aren't running with the MMU on (and therefore, we are
501 * not in the correct address space).  We have to calculate the offset.
502 *
503 *  r1 = machine architecture number
504 * Returns:
505 *  r3, r4, r6 corrupted
506 *  r5 = mach_info pointer in physical address space
507 */
508	.type	__lookup_machine_type, %function
509__lookup_machine_type:
510	adr	r3, 3b
511	ldmia	r3, {r4, r5, r6}
512	sub	r3, r3, r4			@ get offset between virt&phys
513	add	r5, r5, r3			@ convert virt addresses to
514	add	r6, r6, r3			@ physical address space
5151:	ldr	r3, [r5, #MACHINFO_TYPE]	@ get machine type
516	teq	r3, r1				@ matches loader number?
517	beq	2f				@ found
518	add	r5, r5, #SIZEOF_MACHINE_DESC	@ next machine_desc
519	cmp	r5, r6
520	blo	1b
521	mov	r5, #0				@ unknown machine
5222:	mov	pc, lr
523
524/*
525 * This provides a C-API version of the above function.
526 */
527ENTRY(lookup_machine_type)
528	stmfd	sp!, {r4 - r6, lr}
529	mov	r1, r0
530	bl	__lookup_machine_type
531	mov	r0, r5
532	ldmfd	sp!, {r4 - r6, pc}
533