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