| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * This file is subject to the terms and conditions of the GNU General Public | 
 | 3 |  * License.  See the file "COPYING" in the main directory of this archive | 
 | 4 |  * for more details. | 
 | 5 |  * | 
 | 6 |  * arch/sh64/kernel/head.S | 
 | 7 |  * | 
 | 8 |  * Copyright (C) 2000, 2001  Paolo Alberelli | 
 | 9 |  * Copyright (C) 2003, 2004  Paul Mundt | 
 | 10 |  * | 
 | 11 |  * | 
 | 12 |  * benedict.gaster@superh.com:	 2nd May 2002 | 
 | 13 |  *    Moved definition of empty_zero_page to its own section allowing | 
 | 14 |  *    it to be placed at an absolute address known at load time. | 
 | 15 |  * | 
 | 16 |  * lethal@linux-sh.org:          9th May 2003 | 
 | 17 |  *    Kill off GLOBAL_NAME() usage. | 
 | 18 |  * | 
 | 19 |  * lethal@linux-sh.org:          8th May 2004 | 
 | 20 |  *    Add early SCIF console DTLB mapping. | 
 | 21 |  */ | 
 | 22 |  | 
 | 23 | #include <linux/config.h> | 
 | 24 |  | 
 | 25 | #include <asm/page.h> | 
 | 26 | #include <asm/mmu_context.h> | 
 | 27 | #include <asm/cache.h> | 
 | 28 | #include <asm/tlb.h> | 
 | 29 | #include <asm/processor.h> | 
 | 30 | #include <asm/registers.h> | 
 | 31 | #include <asm/thread_info.h> | 
 | 32 |  | 
 | 33 | /* | 
 | 34 |  * MMU defines: TLB boundaries. | 
 | 35 |  */ | 
 | 36 |  | 
 | 37 | #define MMUIR_FIRST	ITLB_FIXED | 
 | 38 | #define MMUIR_END	ITLB_LAST_VAR_UNRESTRICTED+TLB_STEP | 
 | 39 | #define MMUIR_STEP	TLB_STEP | 
 | 40 |  | 
 | 41 | #define MMUDR_FIRST	DTLB_FIXED | 
 | 42 | #define MMUDR_END	DTLB_LAST_VAR_UNRESTRICTED+TLB_STEP | 
 | 43 | #define MMUDR_STEP	TLB_STEP | 
 | 44 |  | 
 | 45 | /* Safety check : CONFIG_CACHED_MEMORY_OFFSET has to be a multiple of 512Mb */ | 
 | 46 | #if (CONFIG_CACHED_MEMORY_OFFSET & ((1UL<<29)-1)) | 
 | 47 | #error "CONFIG_CACHED_MEMORY_OFFSET must be a multiple of 512Mb" | 
 | 48 | #endif | 
 | 49 |  | 
 | 50 | /* | 
 | 51 |  * MMU defines: Fixed TLBs. | 
 | 52 |  */ | 
 | 53 | /* Deal safely with the case where the base of RAM is not 512Mb aligned */ | 
 | 54 |  | 
 | 55 | #define ALIGN_512M_MASK (0xffffffffe0000000) | 
 | 56 | #define ALIGNED_EFFECTIVE ((CONFIG_CACHED_MEMORY_OFFSET + CONFIG_MEMORY_START) & ALIGN_512M_MASK) | 
 | 57 | #define ALIGNED_PHYSICAL (CONFIG_MEMORY_START & ALIGN_512M_MASK) | 
 | 58 |  | 
 | 59 | #define MMUIR_TEXT_H	(0x0000000000000003 | ALIGNED_EFFECTIVE) | 
 | 60 | 			/* Enabled, Shared, ASID 0, Eff. Add. 0xA0000000 */ | 
 | 61 |  | 
 | 62 | #define MMUIR_TEXT_L	(0x000000000000009a | ALIGNED_PHYSICAL) | 
 | 63 | 			/* 512 Mb, Cacheable, Write-back, execute, Not User, Ph. Add. */ | 
 | 64 |  | 
 | 65 | #define MMUDR_CACHED_H	0x0000000000000003 | ALIGNED_EFFECTIVE | 
 | 66 | 			/* Enabled, Shared, ASID 0, Eff. Add. 0xA0000000 */ | 
 | 67 | #define MMUDR_CACHED_L	0x000000000000015a | ALIGNED_PHYSICAL | 
 | 68 | 			/* 512 Mb, Cacheable, Write-back, read/write, Not User, Ph. Add. */ | 
 | 69 |  | 
 | 70 | #ifdef CONFIG_ICACHE_DISABLED | 
 | 71 | #define	ICCR0_INIT_VAL	ICCR0_OFF			/* ICACHE off */ | 
 | 72 | #else | 
 | 73 | #define	ICCR0_INIT_VAL	ICCR0_ON | ICCR0_ICI		/* ICE + ICI */ | 
 | 74 | #endif | 
 | 75 | #define	ICCR1_INIT_VAL	ICCR1_NOLOCK			/* No locking */ | 
 | 76 |  | 
 | 77 | #if defined (CONFIG_DCACHE_DISABLED) | 
 | 78 | #define	OCCR0_INIT_VAL	OCCR0_OFF			   /* D-cache: off  */ | 
 | 79 | #elif defined (CONFIG_DCACHE_WRITE_THROUGH) | 
 | 80 | #define	OCCR0_INIT_VAL	OCCR0_ON | OCCR0_OCI | OCCR0_WT	   /* D-cache: on,   */ | 
 | 81 | 							   /* WT, invalidate */ | 
 | 82 | #elif defined (CONFIG_DCACHE_WRITE_BACK) | 
 | 83 | #define	OCCR0_INIT_VAL	OCCR0_ON | OCCR0_OCI | OCCR0_WB	   /* D-cache: on,   */ | 
 | 84 | 							   /* WB, invalidate */ | 
 | 85 | #else | 
 | 86 | #error preprocessor flag CONFIG_DCACHE_... not recognized! | 
 | 87 | #endif | 
 | 88 |  | 
 | 89 | #define	OCCR1_INIT_VAL	OCCR1_NOLOCK			   /* No locking     */ | 
 | 90 |  | 
 | 91 | 	.section	.empty_zero_page, "aw" | 
 | 92 | 	.global empty_zero_page | 
 | 93 |  | 
 | 94 | empty_zero_page: | 
 | 95 | 	.long	1		/* MOUNT_ROOT_RDONLY */ | 
 | 96 | 	.long	0		/* RAMDISK_FLAGS */ | 
 | 97 | 	.long	0x0200		/* ORIG_ROOT_DEV */ | 
 | 98 | 	.long	1		/* LOADER_TYPE */ | 
 | 99 | 	.long	0x00800000	/* INITRD_START */ | 
 | 100 | 	.long	0x00800000	/* INITRD_SIZE */ | 
 | 101 | 	.long	0 | 
 | 102 |  | 
 | 103 | 	.text | 
 | 104 | 	.balign 4096,0,4096 | 
 | 105 |  | 
 | 106 | 	.section	.data, "aw" | 
 | 107 | 	.balign	PAGE_SIZE | 
 | 108 |  | 
 | 109 | 	.section	.data, "aw" | 
 | 110 | 	.balign	PAGE_SIZE | 
 | 111 |  | 
 | 112 | 	.global swapper_pg_dir | 
 | 113 | swapper_pg_dir: | 
 | 114 | 	.space PAGE_SIZE, 0 | 
 | 115 |  | 
 | 116 | 	.global empty_bad_page | 
 | 117 | empty_bad_page: | 
 | 118 | 	.space PAGE_SIZE, 0 | 
 | 119 |  | 
 | 120 | 	.global empty_bad_pte_table | 
 | 121 | empty_bad_pte_table: | 
 | 122 | 	.space PAGE_SIZE, 0 | 
 | 123 |  | 
 | 124 | 	.global	fpu_in_use | 
 | 125 | fpu_in_use:	.quad	0 | 
 | 126 |  | 
 | 127 |  | 
 | 128 | 	.section	.text, "ax" | 
 | 129 | 	.balign L1_CACHE_BYTES | 
 | 130 | /* | 
 | 131 |  * Condition at the entry of __stext: | 
 | 132 |  * . Reset state: | 
 | 133 |  *   . SR.FD    = 1		(FPU disabled) | 
 | 134 |  *   . SR.BL    = 1		(Exceptions disabled) | 
 | 135 |  *   . SR.MD    = 1		(Privileged Mode) | 
 | 136 |  *   . SR.MMU   = 0		(MMU Disabled) | 
 | 137 |  *   . SR.CD    = 0		(CTC User Visible) | 
 | 138 |  *   . SR.IMASK = Undefined	(Interrupt Mask) | 
 | 139 |  * | 
 | 140 |  * Operations supposed to be performed by __stext: | 
 | 141 |  * . prevent speculative fetch onto device memory while MMU is off | 
 | 142 |  * . reflect as much as possible SH5 ABI (r15, r26, r27, r18) | 
 | 143 |  * . first, save CPU state and set it to something harmless | 
 | 144 |  * . any CPU detection and/or endianness settings (?) | 
 | 145 |  * . initialize EMI/LMI (but not TMU/RTC/INTC/SCIF): TBD | 
 | 146 |  * . set initial TLB entries for cached and uncached regions | 
 | 147 |  *   (no fine granularity paging) | 
 | 148 |  * . set initial cache state | 
 | 149 |  * . enable MMU and caches | 
 | 150 |  * . set CPU to a consistent state | 
 | 151 |  *   . registers (including stack pointer and current/KCR0) | 
 | 152 |  *   . NOT expecting to set Exception handling nor VBR/RESVEC/DCR | 
 | 153 |  *     at this stage. This is all to later Linux initialization steps. | 
 | 154 |  *   . initialize FPU | 
 | 155 |  * . clear BSS | 
 | 156 |  * . jump into start_kernel() | 
 | 157 |  * . be prepared to hopeless start_kernel() returns. | 
 | 158 |  * | 
 | 159 |  */ | 
 | 160 | 	.global _stext | 
 | 161 | _stext: | 
 | 162 | 	/* | 
 | 163 | 	 * Prevent speculative fetch on device memory due to | 
 | 164 | 	 * uninitialized target registers. | 
 | 165 | 	 */ | 
 | 166 | 	ptabs/u	ZERO, tr0 | 
 | 167 | 	ptabs/u	ZERO, tr1 | 
 | 168 | 	ptabs/u	ZERO, tr2 | 
 | 169 | 	ptabs/u	ZERO, tr3 | 
 | 170 | 	ptabs/u	ZERO, tr4 | 
 | 171 | 	ptabs/u	ZERO, tr5 | 
 | 172 | 	ptabs/u	ZERO, tr6 | 
 | 173 | 	ptabs/u	ZERO, tr7 | 
 | 174 | 	synci | 
 | 175 |  | 
 | 176 | 	/* | 
 | 177 | 	 * Read/Set CPU state. After this block: | 
 | 178 | 	 * r29 = Initial SR | 
 | 179 | 	 */ | 
 | 180 | 	getcon	SR, r29 | 
 | 181 | 	movi	SR_HARMLESS, r20 | 
 | 182 | 	putcon	r20, SR | 
 | 183 |  | 
 | 184 | 	/* | 
 | 185 | 	 * Initialize EMI/LMI. To Be Done. | 
 | 186 | 	 */ | 
 | 187 |  | 
 | 188 | 	/* | 
 | 189 | 	 * CPU detection and/or endianness settings (?). To Be Done. | 
 | 190 | 	 * Pure PIC code here, please ! Just save state into r30. | 
 | 191 |          * After this block: | 
 | 192 | 	 * r30 = CPU type/Platform Endianness | 
 | 193 | 	 */ | 
 | 194 |  | 
 | 195 | 	/* | 
 | 196 | 	 * Set initial TLB entries for cached and uncached regions. | 
 | 197 | 	 * Note: PTA/BLINK is PIC code, PTABS/BLINK isn't ! | 
 | 198 | 	 */ | 
 | 199 | 	/* Clear ITLBs */ | 
 | 200 | 	pta	clear_ITLB, tr1 | 
 | 201 | 	movi	MMUIR_FIRST, r21 | 
 | 202 | 	movi	MMUIR_END, r22 | 
 | 203 | clear_ITLB: | 
 | 204 | 	putcfg	r21, 0, ZERO		/* Clear MMUIR[n].PTEH.V */ | 
 | 205 | 	addi	r21, MMUIR_STEP, r21 | 
 | 206 |         bne	r21, r22, tr1 | 
 | 207 |  | 
 | 208 | 	/* Clear DTLBs */ | 
 | 209 | 	pta	clear_DTLB, tr1 | 
 | 210 | 	movi	MMUDR_FIRST, r21 | 
 | 211 | 	movi	MMUDR_END, r22 | 
 | 212 | clear_DTLB: | 
 | 213 | 	putcfg	r21, 0, ZERO		/* Clear MMUDR[n].PTEH.V */ | 
 | 214 | 	addi	r21, MMUDR_STEP, r21 | 
 | 215 |         bne	r21, r22, tr1 | 
 | 216 |  | 
 | 217 | 	/* Map one big (512Mb) page for ITLB */ | 
 | 218 | 	movi	MMUIR_FIRST, r21 | 
 | 219 | 	movi	MMUIR_TEXT_L, r22	/* PTEL first */ | 
 | 220 | 	add.l	r22, r63, r22		/* Sign extend */ | 
 | 221 | 	putcfg	r21, 1, r22		/* Set MMUIR[0].PTEL */ | 
 | 222 | 	movi	MMUIR_TEXT_H, r22	/* PTEH last */ | 
 | 223 | 	add.l	r22, r63, r22		/* Sign extend */ | 
 | 224 | 	putcfg	r21, 0, r22		/* Set MMUIR[0].PTEH */ | 
 | 225 |  | 
 | 226 | 	/* Map one big CACHED (512Mb) page for DTLB */ | 
 | 227 | 	movi	MMUDR_FIRST, r21 | 
 | 228 | 	movi	MMUDR_CACHED_L, r22	/* PTEL first */ | 
 | 229 | 	add.l	r22, r63, r22		/* Sign extend */ | 
 | 230 | 	putcfg	r21, 1, r22		/* Set MMUDR[0].PTEL */ | 
 | 231 | 	movi	MMUDR_CACHED_H, r22	/* PTEH last */ | 
 | 232 | 	add.l	r22, r63, r22		/* Sign extend */ | 
 | 233 | 	putcfg	r21, 0, r22		/* Set MMUDR[0].PTEH */ | 
 | 234 |  | 
 | 235 | #ifdef CONFIG_EARLY_PRINTK | 
 | 236 | 	/* | 
 | 237 | 	 * Setup a DTLB translation for SCIF phys. | 
 | 238 | 	 */ | 
 | 239 | 	addi    r21, MMUDR_STEP, r21 | 
 | 240 | 	movi    0x0a03, r22	/* SCIF phys */ | 
 | 241 | 	shori   0x0148, r22 | 
 | 242 | 	putcfg  r21, 1, r22	/* PTEL first */ | 
 | 243 | 	movi    0xfa03, r22	/* 0xfa030000, fixed SCIF virt */ | 
 | 244 | 	shori   0x0003, r22 | 
 | 245 | 	putcfg  r21, 0, r22	/* PTEH last */ | 
 | 246 | #endif | 
 | 247 |  | 
 | 248 | 	/* | 
 | 249 | 	 * Set cache behaviours. | 
 | 250 | 	 */ | 
 | 251 | 	/* ICache */ | 
 | 252 | 	movi	ICCR_BASE, r21 | 
 | 253 | 	movi	ICCR0_INIT_VAL, r22 | 
 | 254 | 	movi	ICCR1_INIT_VAL, r23 | 
 | 255 | 	putcfg	r21, ICCR_REG0, r22 | 
 | 256 | 	putcfg	r21, ICCR_REG1, r23 | 
 | 257 |  | 
 | 258 | 	/* OCache */ | 
 | 259 | 	movi	OCCR_BASE, r21 | 
 | 260 | 	movi	OCCR0_INIT_VAL, r22 | 
 | 261 | 	movi	OCCR1_INIT_VAL, r23 | 
 | 262 | 	putcfg	r21, OCCR_REG0, r22 | 
 | 263 | 	putcfg	r21, OCCR_REG1, r23 | 
 | 264 |  | 
 | 265 |  | 
 | 266 | 	/* | 
 | 267 | 	 * Enable Caches and MMU. Do the first non-PIC jump. | 
 | 268 |          * Now head.S global variables, constants and externs | 
 | 269 | 	 * can be used. | 
 | 270 | 	 */ | 
 | 271 | 	getcon	SR, r21 | 
 | 272 | 	movi	SR_ENABLE_MMU, r22 | 
 | 273 | 	or	r21, r22, r21 | 
 | 274 | 	putcon	r21, SSR | 
 | 275 | 	movi	hyperspace, r22 | 
 | 276 | 	ori	r22, 1, r22	    /* Make it SHmedia, not required but..*/ | 
 | 277 | 	putcon	r22, SPC | 
 | 278 | 	synco | 
 | 279 | 	rte			    /* And now go into the hyperspace ... */ | 
 | 280 | hyperspace:			    /* ... that's the next instruction !  */ | 
 | 281 |  | 
 | 282 | 	/* | 
 | 283 | 	 * Set CPU to a consistent state. | 
 | 284 | 	 * r31 = FPU support flag | 
 | 285 | 	 * tr0/tr7 in use. Others give a chance to loop somewhere safe | 
 | 286 | 	 */ | 
 | 287 | 	movi	start_kernel, r32 | 
 | 288 | 	ori	r32, 1, r32 | 
 | 289 |  | 
 | 290 | 	ptabs	r32, tr0		    /* r32 = _start_kernel address        */ | 
 | 291 | 	pta/u	hopeless, tr1 | 
 | 292 | 	pta/u	hopeless, tr2 | 
 | 293 | 	pta/u	hopeless, tr3 | 
 | 294 | 	pta/u	hopeless, tr4 | 
 | 295 | 	pta/u	hopeless, tr5 | 
 | 296 | 	pta/u	hopeless, tr6 | 
 | 297 | 	pta/u	hopeless, tr7 | 
 | 298 | 	gettr	tr1, r28			/* r28 = hopeless address */ | 
 | 299 |  | 
 | 300 | 	/* Set initial stack pointer */ | 
 | 301 | 	movi	init_thread_union, SP | 
 | 302 | 	putcon	SP, KCR0		/* Set current to init_task */ | 
 | 303 | 	movi	THREAD_SIZE, r22	/* Point to the end */ | 
 | 304 | 	add	SP, r22, SP | 
 | 305 |  | 
 | 306 | 	/* | 
 | 307 | 	 * Initialize FPU. | 
 | 308 | 	 * Keep FPU flag in r31. After this block: | 
 | 309 | 	 * r31 = FPU flag | 
 | 310 | 	 */ | 
 | 311 | 	movi fpu_in_use, r31	/* Temporary */ | 
 | 312 |  | 
 | 313 | #ifdef CONFIG_SH_FPU | 
 | 314 | 	getcon	SR, r21 | 
 | 315 | 	movi	SR_ENABLE_FPU, r22 | 
 | 316 | 	and	r21, r22, r22 | 
 | 317 | 	putcon	r22, SR			/* Try to enable */ | 
 | 318 | 	getcon	SR, r22 | 
 | 319 | 	xor	r21, r22, r21 | 
 | 320 | 	shlri	r21, 15, r21		/* Supposedly 0/1 */ | 
 | 321 | 	st.q	r31, 0 , r21		/* Set fpu_in_use */ | 
 | 322 | #else | 
 | 323 | 	movi	0, r21 | 
 | 324 | 	st.q	r31, 0 , r21		/* Set fpu_in_use */ | 
 | 325 | #endif | 
 | 326 | 	or	r21, ZERO, r31		/* Set FPU flag at last */ | 
 | 327 |  | 
 | 328 | #ifndef CONFIG_SH_NO_BSS_INIT | 
 | 329 | /* Don't clear BSS if running on slow platforms such as an RTL simulation, | 
 | 330 |    remote memory via SHdebug link, etc.  For these the memory can be guaranteed | 
 | 331 |    to be all zero on boot anyway. */ | 
 | 332 | 	/* | 
 | 333 | 	 * Clear bss | 
 | 334 | 	 */ | 
 | 335 | 	pta	clear_quad, tr1 | 
 | 336 | 	movi	__bss_start, r22 | 
 | 337 | 	movi	_end, r23 | 
 | 338 | clear_quad: | 
 | 339 | 	st.q	r22, 0, ZERO | 
 | 340 | 	addi	r22, 8, r22 | 
 | 341 | 	bne	r22, r23, tr1		/* Both quad aligned, see vmlinux.lds.S */ | 
 | 342 | #endif | 
 | 343 | 	pta/u	hopeless, tr1 | 
 | 344 |  | 
 | 345 | 	/* Say bye to head.S but be prepared to wrongly get back ... */ | 
 | 346 | 	blink	tr0, LINK | 
 | 347 |  | 
 | 348 | 	/* If we ever get back here through LINK/tr1-tr7 */ | 
 | 349 | 	pta/u	hopeless, tr7 | 
 | 350 |  | 
 | 351 | hopeless: | 
 | 352 | 	/* | 
 | 353 | 	 * Something's badly wrong here. Loop endlessly, | 
 | 354 |          * there's nothing more we can do about it. | 
 | 355 | 	 * | 
 | 356 | 	 * Note on hopeless: it can be jumped into invariably | 
 | 357 | 	 * before or after jumping into hyperspace. The only | 
 | 358 | 	 * requirement is to be PIC called (PTA) before and | 
 | 359 | 	 * any way (PTA/PTABS) after. According to Virtual | 
 | 360 | 	 * to Physical mapping a simulator/emulator can easily | 
 | 361 | 	 * tell where we came here from just looking at hopeless | 
 | 362 | 	 * (PC) address. | 
 | 363 | 	 * | 
 | 364 | 	 * For debugging purposes: | 
 | 365 | 	 * (r28) hopeless/loop address | 
 | 366 | 	 * (r29) Original SR | 
 | 367 | 	 * (r30) CPU type/Platform endianness | 
 | 368 | 	 * (r31) FPU Support | 
 | 369 | 	 * (r32) _start_kernel address | 
 | 370 | 	 */ | 
 | 371 | 	blink	tr7, ZERO | 
 | 372 |  | 
 | 373 |  |