xref: /openbmc/linux/arch/powerpc/kernel/misc_64.S (revision 7d40aff8213c92e64a1576ba9dfebcd201c0564d)
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
30ca9d7aeaSDavid Woodhouse_GLOBAL(__bswapdi2)
319445aa1aSAl ViroEXPORT_SYMBOL(__bswapdi2)
32ca9d7aeaSDavid Woodhouse	srdi	r8,r3,32
33ca9d7aeaSDavid Woodhouse	rlwinm	r7,r3,8,0xffffffff
34ca9d7aeaSDavid Woodhouse	rlwimi	r7,r3,24,0,7
35ca9d7aeaSDavid Woodhouse	rlwinm	r9,r8,8,0xffffffff
36ca9d7aeaSDavid Woodhouse	rlwimi	r7,r3,24,16,23
37ca9d7aeaSDavid Woodhouse	rlwimi	r9,r8,24,0,7
38ca9d7aeaSDavid Woodhouse	rlwimi	r9,r8,24,16,23
39ca9d7aeaSDavid Woodhouse	sldi	r7,r7,32
40ca9d7aeaSDavid Woodhouse	or	r3,r7,r9
41ca9d7aeaSDavid Woodhouse	blr
423f639ee8SStephen Rothwell
437191b615SBenjamin Herrenschmidt
442d6f0c3aSMichael Ellerman#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
457191b615SBenjamin Herrenschmidt_GLOBAL(rmci_on)
467191b615SBenjamin Herrenschmidt	sync
477191b615SBenjamin Herrenschmidt	isync
487191b615SBenjamin Herrenschmidt	li	r3,0x100
497191b615SBenjamin Herrenschmidt	rldicl	r3,r3,32,0
507191b615SBenjamin Herrenschmidt	mfspr	r5,SPRN_HID4
517191b615SBenjamin Herrenschmidt	or	r5,r5,r3
527191b615SBenjamin Herrenschmidt	sync
537191b615SBenjamin Herrenschmidt	mtspr	SPRN_HID4,r5
547191b615SBenjamin Herrenschmidt	isync
557191b615SBenjamin Herrenschmidt	slbia
567191b615SBenjamin Herrenschmidt	isync
577191b615SBenjamin Herrenschmidt	sync
587191b615SBenjamin Herrenschmidt	blr
597191b615SBenjamin Herrenschmidt
607191b615SBenjamin Herrenschmidt_GLOBAL(rmci_off)
617191b615SBenjamin Herrenschmidt	sync
627191b615SBenjamin Herrenschmidt	isync
637191b615SBenjamin Herrenschmidt	li	r3,0x100
647191b615SBenjamin Herrenschmidt	rldicl	r3,r3,32,0
657191b615SBenjamin Herrenschmidt	mfspr	r5,SPRN_HID4
667191b615SBenjamin Herrenschmidt	andc	r5,r5,r3
677191b615SBenjamin Herrenschmidt	sync
687191b615SBenjamin Herrenschmidt	mtspr	SPRN_HID4,r5
697191b615SBenjamin Herrenschmidt	isync
707191b615SBenjamin Herrenschmidt	slbia
717191b615SBenjamin Herrenschmidt	isync
727191b615SBenjamin Herrenschmidt	sync
737191b615SBenjamin Herrenschmidt	blr
742d6f0c3aSMichael Ellerman#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
752d6f0c3aSMichael Ellerman
762d6f0c3aSMichael Ellerman#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
777191b615SBenjamin Herrenschmidt
789994a338SPaul Mackerras/*
799994a338SPaul Mackerras * Do an IO access in real mode
809994a338SPaul Mackerras */
819994a338SPaul Mackerras_GLOBAL(real_readb)
829994a338SPaul Mackerras	mfmsr	r7
839994a338SPaul Mackerras	ori	r0,r7,MSR_DR
849994a338SPaul Mackerras	xori	r0,r0,MSR_DR
859994a338SPaul Mackerras	sync
869994a338SPaul Mackerras	mtmsrd	r0
879994a338SPaul Mackerras	sync
889994a338SPaul Mackerras	isync
899994a338SPaul Mackerras	mfspr	r6,SPRN_HID4
909994a338SPaul Mackerras	rldicl	r5,r6,32,0
919994a338SPaul Mackerras	ori	r5,r5,0x100
929994a338SPaul Mackerras	rldicl	r5,r5,32,0
939994a338SPaul Mackerras	sync
949994a338SPaul Mackerras	mtspr	SPRN_HID4,r5
959994a338SPaul Mackerras	isync
969994a338SPaul Mackerras	slbia
979994a338SPaul Mackerras	isync
989994a338SPaul Mackerras	lbz	r3,0(r3)
999994a338SPaul Mackerras	sync
1009994a338SPaul Mackerras	mtspr	SPRN_HID4,r6
1019994a338SPaul Mackerras	isync
1029994a338SPaul Mackerras	slbia
1039994a338SPaul Mackerras	isync
1049994a338SPaul Mackerras	mtmsrd	r7
1059994a338SPaul Mackerras	sync
1069994a338SPaul Mackerras	isync
1079994a338SPaul Mackerras	blr
1089994a338SPaul Mackerras
1099994a338SPaul Mackerras	/*
1109994a338SPaul Mackerras * Do an IO access in real mode
1119994a338SPaul Mackerras */
1129994a338SPaul Mackerras_GLOBAL(real_writeb)
1139994a338SPaul Mackerras	mfmsr	r7
1149994a338SPaul Mackerras	ori	r0,r7,MSR_DR
1159994a338SPaul Mackerras	xori	r0,r0,MSR_DR
1169994a338SPaul Mackerras	sync
1179994a338SPaul Mackerras	mtmsrd	r0
1189994a338SPaul Mackerras	sync
1199994a338SPaul Mackerras	isync
1209994a338SPaul Mackerras	mfspr	r6,SPRN_HID4
1219994a338SPaul Mackerras	rldicl	r5,r6,32,0
1229994a338SPaul Mackerras	ori	r5,r5,0x100
1239994a338SPaul Mackerras	rldicl	r5,r5,32,0
1249994a338SPaul Mackerras	sync
1259994a338SPaul Mackerras	mtspr	SPRN_HID4,r5
1269994a338SPaul Mackerras	isync
1279994a338SPaul Mackerras	slbia
1289994a338SPaul Mackerras	isync
1299994a338SPaul Mackerras	stb	r3,0(r4)
1309994a338SPaul Mackerras	sync
1319994a338SPaul Mackerras	mtspr	SPRN_HID4,r6
1329994a338SPaul Mackerras	isync
1339994a338SPaul Mackerras	slbia
1349994a338SPaul Mackerras	isync
1359994a338SPaul Mackerras	mtmsrd	r7
1369994a338SPaul Mackerras	sync
1379994a338SPaul Mackerras	isync
1389994a338SPaul Mackerras	blr
1399994a338SPaul Mackerras#endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */
1409994a338SPaul Mackerras
14139c870d5SOlof Johansson#ifdef CONFIG_PPC_PASEMI
14239c870d5SOlof Johansson
14339c870d5SOlof Johansson_GLOBAL(real_205_readb)
14439c870d5SOlof Johansson	mfmsr	r7
14539c870d5SOlof Johansson	ori	r0,r7,MSR_DR
14639c870d5SOlof Johansson	xori	r0,r0,MSR_DR
14739c870d5SOlof Johansson	sync
14839c870d5SOlof Johansson	mtmsrd	r0
14939c870d5SOlof Johansson	sync
15039c870d5SOlof Johansson	isync
151e55174e9SMichael Neuling	LBZCIX(R3,R0,R3)
15239c870d5SOlof Johansson	isync
15339c870d5SOlof Johansson	mtmsrd	r7
15439c870d5SOlof Johansson	sync
15539c870d5SOlof Johansson	isync
15639c870d5SOlof Johansson	blr
15739c870d5SOlof Johansson
15839c870d5SOlof Johansson_GLOBAL(real_205_writeb)
15939c870d5SOlof Johansson	mfmsr	r7
16039c870d5SOlof Johansson	ori	r0,r7,MSR_DR
16139c870d5SOlof Johansson	xori	r0,r0,MSR_DR
16239c870d5SOlof Johansson	sync
16339c870d5SOlof Johansson	mtmsrd	r0
16439c870d5SOlof Johansson	sync
16539c870d5SOlof Johansson	isync
166e55174e9SMichael Neuling	STBCIX(R3,R0,R4)
16739c870d5SOlof Johansson	isync
16839c870d5SOlof Johansson	mtmsrd	r7
16939c870d5SOlof Johansson	sync
17039c870d5SOlof Johansson	isync
17139c870d5SOlof Johansson	blr
17239c870d5SOlof Johansson
17339c870d5SOlof Johansson#endif /* CONFIG_PPC_PASEMI */
17439c870d5SOlof Johansson
17539c870d5SOlof Johansson
176e48f7eb2SDmitry Eremin-Solenikov#if defined(CONFIG_CPU_FREQ_PMAC64) || defined(CONFIG_CPU_FREQ_MAPLE)
1779994a338SPaul Mackerras/*
1784350147aSBenjamin Herrenschmidt * SCOM access functions for 970 (FX only for now)
1794350147aSBenjamin Herrenschmidt *
1804350147aSBenjamin Herrenschmidt * unsigned long scom970_read(unsigned int address);
1814350147aSBenjamin Herrenschmidt * void scom970_write(unsigned int address, unsigned long value);
1824350147aSBenjamin Herrenschmidt *
1834350147aSBenjamin Herrenschmidt * The address passed in is the 24 bits register address. This code
1844350147aSBenjamin Herrenschmidt * is 970 specific and will not check the status bits, so you should
1854350147aSBenjamin Herrenschmidt * know what you are doing.
1864350147aSBenjamin Herrenschmidt */
1874350147aSBenjamin Herrenschmidt_GLOBAL(scom970_read)
1884350147aSBenjamin Herrenschmidt	/* interrupts off */
1894350147aSBenjamin Herrenschmidt	mfmsr	r4
1904350147aSBenjamin Herrenschmidt	ori	r0,r4,MSR_EE
1914350147aSBenjamin Herrenschmidt	xori	r0,r0,MSR_EE
1924350147aSBenjamin Herrenschmidt	mtmsrd	r0,1
1934350147aSBenjamin Herrenschmidt
1944350147aSBenjamin Herrenschmidt	/* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits
1954350147aSBenjamin Herrenschmidt	 * (including parity). On current CPUs they must be 0'd,
1964350147aSBenjamin Herrenschmidt	 * and finally or in RW bit
1974350147aSBenjamin Herrenschmidt	 */
1984350147aSBenjamin Herrenschmidt	rlwinm	r3,r3,8,0,15
1994350147aSBenjamin Herrenschmidt	ori	r3,r3,0x8000
2004350147aSBenjamin Herrenschmidt
2014350147aSBenjamin Herrenschmidt	/* do the actual scom read */
2024350147aSBenjamin Herrenschmidt	sync
2034350147aSBenjamin Herrenschmidt	mtspr	SPRN_SCOMC,r3
2044350147aSBenjamin Herrenschmidt	isync
2054350147aSBenjamin Herrenschmidt	mfspr	r3,SPRN_SCOMD
2064350147aSBenjamin Herrenschmidt	isync
2074350147aSBenjamin Herrenschmidt	mfspr	r0,SPRN_SCOMC
2084350147aSBenjamin Herrenschmidt	isync
2094350147aSBenjamin Herrenschmidt
2104350147aSBenjamin Herrenschmidt	/* XXX:	fixup result on some buggy 970's (ouch ! we lost a bit, bah
2114350147aSBenjamin Herrenschmidt	 * that's the best we can do). Not implemented yet as we don't use
2124350147aSBenjamin Herrenschmidt	 * the scom on any of the bogus CPUs yet, but may have to be done
2134350147aSBenjamin Herrenschmidt	 * ultimately
2144350147aSBenjamin Herrenschmidt	 */
2154350147aSBenjamin Herrenschmidt
2164350147aSBenjamin Herrenschmidt	/* restore interrupts */
2174350147aSBenjamin Herrenschmidt	mtmsrd	r4,1
2184350147aSBenjamin Herrenschmidt	blr
2194350147aSBenjamin Herrenschmidt
2204350147aSBenjamin Herrenschmidt
2214350147aSBenjamin Herrenschmidt_GLOBAL(scom970_write)
2224350147aSBenjamin Herrenschmidt	/* interrupts off */
2234350147aSBenjamin Herrenschmidt	mfmsr	r5
2244350147aSBenjamin Herrenschmidt	ori	r0,r5,MSR_EE
2254350147aSBenjamin Herrenschmidt	xori	r0,r0,MSR_EE
2264350147aSBenjamin Herrenschmidt	mtmsrd	r0,1
2274350147aSBenjamin Herrenschmidt
2284350147aSBenjamin Herrenschmidt	/* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits
2294350147aSBenjamin Herrenschmidt	 * (including parity). On current CPUs they must be 0'd.
2304350147aSBenjamin Herrenschmidt	 */
2314350147aSBenjamin Herrenschmidt
2324350147aSBenjamin Herrenschmidt	rlwinm	r3,r3,8,0,15
2334350147aSBenjamin Herrenschmidt
2344350147aSBenjamin Herrenschmidt	sync
2354350147aSBenjamin Herrenschmidt	mtspr	SPRN_SCOMD,r4      /* write data */
2364350147aSBenjamin Herrenschmidt	isync
2374350147aSBenjamin Herrenschmidt	mtspr	SPRN_SCOMC,r3      /* write command */
2384350147aSBenjamin Herrenschmidt	isync
2394350147aSBenjamin Herrenschmidt	mfspr	3,SPRN_SCOMC
2404350147aSBenjamin Herrenschmidt	isync
2414350147aSBenjamin Herrenschmidt
2424350147aSBenjamin Herrenschmidt	/* restore interrupts */
2434350147aSBenjamin Herrenschmidt	mtmsrd	r5,1
2444350147aSBenjamin Herrenschmidt	blr
245e48f7eb2SDmitry Eremin-Solenikov#endif /* CONFIG_CPU_FREQ_PMAC64 || CONFIG_CPU_FREQ_MAPLE */
2464350147aSBenjamin Herrenschmidt
2479994a338SPaul Mackerras/* kexec_wait(phys_cpu)
2489994a338SPaul Mackerras *
2499994a338SPaul Mackerras * wait for the flag to change, indicating this kernel is going away but
2509994a338SPaul Mackerras * the slave code for the next one is at addresses 0 to 100.
2519994a338SPaul Mackerras *
2523d2cea73SMilton Miller * This is used by all slaves, even those that did not find a matching
2533d2cea73SMilton Miller * paca in the secondary startup code.
2549994a338SPaul Mackerras *
2559994a338SPaul Mackerras * Physical (hardware) cpu id should be in r3.
2569994a338SPaul Mackerras */
2579994a338SPaul Mackerras_GLOBAL(kexec_wait)
25833e14024SChristophe Leroy	bcl	20,31,$+4
2599994a338SPaul Mackerras1:	mflr	r5
2609994a338SPaul Mackerras	addi	r5,r5,kexec_flag-1b
2619994a338SPaul Mackerras
2629994a338SPaul Mackerras99:	HMT_LOW
263da665885SThiago Jung Bauermann#ifdef CONFIG_KEXEC_CORE	/* use no memory without kexec */
2649994a338SPaul Mackerras	lwz	r4,0(r5)
2659994a338SPaul Mackerras	cmpwi	0,r4,0
266ffebf5f3SSamuel Mendoza-Jonas	beq	99b
267ffebf5f3SSamuel Mendoza-Jonas#ifdef CONFIG_PPC_BOOK3S_64
268ffebf5f3SSamuel Mendoza-Jonas	li	r10,0x60
269ffebf5f3SSamuel Mendoza-Jonas	mfmsr	r11
270ffebf5f3SSamuel Mendoza-Jonas	clrrdi	r11,r11,1	/* Clear MSR_LE */
271ffebf5f3SSamuel Mendoza-Jonas	mtsrr0	r10
272ffebf5f3SSamuel Mendoza-Jonas	mtsrr1	r11
273ffebf5f3SSamuel Mendoza-Jonas	rfid
274ffebf5f3SSamuel Mendoza-Jonas#else
275ae73e4ccSScott Wood	/* Create TLB entry in book3e_secondary_core_init */
276ae73e4ccSScott Wood	li	r4,0
277ffebf5f3SSamuel Mendoza-Jonas	ba	0x60
2789994a338SPaul Mackerras#endif
279ffebf5f3SSamuel Mendoza-Jonas#endif
2809994a338SPaul Mackerras
2819994a338SPaul Mackerras/* this can be in text because we won't change it until we are
2829994a338SPaul Mackerras * running in real anyways
2839994a338SPaul Mackerras */
2849994a338SPaul Mackerraskexec_flag:
2859994a338SPaul Mackerras	.long	0
2869994a338SPaul Mackerras
2879994a338SPaul Mackerras
288da665885SThiago Jung Bauermann#ifdef CONFIG_KEXEC_CORE
289cf904e30STiejun Chen#ifdef CONFIG_PPC_BOOK3E
290cf904e30STiejun Chen/*
291cf904e30STiejun Chen * BOOK3E has no real MMU mode, so we have to setup the initial TLB
292cf904e30STiejun Chen * for a core to identity map v:0 to p:0.  This current implementation
293cf904e30STiejun Chen * assumes that 1G is enough for kexec.
294cf904e30STiejun Chen */
295cf904e30STiejun Chenkexec_create_tlb:
296cf904e30STiejun Chen	/*
297cf904e30STiejun Chen	 * Invalidate all non-IPROT TLB entries to avoid any TLB conflict.
298cf904e30STiejun Chen	 * IPROT TLB entries should be >= PAGE_OFFSET and thus not conflict.
299cf904e30STiejun Chen	 */
300cf904e30STiejun Chen	PPC_TLBILX_ALL(0,R0)
301cf904e30STiejun Chen	sync
302cf904e30STiejun Chen	isync
303cf904e30STiejun Chen
304cf904e30STiejun Chen	mfspr	r10,SPRN_TLB1CFG
305cf904e30STiejun Chen	andi.	r10,r10,TLBnCFG_N_ENTRY	/* Extract # entries */
306cf904e30STiejun Chen	subi	r10,r10,1	/* Last entry: no conflict with kernel text */
307cf904e30STiejun Chen	lis	r9,MAS0_TLBSEL(1)@h
308cf904e30STiejun Chen	rlwimi	r9,r10,16,4,15		/* Setup MAS0 = TLBSEL | ESEL(r9) */
309cf904e30STiejun Chen
310cf904e30STiejun Chen/* Set up a temp identity mapping v:0 to p:0 and return to it. */
311cf904e30STiejun Chen	mtspr	SPRN_MAS0,r9
312cf904e30STiejun Chen
313cf904e30STiejun Chen	lis	r9,(MAS1_VALID|MAS1_IPROT)@h
314cf904e30STiejun Chen	ori	r9,r9,(MAS1_TSIZE(BOOK3E_PAGESZ_1GB))@l
315cf904e30STiejun Chen	mtspr	SPRN_MAS1,r9
316cf904e30STiejun Chen
3178054df05SJason Yan	LOAD_REG_IMMEDIATE(r9, 0x0 | MAS2_M_IF_NEEDED)
318cf904e30STiejun Chen	mtspr	SPRN_MAS2,r9
319cf904e30STiejun Chen
320cf904e30STiejun Chen	LOAD_REG_IMMEDIATE(r9, 0x0 | MAS3_SR | MAS3_SW | MAS3_SX)
321cf904e30STiejun Chen	mtspr	SPRN_MAS3,r9
322cf904e30STiejun Chen	li	r9,0
323cf904e30STiejun Chen	mtspr	SPRN_MAS7,r9
324cf904e30STiejun Chen
325cf904e30STiejun Chen	tlbwe
326cf904e30STiejun Chen	isync
327cf904e30STiejun Chen	blr
328cf904e30STiejun Chen#endif
3299994a338SPaul Mackerras
3309994a338SPaul Mackerras/* kexec_smp_wait(void)
3319994a338SPaul Mackerras *
3329994a338SPaul Mackerras * call with interrupts off
3339994a338SPaul Mackerras * note: this is a terminal routine, it does not save lr
3349994a338SPaul Mackerras *
3359994a338SPaul Mackerras * get phys id from paca
3369994a338SPaul Mackerras * switch to real mode
3373d2cea73SMilton Miller * mark the paca as no longer used
3389994a338SPaul Mackerras * join other cpus in kexec_wait(phys_id)
3399994a338SPaul Mackerras */
3409994a338SPaul Mackerras_GLOBAL(kexec_smp_wait)
3419994a338SPaul Mackerras	lhz	r3,PACAHWCPUID(r13)
3429994a338SPaul Mackerras	bl	real_mode
3433d2cea73SMilton Miller
3443d2cea73SMilton Miller	li	r4,KEXEC_STATE_REAL_MODE
3453d2cea73SMilton Miller	stb	r4,PACAKEXECSTATE(r13)
3463d2cea73SMilton Miller
347b1576fecSAnton Blanchard	b	kexec_wait
3489994a338SPaul Mackerras
3499994a338SPaul Mackerras/*
3509994a338SPaul Mackerras * switch to real mode (turn mmu off)
3519994a338SPaul Mackerras * we use the early kernel trick that the hardware ignores bits
3529994a338SPaul Mackerras * 0 and 1 (big endian) of the effective address in real mode
3539994a338SPaul Mackerras *
3549994a338SPaul Mackerras * don't overwrite r3 here, it is live for kexec_wait above.
3559994a338SPaul Mackerras */
3569994a338SPaul Mackerrasreal_mode:	/* assume normal blr return */
357cf904e30STiejun Chen#ifdef CONFIG_PPC_BOOK3E
358cf904e30STiejun Chen	/* Create an identity mapping. */
359cf904e30STiejun Chen	b	kexec_create_tlb
360cf904e30STiejun Chen#else
3619994a338SPaul Mackerras1:	li	r9,MSR_RI
3629994a338SPaul Mackerras	li	r10,MSR_DR|MSR_IR
3639994a338SPaul Mackerras	mflr	r11		/* return address to SRR0 */
3649994a338SPaul Mackerras	mfmsr	r12
3659994a338SPaul Mackerras	andc	r9,r12,r9
3669994a338SPaul Mackerras	andc	r10,r12,r10
3679994a338SPaul Mackerras
3689994a338SPaul Mackerras	mtmsrd	r9,1
3699994a338SPaul Mackerras	mtspr	SPRN_SRR1,r10
3709994a338SPaul Mackerras	mtspr	SPRN_SRR0,r11
3719994a338SPaul Mackerras	rfid
372cf904e30STiejun Chen#endif
3739994a338SPaul Mackerras
3749994a338SPaul Mackerras/*
375b970b41eSBenjamin Herrenschmidt * kexec_sequence(newstack, start, image, control, clear_all(),
376b970b41eSBenjamin Herrenschmidt	          copy_with_mmu_off)
3779994a338SPaul Mackerras *
3789994a338SPaul Mackerras * does the grungy work with stack switching and real mode switches
3799994a338SPaul Mackerras * also does simple calls to other code
3809994a338SPaul Mackerras */
3819994a338SPaul Mackerras
3829994a338SPaul Mackerras_GLOBAL(kexec_sequence)
3839994a338SPaul Mackerras	mflr	r0
3849994a338SPaul Mackerras	std	r0,16(r1)
3859994a338SPaul Mackerras
3869994a338SPaul Mackerras	/* switch stacks to newstack -- &kexec_stack.stack */
3874ae2dcb6SKumar Gala	stdu	r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
3889994a338SPaul Mackerras	mr	r1,r3
3899994a338SPaul Mackerras
3909994a338SPaul Mackerras	li	r0,0
3919994a338SPaul Mackerras	std	r0,16(r1)
3929994a338SPaul Mackerras
3939994a338SPaul Mackerras	/* save regs for local vars on new stack.
3949994a338SPaul Mackerras	 * yes, we won't go back, but ...
3959994a338SPaul Mackerras	 */
3969994a338SPaul Mackerras	std	r31,-8(r1)
3979994a338SPaul Mackerras	std	r30,-16(r1)
3989994a338SPaul Mackerras	std	r29,-24(r1)
3999994a338SPaul Mackerras	std	r28,-32(r1)
4009994a338SPaul Mackerras	std	r27,-40(r1)
4019994a338SPaul Mackerras	std	r26,-48(r1)
4029994a338SPaul Mackerras	std	r25,-56(r1)
4039994a338SPaul Mackerras
4044ae2dcb6SKumar Gala	stdu	r1,-STACK_FRAME_OVERHEAD-64(r1)
4059994a338SPaul Mackerras
4069994a338SPaul Mackerras	/* save args into preserved regs */
4079994a338SPaul Mackerras	mr	r31,r3			/* newstack (both) */
4089994a338SPaul Mackerras	mr	r30,r4			/* start (real) */
4099994a338SPaul Mackerras	mr	r29,r5			/* image (virt) */
4109994a338SPaul Mackerras	mr	r28,r6			/* control, unused */
4119994a338SPaul Mackerras	mr	r27,r7			/* clear_all() fn desc */
412b970b41eSBenjamin Herrenschmidt	mr	r26,r8			/* copy_with_mmu_off */
4139994a338SPaul Mackerras	lhz	r25,PACAHWCPUID(r13)	/* get our phys cpu from paca */
4149994a338SPaul Mackerras
4159994a338SPaul Mackerras	/* disable interrupts, we are overwriting kernel data next */
41696eea642STiejun Chen#ifdef CONFIG_PPC_BOOK3E
41796eea642STiejun Chen	wrteei	0
41896eea642STiejun Chen#else
4199994a338SPaul Mackerras	mfmsr	r3
4209994a338SPaul Mackerras	rlwinm	r3,r3,0,17,15
4219994a338SPaul Mackerras	mtmsrd	r3,1
42296eea642STiejun Chen#endif
4239994a338SPaul Mackerras
424b970b41eSBenjamin Herrenschmidt	/* We need to turn the MMU off unless we are in hash mode
425b970b41eSBenjamin Herrenschmidt	 * under a hypervisor
426b970b41eSBenjamin Herrenschmidt	 */
427b970b41eSBenjamin Herrenschmidt	cmpdi	r26,0
428b970b41eSBenjamin Herrenschmidt	beq	1f
429b970b41eSBenjamin Herrenschmidt	bl	real_mode
430b970b41eSBenjamin Herrenschmidt1:
4319994a338SPaul Mackerras	/* copy dest pages, flush whole dest image */
4329994a338SPaul Mackerras	mr	r3,r29
433b1576fecSAnton Blanchard	bl	kexec_copy_flush	/* (image) */
4349994a338SPaul Mackerras
435b970b41eSBenjamin Herrenschmidt	/* turn off mmu now if not done earlier */
436b970b41eSBenjamin Herrenschmidt	cmpdi	r26,0
437b970b41eSBenjamin Herrenschmidt	bne	1f
4389994a338SPaul Mackerras	bl	real_mode
4399994a338SPaul Mackerras
440ee46a90bSMilton Miller	/* copy  0x100 bytes starting at start to 0 */
441b970b41eSBenjamin Herrenschmidt1:	li	r3,0
442ee46a90bSMilton Miller	mr	r4,r30		/* start, aka phys mem offset */
443ee46a90bSMilton Miller	li	r5,0x100
444ee46a90bSMilton Miller	li	r6,0
445b1576fecSAnton Blanchard	bl	copy_and_flush	/* (dest, src, copy limit, start offset) */
446ee46a90bSMilton Miller1:	/* assume normal blr return */
447ee46a90bSMilton Miller
448ee46a90bSMilton Miller	/* release other cpus to the new kernel secondary start at 0x60 */
449ee46a90bSMilton Miller	mflr	r5
450ee46a90bSMilton Miller	li	r6,1
451ee46a90bSMilton Miller	stw	r6,kexec_flag-1b(5)
452ee46a90bSMilton Miller
453fc48bad5SBenjamin Herrenschmidt	cmpdi	r27,0
454fc48bad5SBenjamin Herrenschmidt	beq	1f
455fc48bad5SBenjamin Herrenschmidt
4569994a338SPaul Mackerras	/* clear out hardware hash page table and tlb */
457*7d40aff8SChristophe Leroy#ifdef CONFIG_PPC64_ELF_ABI_V1
458cc7efbf9SAnton Blanchard	ld	r12,0(r27)		/* deref function descriptor */
459cc7efbf9SAnton Blanchard#else
460cc7efbf9SAnton Blanchard	mr	r12,r27
461cc7efbf9SAnton Blanchard#endif
462cc7efbf9SAnton Blanchard	mtctr	r12
4637025776eSBenjamin Herrenschmidt	bctrl				/* mmu_hash_ops.hpte_clear_all(void); */
4649994a338SPaul Mackerras
4659994a338SPaul Mackerras/*
4669994a338SPaul Mackerras *   kexec image calling is:
4679994a338SPaul Mackerras *      the first 0x100 bytes of the entry point are copied to 0
4689994a338SPaul Mackerras *
4699994a338SPaul Mackerras *      all slaves branch to slave = 0x60 (absolute)
4709994a338SPaul Mackerras *              slave(phys_cpu_id);
4719994a338SPaul Mackerras *
4729994a338SPaul Mackerras *      master goes to start = entry point
4739994a338SPaul Mackerras *              start(phys_cpu_id, start, 0);
4749994a338SPaul Mackerras *
4759994a338SPaul Mackerras *
4769994a338SPaul Mackerras *   a wrapper is needed to call existing kernels, here is an approximate
4779994a338SPaul Mackerras *   description of one method:
4789994a338SPaul Mackerras *
4799994a338SPaul Mackerras * v2: (2.6.10)
4809994a338SPaul Mackerras *   start will be near the boot_block (maybe 0x100 bytes before it?)
4819994a338SPaul Mackerras *   it will have a 0x60, which will b to boot_block, where it will wait
4829994a338SPaul Mackerras *   and 0 will store phys into struct boot-block and load r3 from there,
4839994a338SPaul Mackerras *   copy kernel 0-0x100 and tell slaves to back down to 0x60 again
4849994a338SPaul Mackerras *
4859994a338SPaul Mackerras * v1: (2.6.9)
4869994a338SPaul Mackerras *    boot block will have all cpus scanning device tree to see if they
4879994a338SPaul Mackerras *    are the boot cpu ?????
4889994a338SPaul Mackerras *    other device tree differences (prop sizes, va vs pa, etc)...
4899994a338SPaul Mackerras */
490fc48bad5SBenjamin Herrenschmidt1:	mr	r3,r25	# my phys cpu
4919994a338SPaul Mackerras	mr	r4,r30	# start, aka phys mem offset
4929994a338SPaul Mackerras	mtlr	4
4939994a338SPaul Mackerras	li	r5,0
4941767c8f3SMilton Miller	blr	/* image->start(physid, image->start, 0); */
495da665885SThiago Jung Bauermann#endif /* CONFIG_KEXEC_CORE */
496