xref: /openbmc/linux/arch/powerpc/kernel/misc_64.S (revision 2c86cd188f8a5631f3d75a1dea14d22df85189b4)
19994a338SPaul Mackerras/*
29994a338SPaul Mackerras * This file contains miscellaneous low-level functions.
39994a338SPaul Mackerras *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
49994a338SPaul Mackerras *
59994a338SPaul Mackerras * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
69994a338SPaul Mackerras * and Paul Mackerras.
79994a338SPaul Mackerras * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
89994a338SPaul Mackerras * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
99994a338SPaul Mackerras *
109994a338SPaul Mackerras * This program is free software; you can redistribute it and/or
119994a338SPaul Mackerras * modify it under the terms of the GNU General Public License
129994a338SPaul Mackerras * as published by the Free Software Foundation; either version
139994a338SPaul Mackerras * 2 of the License, or (at your option) any later version.
149994a338SPaul Mackerras *
159994a338SPaul Mackerras */
169994a338SPaul Mackerras
179994a338SPaul Mackerras#include <linux/sys.h>
189994a338SPaul Mackerras#include <asm/unistd.h>
199994a338SPaul Mackerras#include <asm/errno.h>
209994a338SPaul Mackerras#include <asm/processor.h>
219994a338SPaul Mackerras#include <asm/page.h>
229994a338SPaul Mackerras#include <asm/cache.h>
239994a338SPaul Mackerras#include <asm/ppc_asm.h>
249994a338SPaul Mackerras#include <asm/asm-offsets.h>
259994a338SPaul Mackerras#include <asm/cputable.h>
266cb7bfebSDavid Gibson#include <asm/thread_info.h>
271fc711f7SMichael Neuling#include <asm/kexec.h>
2846f52210SStephen Rothwell#include <asm/ptrace.h>
29cf904e30STiejun Chen#include <asm/mmu.h>
309445aa1aSAl Viro#include <asm/export.h>
31*2c86cd18SChristophe Leroy#include <asm/feature-fixups.h>
329994a338SPaul Mackerras
339994a338SPaul Mackerras	.text
349994a338SPaul Mackerras
359994a338SPaul Mackerras_GLOBAL(call_do_softirq)
369994a338SPaul Mackerras	mflr	r0
379994a338SPaul Mackerras	std	r0,16(r1)
384ae2dcb6SKumar Gala	stdu	r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
399994a338SPaul Mackerras	mr	r1,r3
40b1576fecSAnton Blanchard	bl	__do_softirq
419994a338SPaul Mackerras	ld	r1,0(r1)
429994a338SPaul Mackerras	ld	r0,16(r1)
439994a338SPaul Mackerras	mtlr	r0
449994a338SPaul Mackerras	blr
459994a338SPaul Mackerras
460366a1c7SBenjamin Herrenschmidt_GLOBAL(call_do_irq)
479994a338SPaul Mackerras	mflr	r0
489994a338SPaul Mackerras	std	r0,16(r1)
490366a1c7SBenjamin Herrenschmidt	stdu	r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r4)
500366a1c7SBenjamin Herrenschmidt	mr	r1,r4
51b1576fecSAnton Blanchard	bl	__do_irq
529994a338SPaul Mackerras	ld	r1,0(r1)
539994a338SPaul Mackerras	ld	r0,16(r1)
549994a338SPaul Mackerras	mtlr	r0
559994a338SPaul Mackerras	blr
569994a338SPaul Mackerras
579994a338SPaul Mackerras	.section	".toc","aw"
589994a338SPaul MackerrasPPC64_CACHES:
599994a338SPaul Mackerras	.tc		ppc64_caches[TC],ppc64_caches
609994a338SPaul Mackerras	.section	".text"
619994a338SPaul Mackerras
629994a338SPaul Mackerras/*
639994a338SPaul Mackerras * Write any modified data cache blocks out to memory
649994a338SPaul Mackerras * and invalidate the corresponding instruction cache blocks.
659994a338SPaul Mackerras *
669994a338SPaul Mackerras * flush_icache_range(unsigned long start, unsigned long stop)
679994a338SPaul Mackerras *
689994a338SPaul Mackerras *   flush all bytes from start through stop-1 inclusive
699994a338SPaul Mackerras */
709994a338SPaul Mackerras
718f5f525dSOliver O'Halloran_GLOBAL_TOC(flush_icache_range)
72abb29c3bSKevin HaoBEGIN_FTR_SECTION
730ce63670SKevin Hao	PURGE_PREFETCHED_INS
74abb29c3bSKevin Hao	blr
75abb29c3bSKevin HaoEND_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
769994a338SPaul Mackerras/*
779994a338SPaul Mackerras * Flush the data cache to memory
789994a338SPaul Mackerras *
799994a338SPaul Mackerras * Different systems have different cache line sizes
809994a338SPaul Mackerras * and in some cases i-cache and d-cache line sizes differ from
819994a338SPaul Mackerras * each other.
829994a338SPaul Mackerras */
839994a338SPaul Mackerras 	ld	r10,PPC64_CACHES@toc(r2)
84bd067f83SBenjamin Herrenschmidt	lwz	r7,DCACHEL1BLOCKSIZE(r10)/* Get cache block size */
859994a338SPaul Mackerras	addi	r5,r7,-1
869994a338SPaul Mackerras	andc	r6,r3,r5		/* round low to line bdy */
879994a338SPaul Mackerras	subf	r8,r6,r4		/* compute length */
889994a338SPaul Mackerras	add	r8,r8,r5		/* ensure we get enough */
89bd067f83SBenjamin Herrenschmidt	lwz	r9,DCACHEL1LOGBLOCKSIZE(r10)	/* Get log-2 of cache block size */
909994a338SPaul Mackerras	srw.	r8,r8,r9		/* compute line count */
919994a338SPaul Mackerras	beqlr				/* nothing to do? */
929994a338SPaul Mackerras	mtctr	r8
939994a338SPaul Mackerras1:	dcbst	0,r6
949994a338SPaul Mackerras	add	r6,r6,r7
959994a338SPaul Mackerras	bdnz	1b
969994a338SPaul Mackerras	sync
979994a338SPaul Mackerras
989994a338SPaul Mackerras/* Now invalidate the instruction cache */
999994a338SPaul Mackerras
100bd067f83SBenjamin Herrenschmidt	lwz	r7,ICACHEL1BLOCKSIZE(r10)	/* Get Icache block size */
1019994a338SPaul Mackerras	addi	r5,r7,-1
1029994a338SPaul Mackerras	andc	r6,r3,r5		/* round low to line bdy */
1039994a338SPaul Mackerras	subf	r8,r6,r4		/* compute length */
1049994a338SPaul Mackerras	add	r8,r8,r5
105bd067f83SBenjamin Herrenschmidt	lwz	r9,ICACHEL1LOGBLOCKSIZE(r10)	/* Get log-2 of Icache block size */
1069994a338SPaul Mackerras	srw.	r8,r8,r9		/* compute line count */
1079994a338SPaul Mackerras	beqlr				/* nothing to do? */
1089994a338SPaul Mackerras	mtctr	r8
1099994a338SPaul Mackerras2:	icbi	0,r6
1109994a338SPaul Mackerras	add	r6,r6,r7
1119994a338SPaul Mackerras	bdnz	2b
1129994a338SPaul Mackerras	isync
1139994a338SPaul Mackerras	blr
1146f698df1SNicholas Piggin_ASM_NOKPROBE_SYMBOL(flush_icache_range)
1159445aa1aSAl ViroEXPORT_SYMBOL(flush_icache_range)
1166f698df1SNicholas Piggin
1179994a338SPaul Mackerras/*
1189994a338SPaul Mackerras * Like above, but only do the D-cache.
1199994a338SPaul Mackerras *
1209994a338SPaul Mackerras * flush_dcache_range(unsigned long start, unsigned long stop)
1219994a338SPaul Mackerras *
1229994a338SPaul Mackerras *    flush all bytes from start to stop-1 inclusive
1239994a338SPaul Mackerras */
1248f5f525dSOliver O'Halloran_GLOBAL_TOC(flush_dcache_range)
1259994a338SPaul Mackerras
1269994a338SPaul Mackerras/*
1279994a338SPaul Mackerras * Flush the data cache to memory
1289994a338SPaul Mackerras *
1299994a338SPaul Mackerras * Different systems have different cache line sizes
1309994a338SPaul Mackerras */
1319994a338SPaul Mackerras 	ld	r10,PPC64_CACHES@toc(r2)
132bd067f83SBenjamin Herrenschmidt	lwz	r7,DCACHEL1BLOCKSIZE(r10)	/* Get dcache block size */
1339994a338SPaul Mackerras	addi	r5,r7,-1
1349994a338SPaul Mackerras	andc	r6,r3,r5		/* round low to line bdy */
1359994a338SPaul Mackerras	subf	r8,r6,r4		/* compute length */
1369994a338SPaul Mackerras	add	r8,r8,r5		/* ensure we get enough */
137bd067f83SBenjamin Herrenschmidt	lwz	r9,DCACHEL1LOGBLOCKSIZE(r10)	/* Get log-2 of dcache block size */
1389994a338SPaul Mackerras	srw.	r8,r8,r9		/* compute line count */
1399994a338SPaul Mackerras	beqlr				/* nothing to do? */
1409994a338SPaul Mackerras	mtctr	r8
1419994a338SPaul Mackerras0:	dcbst	0,r6
1429994a338SPaul Mackerras	add	r6,r6,r7
1439994a338SPaul Mackerras	bdnz	0b
1449994a338SPaul Mackerras	sync
1459994a338SPaul Mackerras	blr
1469445aa1aSAl ViroEXPORT_SYMBOL(flush_dcache_range)
1479994a338SPaul Mackerras
1489994a338SPaul Mackerras_GLOBAL(flush_inval_dcache_range)
1499994a338SPaul Mackerras 	ld	r10,PPC64_CACHES@toc(r2)
150bd067f83SBenjamin Herrenschmidt	lwz	r7,DCACHEL1BLOCKSIZE(r10)	/* Get dcache block size */
1519994a338SPaul Mackerras	addi	r5,r7,-1
1529994a338SPaul Mackerras	andc	r6,r3,r5		/* round low to line bdy */
1539994a338SPaul Mackerras	subf	r8,r6,r4		/* compute length */
1549994a338SPaul Mackerras	add	r8,r8,r5		/* ensure we get enough */
155bd067f83SBenjamin Herrenschmidt	lwz	r9,DCACHEL1LOGBLOCKSIZE(r10)/* Get log-2 of dcache block size */
1569994a338SPaul Mackerras	srw.	r8,r8,r9		/* compute line count */
1579994a338SPaul Mackerras	beqlr				/* nothing to do? */
1589994a338SPaul Mackerras	sync
1599994a338SPaul Mackerras	isync
1609994a338SPaul Mackerras	mtctr	r8
1619994a338SPaul Mackerras0:	dcbf	0,r6
1629994a338SPaul Mackerras	add	r6,r6,r7
1639994a338SPaul Mackerras	bdnz	0b
1649994a338SPaul Mackerras	sync
1659994a338SPaul Mackerras	isync
1669994a338SPaul Mackerras	blr
1679994a338SPaul Mackerras
1689994a338SPaul Mackerras
1699994a338SPaul Mackerras/*
1709994a338SPaul Mackerras * Flush a particular page from the data cache to RAM.
1719994a338SPaul Mackerras * Note: this is necessary because the instruction cache does *not*
1729994a338SPaul Mackerras * snoop from the data cache.
1739994a338SPaul Mackerras *
1749994a338SPaul Mackerras *	void __flush_dcache_icache(void *page)
1759994a338SPaul Mackerras */
1769994a338SPaul Mackerras_GLOBAL(__flush_dcache_icache)
1779994a338SPaul Mackerras/*
1789994a338SPaul Mackerras * Flush the data cache to memory
1799994a338SPaul Mackerras *
1809994a338SPaul Mackerras * Different systems have different cache line sizes
1819994a338SPaul Mackerras */
1829994a338SPaul Mackerras
1830ce63670SKevin HaoBEGIN_FTR_SECTION
1840ce63670SKevin Hao	PURGE_PREFETCHED_INS
1850ce63670SKevin Hao	blr
1860ce63670SKevin HaoEND_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
1870ce63670SKevin Hao
1889994a338SPaul Mackerras/* Flush the dcache */
1899994a338SPaul Mackerras 	ld	r7,PPC64_CACHES@toc(r2)
1909994a338SPaul Mackerras	clrrdi	r3,r3,PAGE_SHIFT           	    /* Page align */
191bd067f83SBenjamin Herrenschmidt	lwz	r4,DCACHEL1BLOCKSPERPAGE(r7)	/* Get # dcache blocks per page */
192bd067f83SBenjamin Herrenschmidt	lwz	r5,DCACHEL1BLOCKSIZE(r7)	/* Get dcache block size */
1939994a338SPaul Mackerras	mr	r6,r3
1949994a338SPaul Mackerras	mtctr	r4
1959994a338SPaul Mackerras0:	dcbst	0,r6
1969994a338SPaul Mackerras	add	r6,r6,r5
1979994a338SPaul Mackerras	bdnz	0b
1989994a338SPaul Mackerras	sync
1999994a338SPaul Mackerras
2009994a338SPaul Mackerras/* Now invalidate the icache */
2019994a338SPaul Mackerras
202bd067f83SBenjamin Herrenschmidt	lwz	r4,ICACHEL1BLOCKSPERPAGE(r7)	/* Get # icache blocks per page */
203bd067f83SBenjamin Herrenschmidt	lwz	r5,ICACHEL1BLOCKSIZE(r7)	/* Get icache block size */
2049994a338SPaul Mackerras	mtctr	r4
2059994a338SPaul Mackerras1:	icbi	0,r3
2069994a338SPaul Mackerras	add	r3,r3,r5
2079994a338SPaul Mackerras	bdnz	1b
2089994a338SPaul Mackerras	isync
2099994a338SPaul Mackerras	blr
2109994a338SPaul Mackerras
211ca9d7aeaSDavid Woodhouse_GLOBAL(__bswapdi2)
2129445aa1aSAl ViroEXPORT_SYMBOL(__bswapdi2)
213ca9d7aeaSDavid Woodhouse	srdi	r8,r3,32
214ca9d7aeaSDavid Woodhouse	rlwinm	r7,r3,8,0xffffffff
215ca9d7aeaSDavid Woodhouse	rlwimi	r7,r3,24,0,7
216ca9d7aeaSDavid Woodhouse	rlwinm	r9,r8,8,0xffffffff
217ca9d7aeaSDavid Woodhouse	rlwimi	r7,r3,24,16,23
218ca9d7aeaSDavid Woodhouse	rlwimi	r9,r8,24,0,7
219ca9d7aeaSDavid Woodhouse	rlwimi	r9,r8,24,16,23
220ca9d7aeaSDavid Woodhouse	sldi	r7,r7,32
221ca9d7aeaSDavid Woodhouse	or	r3,r7,r9
222ca9d7aeaSDavid Woodhouse	blr
2233f639ee8SStephen Rothwell
2247191b615SBenjamin Herrenschmidt
2252d6f0c3aSMichael Ellerman#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
2267191b615SBenjamin Herrenschmidt_GLOBAL(rmci_on)
2277191b615SBenjamin Herrenschmidt	sync
2287191b615SBenjamin Herrenschmidt	isync
2297191b615SBenjamin Herrenschmidt	li	r3,0x100
2307191b615SBenjamin Herrenschmidt	rldicl	r3,r3,32,0
2317191b615SBenjamin Herrenschmidt	mfspr	r5,SPRN_HID4
2327191b615SBenjamin Herrenschmidt	or	r5,r5,r3
2337191b615SBenjamin Herrenschmidt	sync
2347191b615SBenjamin Herrenschmidt	mtspr	SPRN_HID4,r5
2357191b615SBenjamin Herrenschmidt	isync
2367191b615SBenjamin Herrenschmidt	slbia
2377191b615SBenjamin Herrenschmidt	isync
2387191b615SBenjamin Herrenschmidt	sync
2397191b615SBenjamin Herrenschmidt	blr
2407191b615SBenjamin Herrenschmidt
2417191b615SBenjamin Herrenschmidt_GLOBAL(rmci_off)
2427191b615SBenjamin Herrenschmidt	sync
2437191b615SBenjamin Herrenschmidt	isync
2447191b615SBenjamin Herrenschmidt	li	r3,0x100
2457191b615SBenjamin Herrenschmidt	rldicl	r3,r3,32,0
2467191b615SBenjamin Herrenschmidt	mfspr	r5,SPRN_HID4
2477191b615SBenjamin Herrenschmidt	andc	r5,r5,r3
2487191b615SBenjamin Herrenschmidt	sync
2497191b615SBenjamin Herrenschmidt	mtspr	SPRN_HID4,r5
2507191b615SBenjamin Herrenschmidt	isync
2517191b615SBenjamin Herrenschmidt	slbia
2527191b615SBenjamin Herrenschmidt	isync
2537191b615SBenjamin Herrenschmidt	sync
2547191b615SBenjamin Herrenschmidt	blr
2552d6f0c3aSMichael Ellerman#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
2562d6f0c3aSMichael Ellerman
2572d6f0c3aSMichael Ellerman#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
2587191b615SBenjamin Herrenschmidt
2599994a338SPaul Mackerras/*
2609994a338SPaul Mackerras * Do an IO access in real mode
2619994a338SPaul Mackerras */
2629994a338SPaul Mackerras_GLOBAL(real_readb)
2639994a338SPaul Mackerras	mfmsr	r7
2649994a338SPaul Mackerras	ori	r0,r7,MSR_DR
2659994a338SPaul Mackerras	xori	r0,r0,MSR_DR
2669994a338SPaul Mackerras	sync
2679994a338SPaul Mackerras	mtmsrd	r0
2689994a338SPaul Mackerras	sync
2699994a338SPaul Mackerras	isync
2709994a338SPaul Mackerras	mfspr	r6,SPRN_HID4
2719994a338SPaul Mackerras	rldicl	r5,r6,32,0
2729994a338SPaul Mackerras	ori	r5,r5,0x100
2739994a338SPaul Mackerras	rldicl	r5,r5,32,0
2749994a338SPaul Mackerras	sync
2759994a338SPaul Mackerras	mtspr	SPRN_HID4,r5
2769994a338SPaul Mackerras	isync
2779994a338SPaul Mackerras	slbia
2789994a338SPaul Mackerras	isync
2799994a338SPaul Mackerras	lbz	r3,0(r3)
2809994a338SPaul Mackerras	sync
2819994a338SPaul Mackerras	mtspr	SPRN_HID4,r6
2829994a338SPaul Mackerras	isync
2839994a338SPaul Mackerras	slbia
2849994a338SPaul Mackerras	isync
2859994a338SPaul Mackerras	mtmsrd	r7
2869994a338SPaul Mackerras	sync
2879994a338SPaul Mackerras	isync
2889994a338SPaul Mackerras	blr
2899994a338SPaul Mackerras
2909994a338SPaul Mackerras	/*
2919994a338SPaul Mackerras * Do an IO access in real mode
2929994a338SPaul Mackerras */
2939994a338SPaul Mackerras_GLOBAL(real_writeb)
2949994a338SPaul Mackerras	mfmsr	r7
2959994a338SPaul Mackerras	ori	r0,r7,MSR_DR
2969994a338SPaul Mackerras	xori	r0,r0,MSR_DR
2979994a338SPaul Mackerras	sync
2989994a338SPaul Mackerras	mtmsrd	r0
2999994a338SPaul Mackerras	sync
3009994a338SPaul Mackerras	isync
3019994a338SPaul Mackerras	mfspr	r6,SPRN_HID4
3029994a338SPaul Mackerras	rldicl	r5,r6,32,0
3039994a338SPaul Mackerras	ori	r5,r5,0x100
3049994a338SPaul Mackerras	rldicl	r5,r5,32,0
3059994a338SPaul Mackerras	sync
3069994a338SPaul Mackerras	mtspr	SPRN_HID4,r5
3079994a338SPaul Mackerras	isync
3089994a338SPaul Mackerras	slbia
3099994a338SPaul Mackerras	isync
3109994a338SPaul Mackerras	stb	r3,0(r4)
3119994a338SPaul Mackerras	sync
3129994a338SPaul Mackerras	mtspr	SPRN_HID4,r6
3139994a338SPaul Mackerras	isync
3149994a338SPaul Mackerras	slbia
3159994a338SPaul Mackerras	isync
3169994a338SPaul Mackerras	mtmsrd	r7
3179994a338SPaul Mackerras	sync
3189994a338SPaul Mackerras	isync
3199994a338SPaul Mackerras	blr
3209994a338SPaul Mackerras#endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */
3219994a338SPaul Mackerras
32239c870d5SOlof Johansson#ifdef CONFIG_PPC_PASEMI
32339c870d5SOlof Johansson
32439c870d5SOlof Johansson_GLOBAL(real_205_readb)
32539c870d5SOlof Johansson	mfmsr	r7
32639c870d5SOlof Johansson	ori	r0,r7,MSR_DR
32739c870d5SOlof Johansson	xori	r0,r0,MSR_DR
32839c870d5SOlof Johansson	sync
32939c870d5SOlof Johansson	mtmsrd	r0
33039c870d5SOlof Johansson	sync
33139c870d5SOlof Johansson	isync
332e55174e9SMichael Neuling	LBZCIX(R3,R0,R3)
33339c870d5SOlof Johansson	isync
33439c870d5SOlof Johansson	mtmsrd	r7
33539c870d5SOlof Johansson	sync
33639c870d5SOlof Johansson	isync
33739c870d5SOlof Johansson	blr
33839c870d5SOlof Johansson
33939c870d5SOlof Johansson_GLOBAL(real_205_writeb)
34039c870d5SOlof Johansson	mfmsr	r7
34139c870d5SOlof Johansson	ori	r0,r7,MSR_DR
34239c870d5SOlof Johansson	xori	r0,r0,MSR_DR
34339c870d5SOlof Johansson	sync
34439c870d5SOlof Johansson	mtmsrd	r0
34539c870d5SOlof Johansson	sync
34639c870d5SOlof Johansson	isync
347e55174e9SMichael Neuling	STBCIX(R3,R0,R4)
34839c870d5SOlof Johansson	isync
34939c870d5SOlof Johansson	mtmsrd	r7
35039c870d5SOlof Johansson	sync
35139c870d5SOlof Johansson	isync
35239c870d5SOlof Johansson	blr
35339c870d5SOlof Johansson
35439c870d5SOlof Johansson#endif /* CONFIG_PPC_PASEMI */
35539c870d5SOlof Johansson
35639c870d5SOlof Johansson
357e48f7eb2SDmitry Eremin-Solenikov#if defined(CONFIG_CPU_FREQ_PMAC64) || defined(CONFIG_CPU_FREQ_MAPLE)
3589994a338SPaul Mackerras/*
3594350147aSBenjamin Herrenschmidt * SCOM access functions for 970 (FX only for now)
3604350147aSBenjamin Herrenschmidt *
3614350147aSBenjamin Herrenschmidt * unsigned long scom970_read(unsigned int address);
3624350147aSBenjamin Herrenschmidt * void scom970_write(unsigned int address, unsigned long value);
3634350147aSBenjamin Herrenschmidt *
3644350147aSBenjamin Herrenschmidt * The address passed in is the 24 bits register address. This code
3654350147aSBenjamin Herrenschmidt * is 970 specific and will not check the status bits, so you should
3664350147aSBenjamin Herrenschmidt * know what you are doing.
3674350147aSBenjamin Herrenschmidt */
3684350147aSBenjamin Herrenschmidt_GLOBAL(scom970_read)
3694350147aSBenjamin Herrenschmidt	/* interrupts off */
3704350147aSBenjamin Herrenschmidt	mfmsr	r4
3714350147aSBenjamin Herrenschmidt	ori	r0,r4,MSR_EE
3724350147aSBenjamin Herrenschmidt	xori	r0,r0,MSR_EE
3734350147aSBenjamin Herrenschmidt	mtmsrd	r0,1
3744350147aSBenjamin Herrenschmidt
3754350147aSBenjamin Herrenschmidt	/* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits
3764350147aSBenjamin Herrenschmidt	 * (including parity). On current CPUs they must be 0'd,
3774350147aSBenjamin Herrenschmidt	 * and finally or in RW bit
3784350147aSBenjamin Herrenschmidt	 */
3794350147aSBenjamin Herrenschmidt	rlwinm	r3,r3,8,0,15
3804350147aSBenjamin Herrenschmidt	ori	r3,r3,0x8000
3814350147aSBenjamin Herrenschmidt
3824350147aSBenjamin Herrenschmidt	/* do the actual scom read */
3834350147aSBenjamin Herrenschmidt	sync
3844350147aSBenjamin Herrenschmidt	mtspr	SPRN_SCOMC,r3
3854350147aSBenjamin Herrenschmidt	isync
3864350147aSBenjamin Herrenschmidt	mfspr	r3,SPRN_SCOMD
3874350147aSBenjamin Herrenschmidt	isync
3884350147aSBenjamin Herrenschmidt	mfspr	r0,SPRN_SCOMC
3894350147aSBenjamin Herrenschmidt	isync
3904350147aSBenjamin Herrenschmidt
3914350147aSBenjamin Herrenschmidt	/* XXX:	fixup result on some buggy 970's (ouch ! we lost a bit, bah
3924350147aSBenjamin Herrenschmidt	 * that's the best we can do). Not implemented yet as we don't use
3934350147aSBenjamin Herrenschmidt	 * the scom on any of the bogus CPUs yet, but may have to be done
3944350147aSBenjamin Herrenschmidt	 * ultimately
3954350147aSBenjamin Herrenschmidt	 */
3964350147aSBenjamin Herrenschmidt
3974350147aSBenjamin Herrenschmidt	/* restore interrupts */
3984350147aSBenjamin Herrenschmidt	mtmsrd	r4,1
3994350147aSBenjamin Herrenschmidt	blr
4004350147aSBenjamin Herrenschmidt
4014350147aSBenjamin Herrenschmidt
4024350147aSBenjamin Herrenschmidt_GLOBAL(scom970_write)
4034350147aSBenjamin Herrenschmidt	/* interrupts off */
4044350147aSBenjamin Herrenschmidt	mfmsr	r5
4054350147aSBenjamin Herrenschmidt	ori	r0,r5,MSR_EE
4064350147aSBenjamin Herrenschmidt	xori	r0,r0,MSR_EE
4074350147aSBenjamin Herrenschmidt	mtmsrd	r0,1
4084350147aSBenjamin Herrenschmidt
4094350147aSBenjamin Herrenschmidt	/* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits
4104350147aSBenjamin Herrenschmidt	 * (including parity). On current CPUs they must be 0'd.
4114350147aSBenjamin Herrenschmidt	 */
4124350147aSBenjamin Herrenschmidt
4134350147aSBenjamin Herrenschmidt	rlwinm	r3,r3,8,0,15
4144350147aSBenjamin Herrenschmidt
4154350147aSBenjamin Herrenschmidt	sync
4164350147aSBenjamin Herrenschmidt	mtspr	SPRN_SCOMD,r4      /* write data */
4174350147aSBenjamin Herrenschmidt	isync
4184350147aSBenjamin Herrenschmidt	mtspr	SPRN_SCOMC,r3      /* write command */
4194350147aSBenjamin Herrenschmidt	isync
4204350147aSBenjamin Herrenschmidt	mfspr	3,SPRN_SCOMC
4214350147aSBenjamin Herrenschmidt	isync
4224350147aSBenjamin Herrenschmidt
4234350147aSBenjamin Herrenschmidt	/* restore interrupts */
4244350147aSBenjamin Herrenschmidt	mtmsrd	r5,1
4254350147aSBenjamin Herrenschmidt	blr
426e48f7eb2SDmitry Eremin-Solenikov#endif /* CONFIG_CPU_FREQ_PMAC64 || CONFIG_CPU_FREQ_MAPLE */
4274350147aSBenjamin Herrenschmidt
4289994a338SPaul Mackerras/* kexec_wait(phys_cpu)
4299994a338SPaul Mackerras *
4309994a338SPaul Mackerras * wait for the flag to change, indicating this kernel is going away but
4319994a338SPaul Mackerras * the slave code for the next one is at addresses 0 to 100.
4329994a338SPaul Mackerras *
4333d2cea73SMilton Miller * This is used by all slaves, even those that did not find a matching
4343d2cea73SMilton Miller * paca in the secondary startup code.
4359994a338SPaul Mackerras *
4369994a338SPaul Mackerras * Physical (hardware) cpu id should be in r3.
4379994a338SPaul Mackerras */
4389994a338SPaul Mackerras_GLOBAL(kexec_wait)
4399994a338SPaul Mackerras	bl	1f
4409994a338SPaul Mackerras1:	mflr	r5
4419994a338SPaul Mackerras	addi	r5,r5,kexec_flag-1b
4429994a338SPaul Mackerras
4439994a338SPaul Mackerras99:	HMT_LOW
444da665885SThiago Jung Bauermann#ifdef CONFIG_KEXEC_CORE	/* use no memory without kexec */
4459994a338SPaul Mackerras	lwz	r4,0(r5)
4469994a338SPaul Mackerras	cmpwi	0,r4,0
447ffebf5f3SSamuel Mendoza-Jonas	beq	99b
448ffebf5f3SSamuel Mendoza-Jonas#ifdef CONFIG_PPC_BOOK3S_64
449ffebf5f3SSamuel Mendoza-Jonas	li	r10,0x60
450ffebf5f3SSamuel Mendoza-Jonas	mfmsr	r11
451ffebf5f3SSamuel Mendoza-Jonas	clrrdi	r11,r11,1	/* Clear MSR_LE */
452ffebf5f3SSamuel Mendoza-Jonas	mtsrr0	r10
453ffebf5f3SSamuel Mendoza-Jonas	mtsrr1	r11
454ffebf5f3SSamuel Mendoza-Jonas	rfid
455ffebf5f3SSamuel Mendoza-Jonas#else
456ae73e4ccSScott Wood	/* Create TLB entry in book3e_secondary_core_init */
457ae73e4ccSScott Wood	li	r4,0
458ffebf5f3SSamuel Mendoza-Jonas	ba	0x60
4599994a338SPaul Mackerras#endif
460ffebf5f3SSamuel Mendoza-Jonas#endif
4619994a338SPaul Mackerras
4629994a338SPaul Mackerras/* this can be in text because we won't change it until we are
4639994a338SPaul Mackerras * running in real anyways
4649994a338SPaul Mackerras */
4659994a338SPaul Mackerraskexec_flag:
4669994a338SPaul Mackerras	.long	0
4679994a338SPaul Mackerras
4689994a338SPaul Mackerras
469da665885SThiago Jung Bauermann#ifdef CONFIG_KEXEC_CORE
470cf904e30STiejun Chen#ifdef CONFIG_PPC_BOOK3E
471cf904e30STiejun Chen/*
472cf904e30STiejun Chen * BOOK3E has no real MMU mode, so we have to setup the initial TLB
473cf904e30STiejun Chen * for a core to identity map v:0 to p:0.  This current implementation
474cf904e30STiejun Chen * assumes that 1G is enough for kexec.
475cf904e30STiejun Chen */
476cf904e30STiejun Chenkexec_create_tlb:
477cf904e30STiejun Chen	/*
478cf904e30STiejun Chen	 * Invalidate all non-IPROT TLB entries to avoid any TLB conflict.
479cf904e30STiejun Chen	 * IPROT TLB entries should be >= PAGE_OFFSET and thus not conflict.
480cf904e30STiejun Chen	 */
481cf904e30STiejun Chen	PPC_TLBILX_ALL(0,R0)
482cf904e30STiejun Chen	sync
483cf904e30STiejun Chen	isync
484cf904e30STiejun Chen
485cf904e30STiejun Chen	mfspr	r10,SPRN_TLB1CFG
486cf904e30STiejun Chen	andi.	r10,r10,TLBnCFG_N_ENTRY	/* Extract # entries */
487cf904e30STiejun Chen	subi	r10,r10,1	/* Last entry: no conflict with kernel text */
488cf904e30STiejun Chen	lis	r9,MAS0_TLBSEL(1)@h
489cf904e30STiejun Chen	rlwimi	r9,r10,16,4,15		/* Setup MAS0 = TLBSEL | ESEL(r9) */
490cf904e30STiejun Chen
491cf904e30STiejun Chen/* Set up a temp identity mapping v:0 to p:0 and return to it. */
492cf904e30STiejun Chen#if defined(CONFIG_SMP) || defined(CONFIG_PPC_E500MC)
493cf904e30STiejun Chen#define M_IF_NEEDED	MAS2_M
494cf904e30STiejun Chen#else
495cf904e30STiejun Chen#define M_IF_NEEDED	0
496cf904e30STiejun Chen#endif
497cf904e30STiejun Chen	mtspr	SPRN_MAS0,r9
498cf904e30STiejun Chen
499cf904e30STiejun Chen	lis	r9,(MAS1_VALID|MAS1_IPROT)@h
500cf904e30STiejun Chen	ori	r9,r9,(MAS1_TSIZE(BOOK3E_PAGESZ_1GB))@l
501cf904e30STiejun Chen	mtspr	SPRN_MAS1,r9
502cf904e30STiejun Chen
503cf904e30STiejun Chen	LOAD_REG_IMMEDIATE(r9, 0x0 | M_IF_NEEDED)
504cf904e30STiejun Chen	mtspr	SPRN_MAS2,r9
505cf904e30STiejun Chen
506cf904e30STiejun Chen	LOAD_REG_IMMEDIATE(r9, 0x0 | MAS3_SR | MAS3_SW | MAS3_SX)
507cf904e30STiejun Chen	mtspr	SPRN_MAS3,r9
508cf904e30STiejun Chen	li	r9,0
509cf904e30STiejun Chen	mtspr	SPRN_MAS7,r9
510cf904e30STiejun Chen
511cf904e30STiejun Chen	tlbwe
512cf904e30STiejun Chen	isync
513cf904e30STiejun Chen	blr
514cf904e30STiejun Chen#endif
5159994a338SPaul Mackerras
5169994a338SPaul Mackerras/* kexec_smp_wait(void)
5179994a338SPaul Mackerras *
5189994a338SPaul Mackerras * call with interrupts off
5199994a338SPaul Mackerras * note: this is a terminal routine, it does not save lr
5209994a338SPaul Mackerras *
5219994a338SPaul Mackerras * get phys id from paca
5229994a338SPaul Mackerras * switch to real mode
5233d2cea73SMilton Miller * mark the paca as no longer used
5249994a338SPaul Mackerras * join other cpus in kexec_wait(phys_id)
5259994a338SPaul Mackerras */
5269994a338SPaul Mackerras_GLOBAL(kexec_smp_wait)
5279994a338SPaul Mackerras	lhz	r3,PACAHWCPUID(r13)
5289994a338SPaul Mackerras	bl	real_mode
5293d2cea73SMilton Miller
5303d2cea73SMilton Miller	li	r4,KEXEC_STATE_REAL_MODE
5313d2cea73SMilton Miller	stb	r4,PACAKEXECSTATE(r13)
5323d2cea73SMilton Miller	SYNC
5333d2cea73SMilton Miller
534b1576fecSAnton Blanchard	b	kexec_wait
5359994a338SPaul Mackerras
5369994a338SPaul Mackerras/*
5379994a338SPaul Mackerras * switch to real mode (turn mmu off)
5389994a338SPaul Mackerras * we use the early kernel trick that the hardware ignores bits
5399994a338SPaul Mackerras * 0 and 1 (big endian) of the effective address in real mode
5409994a338SPaul Mackerras *
5419994a338SPaul Mackerras * don't overwrite r3 here, it is live for kexec_wait above.
5429994a338SPaul Mackerras */
5439994a338SPaul Mackerrasreal_mode:	/* assume normal blr return */
544cf904e30STiejun Chen#ifdef CONFIG_PPC_BOOK3E
545cf904e30STiejun Chen	/* Create an identity mapping. */
546cf904e30STiejun Chen	b	kexec_create_tlb
547cf904e30STiejun Chen#else
5489994a338SPaul Mackerras1:	li	r9,MSR_RI
5499994a338SPaul Mackerras	li	r10,MSR_DR|MSR_IR
5509994a338SPaul Mackerras	mflr	r11		/* return address to SRR0 */
5519994a338SPaul Mackerras	mfmsr	r12
5529994a338SPaul Mackerras	andc	r9,r12,r9
5539994a338SPaul Mackerras	andc	r10,r12,r10
5549994a338SPaul Mackerras
5559994a338SPaul Mackerras	mtmsrd	r9,1
5569994a338SPaul Mackerras	mtspr	SPRN_SRR1,r10
5579994a338SPaul Mackerras	mtspr	SPRN_SRR0,r11
5589994a338SPaul Mackerras	rfid
559cf904e30STiejun Chen#endif
5609994a338SPaul Mackerras
5619994a338SPaul Mackerras/*
562b970b41eSBenjamin Herrenschmidt * kexec_sequence(newstack, start, image, control, clear_all(),
563b970b41eSBenjamin Herrenschmidt	          copy_with_mmu_off)
5649994a338SPaul Mackerras *
5659994a338SPaul Mackerras * does the grungy work with stack switching and real mode switches
5669994a338SPaul Mackerras * also does simple calls to other code
5679994a338SPaul Mackerras */
5689994a338SPaul Mackerras
5699994a338SPaul Mackerras_GLOBAL(kexec_sequence)
5709994a338SPaul Mackerras	mflr	r0
5719994a338SPaul Mackerras	std	r0,16(r1)
5729994a338SPaul Mackerras
5739994a338SPaul Mackerras	/* switch stacks to newstack -- &kexec_stack.stack */
5744ae2dcb6SKumar Gala	stdu	r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
5759994a338SPaul Mackerras	mr	r1,r3
5769994a338SPaul Mackerras
5779994a338SPaul Mackerras	li	r0,0
5789994a338SPaul Mackerras	std	r0,16(r1)
5799994a338SPaul Mackerras
5801e2a516eSBalbir SinghBEGIN_FTR_SECTION
5811e2a516eSBalbir Singh	/*
5821e2a516eSBalbir Singh	 * This is the best time to turn AMR/IAMR off.
5831e2a516eSBalbir Singh	 * key 0 is used in radix for supervisor<->user
5841e2a516eSBalbir Singh	 * protection, but on hash key 0 is reserved
5851e2a516eSBalbir Singh	 * ideally we want to enter with a clean state.
5861e2a516eSBalbir Singh	 * NOTE, we rely on r0 being 0 from above.
5871e2a516eSBalbir Singh	 */
5881e2a516eSBalbir Singh	mtspr	SPRN_IAMR,r0
5892621e945SMichael EllermanBEGIN_FTR_SECTION_NESTED(42)
5901e2a516eSBalbir Singh	mtspr	SPRN_AMOR,r0
5912621e945SMichael EllermanEND_FTR_SECTION_NESTED_IFSET(CPU_FTR_HVMODE, 42)
5921e2a516eSBalbir SinghEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
5931e2a516eSBalbir Singh
5949994a338SPaul Mackerras	/* save regs for local vars on new stack.
5959994a338SPaul Mackerras	 * yes, we won't go back, but ...
5969994a338SPaul Mackerras	 */
5979994a338SPaul Mackerras	std	r31,-8(r1)
5989994a338SPaul Mackerras	std	r30,-16(r1)
5999994a338SPaul Mackerras	std	r29,-24(r1)
6009994a338SPaul Mackerras	std	r28,-32(r1)
6019994a338SPaul Mackerras	std	r27,-40(r1)
6029994a338SPaul Mackerras	std	r26,-48(r1)
6039994a338SPaul Mackerras	std	r25,-56(r1)
6049994a338SPaul Mackerras
6054ae2dcb6SKumar Gala	stdu	r1,-STACK_FRAME_OVERHEAD-64(r1)
6069994a338SPaul Mackerras
6079994a338SPaul Mackerras	/* save args into preserved regs */
6089994a338SPaul Mackerras	mr	r31,r3			/* newstack (both) */
6099994a338SPaul Mackerras	mr	r30,r4			/* start (real) */
6109994a338SPaul Mackerras	mr	r29,r5			/* image (virt) */
6119994a338SPaul Mackerras	mr	r28,r6			/* control, unused */
6129994a338SPaul Mackerras	mr	r27,r7			/* clear_all() fn desc */
613b970b41eSBenjamin Herrenschmidt	mr	r26,r8			/* copy_with_mmu_off */
6149994a338SPaul Mackerras	lhz	r25,PACAHWCPUID(r13)	/* get our phys cpu from paca */
6159994a338SPaul Mackerras
6169994a338SPaul Mackerras	/* disable interrupts, we are overwriting kernel data next */
61796eea642STiejun Chen#ifdef CONFIG_PPC_BOOK3E
61896eea642STiejun Chen	wrteei	0
61996eea642STiejun Chen#else
6209994a338SPaul Mackerras	mfmsr	r3
6219994a338SPaul Mackerras	rlwinm	r3,r3,0,17,15
6229994a338SPaul Mackerras	mtmsrd	r3,1
62396eea642STiejun Chen#endif
6249994a338SPaul Mackerras
625b970b41eSBenjamin Herrenschmidt	/* We need to turn the MMU off unless we are in hash mode
626b970b41eSBenjamin Herrenschmidt	 * under a hypervisor
627b970b41eSBenjamin Herrenschmidt	 */
628b970b41eSBenjamin Herrenschmidt	cmpdi	r26,0
629b970b41eSBenjamin Herrenschmidt	beq	1f
630b970b41eSBenjamin Herrenschmidt	bl	real_mode
631b970b41eSBenjamin Herrenschmidt1:
6329994a338SPaul Mackerras	/* copy dest pages, flush whole dest image */
6339994a338SPaul Mackerras	mr	r3,r29
634b1576fecSAnton Blanchard	bl	kexec_copy_flush	/* (image) */
6359994a338SPaul Mackerras
636b970b41eSBenjamin Herrenschmidt	/* turn off mmu now if not done earlier */
637b970b41eSBenjamin Herrenschmidt	cmpdi	r26,0
638b970b41eSBenjamin Herrenschmidt	bne	1f
6399994a338SPaul Mackerras	bl	real_mode
6409994a338SPaul Mackerras
641ee46a90bSMilton Miller	/* copy  0x100 bytes starting at start to 0 */
642b970b41eSBenjamin Herrenschmidt1:	li	r3,0
643ee46a90bSMilton Miller	mr	r4,r30		/* start, aka phys mem offset */
644ee46a90bSMilton Miller	li	r5,0x100
645ee46a90bSMilton Miller	li	r6,0
646b1576fecSAnton Blanchard	bl	copy_and_flush	/* (dest, src, copy limit, start offset) */
647ee46a90bSMilton Miller1:	/* assume normal blr return */
648ee46a90bSMilton Miller
649ee46a90bSMilton Miller	/* release other cpus to the new kernel secondary start at 0x60 */
650ee46a90bSMilton Miller	mflr	r5
651ee46a90bSMilton Miller	li	r6,1
652ee46a90bSMilton Miller	stw	r6,kexec_flag-1b(5)
653ee46a90bSMilton Miller
654fc48bad5SBenjamin Herrenschmidt	cmpdi	r27,0
655fc48bad5SBenjamin Herrenschmidt	beq	1f
656fc48bad5SBenjamin Herrenschmidt
6579994a338SPaul Mackerras	/* clear out hardware hash page table and tlb */
658f55d9665SMichael Ellerman#ifdef PPC64_ELF_ABI_v1
659cc7efbf9SAnton Blanchard	ld	r12,0(r27)		/* deref function descriptor */
660cc7efbf9SAnton Blanchard#else
661cc7efbf9SAnton Blanchard	mr	r12,r27
662cc7efbf9SAnton Blanchard#endif
663cc7efbf9SAnton Blanchard	mtctr	r12
6647025776eSBenjamin Herrenschmidt	bctrl				/* mmu_hash_ops.hpte_clear_all(void); */
6659994a338SPaul Mackerras
6669994a338SPaul Mackerras/*
6679994a338SPaul Mackerras *   kexec image calling is:
6689994a338SPaul Mackerras *      the first 0x100 bytes of the entry point are copied to 0
6699994a338SPaul Mackerras *
6709994a338SPaul Mackerras *      all slaves branch to slave = 0x60 (absolute)
6719994a338SPaul Mackerras *              slave(phys_cpu_id);
6729994a338SPaul Mackerras *
6739994a338SPaul Mackerras *      master goes to start = entry point
6749994a338SPaul Mackerras *              start(phys_cpu_id, start, 0);
6759994a338SPaul Mackerras *
6769994a338SPaul Mackerras *
6779994a338SPaul Mackerras *   a wrapper is needed to call existing kernels, here is an approximate
6789994a338SPaul Mackerras *   description of one method:
6799994a338SPaul Mackerras *
6809994a338SPaul Mackerras * v2: (2.6.10)
6819994a338SPaul Mackerras *   start will be near the boot_block (maybe 0x100 bytes before it?)
6829994a338SPaul Mackerras *   it will have a 0x60, which will b to boot_block, where it will wait
6839994a338SPaul Mackerras *   and 0 will store phys into struct boot-block and load r3 from there,
6849994a338SPaul Mackerras *   copy kernel 0-0x100 and tell slaves to back down to 0x60 again
6859994a338SPaul Mackerras *
6869994a338SPaul Mackerras * v1: (2.6.9)
6879994a338SPaul Mackerras *    boot block will have all cpus scanning device tree to see if they
6889994a338SPaul Mackerras *    are the boot cpu ?????
6899994a338SPaul Mackerras *    other device tree differences (prop sizes, va vs pa, etc)...
6909994a338SPaul Mackerras */
691fc48bad5SBenjamin Herrenschmidt1:	mr	r3,r25	# my phys cpu
6929994a338SPaul Mackerras	mr	r4,r30	# start, aka phys mem offset
6939994a338SPaul Mackerras	mtlr	4
6949994a338SPaul Mackerras	li	r5,0
6951767c8f3SMilton Miller	blr	/* image->start(physid, image->start, 0); */
696da665885SThiago Jung Bauermann#endif /* CONFIG_KEXEC_CORE */
697