162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * This file contains kexec low-level functions. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com> 662306a36Sopenharmony_ci * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz 762306a36Sopenharmony_ci * PPC44x port. Copyright (C) 2011, IBM Corporation 862306a36Sopenharmony_ci * Author: Suzuki Poulose <suzuki@in.ibm.com> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <asm/reg.h> 1262306a36Sopenharmony_ci#include <asm/page.h> 1362306a36Sopenharmony_ci#include <asm/mmu.h> 1462306a36Sopenharmony_ci#include <asm/ppc_asm.h> 1562306a36Sopenharmony_ci#include <asm/kexec.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci .text 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci /* 2062306a36Sopenharmony_ci * Must be relocatable PIC code callable as a C function. 2162306a36Sopenharmony_ci */ 2262306a36Sopenharmony_ci .globl relocate_new_kernel 2362306a36Sopenharmony_cirelocate_new_kernel: 2462306a36Sopenharmony_ci /* r3 = page_list */ 2562306a36Sopenharmony_ci /* r4 = reboot_code_buffer */ 2662306a36Sopenharmony_ci /* r5 = start_address */ 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#ifdef CONFIG_PPC_85xx 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci mr r29, r3 3162306a36Sopenharmony_ci mr r30, r4 3262306a36Sopenharmony_ci mr r31, r5 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define ENTRY_MAPPING_KEXEC_SETUP 3562306a36Sopenharmony_ci#include <kernel/85xx_entry_mapping.S> 3662306a36Sopenharmony_ci#undef ENTRY_MAPPING_KEXEC_SETUP 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci mr r3, r29 3962306a36Sopenharmony_ci mr r4, r30 4062306a36Sopenharmony_ci mr r5, r31 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci li r0, 0 4362306a36Sopenharmony_ci#elif defined(CONFIG_44x) 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci /* Save our parameters */ 4662306a36Sopenharmony_ci mr r29, r3 4762306a36Sopenharmony_ci mr r30, r4 4862306a36Sopenharmony_ci mr r31, r5 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#ifdef CONFIG_PPC_47x 5162306a36Sopenharmony_ci /* Check for 47x cores */ 5262306a36Sopenharmony_ci mfspr r3,SPRN_PVR 5362306a36Sopenharmony_ci srwi r3,r3,16 5462306a36Sopenharmony_ci cmplwi cr0,r3,PVR_476FPE@h 5562306a36Sopenharmony_ci beq setup_map_47x 5662306a36Sopenharmony_ci cmplwi cr0,r3,PVR_476@h 5762306a36Sopenharmony_ci beq setup_map_47x 5862306a36Sopenharmony_ci cmplwi cr0,r3,PVR_476_ISS@h 5962306a36Sopenharmony_ci beq setup_map_47x 6062306a36Sopenharmony_ci#endif /* CONFIG_PPC_47x */ 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci/* 6362306a36Sopenharmony_ci * Code for setting up 1:1 mapping for PPC440x for KEXEC 6462306a36Sopenharmony_ci * 6562306a36Sopenharmony_ci * We cannot switch off the MMU on PPC44x. 6662306a36Sopenharmony_ci * So we: 6762306a36Sopenharmony_ci * 1) Invalidate all the mappings except the one we are running from. 6862306a36Sopenharmony_ci * 2) Create a tmp mapping for our code in the other address space(TS) and 6962306a36Sopenharmony_ci * jump to it. Invalidate the entry we started in. 7062306a36Sopenharmony_ci * 3) Create a 1:1 mapping for 0-2GiB in chunks of 256M in original TS. 7162306a36Sopenharmony_ci * 4) Jump to the 1:1 mapping in original TS. 7262306a36Sopenharmony_ci * 5) Invalidate the tmp mapping. 7362306a36Sopenharmony_ci * 7462306a36Sopenharmony_ci * - Based on the kexec support code for FSL BookE 7562306a36Sopenharmony_ci * 7662306a36Sopenharmony_ci */ 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci /* 7962306a36Sopenharmony_ci * Load the PID with kernel PID (0). 8062306a36Sopenharmony_ci * Also load our MSR_IS and TID to MMUCR for TLB search. 8162306a36Sopenharmony_ci */ 8262306a36Sopenharmony_ci li r3, 0 8362306a36Sopenharmony_ci mtspr SPRN_PID, r3 8462306a36Sopenharmony_ci mfmsr r4 8562306a36Sopenharmony_ci andi. r4,r4,MSR_IS@l 8662306a36Sopenharmony_ci beq wmmucr 8762306a36Sopenharmony_ci oris r3,r3,PPC44x_MMUCR_STS@h 8862306a36Sopenharmony_ciwmmucr: 8962306a36Sopenharmony_ci mtspr SPRN_MMUCR,r3 9062306a36Sopenharmony_ci sync 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci /* 9362306a36Sopenharmony_ci * Invalidate all the TLB entries except the current entry 9462306a36Sopenharmony_ci * where we are running from 9562306a36Sopenharmony_ci */ 9662306a36Sopenharmony_ci bcl 20,31,$+4 /* Find our address */ 9762306a36Sopenharmony_ci0: mflr r5 /* Make it accessible */ 9862306a36Sopenharmony_ci tlbsx r23,0,r5 /* Find entry we are in */ 9962306a36Sopenharmony_ci li r4,0 /* Start at TLB entry 0 */ 10062306a36Sopenharmony_ci li r3,0 /* Set PAGEID inval value */ 10162306a36Sopenharmony_ci1: cmpw r23,r4 /* Is this our entry? */ 10262306a36Sopenharmony_ci beq skip /* If so, skip the inval */ 10362306a36Sopenharmony_ci tlbwe r3,r4,PPC44x_TLB_PAGEID /* If not, inval the entry */ 10462306a36Sopenharmony_ciskip: 10562306a36Sopenharmony_ci addi r4,r4,1 /* Increment */ 10662306a36Sopenharmony_ci cmpwi r4,64 /* Are we done? */ 10762306a36Sopenharmony_ci bne 1b /* If not, repeat */ 10862306a36Sopenharmony_ci isync 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci /* Create a temp mapping and jump to it */ 11162306a36Sopenharmony_ci andi. r6, r23, 1 /* Find the index to use */ 11262306a36Sopenharmony_ci addi r24, r6, 1 /* r24 will contain 1 or 2 */ 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci mfmsr r9 /* get the MSR */ 11562306a36Sopenharmony_ci rlwinm r5, r9, 27, 31, 31 /* Extract the MSR[IS] */ 11662306a36Sopenharmony_ci xori r7, r5, 1 /* Use the other address space */ 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci /* Read the current mapping entries */ 11962306a36Sopenharmony_ci tlbre r3, r23, PPC44x_TLB_PAGEID 12062306a36Sopenharmony_ci tlbre r4, r23, PPC44x_TLB_XLAT 12162306a36Sopenharmony_ci tlbre r5, r23, PPC44x_TLB_ATTRIB 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci /* Save our current XLAT entry */ 12462306a36Sopenharmony_ci mr r25, r4 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci /* Extract the TLB PageSize */ 12762306a36Sopenharmony_ci li r10, 1 /* r10 will hold PageSize */ 12862306a36Sopenharmony_ci rlwinm r11, r3, 0, 24, 27 /* bits 24-27 */ 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci /* XXX: As of now we use 256M, 4K pages */ 13162306a36Sopenharmony_ci cmpwi r11, PPC44x_TLB_256M 13262306a36Sopenharmony_ci bne tlb_4k 13362306a36Sopenharmony_ci rotlwi r10, r10, 28 /* r10 = 256M */ 13462306a36Sopenharmony_ci b write_out 13562306a36Sopenharmony_citlb_4k: 13662306a36Sopenharmony_ci cmpwi r11, PPC44x_TLB_4K 13762306a36Sopenharmony_ci bne default 13862306a36Sopenharmony_ci rotlwi r10, r10, 12 /* r10 = 4K */ 13962306a36Sopenharmony_ci b write_out 14062306a36Sopenharmony_cidefault: 14162306a36Sopenharmony_ci rotlwi r10, r10, 10 /* r10 = 1K */ 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ciwrite_out: 14462306a36Sopenharmony_ci /* 14562306a36Sopenharmony_ci * Write out the tmp 1:1 mapping for this code in other address space 14662306a36Sopenharmony_ci * Fixup EPN = RPN , TS=other address space 14762306a36Sopenharmony_ci */ 14862306a36Sopenharmony_ci insrwi r3, r7, 1, 23 /* Bit 23 is TS for PAGEID field */ 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci /* Write out the tmp mapping entries */ 15162306a36Sopenharmony_ci tlbwe r3, r24, PPC44x_TLB_PAGEID 15262306a36Sopenharmony_ci tlbwe r4, r24, PPC44x_TLB_XLAT 15362306a36Sopenharmony_ci tlbwe r5, r24, PPC44x_TLB_ATTRIB 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci subi r11, r10, 1 /* PageOffset Mask = PageSize - 1 */ 15662306a36Sopenharmony_ci not r10, r11 /* Mask for PageNum */ 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci /* Switch to other address space in MSR */ 15962306a36Sopenharmony_ci insrwi r9, r7, 1, 26 /* Set MSR[IS] = r7 */ 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci bcl 20,31,$+4 16262306a36Sopenharmony_ci1: mflr r8 16362306a36Sopenharmony_ci addi r8, r8, (2f-1b) /* Find the target offset */ 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci /* Jump to the tmp mapping */ 16662306a36Sopenharmony_ci mtspr SPRN_SRR0, r8 16762306a36Sopenharmony_ci mtspr SPRN_SRR1, r9 16862306a36Sopenharmony_ci rfi 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci2: 17162306a36Sopenharmony_ci /* Invalidate the entry we were executing from */ 17262306a36Sopenharmony_ci li r3, 0 17362306a36Sopenharmony_ci tlbwe r3, r23, PPC44x_TLB_PAGEID 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci /* attribute fields. rwx for SUPERVISOR mode */ 17662306a36Sopenharmony_ci li r5, 0 17762306a36Sopenharmony_ci ori r5, r5, (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G) 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci /* Create 1:1 mapping in 256M pages */ 18062306a36Sopenharmony_ci xori r7, r7, 1 /* Revert back to Original TS */ 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci li r8, 0 /* PageNumber */ 18362306a36Sopenharmony_ci li r6, 3 /* TLB Index, start at 3 */ 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_cinext_tlb: 18662306a36Sopenharmony_ci rotlwi r3, r8, 28 /* Create EPN (bits 0-3) */ 18762306a36Sopenharmony_ci mr r4, r3 /* RPN = EPN */ 18862306a36Sopenharmony_ci ori r3, r3, (PPC44x_TLB_VALID | PPC44x_TLB_256M) /* SIZE = 256M, Valid */ 18962306a36Sopenharmony_ci insrwi r3, r7, 1, 23 /* Set TS from r7 */ 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci tlbwe r3, r6, PPC44x_TLB_PAGEID /* PageID field : EPN, V, SIZE */ 19262306a36Sopenharmony_ci tlbwe r4, r6, PPC44x_TLB_XLAT /* Address translation : RPN */ 19362306a36Sopenharmony_ci tlbwe r5, r6, PPC44x_TLB_ATTRIB /* Attributes */ 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci addi r8, r8, 1 /* Increment PN */ 19662306a36Sopenharmony_ci addi r6, r6, 1 /* Increment TLB Index */ 19762306a36Sopenharmony_ci cmpwi r8, 8 /* Are we done ? */ 19862306a36Sopenharmony_ci bne next_tlb 19962306a36Sopenharmony_ci isync 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci /* Jump to the new mapping 1:1 */ 20262306a36Sopenharmony_ci li r9,0 20362306a36Sopenharmony_ci insrwi r9, r7, 1, 26 /* Set MSR[IS] = r7 */ 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci bcl 20,31,$+4 20662306a36Sopenharmony_ci1: mflr r8 20762306a36Sopenharmony_ci and r8, r8, r11 /* Get our offset within page */ 20862306a36Sopenharmony_ci addi r8, r8, (2f-1b) 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci and r5, r25, r10 /* Get our target PageNum */ 21162306a36Sopenharmony_ci or r8, r8, r5 /* Target jump address */ 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci mtspr SPRN_SRR0, r8 21462306a36Sopenharmony_ci mtspr SPRN_SRR1, r9 21562306a36Sopenharmony_ci rfi 21662306a36Sopenharmony_ci2: 21762306a36Sopenharmony_ci /* Invalidate the tmp entry we used */ 21862306a36Sopenharmony_ci li r3, 0 21962306a36Sopenharmony_ci tlbwe r3, r24, PPC44x_TLB_PAGEID 22062306a36Sopenharmony_ci sync 22162306a36Sopenharmony_ci b ppc44x_map_done 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci#ifdef CONFIG_PPC_47x 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci /* 1:1 mapping for 47x */ 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cisetup_map_47x: 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci /* 23062306a36Sopenharmony_ci * Load the kernel pid (0) to PID and also to MMUCR[TID]. 23162306a36Sopenharmony_ci * Also set the MSR IS->MMUCR STS 23262306a36Sopenharmony_ci */ 23362306a36Sopenharmony_ci li r3, 0 23462306a36Sopenharmony_ci mtspr SPRN_PID, r3 /* Set PID */ 23562306a36Sopenharmony_ci mfmsr r4 /* Get MSR */ 23662306a36Sopenharmony_ci andi. r4, r4, MSR_IS@l /* TS=1? */ 23762306a36Sopenharmony_ci beq 1f /* If not, leave STS=0 */ 23862306a36Sopenharmony_ci oris r3, r3, PPC47x_MMUCR_STS@h /* Set STS=1 */ 23962306a36Sopenharmony_ci1: mtspr SPRN_MMUCR, r3 /* Put MMUCR */ 24062306a36Sopenharmony_ci sync 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci /* Find the entry we are running from */ 24362306a36Sopenharmony_ci bcl 20,31,$+4 24462306a36Sopenharmony_ci2: mflr r23 24562306a36Sopenharmony_ci tlbsx r23, 0, r23 24662306a36Sopenharmony_ci tlbre r24, r23, 0 /* TLB Word 0 */ 24762306a36Sopenharmony_ci tlbre r25, r23, 1 /* TLB Word 1 */ 24862306a36Sopenharmony_ci tlbre r26, r23, 2 /* TLB Word 2 */ 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci /* 25262306a36Sopenharmony_ci * Invalidates all the tlb entries by writing to 256 RPNs(r4) 25362306a36Sopenharmony_ci * of 4k page size in all 4 ways (0-3 in r3). 25462306a36Sopenharmony_ci * This would invalidate the entire UTLB including the one we are 25562306a36Sopenharmony_ci * running from. However the shadow TLB entries would help us 25662306a36Sopenharmony_ci * to continue the execution, until we flush them (rfi/isync). 25762306a36Sopenharmony_ci */ 25862306a36Sopenharmony_ci addis r3, 0, 0x8000 /* specify the way */ 25962306a36Sopenharmony_ci addi r4, 0, 0 /* TLB Word0 = (EPN=0, VALID = 0) */ 26062306a36Sopenharmony_ci addi r5, 0, 0 26162306a36Sopenharmony_ci b clear_utlb_entry 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci /* Align the loop to speed things up. from head_44x.S */ 26462306a36Sopenharmony_ci .align 6 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ciclear_utlb_entry: 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci tlbwe r4, r3, 0 26962306a36Sopenharmony_ci tlbwe r5, r3, 1 27062306a36Sopenharmony_ci tlbwe r5, r3, 2 27162306a36Sopenharmony_ci addis r3, r3, 0x2000 /* Increment the way */ 27262306a36Sopenharmony_ci cmpwi r3, 0 27362306a36Sopenharmony_ci bne clear_utlb_entry 27462306a36Sopenharmony_ci addis r3, 0, 0x8000 27562306a36Sopenharmony_ci addis r4, r4, 0x100 /* Increment the EPN */ 27662306a36Sopenharmony_ci cmpwi r4, 0 27762306a36Sopenharmony_ci bne clear_utlb_entry 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci /* Create the entries in the other address space */ 28062306a36Sopenharmony_ci mfmsr r5 28162306a36Sopenharmony_ci rlwinm r7, r5, 27, 31, 31 /* Get the TS (Bit 26) from MSR */ 28262306a36Sopenharmony_ci xori r7, r7, 1 /* r7 = !TS */ 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci insrwi r24, r7, 1, 21 /* Change the TS in the saved TLB word 0 */ 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci /* 28762306a36Sopenharmony_ci * write out the TLB entries for the tmp mapping 28862306a36Sopenharmony_ci * Use way '0' so that we could easily invalidate it later. 28962306a36Sopenharmony_ci */ 29062306a36Sopenharmony_ci lis r3, 0x8000 /* Way '0' */ 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci tlbwe r24, r3, 0 29362306a36Sopenharmony_ci tlbwe r25, r3, 1 29462306a36Sopenharmony_ci tlbwe r26, r3, 2 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci /* Update the msr to the new TS */ 29762306a36Sopenharmony_ci insrwi r5, r7, 1, 26 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci bcl 20,31,$+4 30062306a36Sopenharmony_ci1: mflr r6 30162306a36Sopenharmony_ci addi r6, r6, (2f-1b) 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci mtspr SPRN_SRR0, r6 30462306a36Sopenharmony_ci mtspr SPRN_SRR1, r5 30562306a36Sopenharmony_ci rfi 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci /* 30862306a36Sopenharmony_ci * Now we are in the tmp address space. 30962306a36Sopenharmony_ci * Create a 1:1 mapping for 0-2GiB in the original TS. 31062306a36Sopenharmony_ci */ 31162306a36Sopenharmony_ci2: 31262306a36Sopenharmony_ci li r3, 0 31362306a36Sopenharmony_ci li r4, 0 /* TLB Word 0 */ 31462306a36Sopenharmony_ci li r5, 0 /* TLB Word 1 */ 31562306a36Sopenharmony_ci li r6, 0 31662306a36Sopenharmony_ci ori r6, r6, PPC47x_TLB2_S_RWX /* TLB word 2 */ 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci li r8, 0 /* PageIndex */ 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci xori r7, r7, 1 /* revert back to original TS */ 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ciwrite_utlb: 32362306a36Sopenharmony_ci rotlwi r5, r8, 28 /* RPN = PageIndex * 256M */ 32462306a36Sopenharmony_ci /* ERPN = 0 as we don't use memory above 2G */ 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci mr r4, r5 /* EPN = RPN */ 32762306a36Sopenharmony_ci ori r4, r4, (PPC47x_TLB0_VALID | PPC47x_TLB0_256M) 32862306a36Sopenharmony_ci insrwi r4, r7, 1, 21 /* Insert the TS to Word 0 */ 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci tlbwe r4, r3, 0 /* Write out the entries */ 33162306a36Sopenharmony_ci tlbwe r5, r3, 1 33262306a36Sopenharmony_ci tlbwe r6, r3, 2 33362306a36Sopenharmony_ci addi r8, r8, 1 33462306a36Sopenharmony_ci cmpwi r8, 8 /* Have we completed ? */ 33562306a36Sopenharmony_ci bne write_utlb 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci /* make sure we complete the TLB write up */ 33862306a36Sopenharmony_ci isync 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci /* 34162306a36Sopenharmony_ci * Prepare to jump to the 1:1 mapping. 34262306a36Sopenharmony_ci * 1) Extract page size of the tmp mapping 34362306a36Sopenharmony_ci * DSIZ = TLB_Word0[22:27] 34462306a36Sopenharmony_ci * 2) Calculate the physical address of the address 34562306a36Sopenharmony_ci * to jump to. 34662306a36Sopenharmony_ci */ 34762306a36Sopenharmony_ci rlwinm r10, r24, 0, 22, 27 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci cmpwi r10, PPC47x_TLB0_4K 35062306a36Sopenharmony_ci bne 0f 35162306a36Sopenharmony_ci li r10, 0x1000 /* r10 = 4k */ 35262306a36Sopenharmony_ci bl 1f 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci0: 35562306a36Sopenharmony_ci /* Defaults to 256M */ 35662306a36Sopenharmony_ci lis r10, 0x1000 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci bcl 20,31,$+4 35962306a36Sopenharmony_ci1: mflr r4 36062306a36Sopenharmony_ci addi r4, r4, (2f-1b) /* virtual address of 2f */ 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci subi r11, r10, 1 /* offsetmask = Pagesize - 1 */ 36362306a36Sopenharmony_ci not r10, r11 /* Pagemask = ~(offsetmask) */ 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci and r5, r25, r10 /* Physical page */ 36662306a36Sopenharmony_ci and r6, r4, r11 /* offset within the current page */ 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci or r5, r5, r6 /* Physical address for 2f */ 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci /* Switch the TS in MSR to the original one */ 37162306a36Sopenharmony_ci mfmsr r8 37262306a36Sopenharmony_ci insrwi r8, r7, 1, 26 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci mtspr SPRN_SRR1, r8 37562306a36Sopenharmony_ci mtspr SPRN_SRR0, r5 37662306a36Sopenharmony_ci rfi 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci2: 37962306a36Sopenharmony_ci /* Invalidate the tmp mapping */ 38062306a36Sopenharmony_ci lis r3, 0x8000 /* Way '0' */ 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci clrrwi r24, r24, 12 /* Clear the valid bit */ 38362306a36Sopenharmony_ci tlbwe r24, r3, 0 38462306a36Sopenharmony_ci tlbwe r25, r3, 1 38562306a36Sopenharmony_ci tlbwe r26, r3, 2 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci /* Make sure we complete the TLB write and flush the shadow TLB */ 38862306a36Sopenharmony_ci isync 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci#endif 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cippc44x_map_done: 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci /* Restore the parameters */ 39662306a36Sopenharmony_ci mr r3, r29 39762306a36Sopenharmony_ci mr r4, r30 39862306a36Sopenharmony_ci mr r5, r31 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci li r0, 0 40162306a36Sopenharmony_ci#else 40262306a36Sopenharmony_ci li r0, 0 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci /* 40562306a36Sopenharmony_ci * Set Machine Status Register to a known status, 40662306a36Sopenharmony_ci * switch the MMU off and jump to 1: in a single step. 40762306a36Sopenharmony_ci */ 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci mr r8, r0 41062306a36Sopenharmony_ci ori r8, r8, MSR_RI|MSR_ME 41162306a36Sopenharmony_ci mtspr SPRN_SRR1, r8 41262306a36Sopenharmony_ci addi r8, r4, 1f - relocate_new_kernel 41362306a36Sopenharmony_ci mtspr SPRN_SRR0, r8 41462306a36Sopenharmony_ci sync 41562306a36Sopenharmony_ci rfi 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci1: 41862306a36Sopenharmony_ci#endif 41962306a36Sopenharmony_ci /* from this point address translation is turned off */ 42062306a36Sopenharmony_ci /* and interrupts are disabled */ 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci /* set a new stack at the bottom of our page... */ 42362306a36Sopenharmony_ci /* (not really needed now) */ 42462306a36Sopenharmony_ci addi r1, r4, KEXEC_CONTROL_PAGE_SIZE - 8 /* for LR Save+Back Chain */ 42562306a36Sopenharmony_ci stw r0, 0(r1) 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci /* Do the copies */ 42862306a36Sopenharmony_ci li r6, 0 /* checksum */ 42962306a36Sopenharmony_ci mr r0, r3 43062306a36Sopenharmony_ci b 1f 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci0: /* top, read another word for the indirection page */ 43362306a36Sopenharmony_ci lwzu r0, 4(r3) 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci1: 43662306a36Sopenharmony_ci /* is it a destination page? (r8) */ 43762306a36Sopenharmony_ci rlwinm. r7, r0, 0, 31, 31 /* IND_DESTINATION (1<<0) */ 43862306a36Sopenharmony_ci beq 2f 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci rlwinm r8, r0, 0, 0, 19 /* clear kexec flags, page align */ 44162306a36Sopenharmony_ci b 0b 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci2: /* is it an indirection page? (r3) */ 44462306a36Sopenharmony_ci rlwinm. r7, r0, 0, 30, 30 /* IND_INDIRECTION (1<<1) */ 44562306a36Sopenharmony_ci beq 2f 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci rlwinm r3, r0, 0, 0, 19 /* clear kexec flags, page align */ 44862306a36Sopenharmony_ci subi r3, r3, 4 44962306a36Sopenharmony_ci b 0b 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci2: /* are we done? */ 45262306a36Sopenharmony_ci rlwinm. r7, r0, 0, 29, 29 /* IND_DONE (1<<2) */ 45362306a36Sopenharmony_ci beq 2f 45462306a36Sopenharmony_ci b 3f 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci2: /* is it a source page? (r9) */ 45762306a36Sopenharmony_ci rlwinm. r7, r0, 0, 28, 28 /* IND_SOURCE (1<<3) */ 45862306a36Sopenharmony_ci beq 0b 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci rlwinm r9, r0, 0, 0, 19 /* clear kexec flags, page align */ 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci li r7, PAGE_SIZE / 4 46362306a36Sopenharmony_ci mtctr r7 46462306a36Sopenharmony_ci subi r9, r9, 4 46562306a36Sopenharmony_ci subi r8, r8, 4 46662306a36Sopenharmony_ci9: 46762306a36Sopenharmony_ci lwzu r0, 4(r9) /* do the copy */ 46862306a36Sopenharmony_ci xor r6, r6, r0 46962306a36Sopenharmony_ci stwu r0, 4(r8) 47062306a36Sopenharmony_ci dcbst 0, r8 47162306a36Sopenharmony_ci sync 47262306a36Sopenharmony_ci icbi 0, r8 47362306a36Sopenharmony_ci bdnz 9b 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci addi r9, r9, 4 47662306a36Sopenharmony_ci addi r8, r8, 4 47762306a36Sopenharmony_ci b 0b 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci3: 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci /* To be certain of avoiding problems with self-modifying code 48262306a36Sopenharmony_ci * execute a serializing instruction here. 48362306a36Sopenharmony_ci */ 48462306a36Sopenharmony_ci isync 48562306a36Sopenharmony_ci sync 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci mfspr r3, SPRN_PIR /* current core we are running on */ 48862306a36Sopenharmony_ci mr r4, r5 /* load physical address of chunk called */ 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci /* jump to the entry point, usually the setup routine */ 49162306a36Sopenharmony_ci mtlr r5 49262306a36Sopenharmony_ci blrl 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci1: b 1b 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_cirelocate_new_kernel_end: 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci .globl relocate_new_kernel_size 49962306a36Sopenharmony_cirelocate_new_kernel_size: 50062306a36Sopenharmony_ci .long relocate_new_kernel_end - relocate_new_kernel 501