162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * This file contains low-level functions for performing various 462306a36Sopenharmony_ci * types of TLB invalidations on various processors with no hash 562306a36Sopenharmony_ci * table. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * This file implements the following functions for all no-hash 862306a36Sopenharmony_ci * processors. Some aren't implemented for some variants. Some 962306a36Sopenharmony_ci * are inline in tlbflush.h 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * - tlbil_va 1262306a36Sopenharmony_ci * - tlbil_pid 1362306a36Sopenharmony_ci * - tlbil_all 1462306a36Sopenharmony_ci * - tlbivax_bcast 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * Code mostly moved over from misc_32.S 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * Partially rewritten by Cort Dougan (cort@cs.nmt.edu) 2162306a36Sopenharmony_ci * Paul Mackerras, Kumar Gala and Benjamin Herrenschmidt. 2262306a36Sopenharmony_ci */ 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include <asm/reg.h> 2562306a36Sopenharmony_ci#include <asm/page.h> 2662306a36Sopenharmony_ci#include <asm/cputable.h> 2762306a36Sopenharmony_ci#include <asm/mmu.h> 2862306a36Sopenharmony_ci#include <asm/ppc_asm.h> 2962306a36Sopenharmony_ci#include <asm/asm-offsets.h> 3062306a36Sopenharmony_ci#include <asm/processor.h> 3162306a36Sopenharmony_ci#include <asm/bug.h> 3262306a36Sopenharmony_ci#include <asm/asm-compat.h> 3362306a36Sopenharmony_ci#include <asm/feature-fixups.h> 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#if defined(CONFIG_40x) 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* 3862306a36Sopenharmony_ci * 40x implementation needs only tlbil_va 3962306a36Sopenharmony_ci */ 4062306a36Sopenharmony_ci_GLOBAL(__tlbil_va) 4162306a36Sopenharmony_ci /* We run the search with interrupts disabled because we have to change 4262306a36Sopenharmony_ci * the PID and I don't want to preempt when that happens. 4362306a36Sopenharmony_ci */ 4462306a36Sopenharmony_ci mfmsr r5 4562306a36Sopenharmony_ci mfspr r6,SPRN_PID 4662306a36Sopenharmony_ci wrteei 0 4762306a36Sopenharmony_ci mtspr SPRN_PID,r4 4862306a36Sopenharmony_ci tlbsx. r3, 0, r3 4962306a36Sopenharmony_ci mtspr SPRN_PID,r6 5062306a36Sopenharmony_ci wrtee r5 5162306a36Sopenharmony_ci bne 1f 5262306a36Sopenharmony_ci sync 5362306a36Sopenharmony_ci /* There are only 64 TLB entries, so r3 < 64, which means bit 25 is 5462306a36Sopenharmony_ci * clear. Since 25 is the V bit in the TLB_TAG, loading this value 5562306a36Sopenharmony_ci * will invalidate the TLB entry. */ 5662306a36Sopenharmony_ci tlbwe r3, r3, TLB_TAG 5762306a36Sopenharmony_ci isync 5862306a36Sopenharmony_ci1: blr 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#elif defined(CONFIG_PPC_8xx) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci/* 6362306a36Sopenharmony_ci * Nothing to do for 8xx, everything is inline 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#elif defined(CONFIG_44x) /* Includes 47x */ 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/* 6962306a36Sopenharmony_ci * 440 implementation uses tlbsx/we for tlbil_va and a full sweep 7062306a36Sopenharmony_ci * of the TLB for everything else. 7162306a36Sopenharmony_ci */ 7262306a36Sopenharmony_ci_GLOBAL(__tlbil_va) 7362306a36Sopenharmony_ci mfspr r5,SPRN_MMUCR 7462306a36Sopenharmony_ci mfmsr r10 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci /* 7762306a36Sopenharmony_ci * We write 16 bits of STID since 47x supports that much, we 7862306a36Sopenharmony_ci * will never be passed out of bounds values on 440 (hopefully) 7962306a36Sopenharmony_ci */ 8062306a36Sopenharmony_ci rlwimi r5,r4,0,16,31 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci /* We have to run the search with interrupts disabled, otherwise 8362306a36Sopenharmony_ci * an interrupt which causes a TLB miss can clobber the MMUCR 8462306a36Sopenharmony_ci * between the mtspr and the tlbsx. 8562306a36Sopenharmony_ci * 8662306a36Sopenharmony_ci * Critical and Machine Check interrupts take care of saving 8762306a36Sopenharmony_ci * and restoring MMUCR, so only normal interrupts have to be 8862306a36Sopenharmony_ci * taken care of. 8962306a36Sopenharmony_ci */ 9062306a36Sopenharmony_ci wrteei 0 9162306a36Sopenharmony_ci mtspr SPRN_MMUCR,r5 9262306a36Sopenharmony_ci tlbsx. r6,0,r3 9362306a36Sopenharmony_ci bne 10f 9462306a36Sopenharmony_ci sync 9562306a36Sopenharmony_ci#ifndef CONFIG_PPC_47x 9662306a36Sopenharmony_ci /* On 440 There are only 64 TLB entries, so r3 < 64, which means bit 9762306a36Sopenharmony_ci * 22, is clear. Since 22 is the V bit in the TLB_PAGEID, loading this 9862306a36Sopenharmony_ci * value will invalidate the TLB entry. 9962306a36Sopenharmony_ci */ 10062306a36Sopenharmony_ci tlbwe r6,r6,PPC44x_TLB_PAGEID 10162306a36Sopenharmony_ci#else 10262306a36Sopenharmony_ci oris r7,r6,0x8000 /* specify way explicitly */ 10362306a36Sopenharmony_ci clrrwi r4,r3,12 /* get an EPN for the hashing with V = 0 */ 10462306a36Sopenharmony_ci ori r4,r4,PPC47x_TLBE_SIZE 10562306a36Sopenharmony_ci tlbwe r4,r7,0 /* write it */ 10662306a36Sopenharmony_ci#endif /* !CONFIG_PPC_47x */ 10762306a36Sopenharmony_ci isync 10862306a36Sopenharmony_ci10: wrtee r10 10962306a36Sopenharmony_ci blr 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci_GLOBAL(_tlbil_all) 11262306a36Sopenharmony_ci_GLOBAL(_tlbil_pid) 11362306a36Sopenharmony_ci#ifndef CONFIG_PPC_47x 11462306a36Sopenharmony_ci li r3,0 11562306a36Sopenharmony_ci sync 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* Load high watermark */ 11862306a36Sopenharmony_ci lis r4,tlb_44x_hwater@ha 11962306a36Sopenharmony_ci lwz r5,tlb_44x_hwater@l(r4) 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci1: tlbwe r3,r3,PPC44x_TLB_PAGEID 12262306a36Sopenharmony_ci addi r3,r3,1 12362306a36Sopenharmony_ci cmpw 0,r3,r5 12462306a36Sopenharmony_ci ble 1b 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci isync 12762306a36Sopenharmony_ci blr 12862306a36Sopenharmony_ci#else 12962306a36Sopenharmony_ci /* 476 variant. There's not simple way to do this, hopefully we'll 13062306a36Sopenharmony_ci * try to limit the amount of such full invalidates 13162306a36Sopenharmony_ci */ 13262306a36Sopenharmony_ci mfmsr r11 /* Interrupts off */ 13362306a36Sopenharmony_ci wrteei 0 13462306a36Sopenharmony_ci li r3,-1 /* Current set */ 13562306a36Sopenharmony_ci lis r10,tlb_47x_boltmap@h 13662306a36Sopenharmony_ci ori r10,r10,tlb_47x_boltmap@l 13762306a36Sopenharmony_ci lis r7,0x8000 /* Specify way explicitly */ 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci b 9f /* For each set */ 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci1: li r9,4 /* Number of ways */ 14262306a36Sopenharmony_ci li r4,0 /* Current way */ 14362306a36Sopenharmony_ci li r6,0 /* Default entry value 0 */ 14462306a36Sopenharmony_ci andi. r0,r8,1 /* Check if way 0 is bolted */ 14562306a36Sopenharmony_ci mtctr r9 /* Load way counter */ 14662306a36Sopenharmony_ci bne- 3f /* Bolted, skip loading it */ 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci2: /* For each way */ 14962306a36Sopenharmony_ci or r5,r3,r4 /* Make way|index for tlbre */ 15062306a36Sopenharmony_ci rlwimi r5,r5,16,8,15 /* Copy index into position */ 15162306a36Sopenharmony_ci tlbre r6,r5,0 /* Read entry */ 15262306a36Sopenharmony_ci3: addis r4,r4,0x2000 /* Next way */ 15362306a36Sopenharmony_ci andi. r0,r6,PPC47x_TLB0_VALID /* Valid entry ? */ 15462306a36Sopenharmony_ci beq 4f /* Nope, skip it */ 15562306a36Sopenharmony_ci rlwimi r7,r5,0,1,2 /* Insert way number */ 15662306a36Sopenharmony_ci rlwinm r6,r6,0,21,19 /* Clear V */ 15762306a36Sopenharmony_ci tlbwe r6,r7,0 /* Write it */ 15862306a36Sopenharmony_ci4: bdnz 2b /* Loop for each way */ 15962306a36Sopenharmony_ci srwi r8,r8,1 /* Next boltmap bit */ 16062306a36Sopenharmony_ci9: cmpwi cr1,r3,255 /* Last set done ? */ 16162306a36Sopenharmony_ci addi r3,r3,1 /* Next set */ 16262306a36Sopenharmony_ci beq cr1,1f /* End of loop */ 16362306a36Sopenharmony_ci andi. r0,r3,0x1f /* Need to load a new boltmap word ? */ 16462306a36Sopenharmony_ci bne 1b /* No, loop */ 16562306a36Sopenharmony_ci lwz r8,0(r10) /* Load boltmap entry */ 16662306a36Sopenharmony_ci addi r10,r10,4 /* Next word */ 16762306a36Sopenharmony_ci b 1b /* Then loop */ 16862306a36Sopenharmony_ci1: isync /* Sync shadows */ 16962306a36Sopenharmony_ci wrtee r11 17062306a36Sopenharmony_ci blr 17162306a36Sopenharmony_ci#endif /* !CONFIG_PPC_47x */ 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci#ifdef CONFIG_PPC_47x 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci/* 17662306a36Sopenharmony_ci * _tlbivax_bcast is only on 47x. We don't bother doing a runtime 17762306a36Sopenharmony_ci * check though, it will blow up soon enough if we mistakenly try 17862306a36Sopenharmony_ci * to use it on a 440. 17962306a36Sopenharmony_ci */ 18062306a36Sopenharmony_ci_GLOBAL(_tlbivax_bcast) 18162306a36Sopenharmony_ci mfspr r5,SPRN_MMUCR 18262306a36Sopenharmony_ci mfmsr r10 18362306a36Sopenharmony_ci rlwimi r5,r4,0,16,31 18462306a36Sopenharmony_ci wrteei 0 18562306a36Sopenharmony_ci mtspr SPRN_MMUCR,r5 18662306a36Sopenharmony_ci isync 18762306a36Sopenharmony_ci PPC_TLBIVAX(0, R3) 18862306a36Sopenharmony_ci isync 18962306a36Sopenharmony_ci mbar 19062306a36Sopenharmony_ci tlbsync 19162306a36Sopenharmony_ciBEGIN_FTR_SECTION 19262306a36Sopenharmony_ci b 1f 19362306a36Sopenharmony_ciEND_FTR_SECTION_IFSET(CPU_FTR_476_DD2) 19462306a36Sopenharmony_ci sync 19562306a36Sopenharmony_ci wrtee r10 19662306a36Sopenharmony_ci blr 19762306a36Sopenharmony_ci/* 19862306a36Sopenharmony_ci * DD2 HW could hang if in instruction fetch happens before msync completes. 19962306a36Sopenharmony_ci * Touch enough instruction cache lines to ensure cache hits 20062306a36Sopenharmony_ci */ 20162306a36Sopenharmony_ci1: mflr r9 20262306a36Sopenharmony_ci bcl 20,31,$+4 20362306a36Sopenharmony_ci2: mflr r6 20462306a36Sopenharmony_ci li r7,32 20562306a36Sopenharmony_ci PPC_ICBT(0,R6,R7) /* touch next cache line */ 20662306a36Sopenharmony_ci add r6,r6,r7 20762306a36Sopenharmony_ci PPC_ICBT(0,R6,R7) /* touch next cache line */ 20862306a36Sopenharmony_ci add r6,r6,r7 20962306a36Sopenharmony_ci PPC_ICBT(0,R6,R7) /* touch next cache line */ 21062306a36Sopenharmony_ci sync 21162306a36Sopenharmony_ci nop 21262306a36Sopenharmony_ci nop 21362306a36Sopenharmony_ci nop 21462306a36Sopenharmony_ci nop 21562306a36Sopenharmony_ci nop 21662306a36Sopenharmony_ci nop 21762306a36Sopenharmony_ci nop 21862306a36Sopenharmony_ci nop 21962306a36Sopenharmony_ci mtlr r9 22062306a36Sopenharmony_ci wrtee r10 22162306a36Sopenharmony_ci blr 22262306a36Sopenharmony_ci#endif /* CONFIG_PPC_47x */ 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci#elif defined(CONFIG_PPC_85xx) 22562306a36Sopenharmony_ci/* 22662306a36Sopenharmony_ci * FSL BookE implementations. 22762306a36Sopenharmony_ci * 22862306a36Sopenharmony_ci * Since feature sections are using _SECTION_ELSE we need 22962306a36Sopenharmony_ci * to have the larger code path before the _SECTION_ELSE 23062306a36Sopenharmony_ci */ 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci/* 23362306a36Sopenharmony_ci * Flush MMU TLB on the local processor 23462306a36Sopenharmony_ci */ 23562306a36Sopenharmony_ci_GLOBAL(_tlbil_all) 23662306a36Sopenharmony_ciBEGIN_MMU_FTR_SECTION 23762306a36Sopenharmony_ci li r3,(MMUCSR0_TLBFI)@l 23862306a36Sopenharmony_ci mtspr SPRN_MMUCSR0, r3 23962306a36Sopenharmony_ci1: 24062306a36Sopenharmony_ci mfspr r3,SPRN_MMUCSR0 24162306a36Sopenharmony_ci andi. r3,r3,MMUCSR0_TLBFI@l 24262306a36Sopenharmony_ci bne 1b 24362306a36Sopenharmony_ciMMU_FTR_SECTION_ELSE 24462306a36Sopenharmony_ci PPC_TLBILX_ALL(0,R0) 24562306a36Sopenharmony_ciALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_USE_TLBILX) 24662306a36Sopenharmony_ci msync 24762306a36Sopenharmony_ci isync 24862306a36Sopenharmony_ci blr 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci_GLOBAL(_tlbil_pid) 25162306a36Sopenharmony_ciBEGIN_MMU_FTR_SECTION 25262306a36Sopenharmony_ci slwi r3,r3,16 25362306a36Sopenharmony_ci mfmsr r10 25462306a36Sopenharmony_ci wrteei 0 25562306a36Sopenharmony_ci mfspr r4,SPRN_MAS6 /* save MAS6 */ 25662306a36Sopenharmony_ci mtspr SPRN_MAS6,r3 25762306a36Sopenharmony_ci PPC_TLBILX_PID(0,R0) 25862306a36Sopenharmony_ci mtspr SPRN_MAS6,r4 /* restore MAS6 */ 25962306a36Sopenharmony_ci wrtee r10 26062306a36Sopenharmony_ciMMU_FTR_SECTION_ELSE 26162306a36Sopenharmony_ci li r3,(MMUCSR0_TLBFI)@l 26262306a36Sopenharmony_ci mtspr SPRN_MMUCSR0, r3 26362306a36Sopenharmony_ci1: 26462306a36Sopenharmony_ci mfspr r3,SPRN_MMUCSR0 26562306a36Sopenharmony_ci andi. r3,r3,MMUCSR0_TLBFI@l 26662306a36Sopenharmony_ci bne 1b 26762306a36Sopenharmony_ciALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_USE_TLBILX) 26862306a36Sopenharmony_ci msync 26962306a36Sopenharmony_ci isync 27062306a36Sopenharmony_ci blr 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci/* 27362306a36Sopenharmony_ci * Flush MMU TLB for a particular address, but only on the local processor 27462306a36Sopenharmony_ci * (no broadcast) 27562306a36Sopenharmony_ci */ 27662306a36Sopenharmony_ci_GLOBAL(__tlbil_va) 27762306a36Sopenharmony_ci mfmsr r10 27862306a36Sopenharmony_ci wrteei 0 27962306a36Sopenharmony_ci slwi r4,r4,16 28062306a36Sopenharmony_ci ori r4,r4,(MAS6_ISIZE(BOOK3E_PAGESZ_4K))@l 28162306a36Sopenharmony_ci mtspr SPRN_MAS6,r4 /* assume AS=0 for now */ 28262306a36Sopenharmony_ciBEGIN_MMU_FTR_SECTION 28362306a36Sopenharmony_ci tlbsx 0,r3 28462306a36Sopenharmony_ci mfspr r4,SPRN_MAS1 /* check valid */ 28562306a36Sopenharmony_ci andis. r3,r4,MAS1_VALID@h 28662306a36Sopenharmony_ci beq 1f 28762306a36Sopenharmony_ci rlwinm r4,r4,0,1,31 28862306a36Sopenharmony_ci mtspr SPRN_MAS1,r4 28962306a36Sopenharmony_ci tlbwe 29062306a36Sopenharmony_ciMMU_FTR_SECTION_ELSE 29162306a36Sopenharmony_ci PPC_TLBILX_VA(0,R3) 29262306a36Sopenharmony_ciALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_USE_TLBILX) 29362306a36Sopenharmony_ci msync 29462306a36Sopenharmony_ci isync 29562306a36Sopenharmony_ci1: wrtee r10 29662306a36Sopenharmony_ci blr 29762306a36Sopenharmony_ci#elif defined(CONFIG_PPC_BOOK3E_64) 29862306a36Sopenharmony_ci/* 29962306a36Sopenharmony_ci * New Book3E (>= 2.06) implementation 30062306a36Sopenharmony_ci * 30162306a36Sopenharmony_ci * Note: We may be able to get away without the interrupt masking stuff 30262306a36Sopenharmony_ci * if we save/restore MAS6 on exceptions that might modify it 30362306a36Sopenharmony_ci */ 30462306a36Sopenharmony_ci_GLOBAL(_tlbil_pid) 30562306a36Sopenharmony_ci slwi r4,r3,MAS6_SPID_SHIFT 30662306a36Sopenharmony_ci mfmsr r10 30762306a36Sopenharmony_ci wrteei 0 30862306a36Sopenharmony_ci mtspr SPRN_MAS6,r4 30962306a36Sopenharmony_ci PPC_TLBILX_PID(0,R0) 31062306a36Sopenharmony_ci wrtee r10 31162306a36Sopenharmony_ci msync 31262306a36Sopenharmony_ci isync 31362306a36Sopenharmony_ci blr 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci_GLOBAL(_tlbil_pid_noind) 31662306a36Sopenharmony_ci slwi r4,r3,MAS6_SPID_SHIFT 31762306a36Sopenharmony_ci mfmsr r10 31862306a36Sopenharmony_ci ori r4,r4,MAS6_SIND 31962306a36Sopenharmony_ci wrteei 0 32062306a36Sopenharmony_ci mtspr SPRN_MAS6,r4 32162306a36Sopenharmony_ci PPC_TLBILX_PID(0,R0) 32262306a36Sopenharmony_ci wrtee r10 32362306a36Sopenharmony_ci msync 32462306a36Sopenharmony_ci isync 32562306a36Sopenharmony_ci blr 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci_GLOBAL(_tlbil_all) 32862306a36Sopenharmony_ci PPC_TLBILX_ALL(0,R0) 32962306a36Sopenharmony_ci msync 33062306a36Sopenharmony_ci isync 33162306a36Sopenharmony_ci blr 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci_GLOBAL(_tlbil_va) 33462306a36Sopenharmony_ci mfmsr r10 33562306a36Sopenharmony_ci wrteei 0 33662306a36Sopenharmony_ci cmpwi cr0,r6,0 33762306a36Sopenharmony_ci slwi r4,r4,MAS6_SPID_SHIFT 33862306a36Sopenharmony_ci rlwimi r4,r5,MAS6_ISIZE_SHIFT,MAS6_ISIZE_MASK 33962306a36Sopenharmony_ci beq 1f 34062306a36Sopenharmony_ci rlwimi r4,r6,MAS6_SIND_SHIFT,MAS6_SIND 34162306a36Sopenharmony_ci1: mtspr SPRN_MAS6,r4 /* assume AS=0 for now */ 34262306a36Sopenharmony_ci PPC_TLBILX_VA(0,R3) 34362306a36Sopenharmony_ci msync 34462306a36Sopenharmony_ci isync 34562306a36Sopenharmony_ci wrtee r10 34662306a36Sopenharmony_ci blr 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci_GLOBAL(_tlbivax_bcast) 34962306a36Sopenharmony_ci mfmsr r10 35062306a36Sopenharmony_ci wrteei 0 35162306a36Sopenharmony_ci cmpwi cr0,r6,0 35262306a36Sopenharmony_ci slwi r4,r4,MAS6_SPID_SHIFT 35362306a36Sopenharmony_ci rlwimi r4,r5,MAS6_ISIZE_SHIFT,MAS6_ISIZE_MASK 35462306a36Sopenharmony_ci beq 1f 35562306a36Sopenharmony_ci rlwimi r4,r6,MAS6_SIND_SHIFT,MAS6_SIND 35662306a36Sopenharmony_ci1: mtspr SPRN_MAS6,r4 /* assume AS=0 for now */ 35762306a36Sopenharmony_ci PPC_TLBIVAX(0,R3) 35862306a36Sopenharmony_ci mbar 35962306a36Sopenharmony_ci tlbsync 36062306a36Sopenharmony_ci sync 36162306a36Sopenharmony_ci wrtee r10 36262306a36Sopenharmony_ci blr 36362306a36Sopenharmony_ci#else 36462306a36Sopenharmony_ci#error Unsupported processor type ! 36562306a36Sopenharmony_ci#endif 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci#if defined(CONFIG_PPC_E500) 36862306a36Sopenharmony_ci/* 36962306a36Sopenharmony_ci * extern void loadcam_entry(unsigned int index) 37062306a36Sopenharmony_ci * 37162306a36Sopenharmony_ci * Load TLBCAM[index] entry in to the L2 CAM MMU 37262306a36Sopenharmony_ci * Must preserve r7, r8, r9, r10, r11, r12 37362306a36Sopenharmony_ci */ 37462306a36Sopenharmony_ci_GLOBAL(loadcam_entry) 37562306a36Sopenharmony_ci mflr r5 37662306a36Sopenharmony_ci LOAD_REG_ADDR_PIC(r4, TLBCAM) 37762306a36Sopenharmony_ci mtlr r5 37862306a36Sopenharmony_ci mulli r5,r3,TLBCAM_SIZE 37962306a36Sopenharmony_ci add r3,r5,r4 38062306a36Sopenharmony_ci lwz r4,TLBCAM_MAS0(r3) 38162306a36Sopenharmony_ci mtspr SPRN_MAS0,r4 38262306a36Sopenharmony_ci lwz r4,TLBCAM_MAS1(r3) 38362306a36Sopenharmony_ci mtspr SPRN_MAS1,r4 38462306a36Sopenharmony_ci PPC_LL r4,TLBCAM_MAS2(r3) 38562306a36Sopenharmony_ci mtspr SPRN_MAS2,r4 38662306a36Sopenharmony_ci lwz r4,TLBCAM_MAS3(r3) 38762306a36Sopenharmony_ci mtspr SPRN_MAS3,r4 38862306a36Sopenharmony_ciBEGIN_MMU_FTR_SECTION 38962306a36Sopenharmony_ci lwz r4,TLBCAM_MAS7(r3) 39062306a36Sopenharmony_ci mtspr SPRN_MAS7,r4 39162306a36Sopenharmony_ciEND_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS) 39262306a36Sopenharmony_ci isync 39362306a36Sopenharmony_ci tlbwe 39462306a36Sopenharmony_ci isync 39562306a36Sopenharmony_ci blr 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci/* 39862306a36Sopenharmony_ci * Load multiple TLB entries at once, using an alternate-space 39962306a36Sopenharmony_ci * trampoline so that we don't have to care about whether the same 40062306a36Sopenharmony_ci * TLB entry maps us before and after. 40162306a36Sopenharmony_ci * 40262306a36Sopenharmony_ci * r3 = first entry to write 40362306a36Sopenharmony_ci * r4 = number of entries to write 40462306a36Sopenharmony_ci * r5 = temporary tlb entry (0 means no switch to AS1) 40562306a36Sopenharmony_ci */ 40662306a36Sopenharmony_ci_GLOBAL(loadcam_multi) 40762306a36Sopenharmony_ci mflr r8 40862306a36Sopenharmony_ci /* Don't switch to AS=1 if already there */ 40962306a36Sopenharmony_ci mfmsr r11 41062306a36Sopenharmony_ci andi. r11,r11,MSR_IS 41162306a36Sopenharmony_ci bne 10f 41262306a36Sopenharmony_ci mr. r12, r5 41362306a36Sopenharmony_ci beq 10f 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci /* 41662306a36Sopenharmony_ci * Set up temporary TLB entry that is the same as what we're 41762306a36Sopenharmony_ci * running from, but in AS=1. 41862306a36Sopenharmony_ci */ 41962306a36Sopenharmony_ci bcl 20,31,$+4 42062306a36Sopenharmony_ci1: mflr r6 42162306a36Sopenharmony_ci tlbsx 0,r8 42262306a36Sopenharmony_ci mfspr r6,SPRN_MAS1 42362306a36Sopenharmony_ci ori r6,r6,MAS1_TS 42462306a36Sopenharmony_ci mtspr SPRN_MAS1,r6 42562306a36Sopenharmony_ci mfspr r6,SPRN_MAS0 42662306a36Sopenharmony_ci rlwimi r6,r5,MAS0_ESEL_SHIFT,MAS0_ESEL_MASK 42762306a36Sopenharmony_ci mr r7,r5 42862306a36Sopenharmony_ci mtspr SPRN_MAS0,r6 42962306a36Sopenharmony_ci isync 43062306a36Sopenharmony_ci tlbwe 43162306a36Sopenharmony_ci isync 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci /* Switch to AS=1 */ 43462306a36Sopenharmony_ci mfmsr r6 43562306a36Sopenharmony_ci ori r6,r6,MSR_IS|MSR_DS 43662306a36Sopenharmony_ci mtmsr r6 43762306a36Sopenharmony_ci isync 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci10: 44062306a36Sopenharmony_ci mr r9,r3 44162306a36Sopenharmony_ci add r10,r3,r4 44262306a36Sopenharmony_ci2: bl loadcam_entry 44362306a36Sopenharmony_ci addi r9,r9,1 44462306a36Sopenharmony_ci cmpw r9,r10 44562306a36Sopenharmony_ci mr r3,r9 44662306a36Sopenharmony_ci blt 2b 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci /* Don't return to AS=0 if we were in AS=1 at function start */ 44962306a36Sopenharmony_ci andi. r11,r11,MSR_IS 45062306a36Sopenharmony_ci bne 3f 45162306a36Sopenharmony_ci cmpwi r12, 0 45262306a36Sopenharmony_ci beq 3f 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci /* Return to AS=0 and clear the temporary entry */ 45562306a36Sopenharmony_ci mfmsr r6 45662306a36Sopenharmony_ci rlwinm. r6,r6,0,~(MSR_IS|MSR_DS) 45762306a36Sopenharmony_ci mtmsr r6 45862306a36Sopenharmony_ci isync 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci li r6,0 46162306a36Sopenharmony_ci mtspr SPRN_MAS1,r6 46262306a36Sopenharmony_ci rlwinm r6,r7,MAS0_ESEL_SHIFT,MAS0_ESEL_MASK 46362306a36Sopenharmony_ci oris r6,r6,MAS0_TLBSEL(1)@h 46462306a36Sopenharmony_ci mtspr SPRN_MAS0,r6 46562306a36Sopenharmony_ci isync 46662306a36Sopenharmony_ci tlbwe 46762306a36Sopenharmony_ci isync 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci3: 47062306a36Sopenharmony_ci mtlr r8 47162306a36Sopenharmony_ci blr 47262306a36Sopenharmony_ci#endif 473