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