xref: /openbmc/linux/arch/powerpc/kernel/misc_64.S (revision cf904e3088fd3760d9f6fed5fde755ac299590b7)
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>
29*cf904e30STiejun Chen#include <asm/mmu.h>
309994a338SPaul Mackerras
319994a338SPaul Mackerras	.text
329994a338SPaul Mackerras
339994a338SPaul Mackerras_GLOBAL(call_do_softirq)
349994a338SPaul Mackerras	mflr	r0
359994a338SPaul Mackerras	std	r0,16(r1)
364ae2dcb6SKumar Gala	stdu	r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
379994a338SPaul Mackerras	mr	r1,r3
38b1576fecSAnton Blanchard	bl	__do_softirq
399994a338SPaul Mackerras	ld	r1,0(r1)
409994a338SPaul Mackerras	ld	r0,16(r1)
419994a338SPaul Mackerras	mtlr	r0
429994a338SPaul Mackerras	blr
439994a338SPaul Mackerras
440366a1c7SBenjamin Herrenschmidt_GLOBAL(call_do_irq)
459994a338SPaul Mackerras	mflr	r0
469994a338SPaul Mackerras	std	r0,16(r1)
470366a1c7SBenjamin Herrenschmidt	stdu	r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r4)
480366a1c7SBenjamin Herrenschmidt	mr	r1,r4
49b1576fecSAnton Blanchard	bl	__do_irq
509994a338SPaul Mackerras	ld	r1,0(r1)
519994a338SPaul Mackerras	ld	r0,16(r1)
529994a338SPaul Mackerras	mtlr	r0
539994a338SPaul Mackerras	blr
549994a338SPaul Mackerras
559994a338SPaul Mackerras	.section	".toc","aw"
569994a338SPaul MackerrasPPC64_CACHES:
579994a338SPaul Mackerras	.tc		ppc64_caches[TC],ppc64_caches
589994a338SPaul Mackerras	.section	".text"
599994a338SPaul Mackerras
609994a338SPaul Mackerras/*
619994a338SPaul Mackerras * Write any modified data cache blocks out to memory
629994a338SPaul Mackerras * and invalidate the corresponding instruction cache blocks.
639994a338SPaul Mackerras *
649994a338SPaul Mackerras * flush_icache_range(unsigned long start, unsigned long stop)
659994a338SPaul Mackerras *
669994a338SPaul Mackerras *   flush all bytes from start through stop-1 inclusive
679994a338SPaul Mackerras */
689994a338SPaul Mackerras
693b04c300SKevin Hao_KPROBE(flush_icache_range)
70abb29c3bSKevin HaoBEGIN_FTR_SECTION
710ce63670SKevin Hao	PURGE_PREFETCHED_INS
72abb29c3bSKevin Hao	blr
73abb29c3bSKevin HaoEND_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
749994a338SPaul Mackerras/*
759994a338SPaul Mackerras * Flush the data cache to memory
769994a338SPaul Mackerras *
779994a338SPaul Mackerras * Different systems have different cache line sizes
789994a338SPaul Mackerras * and in some cases i-cache and d-cache line sizes differ from
799994a338SPaul Mackerras * each other.
809994a338SPaul Mackerras */
819994a338SPaul Mackerras 	ld	r10,PPC64_CACHES@toc(r2)
829994a338SPaul Mackerras	lwz	r7,DCACHEL1LINESIZE(r10)/* Get cache line size */
839994a338SPaul Mackerras	addi	r5,r7,-1
849994a338SPaul Mackerras	andc	r6,r3,r5		/* round low to line bdy */
859994a338SPaul Mackerras	subf	r8,r6,r4		/* compute length */
869994a338SPaul Mackerras	add	r8,r8,r5		/* ensure we get enough */
879994a338SPaul Mackerras	lwz	r9,DCACHEL1LOGLINESIZE(r10)	/* Get log-2 of cache line size */
889994a338SPaul Mackerras	srw.	r8,r8,r9		/* compute line count */
899994a338SPaul Mackerras	beqlr				/* nothing to do? */
909994a338SPaul Mackerras	mtctr	r8
919994a338SPaul Mackerras1:	dcbst	0,r6
929994a338SPaul Mackerras	add	r6,r6,r7
939994a338SPaul Mackerras	bdnz	1b
949994a338SPaul Mackerras	sync
959994a338SPaul Mackerras
969994a338SPaul Mackerras/* Now invalidate the instruction cache */
979994a338SPaul Mackerras
989994a338SPaul Mackerras	lwz	r7,ICACHEL1LINESIZE(r10)	/* Get Icache line size */
999994a338SPaul Mackerras	addi	r5,r7,-1
1009994a338SPaul Mackerras	andc	r6,r3,r5		/* round low to line bdy */
1019994a338SPaul Mackerras	subf	r8,r6,r4		/* compute length */
1029994a338SPaul Mackerras	add	r8,r8,r5
1039994a338SPaul Mackerras	lwz	r9,ICACHEL1LOGLINESIZE(r10)	/* Get log-2 of Icache line size */
1049994a338SPaul Mackerras	srw.	r8,r8,r9		/* compute line count */
1059994a338SPaul Mackerras	beqlr				/* nothing to do? */
1069994a338SPaul Mackerras	mtctr	r8
1079994a338SPaul Mackerras2:	icbi	0,r6
1089994a338SPaul Mackerras	add	r6,r6,r7
1099994a338SPaul Mackerras	bdnz	2b
1109994a338SPaul Mackerras	isync
1119994a338SPaul Mackerras	blr
1129994a338SPaul Mackerras	.previous .text
1139994a338SPaul Mackerras/*
1149994a338SPaul Mackerras * Like above, but only do the D-cache.
1159994a338SPaul Mackerras *
1169994a338SPaul Mackerras * flush_dcache_range(unsigned long start, unsigned long stop)
1179994a338SPaul Mackerras *
1189994a338SPaul Mackerras *    flush all bytes from start to stop-1 inclusive
1199994a338SPaul Mackerras */
1209994a338SPaul Mackerras_GLOBAL(flush_dcache_range)
1219994a338SPaul Mackerras
1229994a338SPaul Mackerras/*
1239994a338SPaul Mackerras * Flush the data cache to memory
1249994a338SPaul Mackerras *
1259994a338SPaul Mackerras * Different systems have different cache line sizes
1269994a338SPaul Mackerras */
1279994a338SPaul Mackerras 	ld	r10,PPC64_CACHES@toc(r2)
1289994a338SPaul Mackerras	lwz	r7,DCACHEL1LINESIZE(r10)	/* Get dcache line size */
1299994a338SPaul Mackerras	addi	r5,r7,-1
1309994a338SPaul Mackerras	andc	r6,r3,r5		/* round low to line bdy */
1319994a338SPaul Mackerras	subf	r8,r6,r4		/* compute length */
1329994a338SPaul Mackerras	add	r8,r8,r5		/* ensure we get enough */
1339994a338SPaul Mackerras	lwz	r9,DCACHEL1LOGLINESIZE(r10)	/* Get log-2 of dcache line size */
1349994a338SPaul Mackerras	srw.	r8,r8,r9		/* compute line count */
1359994a338SPaul Mackerras	beqlr				/* nothing to do? */
1369994a338SPaul Mackerras	mtctr	r8
1379994a338SPaul Mackerras0:	dcbst	0,r6
1389994a338SPaul Mackerras	add	r6,r6,r7
1399994a338SPaul Mackerras	bdnz	0b
1409994a338SPaul Mackerras	sync
1419994a338SPaul Mackerras	blr
1429994a338SPaul Mackerras
1439994a338SPaul Mackerras/*
1449994a338SPaul Mackerras * Like above, but works on non-mapped physical addresses.
1459994a338SPaul Mackerras * Use only for non-LPAR setups ! It also assumes real mode
1469994a338SPaul Mackerras * is cacheable. Used for flushing out the DART before using
1479994a338SPaul Mackerras * it as uncacheable memory
1489994a338SPaul Mackerras *
1499994a338SPaul Mackerras * flush_dcache_phys_range(unsigned long start, unsigned long stop)
1509994a338SPaul Mackerras *
1519994a338SPaul Mackerras *    flush all bytes from start to stop-1 inclusive
1529994a338SPaul Mackerras */
1539994a338SPaul Mackerras_GLOBAL(flush_dcache_phys_range)
1549994a338SPaul Mackerras 	ld	r10,PPC64_CACHES@toc(r2)
1559994a338SPaul Mackerras	lwz	r7,DCACHEL1LINESIZE(r10)	/* Get dcache line size */
1569994a338SPaul Mackerras	addi	r5,r7,-1
1579994a338SPaul Mackerras	andc	r6,r3,r5		/* round low to line bdy */
1589994a338SPaul Mackerras	subf	r8,r6,r4		/* compute length */
1599994a338SPaul Mackerras	add	r8,r8,r5		/* ensure we get enough */
1609994a338SPaul Mackerras	lwz	r9,DCACHEL1LOGLINESIZE(r10)	/* Get log-2 of dcache line size */
1619994a338SPaul Mackerras	srw.	r8,r8,r9		/* compute line count */
1629994a338SPaul Mackerras	beqlr				/* nothing to do? */
1639994a338SPaul Mackerras	mfmsr	r5			/* Disable MMU Data Relocation */
1649994a338SPaul Mackerras	ori	r0,r5,MSR_DR
1659994a338SPaul Mackerras	xori	r0,r0,MSR_DR
1669994a338SPaul Mackerras	sync
1679994a338SPaul Mackerras	mtmsr	r0
1689994a338SPaul Mackerras	sync
1699994a338SPaul Mackerras	isync
1709994a338SPaul Mackerras	mtctr	r8
1719994a338SPaul Mackerras0:	dcbst	0,r6
1729994a338SPaul Mackerras	add	r6,r6,r7
1739994a338SPaul Mackerras	bdnz	0b
1749994a338SPaul Mackerras	sync
1759994a338SPaul Mackerras	isync
1769994a338SPaul Mackerras	mtmsr	r5			/* Re-enable MMU Data Relocation */
1779994a338SPaul Mackerras	sync
1789994a338SPaul Mackerras	isync
1799994a338SPaul Mackerras	blr
1809994a338SPaul Mackerras
1819994a338SPaul Mackerras_GLOBAL(flush_inval_dcache_range)
1829994a338SPaul Mackerras 	ld	r10,PPC64_CACHES@toc(r2)
1839994a338SPaul Mackerras	lwz	r7,DCACHEL1LINESIZE(r10)	/* Get dcache line size */
1849994a338SPaul Mackerras	addi	r5,r7,-1
1859994a338SPaul Mackerras	andc	r6,r3,r5		/* round low to line bdy */
1869994a338SPaul Mackerras	subf	r8,r6,r4		/* compute length */
1879994a338SPaul Mackerras	add	r8,r8,r5		/* ensure we get enough */
1889994a338SPaul Mackerras	lwz	r9,DCACHEL1LOGLINESIZE(r10)/* Get log-2 of dcache line size */
1899994a338SPaul Mackerras	srw.	r8,r8,r9		/* compute line count */
1909994a338SPaul Mackerras	beqlr				/* nothing to do? */
1919994a338SPaul Mackerras	sync
1929994a338SPaul Mackerras	isync
1939994a338SPaul Mackerras	mtctr	r8
1949994a338SPaul Mackerras0:	dcbf	0,r6
1959994a338SPaul Mackerras	add	r6,r6,r7
1969994a338SPaul Mackerras	bdnz	0b
1979994a338SPaul Mackerras	sync
1989994a338SPaul Mackerras	isync
1999994a338SPaul Mackerras	blr
2009994a338SPaul Mackerras
2019994a338SPaul Mackerras
2029994a338SPaul Mackerras/*
2039994a338SPaul Mackerras * Flush a particular page from the data cache to RAM.
2049994a338SPaul Mackerras * Note: this is necessary because the instruction cache does *not*
2059994a338SPaul Mackerras * snoop from the data cache.
2069994a338SPaul Mackerras *
2079994a338SPaul Mackerras *	void __flush_dcache_icache(void *page)
2089994a338SPaul Mackerras */
2099994a338SPaul Mackerras_GLOBAL(__flush_dcache_icache)
2109994a338SPaul Mackerras/*
2119994a338SPaul Mackerras * Flush the data cache to memory
2129994a338SPaul Mackerras *
2139994a338SPaul Mackerras * Different systems have different cache line sizes
2149994a338SPaul Mackerras */
2159994a338SPaul Mackerras
2160ce63670SKevin HaoBEGIN_FTR_SECTION
2170ce63670SKevin Hao	PURGE_PREFETCHED_INS
2180ce63670SKevin Hao	blr
2190ce63670SKevin HaoEND_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
2200ce63670SKevin Hao
2219994a338SPaul Mackerras/* Flush the dcache */
2229994a338SPaul Mackerras 	ld	r7,PPC64_CACHES@toc(r2)
2239994a338SPaul Mackerras	clrrdi	r3,r3,PAGE_SHIFT           	    /* Page align */
2249994a338SPaul Mackerras	lwz	r4,DCACHEL1LINESPERPAGE(r7)	/* Get # dcache lines per page */
2259994a338SPaul Mackerras	lwz	r5,DCACHEL1LINESIZE(r7)		/* Get dcache line size */
2269994a338SPaul Mackerras	mr	r6,r3
2279994a338SPaul Mackerras	mtctr	r4
2289994a338SPaul Mackerras0:	dcbst	0,r6
2299994a338SPaul Mackerras	add	r6,r6,r5
2309994a338SPaul Mackerras	bdnz	0b
2319994a338SPaul Mackerras	sync
2329994a338SPaul Mackerras
2339994a338SPaul Mackerras/* Now invalidate the icache */
2349994a338SPaul Mackerras
2359994a338SPaul Mackerras	lwz	r4,ICACHEL1LINESPERPAGE(r7)	/* Get # icache lines per page */
2369994a338SPaul Mackerras	lwz	r5,ICACHEL1LINESIZE(r7)		/* Get icache line size */
2379994a338SPaul Mackerras	mtctr	r4
2389994a338SPaul Mackerras1:	icbi	0,r3
2399994a338SPaul Mackerras	add	r3,r3,r5
2409994a338SPaul Mackerras	bdnz	1b
2419994a338SPaul Mackerras	isync
2429994a338SPaul Mackerras	blr
2439994a338SPaul Mackerras
244ca9d7aeaSDavid Woodhouse_GLOBAL(__bswapdi2)
245ca9d7aeaSDavid Woodhouse	srdi	r8,r3,32
246ca9d7aeaSDavid Woodhouse	rlwinm	r7,r3,8,0xffffffff
247ca9d7aeaSDavid Woodhouse	rlwimi	r7,r3,24,0,7
248ca9d7aeaSDavid Woodhouse	rlwinm	r9,r8,8,0xffffffff
249ca9d7aeaSDavid Woodhouse	rlwimi	r7,r3,24,16,23
250ca9d7aeaSDavid Woodhouse	rlwimi	r9,r8,24,0,7
251ca9d7aeaSDavid Woodhouse	rlwimi	r9,r8,24,16,23
252ca9d7aeaSDavid Woodhouse	sldi	r7,r7,32
253ca9d7aeaSDavid Woodhouse	or	r3,r7,r9
254ca9d7aeaSDavid Woodhouse	blr
2553f639ee8SStephen Rothwell
2567191b615SBenjamin Herrenschmidt
2572d6f0c3aSMichael Ellerman#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
2587191b615SBenjamin Herrenschmidt_GLOBAL(rmci_on)
2597191b615SBenjamin Herrenschmidt	sync
2607191b615SBenjamin Herrenschmidt	isync
2617191b615SBenjamin Herrenschmidt	li	r3,0x100
2627191b615SBenjamin Herrenschmidt	rldicl	r3,r3,32,0
2637191b615SBenjamin Herrenschmidt	mfspr	r5,SPRN_HID4
2647191b615SBenjamin Herrenschmidt	or	r5,r5,r3
2657191b615SBenjamin Herrenschmidt	sync
2667191b615SBenjamin Herrenschmidt	mtspr	SPRN_HID4,r5
2677191b615SBenjamin Herrenschmidt	isync
2687191b615SBenjamin Herrenschmidt	slbia
2697191b615SBenjamin Herrenschmidt	isync
2707191b615SBenjamin Herrenschmidt	sync
2717191b615SBenjamin Herrenschmidt	blr
2727191b615SBenjamin Herrenschmidt
2737191b615SBenjamin Herrenschmidt_GLOBAL(rmci_off)
2747191b615SBenjamin Herrenschmidt	sync
2757191b615SBenjamin Herrenschmidt	isync
2767191b615SBenjamin Herrenschmidt	li	r3,0x100
2777191b615SBenjamin Herrenschmidt	rldicl	r3,r3,32,0
2787191b615SBenjamin Herrenschmidt	mfspr	r5,SPRN_HID4
2797191b615SBenjamin Herrenschmidt	andc	r5,r5,r3
2807191b615SBenjamin Herrenschmidt	sync
2817191b615SBenjamin Herrenschmidt	mtspr	SPRN_HID4,r5
2827191b615SBenjamin Herrenschmidt	isync
2837191b615SBenjamin Herrenschmidt	slbia
2847191b615SBenjamin Herrenschmidt	isync
2857191b615SBenjamin Herrenschmidt	sync
2867191b615SBenjamin Herrenschmidt	blr
2872d6f0c3aSMichael Ellerman#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
2882d6f0c3aSMichael Ellerman
2892d6f0c3aSMichael Ellerman#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
2907191b615SBenjamin Herrenschmidt
2919994a338SPaul Mackerras/*
2929994a338SPaul Mackerras * Do an IO access in real mode
2939994a338SPaul Mackerras */
2949994a338SPaul Mackerras_GLOBAL(real_readb)
2959994a338SPaul Mackerras	mfmsr	r7
2969994a338SPaul Mackerras	ori	r0,r7,MSR_DR
2979994a338SPaul Mackerras	xori	r0,r0,MSR_DR
2989994a338SPaul Mackerras	sync
2999994a338SPaul Mackerras	mtmsrd	r0
3009994a338SPaul Mackerras	sync
3019994a338SPaul Mackerras	isync
3029994a338SPaul Mackerras	mfspr	r6,SPRN_HID4
3039994a338SPaul Mackerras	rldicl	r5,r6,32,0
3049994a338SPaul Mackerras	ori	r5,r5,0x100
3059994a338SPaul Mackerras	rldicl	r5,r5,32,0
3069994a338SPaul Mackerras	sync
3079994a338SPaul Mackerras	mtspr	SPRN_HID4,r5
3089994a338SPaul Mackerras	isync
3099994a338SPaul Mackerras	slbia
3109994a338SPaul Mackerras	isync
3119994a338SPaul Mackerras	lbz	r3,0(r3)
3129994a338SPaul Mackerras	sync
3139994a338SPaul Mackerras	mtspr	SPRN_HID4,r6
3149994a338SPaul Mackerras	isync
3159994a338SPaul Mackerras	slbia
3169994a338SPaul Mackerras	isync
3179994a338SPaul Mackerras	mtmsrd	r7
3189994a338SPaul Mackerras	sync
3199994a338SPaul Mackerras	isync
3209994a338SPaul Mackerras	blr
3219994a338SPaul Mackerras
3229994a338SPaul Mackerras	/*
3239994a338SPaul Mackerras * Do an IO access in real mode
3249994a338SPaul Mackerras */
3259994a338SPaul Mackerras_GLOBAL(real_writeb)
3269994a338SPaul Mackerras	mfmsr	r7
3279994a338SPaul Mackerras	ori	r0,r7,MSR_DR
3289994a338SPaul Mackerras	xori	r0,r0,MSR_DR
3299994a338SPaul Mackerras	sync
3309994a338SPaul Mackerras	mtmsrd	r0
3319994a338SPaul Mackerras	sync
3329994a338SPaul Mackerras	isync
3339994a338SPaul Mackerras	mfspr	r6,SPRN_HID4
3349994a338SPaul Mackerras	rldicl	r5,r6,32,0
3359994a338SPaul Mackerras	ori	r5,r5,0x100
3369994a338SPaul Mackerras	rldicl	r5,r5,32,0
3379994a338SPaul Mackerras	sync
3389994a338SPaul Mackerras	mtspr	SPRN_HID4,r5
3399994a338SPaul Mackerras	isync
3409994a338SPaul Mackerras	slbia
3419994a338SPaul Mackerras	isync
3429994a338SPaul Mackerras	stb	r3,0(r4)
3439994a338SPaul Mackerras	sync
3449994a338SPaul Mackerras	mtspr	SPRN_HID4,r6
3459994a338SPaul Mackerras	isync
3469994a338SPaul Mackerras	slbia
3479994a338SPaul Mackerras	isync
3489994a338SPaul Mackerras	mtmsrd	r7
3499994a338SPaul Mackerras	sync
3509994a338SPaul Mackerras	isync
3519994a338SPaul Mackerras	blr
3529994a338SPaul Mackerras#endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */
3539994a338SPaul Mackerras
35439c870d5SOlof Johansson#ifdef CONFIG_PPC_PASEMI
35539c870d5SOlof Johansson
35639c870d5SOlof Johansson_GLOBAL(real_205_readb)
35739c870d5SOlof Johansson	mfmsr	r7
35839c870d5SOlof Johansson	ori	r0,r7,MSR_DR
35939c870d5SOlof Johansson	xori	r0,r0,MSR_DR
36039c870d5SOlof Johansson	sync
36139c870d5SOlof Johansson	mtmsrd	r0
36239c870d5SOlof Johansson	sync
36339c870d5SOlof Johansson	isync
364e55174e9SMichael Neuling	LBZCIX(R3,R0,R3)
36539c870d5SOlof Johansson	isync
36639c870d5SOlof Johansson	mtmsrd	r7
36739c870d5SOlof Johansson	sync
36839c870d5SOlof Johansson	isync
36939c870d5SOlof Johansson	blr
37039c870d5SOlof Johansson
37139c870d5SOlof Johansson_GLOBAL(real_205_writeb)
37239c870d5SOlof Johansson	mfmsr	r7
37339c870d5SOlof Johansson	ori	r0,r7,MSR_DR
37439c870d5SOlof Johansson	xori	r0,r0,MSR_DR
37539c870d5SOlof Johansson	sync
37639c870d5SOlof Johansson	mtmsrd	r0
37739c870d5SOlof Johansson	sync
37839c870d5SOlof Johansson	isync
379e55174e9SMichael Neuling	STBCIX(R3,R0,R4)
38039c870d5SOlof Johansson	isync
38139c870d5SOlof Johansson	mtmsrd	r7
38239c870d5SOlof Johansson	sync
38339c870d5SOlof Johansson	isync
38439c870d5SOlof Johansson	blr
38539c870d5SOlof Johansson
38639c870d5SOlof Johansson#endif /* CONFIG_PPC_PASEMI */
38739c870d5SOlof Johansson
38839c870d5SOlof Johansson
389e48f7eb2SDmitry Eremin-Solenikov#if defined(CONFIG_CPU_FREQ_PMAC64) || defined(CONFIG_CPU_FREQ_MAPLE)
3909994a338SPaul Mackerras/*
3914350147aSBenjamin Herrenschmidt * SCOM access functions for 970 (FX only for now)
3924350147aSBenjamin Herrenschmidt *
3934350147aSBenjamin Herrenschmidt * unsigned long scom970_read(unsigned int address);
3944350147aSBenjamin Herrenschmidt * void scom970_write(unsigned int address, unsigned long value);
3954350147aSBenjamin Herrenschmidt *
3964350147aSBenjamin Herrenschmidt * The address passed in is the 24 bits register address. This code
3974350147aSBenjamin Herrenschmidt * is 970 specific and will not check the status bits, so you should
3984350147aSBenjamin Herrenschmidt * know what you are doing.
3994350147aSBenjamin Herrenschmidt */
4004350147aSBenjamin Herrenschmidt_GLOBAL(scom970_read)
4014350147aSBenjamin Herrenschmidt	/* interrupts off */
4024350147aSBenjamin Herrenschmidt	mfmsr	r4
4034350147aSBenjamin Herrenschmidt	ori	r0,r4,MSR_EE
4044350147aSBenjamin Herrenschmidt	xori	r0,r0,MSR_EE
4054350147aSBenjamin Herrenschmidt	mtmsrd	r0,1
4064350147aSBenjamin Herrenschmidt
4074350147aSBenjamin Herrenschmidt	/* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits
4084350147aSBenjamin Herrenschmidt	 * (including parity). On current CPUs they must be 0'd,
4094350147aSBenjamin Herrenschmidt	 * and finally or in RW bit
4104350147aSBenjamin Herrenschmidt	 */
4114350147aSBenjamin Herrenschmidt	rlwinm	r3,r3,8,0,15
4124350147aSBenjamin Herrenschmidt	ori	r3,r3,0x8000
4134350147aSBenjamin Herrenschmidt
4144350147aSBenjamin Herrenschmidt	/* do the actual scom read */
4154350147aSBenjamin Herrenschmidt	sync
4164350147aSBenjamin Herrenschmidt	mtspr	SPRN_SCOMC,r3
4174350147aSBenjamin Herrenschmidt	isync
4184350147aSBenjamin Herrenschmidt	mfspr	r3,SPRN_SCOMD
4194350147aSBenjamin Herrenschmidt	isync
4204350147aSBenjamin Herrenschmidt	mfspr	r0,SPRN_SCOMC
4214350147aSBenjamin Herrenschmidt	isync
4224350147aSBenjamin Herrenschmidt
4234350147aSBenjamin Herrenschmidt	/* XXX:	fixup result on some buggy 970's (ouch ! we lost a bit, bah
4244350147aSBenjamin Herrenschmidt	 * that's the best we can do). Not implemented yet as we don't use
4254350147aSBenjamin Herrenschmidt	 * the scom on any of the bogus CPUs yet, but may have to be done
4264350147aSBenjamin Herrenschmidt	 * ultimately
4274350147aSBenjamin Herrenschmidt	 */
4284350147aSBenjamin Herrenschmidt
4294350147aSBenjamin Herrenschmidt	/* restore interrupts */
4304350147aSBenjamin Herrenschmidt	mtmsrd	r4,1
4314350147aSBenjamin Herrenschmidt	blr
4324350147aSBenjamin Herrenschmidt
4334350147aSBenjamin Herrenschmidt
4344350147aSBenjamin Herrenschmidt_GLOBAL(scom970_write)
4354350147aSBenjamin Herrenschmidt	/* interrupts off */
4364350147aSBenjamin Herrenschmidt	mfmsr	r5
4374350147aSBenjamin Herrenschmidt	ori	r0,r5,MSR_EE
4384350147aSBenjamin Herrenschmidt	xori	r0,r0,MSR_EE
4394350147aSBenjamin Herrenschmidt	mtmsrd	r0,1
4404350147aSBenjamin Herrenschmidt
4414350147aSBenjamin Herrenschmidt	/* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits
4424350147aSBenjamin Herrenschmidt	 * (including parity). On current CPUs they must be 0'd.
4434350147aSBenjamin Herrenschmidt	 */
4444350147aSBenjamin Herrenschmidt
4454350147aSBenjamin Herrenschmidt	rlwinm	r3,r3,8,0,15
4464350147aSBenjamin Herrenschmidt
4474350147aSBenjamin Herrenschmidt	sync
4484350147aSBenjamin Herrenschmidt	mtspr	SPRN_SCOMD,r4      /* write data */
4494350147aSBenjamin Herrenschmidt	isync
4504350147aSBenjamin Herrenschmidt	mtspr	SPRN_SCOMC,r3      /* write command */
4514350147aSBenjamin Herrenschmidt	isync
4524350147aSBenjamin Herrenschmidt	mfspr	3,SPRN_SCOMC
4534350147aSBenjamin Herrenschmidt	isync
4544350147aSBenjamin Herrenschmidt
4554350147aSBenjamin Herrenschmidt	/* restore interrupts */
4564350147aSBenjamin Herrenschmidt	mtmsrd	r5,1
4574350147aSBenjamin Herrenschmidt	blr
458e48f7eb2SDmitry Eremin-Solenikov#endif /* CONFIG_CPU_FREQ_PMAC64 || CONFIG_CPU_FREQ_MAPLE */
4594350147aSBenjamin Herrenschmidt
4609994a338SPaul Mackerras/* kexec_wait(phys_cpu)
4619994a338SPaul Mackerras *
4629994a338SPaul Mackerras * wait for the flag to change, indicating this kernel is going away but
4639994a338SPaul Mackerras * the slave code for the next one is at addresses 0 to 100.
4649994a338SPaul Mackerras *
4653d2cea73SMilton Miller * This is used by all slaves, even those that did not find a matching
4663d2cea73SMilton Miller * paca in the secondary startup code.
4679994a338SPaul Mackerras *
4689994a338SPaul Mackerras * Physical (hardware) cpu id should be in r3.
4699994a338SPaul Mackerras */
4709994a338SPaul Mackerras_GLOBAL(kexec_wait)
4719994a338SPaul Mackerras	bl	1f
4729994a338SPaul Mackerras1:	mflr	r5
4739994a338SPaul Mackerras	addi	r5,r5,kexec_flag-1b
4749994a338SPaul Mackerras
4759994a338SPaul Mackerras99:	HMT_LOW
4769994a338SPaul Mackerras#ifdef CONFIG_KEXEC		/* use no memory without kexec */
4779994a338SPaul Mackerras	lwz	r4,0(r5)
4789994a338SPaul Mackerras	cmpwi	0,r4,0
479ffebf5f3SSamuel Mendoza-Jonas	beq	99b
480ffebf5f3SSamuel Mendoza-Jonas#ifdef CONFIG_PPC_BOOK3S_64
481ffebf5f3SSamuel Mendoza-Jonas	li	r10,0x60
482ffebf5f3SSamuel Mendoza-Jonas	mfmsr	r11
483ffebf5f3SSamuel Mendoza-Jonas	clrrdi	r11,r11,1	/* Clear MSR_LE */
484ffebf5f3SSamuel Mendoza-Jonas	mtsrr0	r10
485ffebf5f3SSamuel Mendoza-Jonas	mtsrr1	r11
486ffebf5f3SSamuel Mendoza-Jonas	rfid
487ffebf5f3SSamuel Mendoza-Jonas#else
488ffebf5f3SSamuel Mendoza-Jonas	ba	0x60
4899994a338SPaul Mackerras#endif
490ffebf5f3SSamuel Mendoza-Jonas#endif
4919994a338SPaul Mackerras
4929994a338SPaul Mackerras/* this can be in text because we won't change it until we are
4939994a338SPaul Mackerras * running in real anyways
4949994a338SPaul Mackerras */
4959994a338SPaul Mackerraskexec_flag:
4969994a338SPaul Mackerras	.long	0
4979994a338SPaul Mackerras
4989994a338SPaul Mackerras
4999994a338SPaul Mackerras#ifdef CONFIG_KEXEC
500*cf904e30STiejun Chen#ifdef CONFIG_PPC_BOOK3E
501*cf904e30STiejun Chen/*
502*cf904e30STiejun Chen * BOOK3E has no real MMU mode, so we have to setup the initial TLB
503*cf904e30STiejun Chen * for a core to identity map v:0 to p:0.  This current implementation
504*cf904e30STiejun Chen * assumes that 1G is enough for kexec.
505*cf904e30STiejun Chen */
506*cf904e30STiejun Chenkexec_create_tlb:
507*cf904e30STiejun Chen	/*
508*cf904e30STiejun Chen	 * Invalidate all non-IPROT TLB entries to avoid any TLB conflict.
509*cf904e30STiejun Chen	 * IPROT TLB entries should be >= PAGE_OFFSET and thus not conflict.
510*cf904e30STiejun Chen	 */
511*cf904e30STiejun Chen	PPC_TLBILX_ALL(0,R0)
512*cf904e30STiejun Chen	sync
513*cf904e30STiejun Chen	isync
514*cf904e30STiejun Chen
515*cf904e30STiejun Chen	mfspr	r10,SPRN_TLB1CFG
516*cf904e30STiejun Chen	andi.	r10,r10,TLBnCFG_N_ENTRY	/* Extract # entries */
517*cf904e30STiejun Chen	subi	r10,r10,1	/* Last entry: no conflict with kernel text */
518*cf904e30STiejun Chen	lis	r9,MAS0_TLBSEL(1)@h
519*cf904e30STiejun Chen	rlwimi	r9,r10,16,4,15		/* Setup MAS0 = TLBSEL | ESEL(r9) */
520*cf904e30STiejun Chen
521*cf904e30STiejun Chen/* Set up a temp identity mapping v:0 to p:0 and return to it. */
522*cf904e30STiejun Chen#if defined(CONFIG_SMP) || defined(CONFIG_PPC_E500MC)
523*cf904e30STiejun Chen#define M_IF_NEEDED	MAS2_M
524*cf904e30STiejun Chen#else
525*cf904e30STiejun Chen#define M_IF_NEEDED	0
526*cf904e30STiejun Chen#endif
527*cf904e30STiejun Chen	mtspr	SPRN_MAS0,r9
528*cf904e30STiejun Chen
529*cf904e30STiejun Chen	lis	r9,(MAS1_VALID|MAS1_IPROT)@h
530*cf904e30STiejun Chen	ori	r9,r9,(MAS1_TSIZE(BOOK3E_PAGESZ_1GB))@l
531*cf904e30STiejun Chen	mtspr	SPRN_MAS1,r9
532*cf904e30STiejun Chen
533*cf904e30STiejun Chen	LOAD_REG_IMMEDIATE(r9, 0x0 | M_IF_NEEDED)
534*cf904e30STiejun Chen	mtspr	SPRN_MAS2,r9
535*cf904e30STiejun Chen
536*cf904e30STiejun Chen	LOAD_REG_IMMEDIATE(r9, 0x0 | MAS3_SR | MAS3_SW | MAS3_SX)
537*cf904e30STiejun Chen	mtspr	SPRN_MAS3,r9
538*cf904e30STiejun Chen	li	r9,0
539*cf904e30STiejun Chen	mtspr	SPRN_MAS7,r9
540*cf904e30STiejun Chen
541*cf904e30STiejun Chen	tlbwe
542*cf904e30STiejun Chen	isync
543*cf904e30STiejun Chen	blr
544*cf904e30STiejun Chen#endif
5459994a338SPaul Mackerras
5469994a338SPaul Mackerras/* kexec_smp_wait(void)
5479994a338SPaul Mackerras *
5489994a338SPaul Mackerras * call with interrupts off
5499994a338SPaul Mackerras * note: this is a terminal routine, it does not save lr
5509994a338SPaul Mackerras *
5519994a338SPaul Mackerras * get phys id from paca
5529994a338SPaul Mackerras * switch to real mode
5533d2cea73SMilton Miller * mark the paca as no longer used
5549994a338SPaul Mackerras * join other cpus in kexec_wait(phys_id)
5559994a338SPaul Mackerras */
5569994a338SPaul Mackerras_GLOBAL(kexec_smp_wait)
5579994a338SPaul Mackerras	lhz	r3,PACAHWCPUID(r13)
5589994a338SPaul Mackerras	bl	real_mode
5593d2cea73SMilton Miller
5603d2cea73SMilton Miller	li	r4,KEXEC_STATE_REAL_MODE
5613d2cea73SMilton Miller	stb	r4,PACAKEXECSTATE(r13)
5623d2cea73SMilton Miller	SYNC
5633d2cea73SMilton Miller
564b1576fecSAnton Blanchard	b	kexec_wait
5659994a338SPaul Mackerras
5669994a338SPaul Mackerras/*
5679994a338SPaul Mackerras * switch to real mode (turn mmu off)
5689994a338SPaul Mackerras * we use the early kernel trick that the hardware ignores bits
5699994a338SPaul Mackerras * 0 and 1 (big endian) of the effective address in real mode
5709994a338SPaul Mackerras *
5719994a338SPaul Mackerras * don't overwrite r3 here, it is live for kexec_wait above.
5729994a338SPaul Mackerras */
5739994a338SPaul Mackerrasreal_mode:	/* assume normal blr return */
574*cf904e30STiejun Chen#ifdef CONFIG_PPC_BOOK3E
575*cf904e30STiejun Chen	/* Create an identity mapping. */
576*cf904e30STiejun Chen	b	kexec_create_tlb
577*cf904e30STiejun Chen#else
5789994a338SPaul Mackerras1:	li	r9,MSR_RI
5799994a338SPaul Mackerras	li	r10,MSR_DR|MSR_IR
5809994a338SPaul Mackerras	mflr	r11		/* return address to SRR0 */
5819994a338SPaul Mackerras	mfmsr	r12
5829994a338SPaul Mackerras	andc	r9,r12,r9
5839994a338SPaul Mackerras	andc	r10,r12,r10
5849994a338SPaul Mackerras
5859994a338SPaul Mackerras	mtmsrd	r9,1
5869994a338SPaul Mackerras	mtspr	SPRN_SRR1,r10
5879994a338SPaul Mackerras	mtspr	SPRN_SRR0,r11
5889994a338SPaul Mackerras	rfid
589*cf904e30STiejun Chen#endif
5909994a338SPaul Mackerras
5919994a338SPaul Mackerras/*
5921767c8f3SMilton Miller * kexec_sequence(newstack, start, image, control, clear_all())
5939994a338SPaul Mackerras *
5949994a338SPaul Mackerras * does the grungy work with stack switching and real mode switches
5959994a338SPaul Mackerras * also does simple calls to other code
5969994a338SPaul Mackerras */
5979994a338SPaul Mackerras
5989994a338SPaul Mackerras_GLOBAL(kexec_sequence)
5999994a338SPaul Mackerras	mflr	r0
6009994a338SPaul Mackerras	std	r0,16(r1)
6019994a338SPaul Mackerras
6029994a338SPaul Mackerras	/* switch stacks to newstack -- &kexec_stack.stack */
6034ae2dcb6SKumar Gala	stdu	r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
6049994a338SPaul Mackerras	mr	r1,r3
6059994a338SPaul Mackerras
6069994a338SPaul Mackerras	li	r0,0
6079994a338SPaul Mackerras	std	r0,16(r1)
6089994a338SPaul Mackerras
6099994a338SPaul Mackerras	/* save regs for local vars on new stack.
6109994a338SPaul Mackerras	 * yes, we won't go back, but ...
6119994a338SPaul Mackerras	 */
6129994a338SPaul Mackerras	std	r31,-8(r1)
6139994a338SPaul Mackerras	std	r30,-16(r1)
6149994a338SPaul Mackerras	std	r29,-24(r1)
6159994a338SPaul Mackerras	std	r28,-32(r1)
6169994a338SPaul Mackerras	std	r27,-40(r1)
6179994a338SPaul Mackerras	std	r26,-48(r1)
6189994a338SPaul Mackerras	std	r25,-56(r1)
6199994a338SPaul Mackerras
6204ae2dcb6SKumar Gala	stdu	r1,-STACK_FRAME_OVERHEAD-64(r1)
6219994a338SPaul Mackerras
6229994a338SPaul Mackerras	/* save args into preserved regs */
6239994a338SPaul Mackerras	mr	r31,r3			/* newstack (both) */
6249994a338SPaul Mackerras	mr	r30,r4			/* start (real) */
6259994a338SPaul Mackerras	mr	r29,r5			/* image (virt) */
6269994a338SPaul Mackerras	mr	r28,r6			/* control, unused */
6279994a338SPaul Mackerras	mr	r27,r7			/* clear_all() fn desc */
6281767c8f3SMilton Miller	mr	r26,r8			/* spare */
6299994a338SPaul Mackerras	lhz	r25,PACAHWCPUID(r13)	/* get our phys cpu from paca */
6309994a338SPaul Mackerras
6319994a338SPaul Mackerras	/* disable interrupts, we are overwriting kernel data next */
6329994a338SPaul Mackerras	mfmsr	r3
6339994a338SPaul Mackerras	rlwinm	r3,r3,0,17,15
6349994a338SPaul Mackerras	mtmsrd	r3,1
6359994a338SPaul Mackerras
6369994a338SPaul Mackerras	/* copy dest pages, flush whole dest image */
6379994a338SPaul Mackerras	mr	r3,r29
638b1576fecSAnton Blanchard	bl	kexec_copy_flush	/* (image) */
6399994a338SPaul Mackerras
6409994a338SPaul Mackerras	/* turn off mmu */
6419994a338SPaul Mackerras	bl	real_mode
6429994a338SPaul Mackerras
643ee46a90bSMilton Miller	/* copy  0x100 bytes starting at start to 0 */
644ee46a90bSMilton Miller	li	r3,0
645ee46a90bSMilton Miller	mr	r4,r30		/* start, aka phys mem offset */
646ee46a90bSMilton Miller	li	r5,0x100
647ee46a90bSMilton Miller	li	r6,0
648b1576fecSAnton Blanchard	bl	copy_and_flush	/* (dest, src, copy limit, start offset) */
649ee46a90bSMilton Miller1:	/* assume normal blr return */
650ee46a90bSMilton Miller
651ee46a90bSMilton Miller	/* release other cpus to the new kernel secondary start at 0x60 */
652ee46a90bSMilton Miller	mflr	r5
653ee46a90bSMilton Miller	li	r6,1
654ee46a90bSMilton Miller	stw	r6,kexec_flag-1b(5)
655ee46a90bSMilton Miller
6569994a338SPaul Mackerras	/* clear out hardware hash page table and tlb */
657cc7efbf9SAnton Blanchard#if !defined(_CALL_ELF) || _CALL_ELF != 2
658cc7efbf9SAnton Blanchard	ld	r12,0(r27)		/* deref function descriptor */
659cc7efbf9SAnton Blanchard#else
660cc7efbf9SAnton Blanchard	mr	r12,r27
661cc7efbf9SAnton Blanchard#endif
662cc7efbf9SAnton Blanchard	mtctr	r12
6638d950cb8SGeoff Levand	bctrl				/* ppc_md.hpte_clear_all(void); */
6649994a338SPaul Mackerras
6659994a338SPaul Mackerras/*
6669994a338SPaul Mackerras *   kexec image calling is:
6679994a338SPaul Mackerras *      the first 0x100 bytes of the entry point are copied to 0
6689994a338SPaul Mackerras *
6699994a338SPaul Mackerras *      all slaves branch to slave = 0x60 (absolute)
6709994a338SPaul Mackerras *              slave(phys_cpu_id);
6719994a338SPaul Mackerras *
6729994a338SPaul Mackerras *      master goes to start = entry point
6739994a338SPaul Mackerras *              start(phys_cpu_id, start, 0);
6749994a338SPaul Mackerras *
6759994a338SPaul Mackerras *
6769994a338SPaul Mackerras *   a wrapper is needed to call existing kernels, here is an approximate
6779994a338SPaul Mackerras *   description of one method:
6789994a338SPaul Mackerras *
6799994a338SPaul Mackerras * v2: (2.6.10)
6809994a338SPaul Mackerras *   start will be near the boot_block (maybe 0x100 bytes before it?)
6819994a338SPaul Mackerras *   it will have a 0x60, which will b to boot_block, where it will wait
6829994a338SPaul Mackerras *   and 0 will store phys into struct boot-block and load r3 from there,
6839994a338SPaul Mackerras *   copy kernel 0-0x100 and tell slaves to back down to 0x60 again
6849994a338SPaul Mackerras *
6859994a338SPaul Mackerras * v1: (2.6.9)
6869994a338SPaul Mackerras *    boot block will have all cpus scanning device tree to see if they
6879994a338SPaul Mackerras *    are the boot cpu ?????
6889994a338SPaul Mackerras *    other device tree differences (prop sizes, va vs pa, etc)...
6899994a338SPaul Mackerras */
6909994a338SPaul Mackerras	mr	r3,r25	# my phys cpu
6919994a338SPaul Mackerras	mr	r4,r30	# start, aka phys mem offset
6929994a338SPaul Mackerras	mtlr	4
6939994a338SPaul Mackerras	li	r5,0
6941767c8f3SMilton Miller	blr	/* image->start(physid, image->start, 0); */
6959994a338SPaul Mackerras#endif /* CONFIG_KEXEC */
6969baeaef6SRusty Russell
6979baeaef6SRusty Russell#ifdef CONFIG_MODULES
6989baeaef6SRusty Russell#if defined(_CALL_ELF) && _CALL_ELF == 2
69971ec7c55SRusty Russell
70071ec7c55SRusty Russell#ifdef CONFIG_MODVERSIONS
70171ec7c55SRusty Russell.weak __crc_TOC.
70271ec7c55SRusty Russell.section "___kcrctab+TOC.","a"
70371ec7c55SRusty Russell.globl __kcrctab_TOC.
70471ec7c55SRusty Russell__kcrctab_TOC.:
70571ec7c55SRusty Russell	.llong	__crc_TOC.
70671ec7c55SRusty Russell#endif
70771ec7c55SRusty Russell
7089baeaef6SRusty Russell/*
7099baeaef6SRusty Russell * Export a fake .TOC. since both modpost and depmod will complain otherwise.
7109baeaef6SRusty Russell * Both modpost and depmod strip the leading . so we do the same here.
7119baeaef6SRusty Russell */
7129baeaef6SRusty Russell.section "__ksymtab_strings","a"
7139baeaef6SRusty Russell__kstrtab_TOC.:
7149baeaef6SRusty Russell	.asciz "TOC."
7159baeaef6SRusty Russell
7169baeaef6SRusty Russell.section "___ksymtab+TOC.","a"
7179baeaef6SRusty Russell/* This symbol name is important: it's used by modpost to find exported syms */
7189baeaef6SRusty Russell.globl __ksymtab_TOC.
7199baeaef6SRusty Russell__ksymtab_TOC.:
7209baeaef6SRusty Russell	.llong 0 /* .value */
7219baeaef6SRusty Russell	.llong __kstrtab_TOC.
7229baeaef6SRusty Russell#endif /* ELFv2 */
7239baeaef6SRusty Russell#endif /* MODULES */
724