xref: /openbmc/linux/arch/powerpc/kernel/misc_64.S (revision 8054df0570588e22007a8be6fa7615462389f27f)
12874c5fdSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-or-later */
29994a338SPaul Mackerras/*
39994a338SPaul Mackerras * This file contains miscellaneous low-level functions.
49994a338SPaul Mackerras *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
59994a338SPaul Mackerras *
69994a338SPaul Mackerras * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
79994a338SPaul Mackerras * and Paul Mackerras.
89994a338SPaul Mackerras * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
99994a338SPaul Mackerras * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
109994a338SPaul Mackerras */
119994a338SPaul Mackerras
129994a338SPaul Mackerras#include <linux/sys.h>
139994a338SPaul Mackerras#include <asm/unistd.h>
149994a338SPaul Mackerras#include <asm/errno.h>
159994a338SPaul Mackerras#include <asm/processor.h>
169994a338SPaul Mackerras#include <asm/page.h>
179994a338SPaul Mackerras#include <asm/cache.h>
189994a338SPaul Mackerras#include <asm/ppc_asm.h>
199994a338SPaul Mackerras#include <asm/asm-offsets.h>
209994a338SPaul Mackerras#include <asm/cputable.h>
216cb7bfebSDavid Gibson#include <asm/thread_info.h>
221fc711f7SMichael Neuling#include <asm/kexec.h>
2346f52210SStephen Rothwell#include <asm/ptrace.h>
24cf904e30STiejun Chen#include <asm/mmu.h>
259445aa1aSAl Viro#include <asm/export.h>
262c86cd18SChristophe Leroy#include <asm/feature-fixups.h>
279994a338SPaul Mackerras
289994a338SPaul Mackerras	.text
299994a338SPaul Mackerras
309994a338SPaul Mackerras_GLOBAL(call_do_softirq)
319994a338SPaul Mackerras	mflr	r0
329994a338SPaul Mackerras	std	r0,16(r1)
334ae2dcb6SKumar Gala	stdu	r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
349994a338SPaul Mackerras	mr	r1,r3
35b1576fecSAnton Blanchard	bl	__do_softirq
369994a338SPaul Mackerras	ld	r1,0(r1)
379994a338SPaul Mackerras	ld	r0,16(r1)
389994a338SPaul Mackerras	mtlr	r0
399994a338SPaul Mackerras	blr
409994a338SPaul Mackerras
410366a1c7SBenjamin Herrenschmidt_GLOBAL(call_do_irq)
429994a338SPaul Mackerras	mflr	r0
439994a338SPaul Mackerras	std	r0,16(r1)
440366a1c7SBenjamin Herrenschmidt	stdu	r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r4)
450366a1c7SBenjamin Herrenschmidt	mr	r1,r4
46b1576fecSAnton Blanchard	bl	__do_irq
479994a338SPaul Mackerras	ld	r1,0(r1)
489994a338SPaul Mackerras	ld	r0,16(r1)
499994a338SPaul Mackerras	mtlr	r0
509994a338SPaul Mackerras	blr
519994a338SPaul Mackerras
529994a338SPaul Mackerras	.section	".toc","aw"
539994a338SPaul MackerrasPPC64_CACHES:
549994a338SPaul Mackerras	.tc		ppc64_caches[TC],ppc64_caches
559994a338SPaul Mackerras	.section	".text"
569994a338SPaul Mackerras
579994a338SPaul Mackerras/*
589994a338SPaul Mackerras * Write any modified data cache blocks out to memory
599994a338SPaul Mackerras * and invalidate the corresponding instruction cache blocks.
609994a338SPaul Mackerras *
619994a338SPaul Mackerras * flush_icache_range(unsigned long start, unsigned long stop)
629994a338SPaul Mackerras *
639994a338SPaul Mackerras *   flush all bytes from start through stop-1 inclusive
649994a338SPaul Mackerras */
659994a338SPaul Mackerras
668f5f525dSOliver O'Halloran_GLOBAL_TOC(flush_icache_range)
67abb29c3bSKevin HaoBEGIN_FTR_SECTION
680ce63670SKevin Hao	PURGE_PREFETCHED_INS
69abb29c3bSKevin Hao	blr
70abb29c3bSKevin HaoEND_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
719994a338SPaul Mackerras/*
729994a338SPaul Mackerras * Flush the data cache to memory
739994a338SPaul Mackerras *
749994a338SPaul Mackerras * Different systems have different cache line sizes
759994a338SPaul Mackerras * and in some cases i-cache and d-cache line sizes differ from
769994a338SPaul Mackerras * each other.
779994a338SPaul Mackerras */
789994a338SPaul Mackerras 	ld	r10,PPC64_CACHES@toc(r2)
79bd067f83SBenjamin Herrenschmidt	lwz	r7,DCACHEL1BLOCKSIZE(r10)/* Get cache block size */
809994a338SPaul Mackerras	addi	r5,r7,-1
819994a338SPaul Mackerras	andc	r6,r3,r5		/* round low to line bdy */
829994a338SPaul Mackerras	subf	r8,r6,r4		/* compute length */
839994a338SPaul Mackerras	add	r8,r8,r5		/* ensure we get enough */
84bd067f83SBenjamin Herrenschmidt	lwz	r9,DCACHEL1LOGBLOCKSIZE(r10)	/* Get log-2 of cache block size */
859994a338SPaul Mackerras	srw.	r8,r8,r9		/* compute line count */
869994a338SPaul Mackerras	beqlr				/* nothing to do? */
879994a338SPaul Mackerras	mtctr	r8
889994a338SPaul Mackerras1:	dcbst	0,r6
899994a338SPaul Mackerras	add	r6,r6,r7
909994a338SPaul Mackerras	bdnz	1b
919994a338SPaul Mackerras	sync
929994a338SPaul Mackerras
939994a338SPaul Mackerras/* Now invalidate the instruction cache */
949994a338SPaul Mackerras
95bd067f83SBenjamin Herrenschmidt	lwz	r7,ICACHEL1BLOCKSIZE(r10)	/* Get Icache block size */
969994a338SPaul Mackerras	addi	r5,r7,-1
979994a338SPaul Mackerras	andc	r6,r3,r5		/* round low to line bdy */
989994a338SPaul Mackerras	subf	r8,r6,r4		/* compute length */
999994a338SPaul Mackerras	add	r8,r8,r5
100bd067f83SBenjamin Herrenschmidt	lwz	r9,ICACHEL1LOGBLOCKSIZE(r10)	/* Get log-2 of Icache block size */
1019994a338SPaul Mackerras	srw.	r8,r8,r9		/* compute line count */
1029994a338SPaul Mackerras	beqlr				/* nothing to do? */
1039994a338SPaul Mackerras	mtctr	r8
1049994a338SPaul Mackerras2:	icbi	0,r6
1059994a338SPaul Mackerras	add	r6,r6,r7
1069994a338SPaul Mackerras	bdnz	2b
1079994a338SPaul Mackerras	isync
1089994a338SPaul Mackerras	blr
1096f698df1SNicholas Piggin_ASM_NOKPROBE_SYMBOL(flush_icache_range)
1109445aa1aSAl ViroEXPORT_SYMBOL(flush_icache_range)
1116f698df1SNicholas Piggin
1129994a338SPaul Mackerras/*
1139994a338SPaul Mackerras * Flush a particular page from the data cache to RAM.
1149994a338SPaul Mackerras * Note: this is necessary because the instruction cache does *not*
1159994a338SPaul Mackerras * snoop from the data cache.
1169994a338SPaul Mackerras *
1179994a338SPaul Mackerras *	void __flush_dcache_icache(void *page)
1189994a338SPaul Mackerras */
1199994a338SPaul Mackerras_GLOBAL(__flush_dcache_icache)
1209994a338SPaul Mackerras/*
1219994a338SPaul Mackerras * Flush the data cache to memory
1229994a338SPaul Mackerras *
1239994a338SPaul Mackerras * Different systems have different cache line sizes
1249994a338SPaul Mackerras */
1259994a338SPaul Mackerras
1260ce63670SKevin HaoBEGIN_FTR_SECTION
1270ce63670SKevin Hao	PURGE_PREFETCHED_INS
1280ce63670SKevin Hao	blr
1290ce63670SKevin HaoEND_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
1300ce63670SKevin Hao
1319994a338SPaul Mackerras/* Flush the dcache */
1329994a338SPaul Mackerras 	ld	r7,PPC64_CACHES@toc(r2)
1339994a338SPaul Mackerras	clrrdi	r3,r3,PAGE_SHIFT           	    /* Page align */
134bd067f83SBenjamin Herrenschmidt	lwz	r4,DCACHEL1BLOCKSPERPAGE(r7)	/* Get # dcache blocks per page */
135bd067f83SBenjamin Herrenschmidt	lwz	r5,DCACHEL1BLOCKSIZE(r7)	/* Get dcache block size */
1369994a338SPaul Mackerras	mr	r6,r3
1379994a338SPaul Mackerras	mtctr	r4
1389994a338SPaul Mackerras0:	dcbst	0,r6
1399994a338SPaul Mackerras	add	r6,r6,r5
1409994a338SPaul Mackerras	bdnz	0b
1419994a338SPaul Mackerras	sync
1429994a338SPaul Mackerras
1439994a338SPaul Mackerras/* Now invalidate the icache */
1449994a338SPaul Mackerras
145bd067f83SBenjamin Herrenschmidt	lwz	r4,ICACHEL1BLOCKSPERPAGE(r7)	/* Get # icache blocks per page */
146bd067f83SBenjamin Herrenschmidt	lwz	r5,ICACHEL1BLOCKSIZE(r7)	/* Get icache block size */
1479994a338SPaul Mackerras	mtctr	r4
1489994a338SPaul Mackerras1:	icbi	0,r3
1499994a338SPaul Mackerras	add	r3,r3,r5
1509994a338SPaul Mackerras	bdnz	1b
1519994a338SPaul Mackerras	isync
1529994a338SPaul Mackerras	blr
1539994a338SPaul Mackerras
154ca9d7aeaSDavid Woodhouse_GLOBAL(__bswapdi2)
1559445aa1aSAl ViroEXPORT_SYMBOL(__bswapdi2)
156ca9d7aeaSDavid Woodhouse	srdi	r8,r3,32
157ca9d7aeaSDavid Woodhouse	rlwinm	r7,r3,8,0xffffffff
158ca9d7aeaSDavid Woodhouse	rlwimi	r7,r3,24,0,7
159ca9d7aeaSDavid Woodhouse	rlwinm	r9,r8,8,0xffffffff
160ca9d7aeaSDavid Woodhouse	rlwimi	r7,r3,24,16,23
161ca9d7aeaSDavid Woodhouse	rlwimi	r9,r8,24,0,7
162ca9d7aeaSDavid Woodhouse	rlwimi	r9,r8,24,16,23
163ca9d7aeaSDavid Woodhouse	sldi	r7,r7,32
164ca9d7aeaSDavid Woodhouse	or	r3,r7,r9
165ca9d7aeaSDavid Woodhouse	blr
1663f639ee8SStephen Rothwell
1677191b615SBenjamin Herrenschmidt
1682d6f0c3aSMichael Ellerman#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
1697191b615SBenjamin Herrenschmidt_GLOBAL(rmci_on)
1707191b615SBenjamin Herrenschmidt	sync
1717191b615SBenjamin Herrenschmidt	isync
1727191b615SBenjamin Herrenschmidt	li	r3,0x100
1737191b615SBenjamin Herrenschmidt	rldicl	r3,r3,32,0
1747191b615SBenjamin Herrenschmidt	mfspr	r5,SPRN_HID4
1757191b615SBenjamin Herrenschmidt	or	r5,r5,r3
1767191b615SBenjamin Herrenschmidt	sync
1777191b615SBenjamin Herrenschmidt	mtspr	SPRN_HID4,r5
1787191b615SBenjamin Herrenschmidt	isync
1797191b615SBenjamin Herrenschmidt	slbia
1807191b615SBenjamin Herrenschmidt	isync
1817191b615SBenjamin Herrenschmidt	sync
1827191b615SBenjamin Herrenschmidt	blr
1837191b615SBenjamin Herrenschmidt
1847191b615SBenjamin Herrenschmidt_GLOBAL(rmci_off)
1857191b615SBenjamin Herrenschmidt	sync
1867191b615SBenjamin Herrenschmidt	isync
1877191b615SBenjamin Herrenschmidt	li	r3,0x100
1887191b615SBenjamin Herrenschmidt	rldicl	r3,r3,32,0
1897191b615SBenjamin Herrenschmidt	mfspr	r5,SPRN_HID4
1907191b615SBenjamin Herrenschmidt	andc	r5,r5,r3
1917191b615SBenjamin Herrenschmidt	sync
1927191b615SBenjamin Herrenschmidt	mtspr	SPRN_HID4,r5
1937191b615SBenjamin Herrenschmidt	isync
1947191b615SBenjamin Herrenschmidt	slbia
1957191b615SBenjamin Herrenschmidt	isync
1967191b615SBenjamin Herrenschmidt	sync
1977191b615SBenjamin Herrenschmidt	blr
1982d6f0c3aSMichael Ellerman#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
1992d6f0c3aSMichael Ellerman
2002d6f0c3aSMichael Ellerman#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
2017191b615SBenjamin Herrenschmidt
2029994a338SPaul Mackerras/*
2039994a338SPaul Mackerras * Do an IO access in real mode
2049994a338SPaul Mackerras */
2059994a338SPaul Mackerras_GLOBAL(real_readb)
2069994a338SPaul Mackerras	mfmsr	r7
2079994a338SPaul Mackerras	ori	r0,r7,MSR_DR
2089994a338SPaul Mackerras	xori	r0,r0,MSR_DR
2099994a338SPaul Mackerras	sync
2109994a338SPaul Mackerras	mtmsrd	r0
2119994a338SPaul Mackerras	sync
2129994a338SPaul Mackerras	isync
2139994a338SPaul Mackerras	mfspr	r6,SPRN_HID4
2149994a338SPaul Mackerras	rldicl	r5,r6,32,0
2159994a338SPaul Mackerras	ori	r5,r5,0x100
2169994a338SPaul Mackerras	rldicl	r5,r5,32,0
2179994a338SPaul Mackerras	sync
2189994a338SPaul Mackerras	mtspr	SPRN_HID4,r5
2199994a338SPaul Mackerras	isync
2209994a338SPaul Mackerras	slbia
2219994a338SPaul Mackerras	isync
2229994a338SPaul Mackerras	lbz	r3,0(r3)
2239994a338SPaul Mackerras	sync
2249994a338SPaul Mackerras	mtspr	SPRN_HID4,r6
2259994a338SPaul Mackerras	isync
2269994a338SPaul Mackerras	slbia
2279994a338SPaul Mackerras	isync
2289994a338SPaul Mackerras	mtmsrd	r7
2299994a338SPaul Mackerras	sync
2309994a338SPaul Mackerras	isync
2319994a338SPaul Mackerras	blr
2329994a338SPaul Mackerras
2339994a338SPaul Mackerras	/*
2349994a338SPaul Mackerras * Do an IO access in real mode
2359994a338SPaul Mackerras */
2369994a338SPaul Mackerras_GLOBAL(real_writeb)
2379994a338SPaul Mackerras	mfmsr	r7
2389994a338SPaul Mackerras	ori	r0,r7,MSR_DR
2399994a338SPaul Mackerras	xori	r0,r0,MSR_DR
2409994a338SPaul Mackerras	sync
2419994a338SPaul Mackerras	mtmsrd	r0
2429994a338SPaul Mackerras	sync
2439994a338SPaul Mackerras	isync
2449994a338SPaul Mackerras	mfspr	r6,SPRN_HID4
2459994a338SPaul Mackerras	rldicl	r5,r6,32,0
2469994a338SPaul Mackerras	ori	r5,r5,0x100
2479994a338SPaul Mackerras	rldicl	r5,r5,32,0
2489994a338SPaul Mackerras	sync
2499994a338SPaul Mackerras	mtspr	SPRN_HID4,r5
2509994a338SPaul Mackerras	isync
2519994a338SPaul Mackerras	slbia
2529994a338SPaul Mackerras	isync
2539994a338SPaul Mackerras	stb	r3,0(r4)
2549994a338SPaul Mackerras	sync
2559994a338SPaul Mackerras	mtspr	SPRN_HID4,r6
2569994a338SPaul Mackerras	isync
2579994a338SPaul Mackerras	slbia
2589994a338SPaul Mackerras	isync
2599994a338SPaul Mackerras	mtmsrd	r7
2609994a338SPaul Mackerras	sync
2619994a338SPaul Mackerras	isync
2629994a338SPaul Mackerras	blr
2639994a338SPaul Mackerras#endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */
2649994a338SPaul Mackerras
26539c870d5SOlof Johansson#ifdef CONFIG_PPC_PASEMI
26639c870d5SOlof Johansson
26739c870d5SOlof Johansson_GLOBAL(real_205_readb)
26839c870d5SOlof Johansson	mfmsr	r7
26939c870d5SOlof Johansson	ori	r0,r7,MSR_DR
27039c870d5SOlof Johansson	xori	r0,r0,MSR_DR
27139c870d5SOlof Johansson	sync
27239c870d5SOlof Johansson	mtmsrd	r0
27339c870d5SOlof Johansson	sync
27439c870d5SOlof Johansson	isync
275e55174e9SMichael Neuling	LBZCIX(R3,R0,R3)
27639c870d5SOlof Johansson	isync
27739c870d5SOlof Johansson	mtmsrd	r7
27839c870d5SOlof Johansson	sync
27939c870d5SOlof Johansson	isync
28039c870d5SOlof Johansson	blr
28139c870d5SOlof Johansson
28239c870d5SOlof Johansson_GLOBAL(real_205_writeb)
28339c870d5SOlof Johansson	mfmsr	r7
28439c870d5SOlof Johansson	ori	r0,r7,MSR_DR
28539c870d5SOlof Johansson	xori	r0,r0,MSR_DR
28639c870d5SOlof Johansson	sync
28739c870d5SOlof Johansson	mtmsrd	r0
28839c870d5SOlof Johansson	sync
28939c870d5SOlof Johansson	isync
290e55174e9SMichael Neuling	STBCIX(R3,R0,R4)
29139c870d5SOlof Johansson	isync
29239c870d5SOlof Johansson	mtmsrd	r7
29339c870d5SOlof Johansson	sync
29439c870d5SOlof Johansson	isync
29539c870d5SOlof Johansson	blr
29639c870d5SOlof Johansson
29739c870d5SOlof Johansson#endif /* CONFIG_PPC_PASEMI */
29839c870d5SOlof Johansson
29939c870d5SOlof Johansson
300e48f7eb2SDmitry Eremin-Solenikov#if defined(CONFIG_CPU_FREQ_PMAC64) || defined(CONFIG_CPU_FREQ_MAPLE)
3019994a338SPaul Mackerras/*
3024350147aSBenjamin Herrenschmidt * SCOM access functions for 970 (FX only for now)
3034350147aSBenjamin Herrenschmidt *
3044350147aSBenjamin Herrenschmidt * unsigned long scom970_read(unsigned int address);
3054350147aSBenjamin Herrenschmidt * void scom970_write(unsigned int address, unsigned long value);
3064350147aSBenjamin Herrenschmidt *
3074350147aSBenjamin Herrenschmidt * The address passed in is the 24 bits register address. This code
3084350147aSBenjamin Herrenschmidt * is 970 specific and will not check the status bits, so you should
3094350147aSBenjamin Herrenschmidt * know what you are doing.
3104350147aSBenjamin Herrenschmidt */
3114350147aSBenjamin Herrenschmidt_GLOBAL(scom970_read)
3124350147aSBenjamin Herrenschmidt	/* interrupts off */
3134350147aSBenjamin Herrenschmidt	mfmsr	r4
3144350147aSBenjamin Herrenschmidt	ori	r0,r4,MSR_EE
3154350147aSBenjamin Herrenschmidt	xori	r0,r0,MSR_EE
3164350147aSBenjamin Herrenschmidt	mtmsrd	r0,1
3174350147aSBenjamin Herrenschmidt
3184350147aSBenjamin Herrenschmidt	/* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits
3194350147aSBenjamin Herrenschmidt	 * (including parity). On current CPUs they must be 0'd,
3204350147aSBenjamin Herrenschmidt	 * and finally or in RW bit
3214350147aSBenjamin Herrenschmidt	 */
3224350147aSBenjamin Herrenschmidt	rlwinm	r3,r3,8,0,15
3234350147aSBenjamin Herrenschmidt	ori	r3,r3,0x8000
3244350147aSBenjamin Herrenschmidt
3254350147aSBenjamin Herrenschmidt	/* do the actual scom read */
3264350147aSBenjamin Herrenschmidt	sync
3274350147aSBenjamin Herrenschmidt	mtspr	SPRN_SCOMC,r3
3284350147aSBenjamin Herrenschmidt	isync
3294350147aSBenjamin Herrenschmidt	mfspr	r3,SPRN_SCOMD
3304350147aSBenjamin Herrenschmidt	isync
3314350147aSBenjamin Herrenschmidt	mfspr	r0,SPRN_SCOMC
3324350147aSBenjamin Herrenschmidt	isync
3334350147aSBenjamin Herrenschmidt
3344350147aSBenjamin Herrenschmidt	/* XXX:	fixup result on some buggy 970's (ouch ! we lost a bit, bah
3354350147aSBenjamin Herrenschmidt	 * that's the best we can do). Not implemented yet as we don't use
3364350147aSBenjamin Herrenschmidt	 * the scom on any of the bogus CPUs yet, but may have to be done
3374350147aSBenjamin Herrenschmidt	 * ultimately
3384350147aSBenjamin Herrenschmidt	 */
3394350147aSBenjamin Herrenschmidt
3404350147aSBenjamin Herrenschmidt	/* restore interrupts */
3414350147aSBenjamin Herrenschmidt	mtmsrd	r4,1
3424350147aSBenjamin Herrenschmidt	blr
3434350147aSBenjamin Herrenschmidt
3444350147aSBenjamin Herrenschmidt
3454350147aSBenjamin Herrenschmidt_GLOBAL(scom970_write)
3464350147aSBenjamin Herrenschmidt	/* interrupts off */
3474350147aSBenjamin Herrenschmidt	mfmsr	r5
3484350147aSBenjamin Herrenschmidt	ori	r0,r5,MSR_EE
3494350147aSBenjamin Herrenschmidt	xori	r0,r0,MSR_EE
3504350147aSBenjamin Herrenschmidt	mtmsrd	r0,1
3514350147aSBenjamin Herrenschmidt
3524350147aSBenjamin Herrenschmidt	/* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits
3534350147aSBenjamin Herrenschmidt	 * (including parity). On current CPUs they must be 0'd.
3544350147aSBenjamin Herrenschmidt	 */
3554350147aSBenjamin Herrenschmidt
3564350147aSBenjamin Herrenschmidt	rlwinm	r3,r3,8,0,15
3574350147aSBenjamin Herrenschmidt
3584350147aSBenjamin Herrenschmidt	sync
3594350147aSBenjamin Herrenschmidt	mtspr	SPRN_SCOMD,r4      /* write data */
3604350147aSBenjamin Herrenschmidt	isync
3614350147aSBenjamin Herrenschmidt	mtspr	SPRN_SCOMC,r3      /* write command */
3624350147aSBenjamin Herrenschmidt	isync
3634350147aSBenjamin Herrenschmidt	mfspr	3,SPRN_SCOMC
3644350147aSBenjamin Herrenschmidt	isync
3654350147aSBenjamin Herrenschmidt
3664350147aSBenjamin Herrenschmidt	/* restore interrupts */
3674350147aSBenjamin Herrenschmidt	mtmsrd	r5,1
3684350147aSBenjamin Herrenschmidt	blr
369e48f7eb2SDmitry Eremin-Solenikov#endif /* CONFIG_CPU_FREQ_PMAC64 || CONFIG_CPU_FREQ_MAPLE */
3704350147aSBenjamin Herrenschmidt
3719994a338SPaul Mackerras/* kexec_wait(phys_cpu)
3729994a338SPaul Mackerras *
3739994a338SPaul Mackerras * wait for the flag to change, indicating this kernel is going away but
3749994a338SPaul Mackerras * the slave code for the next one is at addresses 0 to 100.
3759994a338SPaul Mackerras *
3763d2cea73SMilton Miller * This is used by all slaves, even those that did not find a matching
3773d2cea73SMilton Miller * paca in the secondary startup code.
3789994a338SPaul Mackerras *
3799994a338SPaul Mackerras * Physical (hardware) cpu id should be in r3.
3809994a338SPaul Mackerras */
3819994a338SPaul Mackerras_GLOBAL(kexec_wait)
3829994a338SPaul Mackerras	bl	1f
3839994a338SPaul Mackerras1:	mflr	r5
3849994a338SPaul Mackerras	addi	r5,r5,kexec_flag-1b
3859994a338SPaul Mackerras
3869994a338SPaul Mackerras99:	HMT_LOW
387da665885SThiago Jung Bauermann#ifdef CONFIG_KEXEC_CORE	/* use no memory without kexec */
3889994a338SPaul Mackerras	lwz	r4,0(r5)
3899994a338SPaul Mackerras	cmpwi	0,r4,0
390ffebf5f3SSamuel Mendoza-Jonas	beq	99b
391ffebf5f3SSamuel Mendoza-Jonas#ifdef CONFIG_PPC_BOOK3S_64
392ffebf5f3SSamuel Mendoza-Jonas	li	r10,0x60
393ffebf5f3SSamuel Mendoza-Jonas	mfmsr	r11
394ffebf5f3SSamuel Mendoza-Jonas	clrrdi	r11,r11,1	/* Clear MSR_LE */
395ffebf5f3SSamuel Mendoza-Jonas	mtsrr0	r10
396ffebf5f3SSamuel Mendoza-Jonas	mtsrr1	r11
397ffebf5f3SSamuel Mendoza-Jonas	rfid
398ffebf5f3SSamuel Mendoza-Jonas#else
399ae73e4ccSScott Wood	/* Create TLB entry in book3e_secondary_core_init */
400ae73e4ccSScott Wood	li	r4,0
401ffebf5f3SSamuel Mendoza-Jonas	ba	0x60
4029994a338SPaul Mackerras#endif
403ffebf5f3SSamuel Mendoza-Jonas#endif
4049994a338SPaul Mackerras
4059994a338SPaul Mackerras/* this can be in text because we won't change it until we are
4069994a338SPaul Mackerras * running in real anyways
4079994a338SPaul Mackerras */
4089994a338SPaul Mackerraskexec_flag:
4099994a338SPaul Mackerras	.long	0
4109994a338SPaul Mackerras
4119994a338SPaul Mackerras
412da665885SThiago Jung Bauermann#ifdef CONFIG_KEXEC_CORE
413cf904e30STiejun Chen#ifdef CONFIG_PPC_BOOK3E
414cf904e30STiejun Chen/*
415cf904e30STiejun Chen * BOOK3E has no real MMU mode, so we have to setup the initial TLB
416cf904e30STiejun Chen * for a core to identity map v:0 to p:0.  This current implementation
417cf904e30STiejun Chen * assumes that 1G is enough for kexec.
418cf904e30STiejun Chen */
419cf904e30STiejun Chenkexec_create_tlb:
420cf904e30STiejun Chen	/*
421cf904e30STiejun Chen	 * Invalidate all non-IPROT TLB entries to avoid any TLB conflict.
422cf904e30STiejun Chen	 * IPROT TLB entries should be >= PAGE_OFFSET and thus not conflict.
423cf904e30STiejun Chen	 */
424cf904e30STiejun Chen	PPC_TLBILX_ALL(0,R0)
425cf904e30STiejun Chen	sync
426cf904e30STiejun Chen	isync
427cf904e30STiejun Chen
428cf904e30STiejun Chen	mfspr	r10,SPRN_TLB1CFG
429cf904e30STiejun Chen	andi.	r10,r10,TLBnCFG_N_ENTRY	/* Extract # entries */
430cf904e30STiejun Chen	subi	r10,r10,1	/* Last entry: no conflict with kernel text */
431cf904e30STiejun Chen	lis	r9,MAS0_TLBSEL(1)@h
432cf904e30STiejun Chen	rlwimi	r9,r10,16,4,15		/* Setup MAS0 = TLBSEL | ESEL(r9) */
433cf904e30STiejun Chen
434cf904e30STiejun Chen/* Set up a temp identity mapping v:0 to p:0 and return to it. */
435cf904e30STiejun Chen	mtspr	SPRN_MAS0,r9
436cf904e30STiejun Chen
437cf904e30STiejun Chen	lis	r9,(MAS1_VALID|MAS1_IPROT)@h
438cf904e30STiejun Chen	ori	r9,r9,(MAS1_TSIZE(BOOK3E_PAGESZ_1GB))@l
439cf904e30STiejun Chen	mtspr	SPRN_MAS1,r9
440cf904e30STiejun Chen
441*8054df05SJason Yan	LOAD_REG_IMMEDIATE(r9, 0x0 | MAS2_M_IF_NEEDED)
442cf904e30STiejun Chen	mtspr	SPRN_MAS2,r9
443cf904e30STiejun Chen
444cf904e30STiejun Chen	LOAD_REG_IMMEDIATE(r9, 0x0 | MAS3_SR | MAS3_SW | MAS3_SX)
445cf904e30STiejun Chen	mtspr	SPRN_MAS3,r9
446cf904e30STiejun Chen	li	r9,0
447cf904e30STiejun Chen	mtspr	SPRN_MAS7,r9
448cf904e30STiejun Chen
449cf904e30STiejun Chen	tlbwe
450cf904e30STiejun Chen	isync
451cf904e30STiejun Chen	blr
452cf904e30STiejun Chen#endif
4539994a338SPaul Mackerras
4549994a338SPaul Mackerras/* kexec_smp_wait(void)
4559994a338SPaul Mackerras *
4569994a338SPaul Mackerras * call with interrupts off
4579994a338SPaul Mackerras * note: this is a terminal routine, it does not save lr
4589994a338SPaul Mackerras *
4599994a338SPaul Mackerras * get phys id from paca
4609994a338SPaul Mackerras * switch to real mode
4613d2cea73SMilton Miller * mark the paca as no longer used
4629994a338SPaul Mackerras * join other cpus in kexec_wait(phys_id)
4639994a338SPaul Mackerras */
4649994a338SPaul Mackerras_GLOBAL(kexec_smp_wait)
4659994a338SPaul Mackerras	lhz	r3,PACAHWCPUID(r13)
4669994a338SPaul Mackerras	bl	real_mode
4673d2cea73SMilton Miller
4683d2cea73SMilton Miller	li	r4,KEXEC_STATE_REAL_MODE
4693d2cea73SMilton Miller	stb	r4,PACAKEXECSTATE(r13)
4703d2cea73SMilton Miller	SYNC
4713d2cea73SMilton Miller
472b1576fecSAnton Blanchard	b	kexec_wait
4739994a338SPaul Mackerras
4749994a338SPaul Mackerras/*
4759994a338SPaul Mackerras * switch to real mode (turn mmu off)
4769994a338SPaul Mackerras * we use the early kernel trick that the hardware ignores bits
4779994a338SPaul Mackerras * 0 and 1 (big endian) of the effective address in real mode
4789994a338SPaul Mackerras *
4799994a338SPaul Mackerras * don't overwrite r3 here, it is live for kexec_wait above.
4809994a338SPaul Mackerras */
4819994a338SPaul Mackerrasreal_mode:	/* assume normal blr return */
482cf904e30STiejun Chen#ifdef CONFIG_PPC_BOOK3E
483cf904e30STiejun Chen	/* Create an identity mapping. */
484cf904e30STiejun Chen	b	kexec_create_tlb
485cf904e30STiejun Chen#else
4869994a338SPaul Mackerras1:	li	r9,MSR_RI
4879994a338SPaul Mackerras	li	r10,MSR_DR|MSR_IR
4889994a338SPaul Mackerras	mflr	r11		/* return address to SRR0 */
4899994a338SPaul Mackerras	mfmsr	r12
4909994a338SPaul Mackerras	andc	r9,r12,r9
4919994a338SPaul Mackerras	andc	r10,r12,r10
4929994a338SPaul Mackerras
4939994a338SPaul Mackerras	mtmsrd	r9,1
4949994a338SPaul Mackerras	mtspr	SPRN_SRR1,r10
4959994a338SPaul Mackerras	mtspr	SPRN_SRR0,r11
4969994a338SPaul Mackerras	rfid
497cf904e30STiejun Chen#endif
4989994a338SPaul Mackerras
4999994a338SPaul Mackerras/*
500b970b41eSBenjamin Herrenschmidt * kexec_sequence(newstack, start, image, control, clear_all(),
501b970b41eSBenjamin Herrenschmidt	          copy_with_mmu_off)
5029994a338SPaul Mackerras *
5039994a338SPaul Mackerras * does the grungy work with stack switching and real mode switches
5049994a338SPaul Mackerras * also does simple calls to other code
5059994a338SPaul Mackerras */
5069994a338SPaul Mackerras
5079994a338SPaul Mackerras_GLOBAL(kexec_sequence)
5089994a338SPaul Mackerras	mflr	r0
5099994a338SPaul Mackerras	std	r0,16(r1)
5109994a338SPaul Mackerras
5119994a338SPaul Mackerras	/* switch stacks to newstack -- &kexec_stack.stack */
5124ae2dcb6SKumar Gala	stdu	r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
5139994a338SPaul Mackerras	mr	r1,r3
5149994a338SPaul Mackerras
5159994a338SPaul Mackerras	li	r0,0
5169994a338SPaul Mackerras	std	r0,16(r1)
5179994a338SPaul Mackerras
5181e2a516eSBalbir SinghBEGIN_FTR_SECTION
5191e2a516eSBalbir Singh	/*
5201e2a516eSBalbir Singh	 * This is the best time to turn AMR/IAMR off.
5211e2a516eSBalbir Singh	 * key 0 is used in radix for supervisor<->user
5221e2a516eSBalbir Singh	 * protection, but on hash key 0 is reserved
5231e2a516eSBalbir Singh	 * ideally we want to enter with a clean state.
5241e2a516eSBalbir Singh	 * NOTE, we rely on r0 being 0 from above.
5251e2a516eSBalbir Singh	 */
5261e2a516eSBalbir Singh	mtspr	SPRN_IAMR,r0
5272621e945SMichael EllermanBEGIN_FTR_SECTION_NESTED(42)
5281e2a516eSBalbir Singh	mtspr	SPRN_AMOR,r0
5292621e945SMichael EllermanEND_FTR_SECTION_NESTED_IFSET(CPU_FTR_HVMODE, 42)
5301e2a516eSBalbir SinghEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
5311e2a516eSBalbir Singh
5329994a338SPaul Mackerras	/* save regs for local vars on new stack.
5339994a338SPaul Mackerras	 * yes, we won't go back, but ...
5349994a338SPaul Mackerras	 */
5359994a338SPaul Mackerras	std	r31,-8(r1)
5369994a338SPaul Mackerras	std	r30,-16(r1)
5379994a338SPaul Mackerras	std	r29,-24(r1)
5389994a338SPaul Mackerras	std	r28,-32(r1)
5399994a338SPaul Mackerras	std	r27,-40(r1)
5409994a338SPaul Mackerras	std	r26,-48(r1)
5419994a338SPaul Mackerras	std	r25,-56(r1)
5429994a338SPaul Mackerras
5434ae2dcb6SKumar Gala	stdu	r1,-STACK_FRAME_OVERHEAD-64(r1)
5449994a338SPaul Mackerras
5459994a338SPaul Mackerras	/* save args into preserved regs */
5469994a338SPaul Mackerras	mr	r31,r3			/* newstack (both) */
5479994a338SPaul Mackerras	mr	r30,r4			/* start (real) */
5489994a338SPaul Mackerras	mr	r29,r5			/* image (virt) */
5499994a338SPaul Mackerras	mr	r28,r6			/* control, unused */
5509994a338SPaul Mackerras	mr	r27,r7			/* clear_all() fn desc */
551b970b41eSBenjamin Herrenschmidt	mr	r26,r8			/* copy_with_mmu_off */
5529994a338SPaul Mackerras	lhz	r25,PACAHWCPUID(r13)	/* get our phys cpu from paca */
5539994a338SPaul Mackerras
5549994a338SPaul Mackerras	/* disable interrupts, we are overwriting kernel data next */
55596eea642STiejun Chen#ifdef CONFIG_PPC_BOOK3E
55696eea642STiejun Chen	wrteei	0
55796eea642STiejun Chen#else
5589994a338SPaul Mackerras	mfmsr	r3
5599994a338SPaul Mackerras	rlwinm	r3,r3,0,17,15
5609994a338SPaul Mackerras	mtmsrd	r3,1
56196eea642STiejun Chen#endif
5629994a338SPaul Mackerras
563b970b41eSBenjamin Herrenschmidt	/* We need to turn the MMU off unless we are in hash mode
564b970b41eSBenjamin Herrenschmidt	 * under a hypervisor
565b970b41eSBenjamin Herrenschmidt	 */
566b970b41eSBenjamin Herrenschmidt	cmpdi	r26,0
567b970b41eSBenjamin Herrenschmidt	beq	1f
568b970b41eSBenjamin Herrenschmidt	bl	real_mode
569b970b41eSBenjamin Herrenschmidt1:
5709994a338SPaul Mackerras	/* copy dest pages, flush whole dest image */
5719994a338SPaul Mackerras	mr	r3,r29
572b1576fecSAnton Blanchard	bl	kexec_copy_flush	/* (image) */
5739994a338SPaul Mackerras
574b970b41eSBenjamin Herrenschmidt	/* turn off mmu now if not done earlier */
575b970b41eSBenjamin Herrenschmidt	cmpdi	r26,0
576b970b41eSBenjamin Herrenschmidt	bne	1f
5779994a338SPaul Mackerras	bl	real_mode
5789994a338SPaul Mackerras
579ee46a90bSMilton Miller	/* copy  0x100 bytes starting at start to 0 */
580b970b41eSBenjamin Herrenschmidt1:	li	r3,0
581ee46a90bSMilton Miller	mr	r4,r30		/* start, aka phys mem offset */
582ee46a90bSMilton Miller	li	r5,0x100
583ee46a90bSMilton Miller	li	r6,0
584b1576fecSAnton Blanchard	bl	copy_and_flush	/* (dest, src, copy limit, start offset) */
585ee46a90bSMilton Miller1:	/* assume normal blr return */
586ee46a90bSMilton Miller
587ee46a90bSMilton Miller	/* release other cpus to the new kernel secondary start at 0x60 */
588ee46a90bSMilton Miller	mflr	r5
589ee46a90bSMilton Miller	li	r6,1
590ee46a90bSMilton Miller	stw	r6,kexec_flag-1b(5)
591ee46a90bSMilton Miller
592fc48bad5SBenjamin Herrenschmidt	cmpdi	r27,0
593fc48bad5SBenjamin Herrenschmidt	beq	1f
594fc48bad5SBenjamin Herrenschmidt
5959994a338SPaul Mackerras	/* clear out hardware hash page table and tlb */
596f55d9665SMichael Ellerman#ifdef PPC64_ELF_ABI_v1
597cc7efbf9SAnton Blanchard	ld	r12,0(r27)		/* deref function descriptor */
598cc7efbf9SAnton Blanchard#else
599cc7efbf9SAnton Blanchard	mr	r12,r27
600cc7efbf9SAnton Blanchard#endif
601cc7efbf9SAnton Blanchard	mtctr	r12
6027025776eSBenjamin Herrenschmidt	bctrl				/* mmu_hash_ops.hpte_clear_all(void); */
6039994a338SPaul Mackerras
6049994a338SPaul Mackerras/*
6059994a338SPaul Mackerras *   kexec image calling is:
6069994a338SPaul Mackerras *      the first 0x100 bytes of the entry point are copied to 0
6079994a338SPaul Mackerras *
6089994a338SPaul Mackerras *      all slaves branch to slave = 0x60 (absolute)
6099994a338SPaul Mackerras *              slave(phys_cpu_id);
6109994a338SPaul Mackerras *
6119994a338SPaul Mackerras *      master goes to start = entry point
6129994a338SPaul Mackerras *              start(phys_cpu_id, start, 0);
6139994a338SPaul Mackerras *
6149994a338SPaul Mackerras *
6159994a338SPaul Mackerras *   a wrapper is needed to call existing kernels, here is an approximate
6169994a338SPaul Mackerras *   description of one method:
6179994a338SPaul Mackerras *
6189994a338SPaul Mackerras * v2: (2.6.10)
6199994a338SPaul Mackerras *   start will be near the boot_block (maybe 0x100 bytes before it?)
6209994a338SPaul Mackerras *   it will have a 0x60, which will b to boot_block, where it will wait
6219994a338SPaul Mackerras *   and 0 will store phys into struct boot-block and load r3 from there,
6229994a338SPaul Mackerras *   copy kernel 0-0x100 and tell slaves to back down to 0x60 again
6239994a338SPaul Mackerras *
6249994a338SPaul Mackerras * v1: (2.6.9)
6259994a338SPaul Mackerras *    boot block will have all cpus scanning device tree to see if they
6269994a338SPaul Mackerras *    are the boot cpu ?????
6279994a338SPaul Mackerras *    other device tree differences (prop sizes, va vs pa, etc)...
6289994a338SPaul Mackerras */
629fc48bad5SBenjamin Herrenschmidt1:	mr	r3,r25	# my phys cpu
6309994a338SPaul Mackerras	mr	r4,r30	# start, aka phys mem offset
6319994a338SPaul Mackerras	mtlr	4
6329994a338SPaul Mackerras	li	r5,0
6331767c8f3SMilton Miller	blr	/* image->start(physid, image->start, 0); */
634da665885SThiago Jung Bauermann#endif /* CONFIG_KEXEC_CORE */
635