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> 29cf904e30STiejun 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 696f698df1SNicholas Piggin_GLOBAL(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 1126f698df1SNicholas Piggin_ASM_NOKPROBE_SYMBOL(flush_icache_range) 1136f698df1SNicholas Piggin 1149994a338SPaul Mackerras/* 1159994a338SPaul Mackerras * Like above, but only do the D-cache. 1169994a338SPaul Mackerras * 1179994a338SPaul Mackerras * flush_dcache_range(unsigned long start, unsigned long stop) 1189994a338SPaul Mackerras * 1199994a338SPaul Mackerras * flush all bytes from start to stop-1 inclusive 1209994a338SPaul Mackerras */ 1219994a338SPaul Mackerras_GLOBAL(flush_dcache_range) 1229994a338SPaul Mackerras 1239994a338SPaul Mackerras/* 1249994a338SPaul Mackerras * Flush the data cache to memory 1259994a338SPaul Mackerras * 1269994a338SPaul Mackerras * Different systems have different cache line sizes 1279994a338SPaul Mackerras */ 1289994a338SPaul Mackerras ld r10,PPC64_CACHES@toc(r2) 1299994a338SPaul Mackerras lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ 1309994a338SPaul Mackerras addi r5,r7,-1 1319994a338SPaul Mackerras andc r6,r3,r5 /* round low to line bdy */ 1329994a338SPaul Mackerras subf r8,r6,r4 /* compute length */ 1339994a338SPaul Mackerras add r8,r8,r5 /* ensure we get enough */ 1349994a338SPaul Mackerras lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ 1359994a338SPaul Mackerras srw. r8,r8,r9 /* compute line count */ 1369994a338SPaul Mackerras beqlr /* nothing to do? */ 1379994a338SPaul Mackerras mtctr r8 1389994a338SPaul Mackerras0: dcbst 0,r6 1399994a338SPaul Mackerras add r6,r6,r7 1409994a338SPaul Mackerras bdnz 0b 1419994a338SPaul Mackerras sync 1429994a338SPaul Mackerras blr 1439994a338SPaul Mackerras 1449994a338SPaul Mackerras/* 1459994a338SPaul Mackerras * Like above, but works on non-mapped physical addresses. 1469994a338SPaul Mackerras * Use only for non-LPAR setups ! It also assumes real mode 1479994a338SPaul Mackerras * is cacheable. Used for flushing out the DART before using 1489994a338SPaul Mackerras * it as uncacheable memory 1499994a338SPaul Mackerras * 1509994a338SPaul Mackerras * flush_dcache_phys_range(unsigned long start, unsigned long stop) 1519994a338SPaul Mackerras * 1529994a338SPaul Mackerras * flush all bytes from start to stop-1 inclusive 1539994a338SPaul Mackerras */ 1549994a338SPaul Mackerras_GLOBAL(flush_dcache_phys_range) 1559994a338SPaul Mackerras ld r10,PPC64_CACHES@toc(r2) 1569994a338SPaul Mackerras lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ 1579994a338SPaul Mackerras addi r5,r7,-1 1589994a338SPaul Mackerras andc r6,r3,r5 /* round low to line bdy */ 1599994a338SPaul Mackerras subf r8,r6,r4 /* compute length */ 1609994a338SPaul Mackerras add r8,r8,r5 /* ensure we get enough */ 1619994a338SPaul Mackerras lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ 1629994a338SPaul Mackerras srw. r8,r8,r9 /* compute line count */ 1639994a338SPaul Mackerras beqlr /* nothing to do? */ 1649994a338SPaul Mackerras mfmsr r5 /* Disable MMU Data Relocation */ 1659994a338SPaul Mackerras ori r0,r5,MSR_DR 1669994a338SPaul Mackerras xori r0,r0,MSR_DR 1679994a338SPaul Mackerras sync 1689994a338SPaul Mackerras mtmsr r0 1699994a338SPaul Mackerras sync 1709994a338SPaul Mackerras isync 1719994a338SPaul Mackerras mtctr r8 1729994a338SPaul Mackerras0: dcbst 0,r6 1739994a338SPaul Mackerras add r6,r6,r7 1749994a338SPaul Mackerras bdnz 0b 1759994a338SPaul Mackerras sync 1769994a338SPaul Mackerras isync 1779994a338SPaul Mackerras mtmsr r5 /* Re-enable MMU Data Relocation */ 1789994a338SPaul Mackerras sync 1799994a338SPaul Mackerras isync 1809994a338SPaul Mackerras blr 1819994a338SPaul Mackerras 1829994a338SPaul Mackerras_GLOBAL(flush_inval_dcache_range) 1839994a338SPaul Mackerras ld r10,PPC64_CACHES@toc(r2) 1849994a338SPaul Mackerras lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ 1859994a338SPaul Mackerras addi r5,r7,-1 1869994a338SPaul Mackerras andc r6,r3,r5 /* round low to line bdy */ 1879994a338SPaul Mackerras subf r8,r6,r4 /* compute length */ 1889994a338SPaul Mackerras add r8,r8,r5 /* ensure we get enough */ 1899994a338SPaul Mackerras lwz r9,DCACHEL1LOGLINESIZE(r10)/* Get log-2 of dcache line size */ 1909994a338SPaul Mackerras srw. r8,r8,r9 /* compute line count */ 1919994a338SPaul Mackerras beqlr /* nothing to do? */ 1929994a338SPaul Mackerras sync 1939994a338SPaul Mackerras isync 1949994a338SPaul Mackerras mtctr r8 1959994a338SPaul Mackerras0: dcbf 0,r6 1969994a338SPaul Mackerras add r6,r6,r7 1979994a338SPaul Mackerras bdnz 0b 1989994a338SPaul Mackerras sync 1999994a338SPaul Mackerras isync 2009994a338SPaul Mackerras blr 2019994a338SPaul Mackerras 2029994a338SPaul Mackerras 2039994a338SPaul Mackerras/* 2049994a338SPaul Mackerras * Flush a particular page from the data cache to RAM. 2059994a338SPaul Mackerras * Note: this is necessary because the instruction cache does *not* 2069994a338SPaul Mackerras * snoop from the data cache. 2079994a338SPaul Mackerras * 2089994a338SPaul Mackerras * void __flush_dcache_icache(void *page) 2099994a338SPaul Mackerras */ 2109994a338SPaul Mackerras_GLOBAL(__flush_dcache_icache) 2119994a338SPaul Mackerras/* 2129994a338SPaul Mackerras * Flush the data cache to memory 2139994a338SPaul Mackerras * 2149994a338SPaul Mackerras * Different systems have different cache line sizes 2159994a338SPaul Mackerras */ 2169994a338SPaul Mackerras 2170ce63670SKevin HaoBEGIN_FTR_SECTION 2180ce63670SKevin Hao PURGE_PREFETCHED_INS 2190ce63670SKevin Hao blr 2200ce63670SKevin HaoEND_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) 2210ce63670SKevin Hao 2229994a338SPaul Mackerras/* Flush the dcache */ 2239994a338SPaul Mackerras ld r7,PPC64_CACHES@toc(r2) 2249994a338SPaul Mackerras clrrdi r3,r3,PAGE_SHIFT /* Page align */ 2259994a338SPaul Mackerras lwz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */ 2269994a338SPaul Mackerras lwz r5,DCACHEL1LINESIZE(r7) /* Get dcache line size */ 2279994a338SPaul Mackerras mr r6,r3 2289994a338SPaul Mackerras mtctr r4 2299994a338SPaul Mackerras0: dcbst 0,r6 2309994a338SPaul Mackerras add r6,r6,r5 2319994a338SPaul Mackerras bdnz 0b 2329994a338SPaul Mackerras sync 2339994a338SPaul Mackerras 2349994a338SPaul Mackerras/* Now invalidate the icache */ 2359994a338SPaul Mackerras 2369994a338SPaul Mackerras lwz r4,ICACHEL1LINESPERPAGE(r7) /* Get # icache lines per page */ 2379994a338SPaul Mackerras lwz r5,ICACHEL1LINESIZE(r7) /* Get icache line size */ 2389994a338SPaul Mackerras mtctr r4 2399994a338SPaul Mackerras1: icbi 0,r3 2409994a338SPaul Mackerras add r3,r3,r5 2419994a338SPaul Mackerras bdnz 1b 2429994a338SPaul Mackerras isync 2439994a338SPaul Mackerras blr 2449994a338SPaul Mackerras 245ca9d7aeaSDavid Woodhouse_GLOBAL(__bswapdi2) 246ca9d7aeaSDavid Woodhouse srdi r8,r3,32 247ca9d7aeaSDavid Woodhouse rlwinm r7,r3,8,0xffffffff 248ca9d7aeaSDavid Woodhouse rlwimi r7,r3,24,0,7 249ca9d7aeaSDavid Woodhouse rlwinm r9,r8,8,0xffffffff 250ca9d7aeaSDavid Woodhouse rlwimi r7,r3,24,16,23 251ca9d7aeaSDavid Woodhouse rlwimi r9,r8,24,0,7 252ca9d7aeaSDavid Woodhouse rlwimi r9,r8,24,16,23 253ca9d7aeaSDavid Woodhouse sldi r7,r7,32 254ca9d7aeaSDavid Woodhouse or r3,r7,r9 255ca9d7aeaSDavid Woodhouse blr 2563f639ee8SStephen Rothwell 2577191b615SBenjamin Herrenschmidt 2582d6f0c3aSMichael Ellerman#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX 2597191b615SBenjamin Herrenschmidt_GLOBAL(rmci_on) 2607191b615SBenjamin Herrenschmidt sync 2617191b615SBenjamin Herrenschmidt isync 2627191b615SBenjamin Herrenschmidt li r3,0x100 2637191b615SBenjamin Herrenschmidt rldicl r3,r3,32,0 2647191b615SBenjamin Herrenschmidt mfspr r5,SPRN_HID4 2657191b615SBenjamin Herrenschmidt or r5,r5,r3 2667191b615SBenjamin Herrenschmidt sync 2677191b615SBenjamin Herrenschmidt mtspr SPRN_HID4,r5 2687191b615SBenjamin Herrenschmidt isync 2697191b615SBenjamin Herrenschmidt slbia 2707191b615SBenjamin Herrenschmidt isync 2717191b615SBenjamin Herrenschmidt sync 2727191b615SBenjamin Herrenschmidt blr 2737191b615SBenjamin Herrenschmidt 2747191b615SBenjamin Herrenschmidt_GLOBAL(rmci_off) 2757191b615SBenjamin Herrenschmidt sync 2767191b615SBenjamin Herrenschmidt isync 2777191b615SBenjamin Herrenschmidt li r3,0x100 2787191b615SBenjamin Herrenschmidt rldicl r3,r3,32,0 2797191b615SBenjamin Herrenschmidt mfspr r5,SPRN_HID4 2807191b615SBenjamin Herrenschmidt andc r5,r5,r3 2817191b615SBenjamin Herrenschmidt sync 2827191b615SBenjamin Herrenschmidt mtspr SPRN_HID4,r5 2837191b615SBenjamin Herrenschmidt isync 2847191b615SBenjamin Herrenschmidt slbia 2857191b615SBenjamin Herrenschmidt isync 2867191b615SBenjamin Herrenschmidt sync 2877191b615SBenjamin Herrenschmidt blr 2882d6f0c3aSMichael Ellerman#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */ 2892d6f0c3aSMichael Ellerman 2902d6f0c3aSMichael Ellerman#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) 2917191b615SBenjamin Herrenschmidt 2929994a338SPaul Mackerras/* 2939994a338SPaul Mackerras * Do an IO access in real mode 2949994a338SPaul Mackerras */ 2959994a338SPaul Mackerras_GLOBAL(real_readb) 2969994a338SPaul Mackerras mfmsr r7 2979994a338SPaul Mackerras ori r0,r7,MSR_DR 2989994a338SPaul Mackerras xori r0,r0,MSR_DR 2999994a338SPaul Mackerras sync 3009994a338SPaul Mackerras mtmsrd r0 3019994a338SPaul Mackerras sync 3029994a338SPaul Mackerras isync 3039994a338SPaul Mackerras mfspr r6,SPRN_HID4 3049994a338SPaul Mackerras rldicl r5,r6,32,0 3059994a338SPaul Mackerras ori r5,r5,0x100 3069994a338SPaul Mackerras rldicl r5,r5,32,0 3079994a338SPaul Mackerras sync 3089994a338SPaul Mackerras mtspr SPRN_HID4,r5 3099994a338SPaul Mackerras isync 3109994a338SPaul Mackerras slbia 3119994a338SPaul Mackerras isync 3129994a338SPaul Mackerras lbz r3,0(r3) 3139994a338SPaul Mackerras sync 3149994a338SPaul Mackerras mtspr SPRN_HID4,r6 3159994a338SPaul Mackerras isync 3169994a338SPaul Mackerras slbia 3179994a338SPaul Mackerras isync 3189994a338SPaul Mackerras mtmsrd r7 3199994a338SPaul Mackerras sync 3209994a338SPaul Mackerras isync 3219994a338SPaul Mackerras blr 3229994a338SPaul Mackerras 3239994a338SPaul Mackerras /* 3249994a338SPaul Mackerras * Do an IO access in real mode 3259994a338SPaul Mackerras */ 3269994a338SPaul Mackerras_GLOBAL(real_writeb) 3279994a338SPaul Mackerras mfmsr r7 3289994a338SPaul Mackerras ori r0,r7,MSR_DR 3299994a338SPaul Mackerras xori r0,r0,MSR_DR 3309994a338SPaul Mackerras sync 3319994a338SPaul Mackerras mtmsrd r0 3329994a338SPaul Mackerras sync 3339994a338SPaul Mackerras isync 3349994a338SPaul Mackerras mfspr r6,SPRN_HID4 3359994a338SPaul Mackerras rldicl r5,r6,32,0 3369994a338SPaul Mackerras ori r5,r5,0x100 3379994a338SPaul Mackerras rldicl r5,r5,32,0 3389994a338SPaul Mackerras sync 3399994a338SPaul Mackerras mtspr SPRN_HID4,r5 3409994a338SPaul Mackerras isync 3419994a338SPaul Mackerras slbia 3429994a338SPaul Mackerras isync 3439994a338SPaul Mackerras stb r3,0(r4) 3449994a338SPaul Mackerras sync 3459994a338SPaul Mackerras mtspr SPRN_HID4,r6 3469994a338SPaul Mackerras isync 3479994a338SPaul Mackerras slbia 3489994a338SPaul Mackerras isync 3499994a338SPaul Mackerras mtmsrd r7 3509994a338SPaul Mackerras sync 3519994a338SPaul Mackerras isync 3529994a338SPaul Mackerras blr 3539994a338SPaul Mackerras#endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */ 3549994a338SPaul Mackerras 35539c870d5SOlof Johansson#ifdef CONFIG_PPC_PASEMI 35639c870d5SOlof Johansson 35739c870d5SOlof Johansson_GLOBAL(real_205_readb) 35839c870d5SOlof Johansson mfmsr r7 35939c870d5SOlof Johansson ori r0,r7,MSR_DR 36039c870d5SOlof Johansson xori r0,r0,MSR_DR 36139c870d5SOlof Johansson sync 36239c870d5SOlof Johansson mtmsrd r0 36339c870d5SOlof Johansson sync 36439c870d5SOlof Johansson isync 365e55174e9SMichael Neuling LBZCIX(R3,R0,R3) 36639c870d5SOlof Johansson isync 36739c870d5SOlof Johansson mtmsrd r7 36839c870d5SOlof Johansson sync 36939c870d5SOlof Johansson isync 37039c870d5SOlof Johansson blr 37139c870d5SOlof Johansson 37239c870d5SOlof Johansson_GLOBAL(real_205_writeb) 37339c870d5SOlof Johansson mfmsr r7 37439c870d5SOlof Johansson ori r0,r7,MSR_DR 37539c870d5SOlof Johansson xori r0,r0,MSR_DR 37639c870d5SOlof Johansson sync 37739c870d5SOlof Johansson mtmsrd r0 37839c870d5SOlof Johansson sync 37939c870d5SOlof Johansson isync 380e55174e9SMichael Neuling STBCIX(R3,R0,R4) 38139c870d5SOlof Johansson isync 38239c870d5SOlof Johansson mtmsrd r7 38339c870d5SOlof Johansson sync 38439c870d5SOlof Johansson isync 38539c870d5SOlof Johansson blr 38639c870d5SOlof Johansson 38739c870d5SOlof Johansson#endif /* CONFIG_PPC_PASEMI */ 38839c870d5SOlof Johansson 38939c870d5SOlof Johansson 390e48f7eb2SDmitry Eremin-Solenikov#if defined(CONFIG_CPU_FREQ_PMAC64) || defined(CONFIG_CPU_FREQ_MAPLE) 3919994a338SPaul Mackerras/* 3924350147aSBenjamin Herrenschmidt * SCOM access functions for 970 (FX only for now) 3934350147aSBenjamin Herrenschmidt * 3944350147aSBenjamin Herrenschmidt * unsigned long scom970_read(unsigned int address); 3954350147aSBenjamin Herrenschmidt * void scom970_write(unsigned int address, unsigned long value); 3964350147aSBenjamin Herrenschmidt * 3974350147aSBenjamin Herrenschmidt * The address passed in is the 24 bits register address. This code 3984350147aSBenjamin Herrenschmidt * is 970 specific and will not check the status bits, so you should 3994350147aSBenjamin Herrenschmidt * know what you are doing. 4004350147aSBenjamin Herrenschmidt */ 4014350147aSBenjamin Herrenschmidt_GLOBAL(scom970_read) 4024350147aSBenjamin Herrenschmidt /* interrupts off */ 4034350147aSBenjamin Herrenschmidt mfmsr r4 4044350147aSBenjamin Herrenschmidt ori r0,r4,MSR_EE 4054350147aSBenjamin Herrenschmidt xori r0,r0,MSR_EE 4064350147aSBenjamin Herrenschmidt mtmsrd r0,1 4074350147aSBenjamin Herrenschmidt 4084350147aSBenjamin Herrenschmidt /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits 4094350147aSBenjamin Herrenschmidt * (including parity). On current CPUs they must be 0'd, 4104350147aSBenjamin Herrenschmidt * and finally or in RW bit 4114350147aSBenjamin Herrenschmidt */ 4124350147aSBenjamin Herrenschmidt rlwinm r3,r3,8,0,15 4134350147aSBenjamin Herrenschmidt ori r3,r3,0x8000 4144350147aSBenjamin Herrenschmidt 4154350147aSBenjamin Herrenschmidt /* do the actual scom read */ 4164350147aSBenjamin Herrenschmidt sync 4174350147aSBenjamin Herrenschmidt mtspr SPRN_SCOMC,r3 4184350147aSBenjamin Herrenschmidt isync 4194350147aSBenjamin Herrenschmidt mfspr r3,SPRN_SCOMD 4204350147aSBenjamin Herrenschmidt isync 4214350147aSBenjamin Herrenschmidt mfspr r0,SPRN_SCOMC 4224350147aSBenjamin Herrenschmidt isync 4234350147aSBenjamin Herrenschmidt 4244350147aSBenjamin Herrenschmidt /* XXX: fixup result on some buggy 970's (ouch ! we lost a bit, bah 4254350147aSBenjamin Herrenschmidt * that's the best we can do). Not implemented yet as we don't use 4264350147aSBenjamin Herrenschmidt * the scom on any of the bogus CPUs yet, but may have to be done 4274350147aSBenjamin Herrenschmidt * ultimately 4284350147aSBenjamin Herrenschmidt */ 4294350147aSBenjamin Herrenschmidt 4304350147aSBenjamin Herrenschmidt /* restore interrupts */ 4314350147aSBenjamin Herrenschmidt mtmsrd r4,1 4324350147aSBenjamin Herrenschmidt blr 4334350147aSBenjamin Herrenschmidt 4344350147aSBenjamin Herrenschmidt 4354350147aSBenjamin Herrenschmidt_GLOBAL(scom970_write) 4364350147aSBenjamin Herrenschmidt /* interrupts off */ 4374350147aSBenjamin Herrenschmidt mfmsr r5 4384350147aSBenjamin Herrenschmidt ori r0,r5,MSR_EE 4394350147aSBenjamin Herrenschmidt xori r0,r0,MSR_EE 4404350147aSBenjamin Herrenschmidt mtmsrd r0,1 4414350147aSBenjamin Herrenschmidt 4424350147aSBenjamin Herrenschmidt /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits 4434350147aSBenjamin Herrenschmidt * (including parity). On current CPUs they must be 0'd. 4444350147aSBenjamin Herrenschmidt */ 4454350147aSBenjamin Herrenschmidt 4464350147aSBenjamin Herrenschmidt rlwinm r3,r3,8,0,15 4474350147aSBenjamin Herrenschmidt 4484350147aSBenjamin Herrenschmidt sync 4494350147aSBenjamin Herrenschmidt mtspr SPRN_SCOMD,r4 /* write data */ 4504350147aSBenjamin Herrenschmidt isync 4514350147aSBenjamin Herrenschmidt mtspr SPRN_SCOMC,r3 /* write command */ 4524350147aSBenjamin Herrenschmidt isync 4534350147aSBenjamin Herrenschmidt mfspr 3,SPRN_SCOMC 4544350147aSBenjamin Herrenschmidt isync 4554350147aSBenjamin Herrenschmidt 4564350147aSBenjamin Herrenschmidt /* restore interrupts */ 4574350147aSBenjamin Herrenschmidt mtmsrd r5,1 4584350147aSBenjamin Herrenschmidt blr 459e48f7eb2SDmitry Eremin-Solenikov#endif /* CONFIG_CPU_FREQ_PMAC64 || CONFIG_CPU_FREQ_MAPLE */ 4604350147aSBenjamin Herrenschmidt 4619994a338SPaul Mackerras/* kexec_wait(phys_cpu) 4629994a338SPaul Mackerras * 4639994a338SPaul Mackerras * wait for the flag to change, indicating this kernel is going away but 4649994a338SPaul Mackerras * the slave code for the next one is at addresses 0 to 100. 4659994a338SPaul Mackerras * 4663d2cea73SMilton Miller * This is used by all slaves, even those that did not find a matching 4673d2cea73SMilton Miller * paca in the secondary startup code. 4689994a338SPaul Mackerras * 4699994a338SPaul Mackerras * Physical (hardware) cpu id should be in r3. 4709994a338SPaul Mackerras */ 4719994a338SPaul Mackerras_GLOBAL(kexec_wait) 4729994a338SPaul Mackerras bl 1f 4739994a338SPaul Mackerras1: mflr r5 4749994a338SPaul Mackerras addi r5,r5,kexec_flag-1b 4759994a338SPaul Mackerras 4769994a338SPaul Mackerras99: HMT_LOW 4779994a338SPaul Mackerras#ifdef CONFIG_KEXEC /* use no memory without kexec */ 4789994a338SPaul Mackerras lwz r4,0(r5) 4799994a338SPaul Mackerras cmpwi 0,r4,0 480ffebf5f3SSamuel Mendoza-Jonas beq 99b 481ffebf5f3SSamuel Mendoza-Jonas#ifdef CONFIG_PPC_BOOK3S_64 482ffebf5f3SSamuel Mendoza-Jonas li r10,0x60 483ffebf5f3SSamuel Mendoza-Jonas mfmsr r11 484ffebf5f3SSamuel Mendoza-Jonas clrrdi r11,r11,1 /* Clear MSR_LE */ 485ffebf5f3SSamuel Mendoza-Jonas mtsrr0 r10 486ffebf5f3SSamuel Mendoza-Jonas mtsrr1 r11 487ffebf5f3SSamuel Mendoza-Jonas rfid 488ffebf5f3SSamuel Mendoza-Jonas#else 489ae73e4ccSScott Wood /* Create TLB entry in book3e_secondary_core_init */ 490ae73e4ccSScott Wood li r4,0 491ffebf5f3SSamuel Mendoza-Jonas ba 0x60 4929994a338SPaul Mackerras#endif 493ffebf5f3SSamuel Mendoza-Jonas#endif 4949994a338SPaul Mackerras 4959994a338SPaul Mackerras/* this can be in text because we won't change it until we are 4969994a338SPaul Mackerras * running in real anyways 4979994a338SPaul Mackerras */ 4989994a338SPaul Mackerraskexec_flag: 4999994a338SPaul Mackerras .long 0 5009994a338SPaul Mackerras 5019994a338SPaul Mackerras 5029994a338SPaul Mackerras#ifdef CONFIG_KEXEC 503cf904e30STiejun Chen#ifdef CONFIG_PPC_BOOK3E 504cf904e30STiejun Chen/* 505cf904e30STiejun Chen * BOOK3E has no real MMU mode, so we have to setup the initial TLB 506cf904e30STiejun Chen * for a core to identity map v:0 to p:0. This current implementation 507cf904e30STiejun Chen * assumes that 1G is enough for kexec. 508cf904e30STiejun Chen */ 509cf904e30STiejun Chenkexec_create_tlb: 510cf904e30STiejun Chen /* 511cf904e30STiejun Chen * Invalidate all non-IPROT TLB entries to avoid any TLB conflict. 512cf904e30STiejun Chen * IPROT TLB entries should be >= PAGE_OFFSET and thus not conflict. 513cf904e30STiejun Chen */ 514cf904e30STiejun Chen PPC_TLBILX_ALL(0,R0) 515cf904e30STiejun Chen sync 516cf904e30STiejun Chen isync 517cf904e30STiejun Chen 518cf904e30STiejun Chen mfspr r10,SPRN_TLB1CFG 519cf904e30STiejun Chen andi. r10,r10,TLBnCFG_N_ENTRY /* Extract # entries */ 520cf904e30STiejun Chen subi r10,r10,1 /* Last entry: no conflict with kernel text */ 521cf904e30STiejun Chen lis r9,MAS0_TLBSEL(1)@h 522cf904e30STiejun Chen rlwimi r9,r10,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r9) */ 523cf904e30STiejun Chen 524cf904e30STiejun Chen/* Set up a temp identity mapping v:0 to p:0 and return to it. */ 525cf904e30STiejun Chen#if defined(CONFIG_SMP) || defined(CONFIG_PPC_E500MC) 526cf904e30STiejun Chen#define M_IF_NEEDED MAS2_M 527cf904e30STiejun Chen#else 528cf904e30STiejun Chen#define M_IF_NEEDED 0 529cf904e30STiejun Chen#endif 530cf904e30STiejun Chen mtspr SPRN_MAS0,r9 531cf904e30STiejun Chen 532cf904e30STiejun Chen lis r9,(MAS1_VALID|MAS1_IPROT)@h 533cf904e30STiejun Chen ori r9,r9,(MAS1_TSIZE(BOOK3E_PAGESZ_1GB))@l 534cf904e30STiejun Chen mtspr SPRN_MAS1,r9 535cf904e30STiejun Chen 536cf904e30STiejun Chen LOAD_REG_IMMEDIATE(r9, 0x0 | M_IF_NEEDED) 537cf904e30STiejun Chen mtspr SPRN_MAS2,r9 538cf904e30STiejun Chen 539cf904e30STiejun Chen LOAD_REG_IMMEDIATE(r9, 0x0 | MAS3_SR | MAS3_SW | MAS3_SX) 540cf904e30STiejun Chen mtspr SPRN_MAS3,r9 541cf904e30STiejun Chen li r9,0 542cf904e30STiejun Chen mtspr SPRN_MAS7,r9 543cf904e30STiejun Chen 544cf904e30STiejun Chen tlbwe 545cf904e30STiejun Chen isync 546cf904e30STiejun Chen blr 547cf904e30STiejun Chen#endif 5489994a338SPaul Mackerras 5499994a338SPaul Mackerras/* kexec_smp_wait(void) 5509994a338SPaul Mackerras * 5519994a338SPaul Mackerras * call with interrupts off 5529994a338SPaul Mackerras * note: this is a terminal routine, it does not save lr 5539994a338SPaul Mackerras * 5549994a338SPaul Mackerras * get phys id from paca 5559994a338SPaul Mackerras * switch to real mode 5563d2cea73SMilton Miller * mark the paca as no longer used 5579994a338SPaul Mackerras * join other cpus in kexec_wait(phys_id) 5589994a338SPaul Mackerras */ 5599994a338SPaul Mackerras_GLOBAL(kexec_smp_wait) 5609994a338SPaul Mackerras lhz r3,PACAHWCPUID(r13) 5619994a338SPaul Mackerras bl real_mode 5623d2cea73SMilton Miller 5633d2cea73SMilton Miller li r4,KEXEC_STATE_REAL_MODE 5643d2cea73SMilton Miller stb r4,PACAKEXECSTATE(r13) 5653d2cea73SMilton Miller SYNC 5663d2cea73SMilton Miller 567b1576fecSAnton Blanchard b kexec_wait 5689994a338SPaul Mackerras 5699994a338SPaul Mackerras/* 5709994a338SPaul Mackerras * switch to real mode (turn mmu off) 5719994a338SPaul Mackerras * we use the early kernel trick that the hardware ignores bits 5729994a338SPaul Mackerras * 0 and 1 (big endian) of the effective address in real mode 5739994a338SPaul Mackerras * 5749994a338SPaul Mackerras * don't overwrite r3 here, it is live for kexec_wait above. 5759994a338SPaul Mackerras */ 5769994a338SPaul Mackerrasreal_mode: /* assume normal blr return */ 577cf904e30STiejun Chen#ifdef CONFIG_PPC_BOOK3E 578cf904e30STiejun Chen /* Create an identity mapping. */ 579cf904e30STiejun Chen b kexec_create_tlb 580cf904e30STiejun Chen#else 5819994a338SPaul Mackerras1: li r9,MSR_RI 5829994a338SPaul Mackerras li r10,MSR_DR|MSR_IR 5839994a338SPaul Mackerras mflr r11 /* return address to SRR0 */ 5849994a338SPaul Mackerras mfmsr r12 5859994a338SPaul Mackerras andc r9,r12,r9 5869994a338SPaul Mackerras andc r10,r12,r10 5879994a338SPaul Mackerras 5889994a338SPaul Mackerras mtmsrd r9,1 5899994a338SPaul Mackerras mtspr SPRN_SRR1,r10 5909994a338SPaul Mackerras mtspr SPRN_SRR0,r11 5919994a338SPaul Mackerras rfid 592cf904e30STiejun Chen#endif 5939994a338SPaul Mackerras 5949994a338SPaul Mackerras/* 5951767c8f3SMilton Miller * kexec_sequence(newstack, start, image, control, clear_all()) 5969994a338SPaul Mackerras * 5979994a338SPaul Mackerras * does the grungy work with stack switching and real mode switches 5989994a338SPaul Mackerras * also does simple calls to other code 5999994a338SPaul Mackerras */ 6009994a338SPaul Mackerras 6019994a338SPaul Mackerras_GLOBAL(kexec_sequence) 6029994a338SPaul Mackerras mflr r0 6039994a338SPaul Mackerras std r0,16(r1) 6049994a338SPaul Mackerras 6059994a338SPaul Mackerras /* switch stacks to newstack -- &kexec_stack.stack */ 6064ae2dcb6SKumar Gala stdu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3) 6079994a338SPaul Mackerras mr r1,r3 6089994a338SPaul Mackerras 6099994a338SPaul Mackerras li r0,0 6109994a338SPaul Mackerras std r0,16(r1) 6119994a338SPaul Mackerras 6129994a338SPaul Mackerras /* save regs for local vars on new stack. 6139994a338SPaul Mackerras * yes, we won't go back, but ... 6149994a338SPaul Mackerras */ 6159994a338SPaul Mackerras std r31,-8(r1) 6169994a338SPaul Mackerras std r30,-16(r1) 6179994a338SPaul Mackerras std r29,-24(r1) 6189994a338SPaul Mackerras std r28,-32(r1) 6199994a338SPaul Mackerras std r27,-40(r1) 6209994a338SPaul Mackerras std r26,-48(r1) 6219994a338SPaul Mackerras std r25,-56(r1) 6229994a338SPaul Mackerras 6234ae2dcb6SKumar Gala stdu r1,-STACK_FRAME_OVERHEAD-64(r1) 6249994a338SPaul Mackerras 6259994a338SPaul Mackerras /* save args into preserved regs */ 6269994a338SPaul Mackerras mr r31,r3 /* newstack (both) */ 6279994a338SPaul Mackerras mr r30,r4 /* start (real) */ 6289994a338SPaul Mackerras mr r29,r5 /* image (virt) */ 6299994a338SPaul Mackerras mr r28,r6 /* control, unused */ 6309994a338SPaul Mackerras mr r27,r7 /* clear_all() fn desc */ 6311767c8f3SMilton Miller mr r26,r8 /* spare */ 6329994a338SPaul Mackerras lhz r25,PACAHWCPUID(r13) /* get our phys cpu from paca */ 6339994a338SPaul Mackerras 6349994a338SPaul Mackerras /* disable interrupts, we are overwriting kernel data next */ 63596eea642STiejun Chen#ifdef CONFIG_PPC_BOOK3E 63696eea642STiejun Chen wrteei 0 63796eea642STiejun Chen#else 6389994a338SPaul Mackerras mfmsr r3 6399994a338SPaul Mackerras rlwinm r3,r3,0,17,15 6409994a338SPaul Mackerras mtmsrd r3,1 64196eea642STiejun Chen#endif 6429994a338SPaul Mackerras 6439994a338SPaul Mackerras /* copy dest pages, flush whole dest image */ 6449994a338SPaul Mackerras mr r3,r29 645b1576fecSAnton Blanchard bl kexec_copy_flush /* (image) */ 6469994a338SPaul Mackerras 6479994a338SPaul Mackerras /* turn off mmu */ 6489994a338SPaul Mackerras bl real_mode 6499994a338SPaul Mackerras 650ee46a90bSMilton Miller /* copy 0x100 bytes starting at start to 0 */ 651ee46a90bSMilton Miller li r3,0 652ee46a90bSMilton Miller mr r4,r30 /* start, aka phys mem offset */ 653ee46a90bSMilton Miller li r5,0x100 654ee46a90bSMilton Miller li r6,0 655b1576fecSAnton Blanchard bl copy_and_flush /* (dest, src, copy limit, start offset) */ 656ee46a90bSMilton Miller1: /* assume normal blr return */ 657ee46a90bSMilton Miller 658ee46a90bSMilton Miller /* release other cpus to the new kernel secondary start at 0x60 */ 659ee46a90bSMilton Miller mflr r5 660ee46a90bSMilton Miller li r6,1 661ee46a90bSMilton Miller stw r6,kexec_flag-1b(5) 662ee46a90bSMilton Miller 663*fc48bad5SBenjamin Herrenschmidt cmpdi r27,0 664*fc48bad5SBenjamin Herrenschmidt beq 1f 665*fc48bad5SBenjamin Herrenschmidt 6669994a338SPaul Mackerras /* clear out hardware hash page table and tlb */ 667f55d9665SMichael Ellerman#ifdef PPC64_ELF_ABI_v1 668cc7efbf9SAnton Blanchard ld r12,0(r27) /* deref function descriptor */ 669cc7efbf9SAnton Blanchard#else 670cc7efbf9SAnton Blanchard mr r12,r27 671cc7efbf9SAnton Blanchard#endif 672cc7efbf9SAnton Blanchard mtctr r12 6737025776eSBenjamin Herrenschmidt bctrl /* mmu_hash_ops.hpte_clear_all(void); */ 6749994a338SPaul Mackerras 6759994a338SPaul Mackerras/* 6769994a338SPaul Mackerras * kexec image calling is: 6779994a338SPaul Mackerras * the first 0x100 bytes of the entry point are copied to 0 6789994a338SPaul Mackerras * 6799994a338SPaul Mackerras * all slaves branch to slave = 0x60 (absolute) 6809994a338SPaul Mackerras * slave(phys_cpu_id); 6819994a338SPaul Mackerras * 6829994a338SPaul Mackerras * master goes to start = entry point 6839994a338SPaul Mackerras * start(phys_cpu_id, start, 0); 6849994a338SPaul Mackerras * 6859994a338SPaul Mackerras * 6869994a338SPaul Mackerras * a wrapper is needed to call existing kernels, here is an approximate 6879994a338SPaul Mackerras * description of one method: 6889994a338SPaul Mackerras * 6899994a338SPaul Mackerras * v2: (2.6.10) 6909994a338SPaul Mackerras * start will be near the boot_block (maybe 0x100 bytes before it?) 6919994a338SPaul Mackerras * it will have a 0x60, which will b to boot_block, where it will wait 6929994a338SPaul Mackerras * and 0 will store phys into struct boot-block and load r3 from there, 6939994a338SPaul Mackerras * copy kernel 0-0x100 and tell slaves to back down to 0x60 again 6949994a338SPaul Mackerras * 6959994a338SPaul Mackerras * v1: (2.6.9) 6969994a338SPaul Mackerras * boot block will have all cpus scanning device tree to see if they 6979994a338SPaul Mackerras * are the boot cpu ????? 6989994a338SPaul Mackerras * other device tree differences (prop sizes, va vs pa, etc)... 6999994a338SPaul Mackerras */ 700*fc48bad5SBenjamin Herrenschmidt1: mr r3,r25 # my phys cpu 7019994a338SPaul Mackerras mr r4,r30 # start, aka phys mem offset 7029994a338SPaul Mackerras mtlr 4 7039994a338SPaul Mackerras li r5,0 7041767c8f3SMilton Miller blr /* image->start(physid, image->start, 0); */ 7059994a338SPaul Mackerras#endif /* CONFIG_KEXEC */ 706