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