11.6Sandvar/*	$NetBSD: start.S,v 1.6 2024/02/09 17:39:33 andvar Exp $	*/
21.1Sreinoud
31.1Sreinoud/*
41.1Sreinoud * Copyright (c) 2002 Reinoud Zandijk
51.1Sreinoud * All rights reserved.
61.1Sreinoud *
71.1Sreinoud * Redistribution and use in source and binary forms, with or without
81.1Sreinoud * modification, are permitted provided that the following conditions
91.1Sreinoud * are met:
101.1Sreinoud * 1. Redistributions of source code must retain the above copyright
111.1Sreinoud *    notice, this list of conditions and the following disclaimer.
121.1Sreinoud * 2. Redistributions in binary form must reproduce the above copyright
131.1Sreinoud *    notice, this list of conditions and the following disclaimer in the
141.1Sreinoud *    documentation and/or other materials provided with the distribution.
151.1Sreinoud * 3. The name of the author may not be used to endorse or promote products
161.1Sreinoud *    derived from this software without specific prior written permission.
171.1Sreinoud *
181.1Sreinoud * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
191.1Sreinoud * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
201.1Sreinoud * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
211.1Sreinoud * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
221.1Sreinoud * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
231.1Sreinoud * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
241.1Sreinoud * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
251.1Sreinoud * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
261.1Sreinoud * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
271.1Sreinoud * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
281.1Sreinoud */
291.1Sreinoud
301.1Sreinoud#include <machine/asm.h>
311.1Sreinoud#include <arm/armreg.h>
321.1Sreinoud#include <riscoscalls.h>
331.1Sreinoud
341.1Sreinoud
351.1Sreinoud/* ----------------------------------------------------------------------- */
361.1SreinoudENTRY(relocate_code)
371.1Sreinoud	/*
381.1Sreinoud		- r0 pointer to configuration structure
391.1Sreinoud		- r1 pointer to physical restart point
401.1Sreinoud		- r3 pointer to physical new L1 page address (P)
411.1Sreinoud		- r4 kernel entry point
421.1Sreinoud	*/
431.1Sreinoud
441.1Sreinoud	/* save registers / move args up in register bank later */
451.1Sreinoud	/* r8-r12 becomes r0-r4 */
461.1Sreinoud	stmfd	sp!, {r0-r4}
471.1Sreinoud	ldmfd	sp!, {r8-r12}
481.1Sreinoud
491.1Sreinoud	/*
501.5Sandvar	 * determine processor architecture version. This is necessary for the
511.1Sreinoud	 * correct coprocessor instruction.
521.1Sreinoud	 */
531.4Sjoerg	mrc	p15, 0, r0, c0, c0, 0					/* read CPU id in r0			*/
541.1Sreinoud	mov	r3, r0							/* store in r3				*/
551.1Sreinoud
561.1Sreinoud	/* assume its ARMv4 instruction set									*/
571.1Sreinoud	mov	r14, #1
581.1Sreinoud
591.1Sreinoud	/* check ARM6. It needs a special mask									*/
601.1Sreinoud	mov	r0, #0x0000ff00
611.1Sreinoud	mov	r1, #0x00000600						/* check for 0xxxxx06xx => ARM6		*/
621.1Sreinoud	and	r2, r3, r0
631.1Sreinoud	cmp	r2, r1
641.1Sreinoud	moveq	r14, #0							/* mark v3				*/
651.1Sreinoud
661.1Sreinoud	/* newer ARM's need a different mask									*/
671.1Sreinoud	mov	r0, #0x0000f000
681.1Sreinoud
691.1Sreinoud	/* check for ARM7 and derivatives like the ARM 7500 and ARM 7500FE					*/
701.1Sreinoud	mov	r1, #0x00007000						/* check for 0xxxxx7xxx => ARM 7	*/
711.1Sreinoud	and	r2, r3, r0
721.1Sreinoud	cmp	r2, r1
731.1Sreinoud	moveq	r14, #0							/* mark v3				*/
741.1Sreinoud
751.3Schris	/* flush everything out before we turn off the MMU */
761.3Schris
771.3Schris	/* flush ID cache											*/
781.3Schris	mov	r0, #0
791.3Schris	cmp	r14, #0
801.4Sjoerg	mcreq	p15, 0, r0, c7, c0, 0					/* flush v3 ID cache			*/
811.4Sjoerg	mcrne	p15, 0, r0, c7, c7, 0					/* flush v4 ID cache			*/
821.4Sjoerg	mcrne	p15, 0, r0, c7, c10, 4					/* drain WB (v4)			*/
831.3Schris
841.3Schris	/* flush TLB												*/
851.4Sjoerg	mcr	p15, 0, r0, c5, c0, 0					/* flush TLB for v3 and v4		*/
861.3Schris
871.1Sreinoud	/* switch off MMU, IDcache and WB and branch to physical code space					*/
881.1Sreinoud	cmp	r14, #0
891.4Sjoerg	mrcne	p15, 0, r0, c1, c0, 0					/* read processor control register if v4*/
901.1Sreinoud	bic	r0, r0, #0x3f						/* clear only known bits		*/
911.1Sreinoud	moveq	r0, #0							/* for v3 just set to zero		*/
921.1Sreinoud	orr	r0, r0, #CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_32BP_ENABLE
931.1Sreinoud	mov	r13, r0							/* save this control value in r13	*/
941.1Sreinoud	cmp	r14, #0
951.4Sjoerg	mcr	p15, 0, r0, c1, c0, 0					/* write control register!		*/
961.4Sjoerg/*1*/	mcrne	p15, 0, r1, c7, c5, 0					/* write zero in ARMv4 MMU disable	*/
971.1Sreinoud/*2*/	mov	pc, r9							/* branch to physical address		*/
981.1Sreinoud
991.1Sreinoudrelocate_code_physical_restart:
1001.1Sreinoud	/* we are running in physical flat 1:1 space now */
1011.3Schris
1021.3Schris	/* make the screen border red */
1031.3Schris	mov	r4, #0x03400000
1041.3Schris	mov	r0, #0x40000000
1051.3Schris	orr	r0, r0, #0xff
1061.3Schris	str	r0, [r4]
1071.3Schris
1081.3Schris	adr	r5, relocate_table_start
1091.3Schris	ldr	r6, [r5], #4						/* r6 = number of relocated pages	*/
1101.3Schris
1111.1Sreinoudloop_relocate_pages:
1121.1Sreinoud	ldr	r2, [r5], #4						/* r2 = from address			*/
1131.1Sreinoud	ldr	r3, [r5], #4						/* r3 = to address			*/
1141.1Sreinoud	ldr	r7, [r5], #4						/* r7 = number of bytes to travel	*/
1151.1Sreinoud	/* its slow ... we dont know anything about alignment here 						*/
1161.1Sreinoudloop_one_page:
1171.3Schris	ldr	r0, [r2], #4
1181.3Schris	str	r0, [r3], #4
1191.3Schris	subs	r7, r7, #4
1201.3Schris	bgt	loop_one_page
1211.3Schris
1221.1Sreinoud	subs	r6, r6, #1
1231.1Sreinoud	bne	loop_relocate_pages
1241.1Sreinoud
1251.3Schris	/* make the screen border go green */
1261.3Schris	mov	r0, #0x40000000
1271.3Schris	orr	r0, r0, #0xff00
1281.3Schris	str	r0, [r4]
1291.3Schris
1301.1Sreinoud	/* OK! all is relocated... now switch over to the new L1 pages						*/
1311.1Sreinoud
1321.1Sreinoud	/* flush ID cache											*/
1331.1Sreinoud	mov	r0, #0
1341.1Sreinoud	cmp	r14, #0
1351.4Sjoerg	mcreq	p15, 0, r0, c7, c0, 0					/* flush v3 ID cache			*/
1361.4Sjoerg	mcrne	p15, 0, r0, c7, c7, 0					/* flush v4 ID cache			*/
1371.1Sreinoud
1381.1Sreinoud	/* drain write buffer (v4)										*/
1391.1Sreinoud	mov	r0, #0
1401.1Sreinoud	cmp	r14, #0
1411.4Sjoerg	mcrne	p15, 0, r0, c7, c10, 4					/* drain WB (v4)			*/
1421.1Sreinoud
1431.1Sreinoud	/* flush TLB												*/
1441.4Sjoerg	mcr	p15, 0, r0, c5, c0, 0					/* flush TLB for v3 and v4		*/
1451.1Sreinoud
1461.1Sreinoud	/* set new TLB address											*/
1471.1Sreinoud	mov	r0, r11
1481.4Sjoerg	mcr	p15, 0, r0, c2, c0, 0					/* write TLB address			*/
1491.1Sreinoud
1501.1Sreinoud	/* Switch on MMU, IDCache and WB and keep on running on flat translated memory				*/
1511.1Sreinoud	orr	r0, r13, #CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_32BP_ENABLE
1521.1Sreinoud	orr	r0, r0,  #CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_DC_ENABLE   | CPU_CONTROL_MMU_ENABLE
1531.4Sjoerg	mcr	p15, 0, r0, c1, c0, 0					/* write register !!!			*/
1541.1Sreinoud	mov	r0, r0							/* flat					*/
1551.1Sreinoud	mov	r0, r0							/* flat					*/
1561.1Sreinoud	/* not flat anymore but we just continue								*/
1571.1Sreinoud
1581.3Schris	/* make the screen border go blue */
1591.3Schris	mov	r0, #0x40000000
1601.3Schris	orr	r0, r0, #0xff0000
1611.3Schris	str	r0, [r4]
1621.3Schris
1631.1Sreinoud	/* call the kernel!											*/
1641.1Sreinoud	mov	r0, r8							/* saved configuration structure	*/
1651.1Sreinoud	mov	pc, r12							/* entry point ..... bye bye!		*/
1661.1Sreinoud
1671.1Sreinoudrelocate_code_end:
1681.1Sreinoud	b	relocate_code_end
1691.1Sreinoud
1701.3Schrisrelocate_table_start:
1711.3Schris	/* relocation table is copied here, so it must be kept small */
1721.3Schris
1731.3Schris
1741.1Sreinoud/* ----------------------------------------------------------------------- */
1751.1Sreinoud
1761.1Sreinoud
1771.1Sreinoud/* we are not expected to ever return from here */
1781.1SreinoudENTRY(start_kernel)
1791.1Sreinoud	/*
1801.1Sreinoud	entry conditions :
1811.1Sreinoud		- on RISC OS page tables in usr26 mode on virtual space
1821.1Sreinoud		- r0 relocation code page (V)
1831.1Sreinoud		- r1 relocation pv offset
1841.1Sreinoud		- r2 configuration structure
1851.3Schris		- r3 relocation table (V)
1861.1Sreinoud		- r4 L1 page descriptor (P)
1871.1Sreinoud		- r5 kernel entry point
1881.1Sreinoud	*/
1891.1Sreinoud	mov	ip, sp
1901.1Sreinoud	stmfd	sp!, {r4-r9, fp, ip, lr, pc}
1911.1Sreinoud	sub	fp, ip, #4
1921.1Sreinoud
1931.1Sreinoud	/* get stuff out of the calling frame */
1941.1Sreinoud	ldr	r4, [ip, #0]
1951.1Sreinoud	ldr	r5, [ip, #4]
1961.1Sreinoud
1971.1Sreinoud	/* relocate the relocation routine to the given page */
1981.1Sreinoud	adr	r6, relocate_code
1991.4Sjoerg	ldr	r7, =relocate_table_start - relocate_code	/* get length to copy */
2001.1Sreinoud	mov	r8, r0
2011.1Sreinoudrelocate_code_loop:
2021.1Sreinoud	ldr	r9, [r6], #4
2031.1Sreinoud	str	r9, [r8], #4
2041.1Sreinoud	subs	r7, r7, #4
2051.1Sreinoud	bne	relocate_code_loop
2061.1Sreinoud
2071.3Schris	/* now relocate the relocate table onto the same page */
2081.3Schris
2091.3Schris	/* next we need to copy the table over */
2101.3Schris	ldr	r6, [r3], #4					/* r6 has number of threes to copy */
2111.3Schris	str	r6, [r8], #4
2121.3Schris
2131.3Schrisrelocate_table_loop:
2141.3Schris	ldr	r9, [r3], #4
2151.3Schris	str	r9, [r8], #4
2161.3Schris	ldr	r9, [r3], #4
2171.3Schris	str	r9, [r8], #4
2181.3Schris	ldr	r9, [r3], #4
2191.3Schris	str	r9, [r8], #4
2201.3Schris	subs	r6, r6, #1
2211.3Schris	bne	relocate_table_loop
2221.3Schris
2231.1Sreinoud	/* we messed up the data cache : lets read a 64 or 128 kb <-- GROSS */
2241.1Sreinoud	mov	r7, #128*1024
2251.1Sreinoud	mov	r6, #0x8000						/* start of RISCOS application area	*/
2261.1Sreinoudflush_ID_cache_try:
2271.1Sreinoud	ldr	r9, [r6], #4
2281.1Sreinoud	subs	r7, r7, #4
2291.1Sreinoud	bne	flush_ID_cache_try
2301.1Sreinoud
2311.1Sreinoud	/* enter sub26 mode */
2321.1Sreinoud	swi	OS_EnterOS
2331.1Sreinoud
2341.1Sreinoud	/* go to sup32 mode with ICQ and FIQ disabled */
2351.1Sreinoud	mrs	r6, cpsr
2361.1Sreinoud	bic	r6, r6, #PSR_MODE					/* clear processor mode			*/
2371.1Sreinoud	orr	r6, r6, #(I32_bit | F32_bit)				/* disable ICQ + FIQ			*/
2381.1Sreinoud	orr	r6, r6, #PSR_SVC32_MODE					/* go to 32 bit supervisor mode		*/
2391.1Sreinoud	msr	cpsr, r6
2401.1Sreinoud	mov	r0, r0							/* nops ... just in case		*/
2411.1Sreinoud	mov	r0, r0
2421.1Sreinoud
2431.1Sreinoud	/* set up info */
2441.1Sreinoud	mov	r9, r0							/* save relocated page address		*/
2451.4Sjoerg	ldr	r7, =relocate_code_physical_restart - relocate_code	/* get offset			*/
2461.1Sreinoud	add	r1, r0, r1						/* get physical address			*/
2471.1Sreinoud	add	r1, r1, r7						/* add offset				*/
2481.1Sreinoud	mov	r0, r2							/* put configuration structure in r0	*/
2491.3Schris	mov	r2, r3
2501.6Sandvar	mov	r3, r4							/* L1 page descriptor			*/
2511.1Sreinoud	mov	r4, r5							/* kernel entry point			*/
2521.1Sreinoud
2531.1Sreinoud	mov	pc, r9							/* jump to page addr == relocate_code	*/
2541.1Sreinoud
2551.1Sreinoudemergency_exit:
2561.1Sreinoud	ldmdb	fp, {r4-r9, fp, sp, pc}
2571.1Sreinoud
258