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 30ca9d7aeaSDavid Woodhouse_GLOBAL(__bswapdi2) 319445aa1aSAl ViroEXPORT_SYMBOL(__bswapdi2) 32ca9d7aeaSDavid Woodhouse srdi r8,r3,32 33ca9d7aeaSDavid Woodhouse rlwinm r7,r3,8,0xffffffff 34ca9d7aeaSDavid Woodhouse rlwimi r7,r3,24,0,7 35ca9d7aeaSDavid Woodhouse rlwinm r9,r8,8,0xffffffff 36ca9d7aeaSDavid Woodhouse rlwimi r7,r3,24,16,23 37ca9d7aeaSDavid Woodhouse rlwimi r9,r8,24,0,7 38ca9d7aeaSDavid Woodhouse rlwimi r9,r8,24,16,23 39ca9d7aeaSDavid Woodhouse sldi r7,r7,32 40ca9d7aeaSDavid Woodhouse or r3,r7,r9 41ca9d7aeaSDavid Woodhouse blr 423f639ee8SStephen Rothwell 437191b615SBenjamin Herrenschmidt 442d6f0c3aSMichael Ellerman#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX 457191b615SBenjamin Herrenschmidt_GLOBAL(rmci_on) 467191b615SBenjamin Herrenschmidt sync 477191b615SBenjamin Herrenschmidt isync 487191b615SBenjamin Herrenschmidt li r3,0x100 497191b615SBenjamin Herrenschmidt rldicl r3,r3,32,0 507191b615SBenjamin Herrenschmidt mfspr r5,SPRN_HID4 517191b615SBenjamin Herrenschmidt or r5,r5,r3 527191b615SBenjamin Herrenschmidt sync 537191b615SBenjamin Herrenschmidt mtspr SPRN_HID4,r5 547191b615SBenjamin Herrenschmidt isync 557191b615SBenjamin Herrenschmidt slbia 567191b615SBenjamin Herrenschmidt isync 577191b615SBenjamin Herrenschmidt sync 587191b615SBenjamin Herrenschmidt blr 597191b615SBenjamin Herrenschmidt 607191b615SBenjamin Herrenschmidt_GLOBAL(rmci_off) 617191b615SBenjamin Herrenschmidt sync 627191b615SBenjamin Herrenschmidt isync 637191b615SBenjamin Herrenschmidt li r3,0x100 647191b615SBenjamin Herrenschmidt rldicl r3,r3,32,0 657191b615SBenjamin Herrenschmidt mfspr r5,SPRN_HID4 667191b615SBenjamin Herrenschmidt andc r5,r5,r3 677191b615SBenjamin Herrenschmidt sync 687191b615SBenjamin Herrenschmidt mtspr SPRN_HID4,r5 697191b615SBenjamin Herrenschmidt isync 707191b615SBenjamin Herrenschmidt slbia 717191b615SBenjamin Herrenschmidt isync 727191b615SBenjamin Herrenschmidt sync 737191b615SBenjamin Herrenschmidt blr 742d6f0c3aSMichael Ellerman#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */ 752d6f0c3aSMichael Ellerman 762d6f0c3aSMichael Ellerman#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) 777191b615SBenjamin Herrenschmidt 789994a338SPaul Mackerras/* 799994a338SPaul Mackerras * Do an IO access in real mode 809994a338SPaul Mackerras */ 819994a338SPaul Mackerras_GLOBAL(real_readb) 829994a338SPaul Mackerras mfmsr r7 839994a338SPaul Mackerras ori r0,r7,MSR_DR 849994a338SPaul Mackerras xori r0,r0,MSR_DR 859994a338SPaul Mackerras sync 869994a338SPaul Mackerras mtmsrd r0 879994a338SPaul Mackerras sync 889994a338SPaul Mackerras isync 899994a338SPaul Mackerras mfspr r6,SPRN_HID4 909994a338SPaul Mackerras rldicl r5,r6,32,0 919994a338SPaul Mackerras ori r5,r5,0x100 929994a338SPaul Mackerras rldicl r5,r5,32,0 939994a338SPaul Mackerras sync 949994a338SPaul Mackerras mtspr SPRN_HID4,r5 959994a338SPaul Mackerras isync 969994a338SPaul Mackerras slbia 979994a338SPaul Mackerras isync 989994a338SPaul Mackerras lbz r3,0(r3) 999994a338SPaul Mackerras sync 1009994a338SPaul Mackerras mtspr SPRN_HID4,r6 1019994a338SPaul Mackerras isync 1029994a338SPaul Mackerras slbia 1039994a338SPaul Mackerras isync 1049994a338SPaul Mackerras mtmsrd r7 1059994a338SPaul Mackerras sync 1069994a338SPaul Mackerras isync 1079994a338SPaul Mackerras blr 1089994a338SPaul Mackerras 1099994a338SPaul Mackerras /* 1109994a338SPaul Mackerras * Do an IO access in real mode 1119994a338SPaul Mackerras */ 1129994a338SPaul Mackerras_GLOBAL(real_writeb) 1139994a338SPaul Mackerras mfmsr r7 1149994a338SPaul Mackerras ori r0,r7,MSR_DR 1159994a338SPaul Mackerras xori r0,r0,MSR_DR 1169994a338SPaul Mackerras sync 1179994a338SPaul Mackerras mtmsrd r0 1189994a338SPaul Mackerras sync 1199994a338SPaul Mackerras isync 1209994a338SPaul Mackerras mfspr r6,SPRN_HID4 1219994a338SPaul Mackerras rldicl r5,r6,32,0 1229994a338SPaul Mackerras ori r5,r5,0x100 1239994a338SPaul Mackerras rldicl r5,r5,32,0 1249994a338SPaul Mackerras sync 1259994a338SPaul Mackerras mtspr SPRN_HID4,r5 1269994a338SPaul Mackerras isync 1279994a338SPaul Mackerras slbia 1289994a338SPaul Mackerras isync 1299994a338SPaul Mackerras stb r3,0(r4) 1309994a338SPaul Mackerras sync 1319994a338SPaul Mackerras mtspr SPRN_HID4,r6 1329994a338SPaul Mackerras isync 1339994a338SPaul Mackerras slbia 1349994a338SPaul Mackerras isync 1359994a338SPaul Mackerras mtmsrd r7 1369994a338SPaul Mackerras sync 1379994a338SPaul Mackerras isync 1389994a338SPaul Mackerras blr 1399994a338SPaul Mackerras#endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */ 1409994a338SPaul Mackerras 14139c870d5SOlof Johansson#ifdef CONFIG_PPC_PASEMI 14239c870d5SOlof Johansson 14339c870d5SOlof Johansson_GLOBAL(real_205_readb) 14439c870d5SOlof Johansson mfmsr r7 14539c870d5SOlof Johansson ori r0,r7,MSR_DR 14639c870d5SOlof Johansson xori r0,r0,MSR_DR 14739c870d5SOlof Johansson sync 14839c870d5SOlof Johansson mtmsrd r0 14939c870d5SOlof Johansson sync 15039c870d5SOlof Johansson isync 151e55174e9SMichael Neuling LBZCIX(R3,R0,R3) 15239c870d5SOlof Johansson isync 15339c870d5SOlof Johansson mtmsrd r7 15439c870d5SOlof Johansson sync 15539c870d5SOlof Johansson isync 15639c870d5SOlof Johansson blr 15739c870d5SOlof Johansson 15839c870d5SOlof Johansson_GLOBAL(real_205_writeb) 15939c870d5SOlof Johansson mfmsr r7 16039c870d5SOlof Johansson ori r0,r7,MSR_DR 16139c870d5SOlof Johansson xori r0,r0,MSR_DR 16239c870d5SOlof Johansson sync 16339c870d5SOlof Johansson mtmsrd r0 16439c870d5SOlof Johansson sync 16539c870d5SOlof Johansson isync 166e55174e9SMichael Neuling STBCIX(R3,R0,R4) 16739c870d5SOlof Johansson isync 16839c870d5SOlof Johansson mtmsrd r7 16939c870d5SOlof Johansson sync 17039c870d5SOlof Johansson isync 17139c870d5SOlof Johansson blr 17239c870d5SOlof Johansson 17339c870d5SOlof Johansson#endif /* CONFIG_PPC_PASEMI */ 17439c870d5SOlof Johansson 17539c870d5SOlof Johansson 176e48f7eb2SDmitry Eremin-Solenikov#if defined(CONFIG_CPU_FREQ_PMAC64) || defined(CONFIG_CPU_FREQ_MAPLE) 1779994a338SPaul Mackerras/* 1784350147aSBenjamin Herrenschmidt * SCOM access functions for 970 (FX only for now) 1794350147aSBenjamin Herrenschmidt * 1804350147aSBenjamin Herrenschmidt * unsigned long scom970_read(unsigned int address); 1814350147aSBenjamin Herrenschmidt * void scom970_write(unsigned int address, unsigned long value); 1824350147aSBenjamin Herrenschmidt * 1834350147aSBenjamin Herrenschmidt * The address passed in is the 24 bits register address. This code 1844350147aSBenjamin Herrenschmidt * is 970 specific and will not check the status bits, so you should 1854350147aSBenjamin Herrenschmidt * know what you are doing. 1864350147aSBenjamin Herrenschmidt */ 1874350147aSBenjamin Herrenschmidt_GLOBAL(scom970_read) 1884350147aSBenjamin Herrenschmidt /* interrupts off */ 1894350147aSBenjamin Herrenschmidt mfmsr r4 1904350147aSBenjamin Herrenschmidt ori r0,r4,MSR_EE 1914350147aSBenjamin Herrenschmidt xori r0,r0,MSR_EE 1924350147aSBenjamin Herrenschmidt mtmsrd r0,1 1934350147aSBenjamin Herrenschmidt 1944350147aSBenjamin Herrenschmidt /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits 1954350147aSBenjamin Herrenschmidt * (including parity). On current CPUs they must be 0'd, 1964350147aSBenjamin Herrenschmidt * and finally or in RW bit 1974350147aSBenjamin Herrenschmidt */ 1984350147aSBenjamin Herrenschmidt rlwinm r3,r3,8,0,15 1994350147aSBenjamin Herrenschmidt ori r3,r3,0x8000 2004350147aSBenjamin Herrenschmidt 2014350147aSBenjamin Herrenschmidt /* do the actual scom read */ 2024350147aSBenjamin Herrenschmidt sync 2034350147aSBenjamin Herrenschmidt mtspr SPRN_SCOMC,r3 2044350147aSBenjamin Herrenschmidt isync 2054350147aSBenjamin Herrenschmidt mfspr r3,SPRN_SCOMD 2064350147aSBenjamin Herrenschmidt isync 2074350147aSBenjamin Herrenschmidt mfspr r0,SPRN_SCOMC 2084350147aSBenjamin Herrenschmidt isync 2094350147aSBenjamin Herrenschmidt 2104350147aSBenjamin Herrenschmidt /* XXX: fixup result on some buggy 970's (ouch ! we lost a bit, bah 2114350147aSBenjamin Herrenschmidt * that's the best we can do). Not implemented yet as we don't use 2124350147aSBenjamin Herrenschmidt * the scom on any of the bogus CPUs yet, but may have to be done 2134350147aSBenjamin Herrenschmidt * ultimately 2144350147aSBenjamin Herrenschmidt */ 2154350147aSBenjamin Herrenschmidt 2164350147aSBenjamin Herrenschmidt /* restore interrupts */ 2174350147aSBenjamin Herrenschmidt mtmsrd r4,1 2184350147aSBenjamin Herrenschmidt blr 2194350147aSBenjamin Herrenschmidt 2204350147aSBenjamin Herrenschmidt 2214350147aSBenjamin Herrenschmidt_GLOBAL(scom970_write) 2224350147aSBenjamin Herrenschmidt /* interrupts off */ 2234350147aSBenjamin Herrenschmidt mfmsr r5 2244350147aSBenjamin Herrenschmidt ori r0,r5,MSR_EE 2254350147aSBenjamin Herrenschmidt xori r0,r0,MSR_EE 2264350147aSBenjamin Herrenschmidt mtmsrd r0,1 2274350147aSBenjamin Herrenschmidt 2284350147aSBenjamin Herrenschmidt /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits 2294350147aSBenjamin Herrenschmidt * (including parity). On current CPUs they must be 0'd. 2304350147aSBenjamin Herrenschmidt */ 2314350147aSBenjamin Herrenschmidt 2324350147aSBenjamin Herrenschmidt rlwinm r3,r3,8,0,15 2334350147aSBenjamin Herrenschmidt 2344350147aSBenjamin Herrenschmidt sync 2354350147aSBenjamin Herrenschmidt mtspr SPRN_SCOMD,r4 /* write data */ 2364350147aSBenjamin Herrenschmidt isync 2374350147aSBenjamin Herrenschmidt mtspr SPRN_SCOMC,r3 /* write command */ 2384350147aSBenjamin Herrenschmidt isync 2394350147aSBenjamin Herrenschmidt mfspr 3,SPRN_SCOMC 2404350147aSBenjamin Herrenschmidt isync 2414350147aSBenjamin Herrenschmidt 2424350147aSBenjamin Herrenschmidt /* restore interrupts */ 2434350147aSBenjamin Herrenschmidt mtmsrd r5,1 2444350147aSBenjamin Herrenschmidt blr 245e48f7eb2SDmitry Eremin-Solenikov#endif /* CONFIG_CPU_FREQ_PMAC64 || CONFIG_CPU_FREQ_MAPLE */ 2464350147aSBenjamin Herrenschmidt 2479994a338SPaul Mackerras/* kexec_wait(phys_cpu) 2489994a338SPaul Mackerras * 2499994a338SPaul Mackerras * wait for the flag to change, indicating this kernel is going away but 2509994a338SPaul Mackerras * the slave code for the next one is at addresses 0 to 100. 2519994a338SPaul Mackerras * 2523d2cea73SMilton Miller * This is used by all slaves, even those that did not find a matching 2533d2cea73SMilton Miller * paca in the secondary startup code. 2549994a338SPaul Mackerras * 2559994a338SPaul Mackerras * Physical (hardware) cpu id should be in r3. 2569994a338SPaul Mackerras */ 2579994a338SPaul Mackerras_GLOBAL(kexec_wait) 25833e14024SChristophe Leroy bcl 20,31,$+4 2599994a338SPaul Mackerras1: mflr r5 2609994a338SPaul Mackerras addi r5,r5,kexec_flag-1b 2619994a338SPaul Mackerras 2629994a338SPaul Mackerras99: HMT_LOW 263da665885SThiago Jung Bauermann#ifdef CONFIG_KEXEC_CORE /* use no memory without kexec */ 2649994a338SPaul Mackerras lwz r4,0(r5) 2659994a338SPaul Mackerras cmpwi 0,r4,0 266ffebf5f3SSamuel Mendoza-Jonas beq 99b 267ffebf5f3SSamuel Mendoza-Jonas#ifdef CONFIG_PPC_BOOK3S_64 268ffebf5f3SSamuel Mendoza-Jonas li r10,0x60 269ffebf5f3SSamuel Mendoza-Jonas mfmsr r11 270ffebf5f3SSamuel Mendoza-Jonas clrrdi r11,r11,1 /* Clear MSR_LE */ 271ffebf5f3SSamuel Mendoza-Jonas mtsrr0 r10 272ffebf5f3SSamuel Mendoza-Jonas mtsrr1 r11 273ffebf5f3SSamuel Mendoza-Jonas rfid 274ffebf5f3SSamuel Mendoza-Jonas#else 275ae73e4ccSScott Wood /* Create TLB entry in book3e_secondary_core_init */ 276ae73e4ccSScott Wood li r4,0 277ffebf5f3SSamuel Mendoza-Jonas ba 0x60 2789994a338SPaul Mackerras#endif 279ffebf5f3SSamuel Mendoza-Jonas#endif 2809994a338SPaul Mackerras 2819994a338SPaul Mackerras/* this can be in text because we won't change it until we are 2829994a338SPaul Mackerras * running in real anyways 2839994a338SPaul Mackerras */ 2849994a338SPaul Mackerraskexec_flag: 2859994a338SPaul Mackerras .long 0 2869994a338SPaul Mackerras 2879994a338SPaul Mackerras 288da665885SThiago Jung Bauermann#ifdef CONFIG_KEXEC_CORE 289cf904e30STiejun Chen#ifdef CONFIG_PPC_BOOK3E 290cf904e30STiejun Chen/* 291cf904e30STiejun Chen * BOOK3E has no real MMU mode, so we have to setup the initial TLB 292cf904e30STiejun Chen * for a core to identity map v:0 to p:0. This current implementation 293cf904e30STiejun Chen * assumes that 1G is enough for kexec. 294cf904e30STiejun Chen */ 295cf904e30STiejun Chenkexec_create_tlb: 296cf904e30STiejun Chen /* 297cf904e30STiejun Chen * Invalidate all non-IPROT TLB entries to avoid any TLB conflict. 298cf904e30STiejun Chen * IPROT TLB entries should be >= PAGE_OFFSET and thus not conflict. 299cf904e30STiejun Chen */ 300cf904e30STiejun Chen PPC_TLBILX_ALL(0,R0) 301cf904e30STiejun Chen sync 302cf904e30STiejun Chen isync 303cf904e30STiejun Chen 304cf904e30STiejun Chen mfspr r10,SPRN_TLB1CFG 305cf904e30STiejun Chen andi. r10,r10,TLBnCFG_N_ENTRY /* Extract # entries */ 306cf904e30STiejun Chen subi r10,r10,1 /* Last entry: no conflict with kernel text */ 307cf904e30STiejun Chen lis r9,MAS0_TLBSEL(1)@h 308cf904e30STiejun Chen rlwimi r9,r10,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r9) */ 309cf904e30STiejun Chen 310cf904e30STiejun Chen/* Set up a temp identity mapping v:0 to p:0 and return to it. */ 311cf904e30STiejun Chen mtspr SPRN_MAS0,r9 312cf904e30STiejun Chen 313cf904e30STiejun Chen lis r9,(MAS1_VALID|MAS1_IPROT)@h 314cf904e30STiejun Chen ori r9,r9,(MAS1_TSIZE(BOOK3E_PAGESZ_1GB))@l 315cf904e30STiejun Chen mtspr SPRN_MAS1,r9 316cf904e30STiejun Chen 3178054df05SJason Yan LOAD_REG_IMMEDIATE(r9, 0x0 | MAS2_M_IF_NEEDED) 318cf904e30STiejun Chen mtspr SPRN_MAS2,r9 319cf904e30STiejun Chen 320cf904e30STiejun Chen LOAD_REG_IMMEDIATE(r9, 0x0 | MAS3_SR | MAS3_SW | MAS3_SX) 321cf904e30STiejun Chen mtspr SPRN_MAS3,r9 322cf904e30STiejun Chen li r9,0 323cf904e30STiejun Chen mtspr SPRN_MAS7,r9 324cf904e30STiejun Chen 325cf904e30STiejun Chen tlbwe 326cf904e30STiejun Chen isync 327cf904e30STiejun Chen blr 328cf904e30STiejun Chen#endif 3299994a338SPaul Mackerras 3309994a338SPaul Mackerras/* kexec_smp_wait(void) 3319994a338SPaul Mackerras * 3329994a338SPaul Mackerras * call with interrupts off 3339994a338SPaul Mackerras * note: this is a terminal routine, it does not save lr 3349994a338SPaul Mackerras * 3359994a338SPaul Mackerras * get phys id from paca 3369994a338SPaul Mackerras * switch to real mode 3373d2cea73SMilton Miller * mark the paca as no longer used 3389994a338SPaul Mackerras * join other cpus in kexec_wait(phys_id) 3399994a338SPaul Mackerras */ 3409994a338SPaul Mackerras_GLOBAL(kexec_smp_wait) 3419994a338SPaul Mackerras lhz r3,PACAHWCPUID(r13) 3429994a338SPaul Mackerras bl real_mode 3433d2cea73SMilton Miller 3443d2cea73SMilton Miller li r4,KEXEC_STATE_REAL_MODE 3453d2cea73SMilton Miller stb r4,PACAKEXECSTATE(r13) 3463d2cea73SMilton Miller 347b1576fecSAnton Blanchard b kexec_wait 3489994a338SPaul Mackerras 3499994a338SPaul Mackerras/* 3509994a338SPaul Mackerras * switch to real mode (turn mmu off) 3519994a338SPaul Mackerras * we use the early kernel trick that the hardware ignores bits 3529994a338SPaul Mackerras * 0 and 1 (big endian) of the effective address in real mode 3539994a338SPaul Mackerras * 3549994a338SPaul Mackerras * don't overwrite r3 here, it is live for kexec_wait above. 3559994a338SPaul Mackerras */ 3569994a338SPaul Mackerrasreal_mode: /* assume normal blr return */ 357cf904e30STiejun Chen#ifdef CONFIG_PPC_BOOK3E 358cf904e30STiejun Chen /* Create an identity mapping. */ 359cf904e30STiejun Chen b kexec_create_tlb 360cf904e30STiejun Chen#else 3619994a338SPaul Mackerras1: li r9,MSR_RI 3629994a338SPaul Mackerras li r10,MSR_DR|MSR_IR 3639994a338SPaul Mackerras mflr r11 /* return address to SRR0 */ 3649994a338SPaul Mackerras mfmsr r12 3659994a338SPaul Mackerras andc r9,r12,r9 3669994a338SPaul Mackerras andc r10,r12,r10 3679994a338SPaul Mackerras 3689994a338SPaul Mackerras mtmsrd r9,1 3699994a338SPaul Mackerras mtspr SPRN_SRR1,r10 3709994a338SPaul Mackerras mtspr SPRN_SRR0,r11 3719994a338SPaul Mackerras rfid 372cf904e30STiejun Chen#endif 3739994a338SPaul Mackerras 3749994a338SPaul Mackerras/* 375b970b41eSBenjamin Herrenschmidt * kexec_sequence(newstack, start, image, control, clear_all(), 376b970b41eSBenjamin Herrenschmidt copy_with_mmu_off) 3779994a338SPaul Mackerras * 3789994a338SPaul Mackerras * does the grungy work with stack switching and real mode switches 3799994a338SPaul Mackerras * also does simple calls to other code 3809994a338SPaul Mackerras */ 3819994a338SPaul Mackerras 3829994a338SPaul Mackerras_GLOBAL(kexec_sequence) 3839994a338SPaul Mackerras mflr r0 3849994a338SPaul Mackerras std r0,16(r1) 3859994a338SPaul Mackerras 3869994a338SPaul Mackerras /* switch stacks to newstack -- &kexec_stack.stack */ 3874ae2dcb6SKumar Gala stdu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3) 3889994a338SPaul Mackerras mr r1,r3 3899994a338SPaul Mackerras 3909994a338SPaul Mackerras li r0,0 3919994a338SPaul Mackerras std r0,16(r1) 3929994a338SPaul Mackerras 3939994a338SPaul Mackerras /* save regs for local vars on new stack. 3949994a338SPaul Mackerras * yes, we won't go back, but ... 3959994a338SPaul Mackerras */ 3969994a338SPaul Mackerras std r31,-8(r1) 3979994a338SPaul Mackerras std r30,-16(r1) 3989994a338SPaul Mackerras std r29,-24(r1) 3999994a338SPaul Mackerras std r28,-32(r1) 4009994a338SPaul Mackerras std r27,-40(r1) 4019994a338SPaul Mackerras std r26,-48(r1) 4029994a338SPaul Mackerras std r25,-56(r1) 4039994a338SPaul Mackerras 4044ae2dcb6SKumar Gala stdu r1,-STACK_FRAME_OVERHEAD-64(r1) 4059994a338SPaul Mackerras 4069994a338SPaul Mackerras /* save args into preserved regs */ 4079994a338SPaul Mackerras mr r31,r3 /* newstack (both) */ 4089994a338SPaul Mackerras mr r30,r4 /* start (real) */ 4099994a338SPaul Mackerras mr r29,r5 /* image (virt) */ 4109994a338SPaul Mackerras mr r28,r6 /* control, unused */ 4119994a338SPaul Mackerras mr r27,r7 /* clear_all() fn desc */ 412b970b41eSBenjamin Herrenschmidt mr r26,r8 /* copy_with_mmu_off */ 4139994a338SPaul Mackerras lhz r25,PACAHWCPUID(r13) /* get our phys cpu from paca */ 4149994a338SPaul Mackerras 4159994a338SPaul Mackerras /* disable interrupts, we are overwriting kernel data next */ 41696eea642STiejun Chen#ifdef CONFIG_PPC_BOOK3E 41796eea642STiejun Chen wrteei 0 41896eea642STiejun Chen#else 4199994a338SPaul Mackerras mfmsr r3 4209994a338SPaul Mackerras rlwinm r3,r3,0,17,15 4219994a338SPaul Mackerras mtmsrd r3,1 42296eea642STiejun Chen#endif 4239994a338SPaul Mackerras 424b970b41eSBenjamin Herrenschmidt /* We need to turn the MMU off unless we are in hash mode 425b970b41eSBenjamin Herrenschmidt * under a hypervisor 426b970b41eSBenjamin Herrenschmidt */ 427b970b41eSBenjamin Herrenschmidt cmpdi r26,0 428b970b41eSBenjamin Herrenschmidt beq 1f 429b970b41eSBenjamin Herrenschmidt bl real_mode 430b970b41eSBenjamin Herrenschmidt1: 4319994a338SPaul Mackerras /* copy dest pages, flush whole dest image */ 4329994a338SPaul Mackerras mr r3,r29 433b1576fecSAnton Blanchard bl kexec_copy_flush /* (image) */ 4349994a338SPaul Mackerras 435b970b41eSBenjamin Herrenschmidt /* turn off mmu now if not done earlier */ 436b970b41eSBenjamin Herrenschmidt cmpdi r26,0 437b970b41eSBenjamin Herrenschmidt bne 1f 4389994a338SPaul Mackerras bl real_mode 4399994a338SPaul Mackerras 440ee46a90bSMilton Miller /* copy 0x100 bytes starting at start to 0 */ 441b970b41eSBenjamin Herrenschmidt1: li r3,0 442ee46a90bSMilton Miller mr r4,r30 /* start, aka phys mem offset */ 443ee46a90bSMilton Miller li r5,0x100 444ee46a90bSMilton Miller li r6,0 445b1576fecSAnton Blanchard bl copy_and_flush /* (dest, src, copy limit, start offset) */ 446ee46a90bSMilton Miller1: /* assume normal blr return */ 447ee46a90bSMilton Miller 448ee46a90bSMilton Miller /* release other cpus to the new kernel secondary start at 0x60 */ 449ee46a90bSMilton Miller mflr r5 450ee46a90bSMilton Miller li r6,1 451ee46a90bSMilton Miller stw r6,kexec_flag-1b(5) 452ee46a90bSMilton Miller 453fc48bad5SBenjamin Herrenschmidt cmpdi r27,0 454fc48bad5SBenjamin Herrenschmidt beq 1f 455fc48bad5SBenjamin Herrenschmidt 4569994a338SPaul Mackerras /* clear out hardware hash page table and tlb */ 457*7d40aff8SChristophe Leroy#ifdef CONFIG_PPC64_ELF_ABI_V1 458cc7efbf9SAnton Blanchard ld r12,0(r27) /* deref function descriptor */ 459cc7efbf9SAnton Blanchard#else 460cc7efbf9SAnton Blanchard mr r12,r27 461cc7efbf9SAnton Blanchard#endif 462cc7efbf9SAnton Blanchard mtctr r12 4637025776eSBenjamin Herrenschmidt bctrl /* mmu_hash_ops.hpte_clear_all(void); */ 4649994a338SPaul Mackerras 4659994a338SPaul Mackerras/* 4669994a338SPaul Mackerras * kexec image calling is: 4679994a338SPaul Mackerras * the first 0x100 bytes of the entry point are copied to 0 4689994a338SPaul Mackerras * 4699994a338SPaul Mackerras * all slaves branch to slave = 0x60 (absolute) 4709994a338SPaul Mackerras * slave(phys_cpu_id); 4719994a338SPaul Mackerras * 4729994a338SPaul Mackerras * master goes to start = entry point 4739994a338SPaul Mackerras * start(phys_cpu_id, start, 0); 4749994a338SPaul Mackerras * 4759994a338SPaul Mackerras * 4769994a338SPaul Mackerras * a wrapper is needed to call existing kernels, here is an approximate 4779994a338SPaul Mackerras * description of one method: 4789994a338SPaul Mackerras * 4799994a338SPaul Mackerras * v2: (2.6.10) 4809994a338SPaul Mackerras * start will be near the boot_block (maybe 0x100 bytes before it?) 4819994a338SPaul Mackerras * it will have a 0x60, which will b to boot_block, where it will wait 4829994a338SPaul Mackerras * and 0 will store phys into struct boot-block and load r3 from there, 4839994a338SPaul Mackerras * copy kernel 0-0x100 and tell slaves to back down to 0x60 again 4849994a338SPaul Mackerras * 4859994a338SPaul Mackerras * v1: (2.6.9) 4869994a338SPaul Mackerras * boot block will have all cpus scanning device tree to see if they 4879994a338SPaul Mackerras * are the boot cpu ????? 4889994a338SPaul Mackerras * other device tree differences (prop sizes, va vs pa, etc)... 4899994a338SPaul Mackerras */ 490fc48bad5SBenjamin Herrenschmidt1: mr r3,r25 # my phys cpu 4919994a338SPaul Mackerras mr r4,r30 # start, aka phys mem offset 4929994a338SPaul Mackerras mtlr 4 4939994a338SPaul Mackerras li r5,0 4941767c8f3SMilton Miller blr /* image->start(physid, image->start, 0); */ 495da665885SThiago Jung Bauermann#endif /* CONFIG_KEXEC_CORE */ 496