1/*
2 *  linux/arch/arm/kernel/head-armv.S
3 *
4 *  Copyright (C) 1994-1999 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 *  32-bit kernel startup code for all architectures
11 */
12#include <linux/config.h>
13#include <linux/linkage.h>
14
15#include <asm/assembler.h>
16#include <asm/mach-types.h>
17#include <asm/mach/arch.h>
18
19#define K(a,b,c)	((a) << 24 | (b) << 12 | (c))
20
21/*
22 * We place the page tables 16K below TEXTADDR.  Therefore, we must make sure
23 * that TEXTADDR is correctly set.  Currently, we expect the least significant
24 * "short" to be 0x8000, but we could probably relax this restriction to
25 * TEXTADDR > PAGE_OFFSET + 0x4000
26 *
27 * Note that swapper_pg_dir is the virtual address of the page tables, and
28 * pgtbl gives us a position-independent reference to these tables.  We can
29 * do this because stext == TEXTADDR
30 *
31 * swapper_pg_dir, pgtbl and krnladr are all closely related.
32 */
33#if (TEXTADDR & 0xffff) != 0x8000
34#error TEXTADDR must start at 0xXXXX8000
35#endif
36
37		.globl	SYMBOL_NAME(swapper_pg_dir)
38		.equ	SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x4000
39
40		.macro	pgtbl, reg, rambase
41		adr	\reg, stext
42		sub	\reg, \reg, #0x4000
43		.endm
44
45/*
46 * Since the page table is closely related to the kernel start address, we
47 * can convert the page table base address to the base address of the section
48 * containing both.
49 */
50		.macro	krnladr, rd, pgtable, rambase
51		bic	\rd, \pgtable, #0x000ff000
52		.endm
53
54/*
55 * Kernel startup entry point.
56 * ---------------------------
57 *
58 * This is normally called from the decompressor code.  The requirements
59 * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
60 * r1 = machine nr.
61 *
62 * This code is mostly position independent, so if you link the kernel at
63 * 0xc0008000, you call this at __pa(0xc0008000).
64 *
65 * See linux/arch/arm/tools/mach-types for the complete list of machine
66 * numbers for r1.
67 *
68 * We're trying to keep crap to a minimum; DO NOT add any machine specific
69 * crap here - that's what the boot loader (or in extreme, well justified
70 * circumstances, zImage) is for.
71 */
72		.section ".text.init",#alloc,#execinstr
73		.type	stext, #function
74ENTRY(stext)
75		mov	r12, r0
76/*
77 * NOTE!  Any code which is placed here should be done for one of
78 * the following reasons:
79 *
80 *  1. Compatability with old production boot firmware (ie, users
81 *     actually have and are booting the kernel with the old firmware)
82 *     and therefore will be eventually removed.
83 *  2. Cover the case when there is no boot firmware.  This is not
84 *     ideal, but in this case, it should ONLY set r0 and r1 to the
85 *     appropriate value.
86 */
87#if defined(CONFIG_ARCH_NETWINDER)
88/*
89 * Compatability cruft for old NetWinder NeTTroms.  This
90 * code is currently scheduled for destruction in 2.5.xx
91 */
92		.rept	8
93		mov	r0, r0
94		.endr
95
96		adr	r2, 1f
97		ldmdb	r2, {r7, r8}
98		and	r3, r2, #0xc000
99		teq	r3, #0x8000
100		beq	__entry
101		bic	r3, r2, #0xc000
102		orr	r3, r3, #0x8000
103		mov	r0, r3
104		mov	r4, #64
105		sub	r5, r8, r7
106		b	1f
107
108		.word	_stext
109		.word	__bss_start
110
1111:
112		.rept	4
113		ldmia	r2!, {r6, r7, r8, r9}
114		stmia	r3!, {r6, r7, r8, r9}
115		.endr
116		subs	r4, r4, #64
117		bcs	1b
118		movs	r4, r5
119		mov	r5, #0
120		movne	pc, r0
121
122		mov	r1, #MACH_TYPE_NETWINDER	@ (will go in 2.5)
123		mov	r12, #2 << 24			@ scheduled for removal in 2.5.xx
124		orr	r12, r12, #5 << 12
125__entry:
126#endif
127#if defined(CONFIG_ARCH_L7200)
128/*
129 * FIXME - No bootloader, so manually set 'r1' with our architecture number.
130 */
131		mov	r1, #MACH_TYPE_L7200
132#endif
133
134		mov	r0, #F_BIT | I_BIT | MODE_SVC	@ make sure svc mode
135		msr	cpsr_c, r0			@ and all irqs disabled
136		bl	__lookup_processor_type
137		teq	r10, #0				@ invalid processor?
138		moveq	r0, #'p'			@ yes, error 'p'
139		beq	__error
140		bl	__lookup_architecture_type
141		teq	r7, #0				@ invalid architecture?
142		moveq	r0, #'a'			@ yes, error 'a'
143		beq	__error
144		bl	__create_page_tables
145		adr	lr, __ret			@ return address
146		add	pc, r10, #12			@ initialise processor
147							@ (return control reg)
148
149		.type	__switch_data, %object
150__switch_data:	.long	__mmap_switched
151		.long	SYMBOL_NAME(__bss_start)
152		.long	SYMBOL_NAME(_end)
153		.long	SYMBOL_NAME(processor_id)
154		.long	SYMBOL_NAME(__machine_arch_type)
155		.long	SYMBOL_NAME(cr_alignment)
156		.long	SYMBOL_NAME(init_task_union)+8192
157
158/*
159 * Enable the MMU.  This completely changes the structure of the visible
160 * memory space.  You will not be able to trace execution through this.
161 * If you have an enquiry about this, *please* check the linux-arm-kernel
162 * mailing list archives BEFORE sending another post to the list.
163 */
164		.type	__ret, %function
165__ret:		ldr	lr, __switch_data
166		mcr	p15, 0, r0, c1, c0
167		mrc	p15, 0, r0, c1, c0, 0		@ read it back.
168		mov	r0, r0
169		mov	r0, r0
170		mov	pc, lr
171
172/*
173 * The following fragment of code is executed with the MMU on, and uses
174 * absolute addresses; this is not position independent.
175 *
176 *  r0  = processor control register
177 *  r1  = machine ID
178 *  r9  = processor ID
179 */
180		.align	5
181__mmap_switched:
182		adr	r3, __switch_data + 4
183		ldmia	r3, {r4, r5, r6, r7, r8, sp}@ r2 = compat
184							@ sp = stack pointer
185
186		mov	fp, #0				@ Clear BSS (and zero fp)
1871:		cmp	r4, r5
188		strcc	fp, [r4],#4
189		bcc	1b
190
191		str	r9, [r6]			@ Save processor ID
192		str	r1, [r7]			@ Save machine type
193#ifdef CONFIG_ALIGNMENT_TRAP
194		orr	r0, r0, #2			@ ...........A.
195#endif
196		bic	r2, r0, #2			@ Clear 'A' bit
197		stmia	r8, {r0, r2}			@ Save control register values
198		b	SYMBOL_NAME(start_kernel)
199
200
201
202/*
203 * Setup the initial page tables.  We only setup the barest
204 * amount which are required to get the kernel running, which
205 * generally means mapping in the kernel code.
206 *
207 * We only map in 4MB of RAM, which should be sufficient in
208 * all cases.
209 *
210 * r5 = physical address of start of RAM
211 * r6 = physical IO address
212 * r7 = byte offset into page tables for IO
213 * r8 = page table flags
214 */
215__create_page_tables:
216		pgtbl	r4, r5				@ page table address
217
218		/*
219		 * Clear the 16K level 1 swapper page table
220		 */
221		mov	r0, r4
222		mov	r3, #0
223		add	r2, r0, #0x4000
2241:		str	r3, [r0], #4
225		str	r3, [r0], #4
226		str	r3, [r0], #4
227		str	r3, [r0], #4
228		teq	r0, r2
229		bne	1b
230
231		/*
232		 * Create identity mapping for first MB of kernel to
233		 * cater for the MMU enable.  This identity mapping
234		 * will be removed by paging_init()
235		 */
236		krnladr	r2, r4, r5			@ start of kernel
237		add	r3, r8, r2			@ flags + kernel base
238		str	r3, [r4, r2, lsr #18]		@ identity mapping
239
240		/*
241		 * Now setup the pagetables for our kernel direct
242		 * mapped region.  We round TEXTADDR down to the
243		 * nearest megabyte boundary.
244		 */
245		add	r0, r4, #(TEXTADDR & 0xff000000) >> 18 @ start of kernel
246		bic	r2, r3, #0x00f00000
247		str	r2, [r0]			@ PAGE_OFFSET + 0MB
248		add	r0, r0, #(TEXTADDR & 0x00f00000) >> 18
249		str	r3, [r0], #4			@ KERNEL + 0MB
250		add	r3, r3, #1 << 20
251		str	r3, [r0], #4			@ KERNEL + 1MB
252		add	r3, r3, #1 << 20
253		str	r3, [r0], #4			@ KERNEL + 2MB
254		add	r3, r3, #1 << 20
255		str	r3, [r0], #4			@ KERNEL + 3MB
256
257		/*
258		 * Ensure that the first section of RAM is present.
259		 * we assume that:
260		 *  1. the RAM is aligned to a 32MB boundary
261		 *  2. the kernel is executing in the same 32MB chunk
262		 *     as the start of RAM.
263		 */
264		bic	r0, r0, #0x01f00000 >> 18	@ round down
265		and	r2, r5, #0xfe000000		@ round down
266		add	r3, r8, r2			@ flags + rambase
267		str	r3, [r0]
268
269		bic	r8, r8, #0x0c			@ turn off cacheable
270							@ and bufferable bits
271#ifdef CONFIG_DEBUG_LL
272		/*
273		 * Map in IO space for serial debugging.
274		 * This allows debug messages to be output
275		 * via a serial console before paging_init.
276		 */
277		add	r0, r4, r7
278		rsb	r3, r7, #0x4000	@ PTRS_PER_PGD*sizeof(long)
279		cmp	r3, #0x0800
280		addge	r2, r0, #0x0800
281		addlt	r2, r0, r3
282		orr	r3, r6, r8
2831:		str	r3, [r0], #4
284		add	r3, r3, #1 << 20
285		teq	r0, r2
286		bne	1b
287#if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS)
288		/*
289		 * If we're using the NetWinder, we need to map in
290		 * the 16550-type serial port for the debug messages
291		 */
292		teq	r1, #MACH_TYPE_NETWINDER
293		teqne	r1, #MACH_TYPE_CATS
294		bne	1f
295		add	r0, r4, #0x3fc0
296		mov	r3, #0x7c000000
297		orr	r3, r3, r8
298		str	r3, [r0], #4
299		add	r3, r3, #1 << 20
300		str	r3, [r0], #4
3011:
302#endif
303#endif
304#ifdef CONFIG_ARCH_RPC
305		/*
306		 * Map in screen at 0x02000000 & SCREEN2_BASE
307		 * Similar reasons here - for debug.  This is
308		 * only for Acorn RiscPC architectures.
309		 */
310		add	r0, r4, #0x80			@ 02000000
311		mov	r3, #0x02000000
312		orr	r3, r3, r8
313		str	r3, [r0]
314		add	r0, r4, #0x3600			@ d8000000
315		str	r3, [r0]
316#endif
317		mov	pc, lr
318
319
320
321/*
322 * Exception handling.  Something went wrong and we can't
323 * proceed.  We ought to tell the user, but since we
324 * don't have any guarantee that we're even running on
325 * the right architecture, we do virtually nothing.
326 * r0 = ascii error character:
327 *	a = invalid architecture
328 *	p = invalid processor
329 *	i = invalid calling convention
330 *
331 * Generally, only serious errors cause this.
332 */
333__error:
334#ifdef CONFIG_DEBUG_LL
335		mov	r8, r0				@ preserve r0
336		adr	r0, err_str
337		bl	printascii
338		mov	r0, r8
339		bl	printch
340#endif
341#ifdef CONFIG_ARCH_RPC
342/*
343 * Turn the screen red on a error - RiscPC only.
344 */
345		mov	r0, #0x02000000
346		mov	r3, #0x11
347		orr	r3, r3, r3, lsl #8
348		orr	r3, r3, r3, lsl #16
349		str	r3, [r0], #4
350		str	r3, [r0], #4
351		str	r3, [r0], #4
352		str	r3, [r0], #4
353#endif
3541:		mov	r0, r0
355		b	1b
356
357#ifdef CONFIG_DEBUG_LL
358err_str:	.asciz	"\nError: "
359		.align
360#endif
361
362/*
363 * Read processor ID register (CP#15, CR0), and look up in the linker-built
364 * supported processor list.  Note that we can't use the absolute addresses
365 * for the __proc_info lists since we aren't running with the MMU on
366 * (and therefore, we are not in the correct address space).  We have to
367 * calculate the offset.
368 *
369 * Returns:
370 *	r5, r6, r7 corrupted
371 *	r8  = page table flags
372 *	r9  = processor ID
373 *	r10 = pointer to processor structure
374 */
375__lookup_processor_type:
376		adr	r5, 2f
377		ldmia	r5, {r7, r9, r10}
378		sub	r5, r5, r10			@ convert addresses
379		add	r7, r7, r5			@ to our address space
380		add	r10, r9, r5
381		mrc	p15, 0, r9, c0, c0		@ get processor id
3821:		ldmia	r10, {r5, r6, r8}		@ value, mask, mmuflags
383		and	r6, r6, r9			@ mask wanted bits
384		teq	r5, r6
385		moveq	pc, lr
386		add	r10, r10, #36			@ sizeof(proc_info_list)
387		cmp	r10, r7
388		blt	1b
389		mov	r10, #0				@ unknown processor
390		mov	pc, lr
391
392/*
393 * Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for
394 * more information about the __proc_info and __arch_info structures.
395 */
3962:		.long	__proc_info_end
397		.long	__proc_info_begin
398		.long	2b
399		.long	__arch_info_begin
400		.long	__arch_info_end
401
402/*
403 * Lookup machine architecture in the linker-build list of architectures.
404 * Note that we can't use the absolute addresses for the __arch_info
405 * lists since we aren't running with the MMU on (and therefore, we are
406 * not in the correct address space).  We have to calculate the offset.
407 *
408 *  r1 = machine architecture number
409 * Returns:
410 *  r2, r3, r4 corrupted
411 *  r5 = physical start address of RAM
412 *  r6 = physical address of IO
413 *  r7 = byte offset into page tables for IO
414 */
415__lookup_architecture_type:
416		adr	r4, 2b
417		ldmia	r4, {r2, r3, r5, r6, r7}	@ throw away r2, r3
418		sub	r5, r4, r5			@ convert addresses
419		add	r4, r6, r5			@ to our address space
420		add	r7, r7, r5
4211:		ldr	r5, [r4]			@ get machine type
422		teq	r5, r1
423		beq	2f
424		add	r4, r4, #SIZEOF_MACHINE_DESC
425		cmp	r4, r7
426		blt	1b
427		mov	r7, #0				@ unknown architecture
428		mov	pc, lr
4292:		ldmib	r4, {r5, r6, r7}		@ found, get results
430		mov	pc, lr
431