18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * This file contains kexec low-level functions. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com> 68c2ecf20Sopenharmony_ci * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz 78c2ecf20Sopenharmony_ci * PPC44x port. Copyright (C) 2011, IBM Corporation 88c2ecf20Sopenharmony_ci * Author: Suzuki Poulose <suzuki@in.ibm.com> 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <asm/reg.h> 128c2ecf20Sopenharmony_ci#include <asm/page.h> 138c2ecf20Sopenharmony_ci#include <asm/mmu.h> 148c2ecf20Sopenharmony_ci#include <asm/ppc_asm.h> 158c2ecf20Sopenharmony_ci#include <asm/kexec.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci .text 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci /* 208c2ecf20Sopenharmony_ci * Must be relocatable PIC code callable as a C function. 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_ci .globl relocate_new_kernel 238c2ecf20Sopenharmony_cirelocate_new_kernel: 248c2ecf20Sopenharmony_ci /* r3 = page_list */ 258c2ecf20Sopenharmony_ci /* r4 = reboot_code_buffer */ 268c2ecf20Sopenharmony_ci /* r5 = start_address */ 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#ifdef CONFIG_FSL_BOOKE 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci mr r29, r3 318c2ecf20Sopenharmony_ci mr r30, r4 328c2ecf20Sopenharmony_ci mr r31, r5 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define ENTRY_MAPPING_KEXEC_SETUP 358c2ecf20Sopenharmony_ci#include <kernel/fsl_booke_entry_mapping.S> 368c2ecf20Sopenharmony_ci#undef ENTRY_MAPPING_KEXEC_SETUP 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci mr r3, r29 398c2ecf20Sopenharmony_ci mr r4, r30 408c2ecf20Sopenharmony_ci mr r5, r31 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci li r0, 0 438c2ecf20Sopenharmony_ci#elif defined(CONFIG_44x) 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci /* Save our parameters */ 468c2ecf20Sopenharmony_ci mr r29, r3 478c2ecf20Sopenharmony_ci mr r30, r4 488c2ecf20Sopenharmony_ci mr r31, r5 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_47x 518c2ecf20Sopenharmony_ci /* Check for 47x cores */ 528c2ecf20Sopenharmony_ci mfspr r3,SPRN_PVR 538c2ecf20Sopenharmony_ci srwi r3,r3,16 548c2ecf20Sopenharmony_ci cmplwi cr0,r3,PVR_476FPE@h 558c2ecf20Sopenharmony_ci beq setup_map_47x 568c2ecf20Sopenharmony_ci cmplwi cr0,r3,PVR_476@h 578c2ecf20Sopenharmony_ci beq setup_map_47x 588c2ecf20Sopenharmony_ci cmplwi cr0,r3,PVR_476_ISS@h 598c2ecf20Sopenharmony_ci beq setup_map_47x 608c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC_47x */ 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci/* 638c2ecf20Sopenharmony_ci * Code for setting up 1:1 mapping for PPC440x for KEXEC 648c2ecf20Sopenharmony_ci * 658c2ecf20Sopenharmony_ci * We cannot switch off the MMU on PPC44x. 668c2ecf20Sopenharmony_ci * So we: 678c2ecf20Sopenharmony_ci * 1) Invalidate all the mappings except the one we are running from. 688c2ecf20Sopenharmony_ci * 2) Create a tmp mapping for our code in the other address space(TS) and 698c2ecf20Sopenharmony_ci * jump to it. Invalidate the entry we started in. 708c2ecf20Sopenharmony_ci * 3) Create a 1:1 mapping for 0-2GiB in chunks of 256M in original TS. 718c2ecf20Sopenharmony_ci * 4) Jump to the 1:1 mapping in original TS. 728c2ecf20Sopenharmony_ci * 5) Invalidate the tmp mapping. 738c2ecf20Sopenharmony_ci * 748c2ecf20Sopenharmony_ci * - Based on the kexec support code for FSL BookE 758c2ecf20Sopenharmony_ci * 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci /* 798c2ecf20Sopenharmony_ci * Load the PID with kernel PID (0). 808c2ecf20Sopenharmony_ci * Also load our MSR_IS and TID to MMUCR for TLB search. 818c2ecf20Sopenharmony_ci */ 828c2ecf20Sopenharmony_ci li r3, 0 838c2ecf20Sopenharmony_ci mtspr SPRN_PID, r3 848c2ecf20Sopenharmony_ci mfmsr r4 858c2ecf20Sopenharmony_ci andi. r4,r4,MSR_IS@l 868c2ecf20Sopenharmony_ci beq wmmucr 878c2ecf20Sopenharmony_ci oris r3,r3,PPC44x_MMUCR_STS@h 888c2ecf20Sopenharmony_ciwmmucr: 898c2ecf20Sopenharmony_ci mtspr SPRN_MMUCR,r3 908c2ecf20Sopenharmony_ci sync 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci /* 938c2ecf20Sopenharmony_ci * Invalidate all the TLB entries except the current entry 948c2ecf20Sopenharmony_ci * where we are running from 958c2ecf20Sopenharmony_ci */ 968c2ecf20Sopenharmony_ci bl 0f /* Find our address */ 978c2ecf20Sopenharmony_ci0: mflr r5 /* Make it accessible */ 988c2ecf20Sopenharmony_ci tlbsx r23,0,r5 /* Find entry we are in */ 998c2ecf20Sopenharmony_ci li r4,0 /* Start at TLB entry 0 */ 1008c2ecf20Sopenharmony_ci li r3,0 /* Set PAGEID inval value */ 1018c2ecf20Sopenharmony_ci1: cmpw r23,r4 /* Is this our entry? */ 1028c2ecf20Sopenharmony_ci beq skip /* If so, skip the inval */ 1038c2ecf20Sopenharmony_ci tlbwe r3,r4,PPC44x_TLB_PAGEID /* If not, inval the entry */ 1048c2ecf20Sopenharmony_ciskip: 1058c2ecf20Sopenharmony_ci addi r4,r4,1 /* Increment */ 1068c2ecf20Sopenharmony_ci cmpwi r4,64 /* Are we done? */ 1078c2ecf20Sopenharmony_ci bne 1b /* If not, repeat */ 1088c2ecf20Sopenharmony_ci isync 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci /* Create a temp mapping and jump to it */ 1118c2ecf20Sopenharmony_ci andi. r6, r23, 1 /* Find the index to use */ 1128c2ecf20Sopenharmony_ci addi r24, r6, 1 /* r24 will contain 1 or 2 */ 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci mfmsr r9 /* get the MSR */ 1158c2ecf20Sopenharmony_ci rlwinm r5, r9, 27, 31, 31 /* Extract the MSR[IS] */ 1168c2ecf20Sopenharmony_ci xori r7, r5, 1 /* Use the other address space */ 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci /* Read the current mapping entries */ 1198c2ecf20Sopenharmony_ci tlbre r3, r23, PPC44x_TLB_PAGEID 1208c2ecf20Sopenharmony_ci tlbre r4, r23, PPC44x_TLB_XLAT 1218c2ecf20Sopenharmony_ci tlbre r5, r23, PPC44x_TLB_ATTRIB 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci /* Save our current XLAT entry */ 1248c2ecf20Sopenharmony_ci mr r25, r4 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* Extract the TLB PageSize */ 1278c2ecf20Sopenharmony_ci li r10, 1 /* r10 will hold PageSize */ 1288c2ecf20Sopenharmony_ci rlwinm r11, r3, 0, 24, 27 /* bits 24-27 */ 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci /* XXX: As of now we use 256M, 4K pages */ 1318c2ecf20Sopenharmony_ci cmpwi r11, PPC44x_TLB_256M 1328c2ecf20Sopenharmony_ci bne tlb_4k 1338c2ecf20Sopenharmony_ci rotlwi r10, r10, 28 /* r10 = 256M */ 1348c2ecf20Sopenharmony_ci b write_out 1358c2ecf20Sopenharmony_citlb_4k: 1368c2ecf20Sopenharmony_ci cmpwi r11, PPC44x_TLB_4K 1378c2ecf20Sopenharmony_ci bne default 1388c2ecf20Sopenharmony_ci rotlwi r10, r10, 12 /* r10 = 4K */ 1398c2ecf20Sopenharmony_ci b write_out 1408c2ecf20Sopenharmony_cidefault: 1418c2ecf20Sopenharmony_ci rotlwi r10, r10, 10 /* r10 = 1K */ 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ciwrite_out: 1448c2ecf20Sopenharmony_ci /* 1458c2ecf20Sopenharmony_ci * Write out the tmp 1:1 mapping for this code in other address space 1468c2ecf20Sopenharmony_ci * Fixup EPN = RPN , TS=other address space 1478c2ecf20Sopenharmony_ci */ 1488c2ecf20Sopenharmony_ci insrwi r3, r7, 1, 23 /* Bit 23 is TS for PAGEID field */ 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci /* Write out the tmp mapping entries */ 1518c2ecf20Sopenharmony_ci tlbwe r3, r24, PPC44x_TLB_PAGEID 1528c2ecf20Sopenharmony_ci tlbwe r4, r24, PPC44x_TLB_XLAT 1538c2ecf20Sopenharmony_ci tlbwe r5, r24, PPC44x_TLB_ATTRIB 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci subi r11, r10, 1 /* PageOffset Mask = PageSize - 1 */ 1568c2ecf20Sopenharmony_ci not r10, r11 /* Mask for PageNum */ 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci /* Switch to other address space in MSR */ 1598c2ecf20Sopenharmony_ci insrwi r9, r7, 1, 26 /* Set MSR[IS] = r7 */ 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci bl 1f 1628c2ecf20Sopenharmony_ci1: mflr r8 1638c2ecf20Sopenharmony_ci addi r8, r8, (2f-1b) /* Find the target offset */ 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci /* Jump to the tmp mapping */ 1668c2ecf20Sopenharmony_ci mtspr SPRN_SRR0, r8 1678c2ecf20Sopenharmony_ci mtspr SPRN_SRR1, r9 1688c2ecf20Sopenharmony_ci rfi 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci2: 1718c2ecf20Sopenharmony_ci /* Invalidate the entry we were executing from */ 1728c2ecf20Sopenharmony_ci li r3, 0 1738c2ecf20Sopenharmony_ci tlbwe r3, r23, PPC44x_TLB_PAGEID 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci /* attribute fields. rwx for SUPERVISOR mode */ 1768c2ecf20Sopenharmony_ci li r5, 0 1778c2ecf20Sopenharmony_ci ori r5, r5, (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G) 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci /* Create 1:1 mapping in 256M pages */ 1808c2ecf20Sopenharmony_ci xori r7, r7, 1 /* Revert back to Original TS */ 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci li r8, 0 /* PageNumber */ 1838c2ecf20Sopenharmony_ci li r6, 3 /* TLB Index, start at 3 */ 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_cinext_tlb: 1868c2ecf20Sopenharmony_ci rotlwi r3, r8, 28 /* Create EPN (bits 0-3) */ 1878c2ecf20Sopenharmony_ci mr r4, r3 /* RPN = EPN */ 1888c2ecf20Sopenharmony_ci ori r3, r3, (PPC44x_TLB_VALID | PPC44x_TLB_256M) /* SIZE = 256M, Valid */ 1898c2ecf20Sopenharmony_ci insrwi r3, r7, 1, 23 /* Set TS from r7 */ 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci tlbwe r3, r6, PPC44x_TLB_PAGEID /* PageID field : EPN, V, SIZE */ 1928c2ecf20Sopenharmony_ci tlbwe r4, r6, PPC44x_TLB_XLAT /* Address translation : RPN */ 1938c2ecf20Sopenharmony_ci tlbwe r5, r6, PPC44x_TLB_ATTRIB /* Attributes */ 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci addi r8, r8, 1 /* Increment PN */ 1968c2ecf20Sopenharmony_ci addi r6, r6, 1 /* Increment TLB Index */ 1978c2ecf20Sopenharmony_ci cmpwi r8, 8 /* Are we done ? */ 1988c2ecf20Sopenharmony_ci bne next_tlb 1998c2ecf20Sopenharmony_ci isync 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci /* Jump to the new mapping 1:1 */ 2028c2ecf20Sopenharmony_ci li r9,0 2038c2ecf20Sopenharmony_ci insrwi r9, r7, 1, 26 /* Set MSR[IS] = r7 */ 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci bl 1f 2068c2ecf20Sopenharmony_ci1: mflr r8 2078c2ecf20Sopenharmony_ci and r8, r8, r11 /* Get our offset within page */ 2088c2ecf20Sopenharmony_ci addi r8, r8, (2f-1b) 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci and r5, r25, r10 /* Get our target PageNum */ 2118c2ecf20Sopenharmony_ci or r8, r8, r5 /* Target jump address */ 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci mtspr SPRN_SRR0, r8 2148c2ecf20Sopenharmony_ci mtspr SPRN_SRR1, r9 2158c2ecf20Sopenharmony_ci rfi 2168c2ecf20Sopenharmony_ci2: 2178c2ecf20Sopenharmony_ci /* Invalidate the tmp entry we used */ 2188c2ecf20Sopenharmony_ci li r3, 0 2198c2ecf20Sopenharmony_ci tlbwe r3, r24, PPC44x_TLB_PAGEID 2208c2ecf20Sopenharmony_ci sync 2218c2ecf20Sopenharmony_ci b ppc44x_map_done 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_47x 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci /* 1:1 mapping for 47x */ 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cisetup_map_47x: 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci /* 2308c2ecf20Sopenharmony_ci * Load the kernel pid (0) to PID and also to MMUCR[TID]. 2318c2ecf20Sopenharmony_ci * Also set the MSR IS->MMUCR STS 2328c2ecf20Sopenharmony_ci */ 2338c2ecf20Sopenharmony_ci li r3, 0 2348c2ecf20Sopenharmony_ci mtspr SPRN_PID, r3 /* Set PID */ 2358c2ecf20Sopenharmony_ci mfmsr r4 /* Get MSR */ 2368c2ecf20Sopenharmony_ci andi. r4, r4, MSR_IS@l /* TS=1? */ 2378c2ecf20Sopenharmony_ci beq 1f /* If not, leave STS=0 */ 2388c2ecf20Sopenharmony_ci oris r3, r3, PPC47x_MMUCR_STS@h /* Set STS=1 */ 2398c2ecf20Sopenharmony_ci1: mtspr SPRN_MMUCR, r3 /* Put MMUCR */ 2408c2ecf20Sopenharmony_ci sync 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci /* Find the entry we are running from */ 2438c2ecf20Sopenharmony_ci bl 2f 2448c2ecf20Sopenharmony_ci2: mflr r23 2458c2ecf20Sopenharmony_ci tlbsx r23, 0, r23 2468c2ecf20Sopenharmony_ci tlbre r24, r23, 0 /* TLB Word 0 */ 2478c2ecf20Sopenharmony_ci tlbre r25, r23, 1 /* TLB Word 1 */ 2488c2ecf20Sopenharmony_ci tlbre r26, r23, 2 /* TLB Word 2 */ 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci /* 2528c2ecf20Sopenharmony_ci * Invalidates all the tlb entries by writing to 256 RPNs(r4) 2538c2ecf20Sopenharmony_ci * of 4k page size in all 4 ways (0-3 in r3). 2548c2ecf20Sopenharmony_ci * This would invalidate the entire UTLB including the one we are 2558c2ecf20Sopenharmony_ci * running from. However the shadow TLB entries would help us 2568c2ecf20Sopenharmony_ci * to continue the execution, until we flush them (rfi/isync). 2578c2ecf20Sopenharmony_ci */ 2588c2ecf20Sopenharmony_ci addis r3, 0, 0x8000 /* specify the way */ 2598c2ecf20Sopenharmony_ci addi r4, 0, 0 /* TLB Word0 = (EPN=0, VALID = 0) */ 2608c2ecf20Sopenharmony_ci addi r5, 0, 0 2618c2ecf20Sopenharmony_ci b clear_utlb_entry 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci /* Align the loop to speed things up. from head_44x.S */ 2648c2ecf20Sopenharmony_ci .align 6 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ciclear_utlb_entry: 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci tlbwe r4, r3, 0 2698c2ecf20Sopenharmony_ci tlbwe r5, r3, 1 2708c2ecf20Sopenharmony_ci tlbwe r5, r3, 2 2718c2ecf20Sopenharmony_ci addis r3, r3, 0x2000 /* Increment the way */ 2728c2ecf20Sopenharmony_ci cmpwi r3, 0 2738c2ecf20Sopenharmony_ci bne clear_utlb_entry 2748c2ecf20Sopenharmony_ci addis r3, 0, 0x8000 2758c2ecf20Sopenharmony_ci addis r4, r4, 0x100 /* Increment the EPN */ 2768c2ecf20Sopenharmony_ci cmpwi r4, 0 2778c2ecf20Sopenharmony_ci bne clear_utlb_entry 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci /* Create the entries in the other address space */ 2808c2ecf20Sopenharmony_ci mfmsr r5 2818c2ecf20Sopenharmony_ci rlwinm r7, r5, 27, 31, 31 /* Get the TS (Bit 26) from MSR */ 2828c2ecf20Sopenharmony_ci xori r7, r7, 1 /* r7 = !TS */ 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci insrwi r24, r7, 1, 21 /* Change the TS in the saved TLB word 0 */ 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci /* 2878c2ecf20Sopenharmony_ci * write out the TLB entries for the tmp mapping 2888c2ecf20Sopenharmony_ci * Use way '0' so that we could easily invalidate it later. 2898c2ecf20Sopenharmony_ci */ 2908c2ecf20Sopenharmony_ci lis r3, 0x8000 /* Way '0' */ 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci tlbwe r24, r3, 0 2938c2ecf20Sopenharmony_ci tlbwe r25, r3, 1 2948c2ecf20Sopenharmony_ci tlbwe r26, r3, 2 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci /* Update the msr to the new TS */ 2978c2ecf20Sopenharmony_ci insrwi r5, r7, 1, 26 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci bl 1f 3008c2ecf20Sopenharmony_ci1: mflr r6 3018c2ecf20Sopenharmony_ci addi r6, r6, (2f-1b) 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci mtspr SPRN_SRR0, r6 3048c2ecf20Sopenharmony_ci mtspr SPRN_SRR1, r5 3058c2ecf20Sopenharmony_ci rfi 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci /* 3088c2ecf20Sopenharmony_ci * Now we are in the tmp address space. 3098c2ecf20Sopenharmony_ci * Create a 1:1 mapping for 0-2GiB in the original TS. 3108c2ecf20Sopenharmony_ci */ 3118c2ecf20Sopenharmony_ci2: 3128c2ecf20Sopenharmony_ci li r3, 0 3138c2ecf20Sopenharmony_ci li r4, 0 /* TLB Word 0 */ 3148c2ecf20Sopenharmony_ci li r5, 0 /* TLB Word 1 */ 3158c2ecf20Sopenharmony_ci li r6, 0 3168c2ecf20Sopenharmony_ci ori r6, r6, PPC47x_TLB2_S_RWX /* TLB word 2 */ 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci li r8, 0 /* PageIndex */ 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci xori r7, r7, 1 /* revert back to original TS */ 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ciwrite_utlb: 3238c2ecf20Sopenharmony_ci rotlwi r5, r8, 28 /* RPN = PageIndex * 256M */ 3248c2ecf20Sopenharmony_ci /* ERPN = 0 as we don't use memory above 2G */ 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci mr r4, r5 /* EPN = RPN */ 3278c2ecf20Sopenharmony_ci ori r4, r4, (PPC47x_TLB0_VALID | PPC47x_TLB0_256M) 3288c2ecf20Sopenharmony_ci insrwi r4, r7, 1, 21 /* Insert the TS to Word 0 */ 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci tlbwe r4, r3, 0 /* Write out the entries */ 3318c2ecf20Sopenharmony_ci tlbwe r5, r3, 1 3328c2ecf20Sopenharmony_ci tlbwe r6, r3, 2 3338c2ecf20Sopenharmony_ci addi r8, r8, 1 3348c2ecf20Sopenharmony_ci cmpwi r8, 8 /* Have we completed ? */ 3358c2ecf20Sopenharmony_ci bne write_utlb 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci /* make sure we complete the TLB write up */ 3388c2ecf20Sopenharmony_ci isync 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci /* 3418c2ecf20Sopenharmony_ci * Prepare to jump to the 1:1 mapping. 3428c2ecf20Sopenharmony_ci * 1) Extract page size of the tmp mapping 3438c2ecf20Sopenharmony_ci * DSIZ = TLB_Word0[22:27] 3448c2ecf20Sopenharmony_ci * 2) Calculate the physical address of the address 3458c2ecf20Sopenharmony_ci * to jump to. 3468c2ecf20Sopenharmony_ci */ 3478c2ecf20Sopenharmony_ci rlwinm r10, r24, 0, 22, 27 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci cmpwi r10, PPC47x_TLB0_4K 3508c2ecf20Sopenharmony_ci bne 0f 3518c2ecf20Sopenharmony_ci li r10, 0x1000 /* r10 = 4k */ 3528c2ecf20Sopenharmony_ci bl 1f 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci0: 3558c2ecf20Sopenharmony_ci /* Defaults to 256M */ 3568c2ecf20Sopenharmony_ci lis r10, 0x1000 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci bl 1f 3598c2ecf20Sopenharmony_ci1: mflr r4 3608c2ecf20Sopenharmony_ci addi r4, r4, (2f-1b) /* virtual address of 2f */ 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci subi r11, r10, 1 /* offsetmask = Pagesize - 1 */ 3638c2ecf20Sopenharmony_ci not r10, r11 /* Pagemask = ~(offsetmask) */ 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci and r5, r25, r10 /* Physical page */ 3668c2ecf20Sopenharmony_ci and r6, r4, r11 /* offset within the current page */ 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci or r5, r5, r6 /* Physical address for 2f */ 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci /* Switch the TS in MSR to the original one */ 3718c2ecf20Sopenharmony_ci mfmsr r8 3728c2ecf20Sopenharmony_ci insrwi r8, r7, 1, 26 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci mtspr SPRN_SRR1, r8 3758c2ecf20Sopenharmony_ci mtspr SPRN_SRR0, r5 3768c2ecf20Sopenharmony_ci rfi 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci2: 3798c2ecf20Sopenharmony_ci /* Invalidate the tmp mapping */ 3808c2ecf20Sopenharmony_ci lis r3, 0x8000 /* Way '0' */ 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci clrrwi r24, r24, 12 /* Clear the valid bit */ 3838c2ecf20Sopenharmony_ci tlbwe r24, r3, 0 3848c2ecf20Sopenharmony_ci tlbwe r25, r3, 1 3858c2ecf20Sopenharmony_ci tlbwe r26, r3, 2 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci /* Make sure we complete the TLB write and flush the shadow TLB */ 3888c2ecf20Sopenharmony_ci isync 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci#endif 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_cippc44x_map_done: 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci /* Restore the parameters */ 3968c2ecf20Sopenharmony_ci mr r3, r29 3978c2ecf20Sopenharmony_ci mr r4, r30 3988c2ecf20Sopenharmony_ci mr r5, r31 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci li r0, 0 4018c2ecf20Sopenharmony_ci#else 4028c2ecf20Sopenharmony_ci li r0, 0 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci /* 4058c2ecf20Sopenharmony_ci * Set Machine Status Register to a known status, 4068c2ecf20Sopenharmony_ci * switch the MMU off and jump to 1: in a single step. 4078c2ecf20Sopenharmony_ci */ 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci mr r8, r0 4108c2ecf20Sopenharmony_ci ori r8, r8, MSR_RI|MSR_ME 4118c2ecf20Sopenharmony_ci mtspr SPRN_SRR1, r8 4128c2ecf20Sopenharmony_ci addi r8, r4, 1f - relocate_new_kernel 4138c2ecf20Sopenharmony_ci mtspr SPRN_SRR0, r8 4148c2ecf20Sopenharmony_ci sync 4158c2ecf20Sopenharmony_ci rfi 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci1: 4188c2ecf20Sopenharmony_ci#endif 4198c2ecf20Sopenharmony_ci /* from this point address translation is turned off */ 4208c2ecf20Sopenharmony_ci /* and interrupts are disabled */ 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci /* set a new stack at the bottom of our page... */ 4238c2ecf20Sopenharmony_ci /* (not really needed now) */ 4248c2ecf20Sopenharmony_ci addi r1, r4, KEXEC_CONTROL_PAGE_SIZE - 8 /* for LR Save+Back Chain */ 4258c2ecf20Sopenharmony_ci stw r0, 0(r1) 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci /* Do the copies */ 4288c2ecf20Sopenharmony_ci li r6, 0 /* checksum */ 4298c2ecf20Sopenharmony_ci mr r0, r3 4308c2ecf20Sopenharmony_ci b 1f 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci0: /* top, read another word for the indirection page */ 4338c2ecf20Sopenharmony_ci lwzu r0, 4(r3) 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci1: 4368c2ecf20Sopenharmony_ci /* is it a destination page? (r8) */ 4378c2ecf20Sopenharmony_ci rlwinm. r7, r0, 0, 31, 31 /* IND_DESTINATION (1<<0) */ 4388c2ecf20Sopenharmony_ci beq 2f 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci rlwinm r8, r0, 0, 0, 19 /* clear kexec flags, page align */ 4418c2ecf20Sopenharmony_ci b 0b 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci2: /* is it an indirection page? (r3) */ 4448c2ecf20Sopenharmony_ci rlwinm. r7, r0, 0, 30, 30 /* IND_INDIRECTION (1<<1) */ 4458c2ecf20Sopenharmony_ci beq 2f 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci rlwinm r3, r0, 0, 0, 19 /* clear kexec flags, page align */ 4488c2ecf20Sopenharmony_ci subi r3, r3, 4 4498c2ecf20Sopenharmony_ci b 0b 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci2: /* are we done? */ 4528c2ecf20Sopenharmony_ci rlwinm. r7, r0, 0, 29, 29 /* IND_DONE (1<<2) */ 4538c2ecf20Sopenharmony_ci beq 2f 4548c2ecf20Sopenharmony_ci b 3f 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci2: /* is it a source page? (r9) */ 4578c2ecf20Sopenharmony_ci rlwinm. r7, r0, 0, 28, 28 /* IND_SOURCE (1<<3) */ 4588c2ecf20Sopenharmony_ci beq 0b 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci rlwinm r9, r0, 0, 0, 19 /* clear kexec flags, page align */ 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci li r7, PAGE_SIZE / 4 4638c2ecf20Sopenharmony_ci mtctr r7 4648c2ecf20Sopenharmony_ci subi r9, r9, 4 4658c2ecf20Sopenharmony_ci subi r8, r8, 4 4668c2ecf20Sopenharmony_ci9: 4678c2ecf20Sopenharmony_ci lwzu r0, 4(r9) /* do the copy */ 4688c2ecf20Sopenharmony_ci xor r6, r6, r0 4698c2ecf20Sopenharmony_ci stwu r0, 4(r8) 4708c2ecf20Sopenharmony_ci dcbst 0, r8 4718c2ecf20Sopenharmony_ci sync 4728c2ecf20Sopenharmony_ci icbi 0, r8 4738c2ecf20Sopenharmony_ci bdnz 9b 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci addi r9, r9, 4 4768c2ecf20Sopenharmony_ci addi r8, r8, 4 4778c2ecf20Sopenharmony_ci b 0b 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci3: 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci /* To be certain of avoiding problems with self-modifying code 4828c2ecf20Sopenharmony_ci * execute a serializing instruction here. 4838c2ecf20Sopenharmony_ci */ 4848c2ecf20Sopenharmony_ci isync 4858c2ecf20Sopenharmony_ci sync 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci mfspr r3, SPRN_PIR /* current core we are running on */ 4888c2ecf20Sopenharmony_ci mr r4, r5 /* load physical address of chunk called */ 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci /* jump to the entry point, usually the setup routine */ 4918c2ecf20Sopenharmony_ci mtlr r5 4928c2ecf20Sopenharmony_ci blrl 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci1: b 1b 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_cirelocate_new_kernel_end: 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci .globl relocate_new_kernel_size 4998c2ecf20Sopenharmony_cirelocate_new_kernel_size: 5008c2ecf20Sopenharmony_ci .long relocate_new_kernel_end - relocate_new_kernel 501