1*2874c5fdSThomas 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 * Like above, but only do the D-cache. 1149994a338SPaul Mackerras * 1159994a338SPaul Mackerras * flush_dcache_range(unsigned long start, unsigned long stop) 1169994a338SPaul Mackerras * 1179994a338SPaul Mackerras * flush all bytes from start to stop-1 inclusive 1189994a338SPaul Mackerras */ 1198f5f525dSOliver O'Halloran_GLOBAL_TOC(flush_dcache_range) 1209994a338SPaul Mackerras 1219994a338SPaul Mackerras/* 1229994a338SPaul Mackerras * Flush the data cache to memory 1239994a338SPaul Mackerras * 1249994a338SPaul Mackerras * Different systems have different cache line sizes 1259994a338SPaul Mackerras */ 1269994a338SPaul Mackerras ld r10,PPC64_CACHES@toc(r2) 127bd067f83SBenjamin Herrenschmidt lwz r7,DCACHEL1BLOCKSIZE(r10) /* Get dcache block size */ 1289994a338SPaul Mackerras addi r5,r7,-1 1299994a338SPaul Mackerras andc r6,r3,r5 /* round low to line bdy */ 1309994a338SPaul Mackerras subf r8,r6,r4 /* compute length */ 1319994a338SPaul Mackerras add r8,r8,r5 /* ensure we get enough */ 132bd067f83SBenjamin Herrenschmidt lwz r9,DCACHEL1LOGBLOCKSIZE(r10) /* Get log-2 of dcache block size */ 1339994a338SPaul Mackerras srw. r8,r8,r9 /* compute line count */ 1349994a338SPaul Mackerras beqlr /* nothing to do? */ 1359994a338SPaul Mackerras mtctr r8 1369994a338SPaul Mackerras0: dcbst 0,r6 1379994a338SPaul Mackerras add r6,r6,r7 1389994a338SPaul Mackerras bdnz 0b 1399994a338SPaul Mackerras sync 1409994a338SPaul Mackerras blr 1419445aa1aSAl ViroEXPORT_SYMBOL(flush_dcache_range) 1429994a338SPaul Mackerras 1439994a338SPaul Mackerras_GLOBAL(flush_inval_dcache_range) 1449994a338SPaul Mackerras ld r10,PPC64_CACHES@toc(r2) 145bd067f83SBenjamin Herrenschmidt lwz r7,DCACHEL1BLOCKSIZE(r10) /* Get dcache block size */ 1469994a338SPaul Mackerras addi r5,r7,-1 1479994a338SPaul Mackerras andc r6,r3,r5 /* round low to line bdy */ 1489994a338SPaul Mackerras subf r8,r6,r4 /* compute length */ 1499994a338SPaul Mackerras add r8,r8,r5 /* ensure we get enough */ 150bd067f83SBenjamin Herrenschmidt lwz r9,DCACHEL1LOGBLOCKSIZE(r10)/* Get log-2 of dcache block size */ 1519994a338SPaul Mackerras srw. r8,r8,r9 /* compute line count */ 1529994a338SPaul Mackerras beqlr /* nothing to do? */ 1539994a338SPaul Mackerras sync 1549994a338SPaul Mackerras isync 1559994a338SPaul Mackerras mtctr r8 1569994a338SPaul Mackerras0: dcbf 0,r6 1579994a338SPaul Mackerras add r6,r6,r7 1589994a338SPaul Mackerras bdnz 0b 1599994a338SPaul Mackerras sync 1609994a338SPaul Mackerras isync 1619994a338SPaul Mackerras blr 1629994a338SPaul Mackerras 1639994a338SPaul Mackerras 1649994a338SPaul Mackerras/* 1659994a338SPaul Mackerras * Flush a particular page from the data cache to RAM. 1669994a338SPaul Mackerras * Note: this is necessary because the instruction cache does *not* 1679994a338SPaul Mackerras * snoop from the data cache. 1689994a338SPaul Mackerras * 1699994a338SPaul Mackerras * void __flush_dcache_icache(void *page) 1709994a338SPaul Mackerras */ 1719994a338SPaul Mackerras_GLOBAL(__flush_dcache_icache) 1729994a338SPaul Mackerras/* 1739994a338SPaul Mackerras * Flush the data cache to memory 1749994a338SPaul Mackerras * 1759994a338SPaul Mackerras * Different systems have different cache line sizes 1769994a338SPaul Mackerras */ 1779994a338SPaul Mackerras 1780ce63670SKevin HaoBEGIN_FTR_SECTION 1790ce63670SKevin Hao PURGE_PREFETCHED_INS 1800ce63670SKevin Hao blr 1810ce63670SKevin HaoEND_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) 1820ce63670SKevin Hao 1839994a338SPaul Mackerras/* Flush the dcache */ 1849994a338SPaul Mackerras ld r7,PPC64_CACHES@toc(r2) 1859994a338SPaul Mackerras clrrdi r3,r3,PAGE_SHIFT /* Page align */ 186bd067f83SBenjamin Herrenschmidt lwz r4,DCACHEL1BLOCKSPERPAGE(r7) /* Get # dcache blocks per page */ 187bd067f83SBenjamin Herrenschmidt lwz r5,DCACHEL1BLOCKSIZE(r7) /* Get dcache block size */ 1889994a338SPaul Mackerras mr r6,r3 1899994a338SPaul Mackerras mtctr r4 1909994a338SPaul Mackerras0: dcbst 0,r6 1919994a338SPaul Mackerras add r6,r6,r5 1929994a338SPaul Mackerras bdnz 0b 1939994a338SPaul Mackerras sync 1949994a338SPaul Mackerras 1959994a338SPaul Mackerras/* Now invalidate the icache */ 1969994a338SPaul Mackerras 197bd067f83SBenjamin Herrenschmidt lwz r4,ICACHEL1BLOCKSPERPAGE(r7) /* Get # icache blocks per page */ 198bd067f83SBenjamin Herrenschmidt lwz r5,ICACHEL1BLOCKSIZE(r7) /* Get icache block size */ 1999994a338SPaul Mackerras mtctr r4 2009994a338SPaul Mackerras1: icbi 0,r3 2019994a338SPaul Mackerras add r3,r3,r5 2029994a338SPaul Mackerras bdnz 1b 2039994a338SPaul Mackerras isync 2049994a338SPaul Mackerras blr 2059994a338SPaul Mackerras 206ca9d7aeaSDavid Woodhouse_GLOBAL(__bswapdi2) 2079445aa1aSAl ViroEXPORT_SYMBOL(__bswapdi2) 208ca9d7aeaSDavid Woodhouse srdi r8,r3,32 209ca9d7aeaSDavid Woodhouse rlwinm r7,r3,8,0xffffffff 210ca9d7aeaSDavid Woodhouse rlwimi r7,r3,24,0,7 211ca9d7aeaSDavid Woodhouse rlwinm r9,r8,8,0xffffffff 212ca9d7aeaSDavid Woodhouse rlwimi r7,r3,24,16,23 213ca9d7aeaSDavid Woodhouse rlwimi r9,r8,24,0,7 214ca9d7aeaSDavid Woodhouse rlwimi r9,r8,24,16,23 215ca9d7aeaSDavid Woodhouse sldi r7,r7,32 216ca9d7aeaSDavid Woodhouse or r3,r7,r9 217ca9d7aeaSDavid Woodhouse blr 2183f639ee8SStephen Rothwell 2197191b615SBenjamin Herrenschmidt 2202d6f0c3aSMichael Ellerman#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX 2217191b615SBenjamin Herrenschmidt_GLOBAL(rmci_on) 2227191b615SBenjamin Herrenschmidt sync 2237191b615SBenjamin Herrenschmidt isync 2247191b615SBenjamin Herrenschmidt li r3,0x100 2257191b615SBenjamin Herrenschmidt rldicl r3,r3,32,0 2267191b615SBenjamin Herrenschmidt mfspr r5,SPRN_HID4 2277191b615SBenjamin Herrenschmidt or r5,r5,r3 2287191b615SBenjamin Herrenschmidt sync 2297191b615SBenjamin Herrenschmidt mtspr SPRN_HID4,r5 2307191b615SBenjamin Herrenschmidt isync 2317191b615SBenjamin Herrenschmidt slbia 2327191b615SBenjamin Herrenschmidt isync 2337191b615SBenjamin Herrenschmidt sync 2347191b615SBenjamin Herrenschmidt blr 2357191b615SBenjamin Herrenschmidt 2367191b615SBenjamin Herrenschmidt_GLOBAL(rmci_off) 2377191b615SBenjamin Herrenschmidt sync 2387191b615SBenjamin Herrenschmidt isync 2397191b615SBenjamin Herrenschmidt li r3,0x100 2407191b615SBenjamin Herrenschmidt rldicl r3,r3,32,0 2417191b615SBenjamin Herrenschmidt mfspr r5,SPRN_HID4 2427191b615SBenjamin Herrenschmidt andc r5,r5,r3 2437191b615SBenjamin Herrenschmidt sync 2447191b615SBenjamin Herrenschmidt mtspr SPRN_HID4,r5 2457191b615SBenjamin Herrenschmidt isync 2467191b615SBenjamin Herrenschmidt slbia 2477191b615SBenjamin Herrenschmidt isync 2487191b615SBenjamin Herrenschmidt sync 2497191b615SBenjamin Herrenschmidt blr 2502d6f0c3aSMichael Ellerman#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */ 2512d6f0c3aSMichael Ellerman 2522d6f0c3aSMichael Ellerman#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) 2537191b615SBenjamin Herrenschmidt 2549994a338SPaul Mackerras/* 2559994a338SPaul Mackerras * Do an IO access in real mode 2569994a338SPaul Mackerras */ 2579994a338SPaul Mackerras_GLOBAL(real_readb) 2589994a338SPaul Mackerras mfmsr r7 2599994a338SPaul Mackerras ori r0,r7,MSR_DR 2609994a338SPaul Mackerras xori r0,r0,MSR_DR 2619994a338SPaul Mackerras sync 2629994a338SPaul Mackerras mtmsrd r0 2639994a338SPaul Mackerras sync 2649994a338SPaul Mackerras isync 2659994a338SPaul Mackerras mfspr r6,SPRN_HID4 2669994a338SPaul Mackerras rldicl r5,r6,32,0 2679994a338SPaul Mackerras ori r5,r5,0x100 2689994a338SPaul Mackerras rldicl r5,r5,32,0 2699994a338SPaul Mackerras sync 2709994a338SPaul Mackerras mtspr SPRN_HID4,r5 2719994a338SPaul Mackerras isync 2729994a338SPaul Mackerras slbia 2739994a338SPaul Mackerras isync 2749994a338SPaul Mackerras lbz r3,0(r3) 2759994a338SPaul Mackerras sync 2769994a338SPaul Mackerras mtspr SPRN_HID4,r6 2779994a338SPaul Mackerras isync 2789994a338SPaul Mackerras slbia 2799994a338SPaul Mackerras isync 2809994a338SPaul Mackerras mtmsrd r7 2819994a338SPaul Mackerras sync 2829994a338SPaul Mackerras isync 2839994a338SPaul Mackerras blr 2849994a338SPaul Mackerras 2859994a338SPaul Mackerras /* 2869994a338SPaul Mackerras * Do an IO access in real mode 2879994a338SPaul Mackerras */ 2889994a338SPaul Mackerras_GLOBAL(real_writeb) 2899994a338SPaul Mackerras mfmsr r7 2909994a338SPaul Mackerras ori r0,r7,MSR_DR 2919994a338SPaul Mackerras xori r0,r0,MSR_DR 2929994a338SPaul Mackerras sync 2939994a338SPaul Mackerras mtmsrd r0 2949994a338SPaul Mackerras sync 2959994a338SPaul Mackerras isync 2969994a338SPaul Mackerras mfspr r6,SPRN_HID4 2979994a338SPaul Mackerras rldicl r5,r6,32,0 2989994a338SPaul Mackerras ori r5,r5,0x100 2999994a338SPaul Mackerras rldicl r5,r5,32,0 3009994a338SPaul Mackerras sync 3019994a338SPaul Mackerras mtspr SPRN_HID4,r5 3029994a338SPaul Mackerras isync 3039994a338SPaul Mackerras slbia 3049994a338SPaul Mackerras isync 3059994a338SPaul Mackerras stb r3,0(r4) 3069994a338SPaul Mackerras sync 3079994a338SPaul Mackerras mtspr SPRN_HID4,r6 3089994a338SPaul Mackerras isync 3099994a338SPaul Mackerras slbia 3109994a338SPaul Mackerras isync 3119994a338SPaul Mackerras mtmsrd r7 3129994a338SPaul Mackerras sync 3139994a338SPaul Mackerras isync 3149994a338SPaul Mackerras blr 3159994a338SPaul Mackerras#endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */ 3169994a338SPaul Mackerras 31739c870d5SOlof Johansson#ifdef CONFIG_PPC_PASEMI 31839c870d5SOlof Johansson 31939c870d5SOlof Johansson_GLOBAL(real_205_readb) 32039c870d5SOlof Johansson mfmsr r7 32139c870d5SOlof Johansson ori r0,r7,MSR_DR 32239c870d5SOlof Johansson xori r0,r0,MSR_DR 32339c870d5SOlof Johansson sync 32439c870d5SOlof Johansson mtmsrd r0 32539c870d5SOlof Johansson sync 32639c870d5SOlof Johansson isync 327e55174e9SMichael Neuling LBZCIX(R3,R0,R3) 32839c870d5SOlof Johansson isync 32939c870d5SOlof Johansson mtmsrd r7 33039c870d5SOlof Johansson sync 33139c870d5SOlof Johansson isync 33239c870d5SOlof Johansson blr 33339c870d5SOlof Johansson 33439c870d5SOlof Johansson_GLOBAL(real_205_writeb) 33539c870d5SOlof Johansson mfmsr r7 33639c870d5SOlof Johansson ori r0,r7,MSR_DR 33739c870d5SOlof Johansson xori r0,r0,MSR_DR 33839c870d5SOlof Johansson sync 33939c870d5SOlof Johansson mtmsrd r0 34039c870d5SOlof Johansson sync 34139c870d5SOlof Johansson isync 342e55174e9SMichael Neuling STBCIX(R3,R0,R4) 34339c870d5SOlof Johansson isync 34439c870d5SOlof Johansson mtmsrd r7 34539c870d5SOlof Johansson sync 34639c870d5SOlof Johansson isync 34739c870d5SOlof Johansson blr 34839c870d5SOlof Johansson 34939c870d5SOlof Johansson#endif /* CONFIG_PPC_PASEMI */ 35039c870d5SOlof Johansson 35139c870d5SOlof Johansson 352e48f7eb2SDmitry Eremin-Solenikov#if defined(CONFIG_CPU_FREQ_PMAC64) || defined(CONFIG_CPU_FREQ_MAPLE) 3539994a338SPaul Mackerras/* 3544350147aSBenjamin Herrenschmidt * SCOM access functions for 970 (FX only for now) 3554350147aSBenjamin Herrenschmidt * 3564350147aSBenjamin Herrenschmidt * unsigned long scom970_read(unsigned int address); 3574350147aSBenjamin Herrenschmidt * void scom970_write(unsigned int address, unsigned long value); 3584350147aSBenjamin Herrenschmidt * 3594350147aSBenjamin Herrenschmidt * The address passed in is the 24 bits register address. This code 3604350147aSBenjamin Herrenschmidt * is 970 specific and will not check the status bits, so you should 3614350147aSBenjamin Herrenschmidt * know what you are doing. 3624350147aSBenjamin Herrenschmidt */ 3634350147aSBenjamin Herrenschmidt_GLOBAL(scom970_read) 3644350147aSBenjamin Herrenschmidt /* interrupts off */ 3654350147aSBenjamin Herrenschmidt mfmsr r4 3664350147aSBenjamin Herrenschmidt ori r0,r4,MSR_EE 3674350147aSBenjamin Herrenschmidt xori r0,r0,MSR_EE 3684350147aSBenjamin Herrenschmidt mtmsrd r0,1 3694350147aSBenjamin Herrenschmidt 3704350147aSBenjamin Herrenschmidt /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits 3714350147aSBenjamin Herrenschmidt * (including parity). On current CPUs they must be 0'd, 3724350147aSBenjamin Herrenschmidt * and finally or in RW bit 3734350147aSBenjamin Herrenschmidt */ 3744350147aSBenjamin Herrenschmidt rlwinm r3,r3,8,0,15 3754350147aSBenjamin Herrenschmidt ori r3,r3,0x8000 3764350147aSBenjamin Herrenschmidt 3774350147aSBenjamin Herrenschmidt /* do the actual scom read */ 3784350147aSBenjamin Herrenschmidt sync 3794350147aSBenjamin Herrenschmidt mtspr SPRN_SCOMC,r3 3804350147aSBenjamin Herrenschmidt isync 3814350147aSBenjamin Herrenschmidt mfspr r3,SPRN_SCOMD 3824350147aSBenjamin Herrenschmidt isync 3834350147aSBenjamin Herrenschmidt mfspr r0,SPRN_SCOMC 3844350147aSBenjamin Herrenschmidt isync 3854350147aSBenjamin Herrenschmidt 3864350147aSBenjamin Herrenschmidt /* XXX: fixup result on some buggy 970's (ouch ! we lost a bit, bah 3874350147aSBenjamin Herrenschmidt * that's the best we can do). Not implemented yet as we don't use 3884350147aSBenjamin Herrenschmidt * the scom on any of the bogus CPUs yet, but may have to be done 3894350147aSBenjamin Herrenschmidt * ultimately 3904350147aSBenjamin Herrenschmidt */ 3914350147aSBenjamin Herrenschmidt 3924350147aSBenjamin Herrenschmidt /* restore interrupts */ 3934350147aSBenjamin Herrenschmidt mtmsrd r4,1 3944350147aSBenjamin Herrenschmidt blr 3954350147aSBenjamin Herrenschmidt 3964350147aSBenjamin Herrenschmidt 3974350147aSBenjamin Herrenschmidt_GLOBAL(scom970_write) 3984350147aSBenjamin Herrenschmidt /* interrupts off */ 3994350147aSBenjamin Herrenschmidt mfmsr r5 4004350147aSBenjamin Herrenschmidt ori r0,r5,MSR_EE 4014350147aSBenjamin Herrenschmidt xori r0,r0,MSR_EE 4024350147aSBenjamin Herrenschmidt mtmsrd r0,1 4034350147aSBenjamin Herrenschmidt 4044350147aSBenjamin Herrenschmidt /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits 4054350147aSBenjamin Herrenschmidt * (including parity). On current CPUs they must be 0'd. 4064350147aSBenjamin Herrenschmidt */ 4074350147aSBenjamin Herrenschmidt 4084350147aSBenjamin Herrenschmidt rlwinm r3,r3,8,0,15 4094350147aSBenjamin Herrenschmidt 4104350147aSBenjamin Herrenschmidt sync 4114350147aSBenjamin Herrenschmidt mtspr SPRN_SCOMD,r4 /* write data */ 4124350147aSBenjamin Herrenschmidt isync 4134350147aSBenjamin Herrenschmidt mtspr SPRN_SCOMC,r3 /* write command */ 4144350147aSBenjamin Herrenschmidt isync 4154350147aSBenjamin Herrenschmidt mfspr 3,SPRN_SCOMC 4164350147aSBenjamin Herrenschmidt isync 4174350147aSBenjamin Herrenschmidt 4184350147aSBenjamin Herrenschmidt /* restore interrupts */ 4194350147aSBenjamin Herrenschmidt mtmsrd r5,1 4204350147aSBenjamin Herrenschmidt blr 421e48f7eb2SDmitry Eremin-Solenikov#endif /* CONFIG_CPU_FREQ_PMAC64 || CONFIG_CPU_FREQ_MAPLE */ 4224350147aSBenjamin Herrenschmidt 4239994a338SPaul Mackerras/* kexec_wait(phys_cpu) 4249994a338SPaul Mackerras * 4259994a338SPaul Mackerras * wait for the flag to change, indicating this kernel is going away but 4269994a338SPaul Mackerras * the slave code for the next one is at addresses 0 to 100. 4279994a338SPaul Mackerras * 4283d2cea73SMilton Miller * This is used by all slaves, even those that did not find a matching 4293d2cea73SMilton Miller * paca in the secondary startup code. 4309994a338SPaul Mackerras * 4319994a338SPaul Mackerras * Physical (hardware) cpu id should be in r3. 4329994a338SPaul Mackerras */ 4339994a338SPaul Mackerras_GLOBAL(kexec_wait) 4349994a338SPaul Mackerras bl 1f 4359994a338SPaul Mackerras1: mflr r5 4369994a338SPaul Mackerras addi r5,r5,kexec_flag-1b 4379994a338SPaul Mackerras 4389994a338SPaul Mackerras99: HMT_LOW 439da665885SThiago Jung Bauermann#ifdef CONFIG_KEXEC_CORE /* use no memory without kexec */ 4409994a338SPaul Mackerras lwz r4,0(r5) 4419994a338SPaul Mackerras cmpwi 0,r4,0 442ffebf5f3SSamuel Mendoza-Jonas beq 99b 443ffebf5f3SSamuel Mendoza-Jonas#ifdef CONFIG_PPC_BOOK3S_64 444ffebf5f3SSamuel Mendoza-Jonas li r10,0x60 445ffebf5f3SSamuel Mendoza-Jonas mfmsr r11 446ffebf5f3SSamuel Mendoza-Jonas clrrdi r11,r11,1 /* Clear MSR_LE */ 447ffebf5f3SSamuel Mendoza-Jonas mtsrr0 r10 448ffebf5f3SSamuel Mendoza-Jonas mtsrr1 r11 449ffebf5f3SSamuel Mendoza-Jonas rfid 450ffebf5f3SSamuel Mendoza-Jonas#else 451ae73e4ccSScott Wood /* Create TLB entry in book3e_secondary_core_init */ 452ae73e4ccSScott Wood li r4,0 453ffebf5f3SSamuel Mendoza-Jonas ba 0x60 4549994a338SPaul Mackerras#endif 455ffebf5f3SSamuel Mendoza-Jonas#endif 4569994a338SPaul Mackerras 4579994a338SPaul Mackerras/* this can be in text because we won't change it until we are 4589994a338SPaul Mackerras * running in real anyways 4599994a338SPaul Mackerras */ 4609994a338SPaul Mackerraskexec_flag: 4619994a338SPaul Mackerras .long 0 4629994a338SPaul Mackerras 4639994a338SPaul Mackerras 464da665885SThiago Jung Bauermann#ifdef CONFIG_KEXEC_CORE 465cf904e30STiejun Chen#ifdef CONFIG_PPC_BOOK3E 466cf904e30STiejun Chen/* 467cf904e30STiejun Chen * BOOK3E has no real MMU mode, so we have to setup the initial TLB 468cf904e30STiejun Chen * for a core to identity map v:0 to p:0. This current implementation 469cf904e30STiejun Chen * assumes that 1G is enough for kexec. 470cf904e30STiejun Chen */ 471cf904e30STiejun Chenkexec_create_tlb: 472cf904e30STiejun Chen /* 473cf904e30STiejun Chen * Invalidate all non-IPROT TLB entries to avoid any TLB conflict. 474cf904e30STiejun Chen * IPROT TLB entries should be >= PAGE_OFFSET and thus not conflict. 475cf904e30STiejun Chen */ 476cf904e30STiejun Chen PPC_TLBILX_ALL(0,R0) 477cf904e30STiejun Chen sync 478cf904e30STiejun Chen isync 479cf904e30STiejun Chen 480cf904e30STiejun Chen mfspr r10,SPRN_TLB1CFG 481cf904e30STiejun Chen andi. r10,r10,TLBnCFG_N_ENTRY /* Extract # entries */ 482cf904e30STiejun Chen subi r10,r10,1 /* Last entry: no conflict with kernel text */ 483cf904e30STiejun Chen lis r9,MAS0_TLBSEL(1)@h 484cf904e30STiejun Chen rlwimi r9,r10,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r9) */ 485cf904e30STiejun Chen 486cf904e30STiejun Chen/* Set up a temp identity mapping v:0 to p:0 and return to it. */ 487cf904e30STiejun Chen#if defined(CONFIG_SMP) || defined(CONFIG_PPC_E500MC) 488cf904e30STiejun Chen#define M_IF_NEEDED MAS2_M 489cf904e30STiejun Chen#else 490cf904e30STiejun Chen#define M_IF_NEEDED 0 491cf904e30STiejun Chen#endif 492cf904e30STiejun Chen mtspr SPRN_MAS0,r9 493cf904e30STiejun Chen 494cf904e30STiejun Chen lis r9,(MAS1_VALID|MAS1_IPROT)@h 495cf904e30STiejun Chen ori r9,r9,(MAS1_TSIZE(BOOK3E_PAGESZ_1GB))@l 496cf904e30STiejun Chen mtspr SPRN_MAS1,r9 497cf904e30STiejun Chen 498cf904e30STiejun Chen LOAD_REG_IMMEDIATE(r9, 0x0 | M_IF_NEEDED) 499cf904e30STiejun Chen mtspr SPRN_MAS2,r9 500cf904e30STiejun Chen 501cf904e30STiejun Chen LOAD_REG_IMMEDIATE(r9, 0x0 | MAS3_SR | MAS3_SW | MAS3_SX) 502cf904e30STiejun Chen mtspr SPRN_MAS3,r9 503cf904e30STiejun Chen li r9,0 504cf904e30STiejun Chen mtspr SPRN_MAS7,r9 505cf904e30STiejun Chen 506cf904e30STiejun Chen tlbwe 507cf904e30STiejun Chen isync 508cf904e30STiejun Chen blr 509cf904e30STiejun Chen#endif 5109994a338SPaul Mackerras 5119994a338SPaul Mackerras/* kexec_smp_wait(void) 5129994a338SPaul Mackerras * 5139994a338SPaul Mackerras * call with interrupts off 5149994a338SPaul Mackerras * note: this is a terminal routine, it does not save lr 5159994a338SPaul Mackerras * 5169994a338SPaul Mackerras * get phys id from paca 5179994a338SPaul Mackerras * switch to real mode 5183d2cea73SMilton Miller * mark the paca as no longer used 5199994a338SPaul Mackerras * join other cpus in kexec_wait(phys_id) 5209994a338SPaul Mackerras */ 5219994a338SPaul Mackerras_GLOBAL(kexec_smp_wait) 5229994a338SPaul Mackerras lhz r3,PACAHWCPUID(r13) 5239994a338SPaul Mackerras bl real_mode 5243d2cea73SMilton Miller 5253d2cea73SMilton Miller li r4,KEXEC_STATE_REAL_MODE 5263d2cea73SMilton Miller stb r4,PACAKEXECSTATE(r13) 5273d2cea73SMilton Miller SYNC 5283d2cea73SMilton Miller 529b1576fecSAnton Blanchard b kexec_wait 5309994a338SPaul Mackerras 5319994a338SPaul Mackerras/* 5329994a338SPaul Mackerras * switch to real mode (turn mmu off) 5339994a338SPaul Mackerras * we use the early kernel trick that the hardware ignores bits 5349994a338SPaul Mackerras * 0 and 1 (big endian) of the effective address in real mode 5359994a338SPaul Mackerras * 5369994a338SPaul Mackerras * don't overwrite r3 here, it is live for kexec_wait above. 5379994a338SPaul Mackerras */ 5389994a338SPaul Mackerrasreal_mode: /* assume normal blr return */ 539cf904e30STiejun Chen#ifdef CONFIG_PPC_BOOK3E 540cf904e30STiejun Chen /* Create an identity mapping. */ 541cf904e30STiejun Chen b kexec_create_tlb 542cf904e30STiejun Chen#else 5439994a338SPaul Mackerras1: li r9,MSR_RI 5449994a338SPaul Mackerras li r10,MSR_DR|MSR_IR 5459994a338SPaul Mackerras mflr r11 /* return address to SRR0 */ 5469994a338SPaul Mackerras mfmsr r12 5479994a338SPaul Mackerras andc r9,r12,r9 5489994a338SPaul Mackerras andc r10,r12,r10 5499994a338SPaul Mackerras 5509994a338SPaul Mackerras mtmsrd r9,1 5519994a338SPaul Mackerras mtspr SPRN_SRR1,r10 5529994a338SPaul Mackerras mtspr SPRN_SRR0,r11 5539994a338SPaul Mackerras rfid 554cf904e30STiejun Chen#endif 5559994a338SPaul Mackerras 5569994a338SPaul Mackerras/* 557b970b41eSBenjamin Herrenschmidt * kexec_sequence(newstack, start, image, control, clear_all(), 558b970b41eSBenjamin Herrenschmidt copy_with_mmu_off) 5599994a338SPaul Mackerras * 5609994a338SPaul Mackerras * does the grungy work with stack switching and real mode switches 5619994a338SPaul Mackerras * also does simple calls to other code 5629994a338SPaul Mackerras */ 5639994a338SPaul Mackerras 5649994a338SPaul Mackerras_GLOBAL(kexec_sequence) 5659994a338SPaul Mackerras mflr r0 5669994a338SPaul Mackerras std r0,16(r1) 5679994a338SPaul Mackerras 5689994a338SPaul Mackerras /* switch stacks to newstack -- &kexec_stack.stack */ 5694ae2dcb6SKumar Gala stdu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3) 5709994a338SPaul Mackerras mr r1,r3 5719994a338SPaul Mackerras 5729994a338SPaul Mackerras li r0,0 5739994a338SPaul Mackerras std r0,16(r1) 5749994a338SPaul Mackerras 5751e2a516eSBalbir SinghBEGIN_FTR_SECTION 5761e2a516eSBalbir Singh /* 5771e2a516eSBalbir Singh * This is the best time to turn AMR/IAMR off. 5781e2a516eSBalbir Singh * key 0 is used in radix for supervisor<->user 5791e2a516eSBalbir Singh * protection, but on hash key 0 is reserved 5801e2a516eSBalbir Singh * ideally we want to enter with a clean state. 5811e2a516eSBalbir Singh * NOTE, we rely on r0 being 0 from above. 5821e2a516eSBalbir Singh */ 5831e2a516eSBalbir Singh mtspr SPRN_IAMR,r0 5842621e945SMichael EllermanBEGIN_FTR_SECTION_NESTED(42) 5851e2a516eSBalbir Singh mtspr SPRN_AMOR,r0 5862621e945SMichael EllermanEND_FTR_SECTION_NESTED_IFSET(CPU_FTR_HVMODE, 42) 5871e2a516eSBalbir SinghEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) 5881e2a516eSBalbir Singh 5899994a338SPaul Mackerras /* save regs for local vars on new stack. 5909994a338SPaul Mackerras * yes, we won't go back, but ... 5919994a338SPaul Mackerras */ 5929994a338SPaul Mackerras std r31,-8(r1) 5939994a338SPaul Mackerras std r30,-16(r1) 5949994a338SPaul Mackerras std r29,-24(r1) 5959994a338SPaul Mackerras std r28,-32(r1) 5969994a338SPaul Mackerras std r27,-40(r1) 5979994a338SPaul Mackerras std r26,-48(r1) 5989994a338SPaul Mackerras std r25,-56(r1) 5999994a338SPaul Mackerras 6004ae2dcb6SKumar Gala stdu r1,-STACK_FRAME_OVERHEAD-64(r1) 6019994a338SPaul Mackerras 6029994a338SPaul Mackerras /* save args into preserved regs */ 6039994a338SPaul Mackerras mr r31,r3 /* newstack (both) */ 6049994a338SPaul Mackerras mr r30,r4 /* start (real) */ 6059994a338SPaul Mackerras mr r29,r5 /* image (virt) */ 6069994a338SPaul Mackerras mr r28,r6 /* control, unused */ 6079994a338SPaul Mackerras mr r27,r7 /* clear_all() fn desc */ 608b970b41eSBenjamin Herrenschmidt mr r26,r8 /* copy_with_mmu_off */ 6099994a338SPaul Mackerras lhz r25,PACAHWCPUID(r13) /* get our phys cpu from paca */ 6109994a338SPaul Mackerras 6119994a338SPaul Mackerras /* disable interrupts, we are overwriting kernel data next */ 61296eea642STiejun Chen#ifdef CONFIG_PPC_BOOK3E 61396eea642STiejun Chen wrteei 0 61496eea642STiejun Chen#else 6159994a338SPaul Mackerras mfmsr r3 6169994a338SPaul Mackerras rlwinm r3,r3,0,17,15 6179994a338SPaul Mackerras mtmsrd r3,1 61896eea642STiejun Chen#endif 6199994a338SPaul Mackerras 620b970b41eSBenjamin Herrenschmidt /* We need to turn the MMU off unless we are in hash mode 621b970b41eSBenjamin Herrenschmidt * under a hypervisor 622b970b41eSBenjamin Herrenschmidt */ 623b970b41eSBenjamin Herrenschmidt cmpdi r26,0 624b970b41eSBenjamin Herrenschmidt beq 1f 625b970b41eSBenjamin Herrenschmidt bl real_mode 626b970b41eSBenjamin Herrenschmidt1: 6279994a338SPaul Mackerras /* copy dest pages, flush whole dest image */ 6289994a338SPaul Mackerras mr r3,r29 629b1576fecSAnton Blanchard bl kexec_copy_flush /* (image) */ 6309994a338SPaul Mackerras 631b970b41eSBenjamin Herrenschmidt /* turn off mmu now if not done earlier */ 632b970b41eSBenjamin Herrenschmidt cmpdi r26,0 633b970b41eSBenjamin Herrenschmidt bne 1f 6349994a338SPaul Mackerras bl real_mode 6359994a338SPaul Mackerras 636ee46a90bSMilton Miller /* copy 0x100 bytes starting at start to 0 */ 637b970b41eSBenjamin Herrenschmidt1: li r3,0 638ee46a90bSMilton Miller mr r4,r30 /* start, aka phys mem offset */ 639ee46a90bSMilton Miller li r5,0x100 640ee46a90bSMilton Miller li r6,0 641b1576fecSAnton Blanchard bl copy_and_flush /* (dest, src, copy limit, start offset) */ 642ee46a90bSMilton Miller1: /* assume normal blr return */ 643ee46a90bSMilton Miller 644ee46a90bSMilton Miller /* release other cpus to the new kernel secondary start at 0x60 */ 645ee46a90bSMilton Miller mflr r5 646ee46a90bSMilton Miller li r6,1 647ee46a90bSMilton Miller stw r6,kexec_flag-1b(5) 648ee46a90bSMilton Miller 649fc48bad5SBenjamin Herrenschmidt cmpdi r27,0 650fc48bad5SBenjamin Herrenschmidt beq 1f 651fc48bad5SBenjamin Herrenschmidt 6529994a338SPaul Mackerras /* clear out hardware hash page table and tlb */ 653f55d9665SMichael Ellerman#ifdef PPC64_ELF_ABI_v1 654cc7efbf9SAnton Blanchard ld r12,0(r27) /* deref function descriptor */ 655cc7efbf9SAnton Blanchard#else 656cc7efbf9SAnton Blanchard mr r12,r27 657cc7efbf9SAnton Blanchard#endif 658cc7efbf9SAnton Blanchard mtctr r12 6597025776eSBenjamin Herrenschmidt bctrl /* mmu_hash_ops.hpte_clear_all(void); */ 6609994a338SPaul Mackerras 6619994a338SPaul Mackerras/* 6629994a338SPaul Mackerras * kexec image calling is: 6639994a338SPaul Mackerras * the first 0x100 bytes of the entry point are copied to 0 6649994a338SPaul Mackerras * 6659994a338SPaul Mackerras * all slaves branch to slave = 0x60 (absolute) 6669994a338SPaul Mackerras * slave(phys_cpu_id); 6679994a338SPaul Mackerras * 6689994a338SPaul Mackerras * master goes to start = entry point 6699994a338SPaul Mackerras * start(phys_cpu_id, start, 0); 6709994a338SPaul Mackerras * 6719994a338SPaul Mackerras * 6729994a338SPaul Mackerras * a wrapper is needed to call existing kernels, here is an approximate 6739994a338SPaul Mackerras * description of one method: 6749994a338SPaul Mackerras * 6759994a338SPaul Mackerras * v2: (2.6.10) 6769994a338SPaul Mackerras * start will be near the boot_block (maybe 0x100 bytes before it?) 6779994a338SPaul Mackerras * it will have a 0x60, which will b to boot_block, where it will wait 6789994a338SPaul Mackerras * and 0 will store phys into struct boot-block and load r3 from there, 6799994a338SPaul Mackerras * copy kernel 0-0x100 and tell slaves to back down to 0x60 again 6809994a338SPaul Mackerras * 6819994a338SPaul Mackerras * v1: (2.6.9) 6829994a338SPaul Mackerras * boot block will have all cpus scanning device tree to see if they 6839994a338SPaul Mackerras * are the boot cpu ????? 6849994a338SPaul Mackerras * other device tree differences (prop sizes, va vs pa, etc)... 6859994a338SPaul Mackerras */ 686fc48bad5SBenjamin Herrenschmidt1: mr r3,r25 # my phys cpu 6879994a338SPaul Mackerras mr r4,r30 # start, aka phys mem offset 6889994a338SPaul Mackerras mtlr 4 6899994a338SPaul Mackerras li r5,0 6901767c8f3SMilton Miller blr /* image->start(physid, image->start, 0); */ 691da665885SThiago Jung Bauermann#endif /* CONFIG_KEXEC_CORE */ 692