18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* tsb.S: Sparc64 TSB table handling. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2006 David S. Miller <davem@davemloft.net> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <asm/tsb.h> 98c2ecf20Sopenharmony_ci#include <asm/hypervisor.h> 108c2ecf20Sopenharmony_ci#include <asm/page.h> 118c2ecf20Sopenharmony_ci#include <asm/cpudata.h> 128c2ecf20Sopenharmony_ci#include <asm/mmu.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci .text 158c2ecf20Sopenharmony_ci .align 32 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci /* Invoked from TLB miss handler, we are in the 188c2ecf20Sopenharmony_ci * MMU global registers and they are setup like 198c2ecf20Sopenharmony_ci * this: 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * %g1: TSB entry pointer 228c2ecf20Sopenharmony_ci * %g2: available temporary 238c2ecf20Sopenharmony_ci * %g3: FAULT_CODE_{D,I}TLB 248c2ecf20Sopenharmony_ci * %g4: available temporary 258c2ecf20Sopenharmony_ci * %g5: available temporary 268c2ecf20Sopenharmony_ci * %g6: TAG TARGET 278c2ecf20Sopenharmony_ci * %g7: available temporary, will be loaded by us with 288c2ecf20Sopenharmony_ci * the physical address base of the linux page 298c2ecf20Sopenharmony_ci * tables for the current address space 308c2ecf20Sopenharmony_ci */ 318c2ecf20Sopenharmony_citsb_miss_dtlb: 328c2ecf20Sopenharmony_ci mov TLB_TAG_ACCESS, %g4 338c2ecf20Sopenharmony_ci ldxa [%g4] ASI_DMMU, %g4 348c2ecf20Sopenharmony_ci srlx %g4, PAGE_SHIFT, %g4 358c2ecf20Sopenharmony_ci ba,pt %xcc, tsb_miss_page_table_walk 368c2ecf20Sopenharmony_ci sllx %g4, PAGE_SHIFT, %g4 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_citsb_miss_itlb: 398c2ecf20Sopenharmony_ci mov TLB_TAG_ACCESS, %g4 408c2ecf20Sopenharmony_ci ldxa [%g4] ASI_IMMU, %g4 418c2ecf20Sopenharmony_ci srlx %g4, PAGE_SHIFT, %g4 428c2ecf20Sopenharmony_ci ba,pt %xcc, tsb_miss_page_table_walk 438c2ecf20Sopenharmony_ci sllx %g4, PAGE_SHIFT, %g4 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci /* At this point we have: 468c2ecf20Sopenharmony_ci * %g1 -- PAGE_SIZE TSB entry address 478c2ecf20Sopenharmony_ci * %g3 -- FAULT_CODE_{D,I}TLB 488c2ecf20Sopenharmony_ci * %g4 -- missing virtual address 498c2ecf20Sopenharmony_ci * %g6 -- TAG TARGET (vaddr >> 22) 508c2ecf20Sopenharmony_ci */ 518c2ecf20Sopenharmony_citsb_miss_page_table_walk: 528c2ecf20Sopenharmony_ci TRAP_LOAD_TRAP_BLOCK(%g7, %g5) 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci /* Before committing to a full page table walk, 558c2ecf20Sopenharmony_ci * check the huge page TSB. 568c2ecf20Sopenharmony_ci */ 578c2ecf20Sopenharmony_ci#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci661: ldx [%g7 + TRAP_PER_CPU_TSB_HUGE], %g5 608c2ecf20Sopenharmony_ci nop 618c2ecf20Sopenharmony_ci .section .sun4v_2insn_patch, "ax" 628c2ecf20Sopenharmony_ci .word 661b 638c2ecf20Sopenharmony_ci mov SCRATCHPAD_UTSBREG2, %g5 648c2ecf20Sopenharmony_ci ldxa [%g5] ASI_SCRATCHPAD, %g5 658c2ecf20Sopenharmony_ci .previous 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci cmp %g5, -1 688c2ecf20Sopenharmony_ci be,pt %xcc, 80f 698c2ecf20Sopenharmony_ci nop 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci /* We need an aligned pair of registers containing 2 values 728c2ecf20Sopenharmony_ci * which can be easily rematerialized. %g6 and %g7 foot the 738c2ecf20Sopenharmony_ci * bill just nicely. We'll save %g6 away into %g2 for the 748c2ecf20Sopenharmony_ci * huge page TSB TAG comparison. 758c2ecf20Sopenharmony_ci * 768c2ecf20Sopenharmony_ci * Perform a huge page TSB lookup. 778c2ecf20Sopenharmony_ci */ 788c2ecf20Sopenharmony_ci mov %g6, %g2 798c2ecf20Sopenharmony_ci and %g5, 0x7, %g6 808c2ecf20Sopenharmony_ci mov 512, %g7 818c2ecf20Sopenharmony_ci andn %g5, 0x7, %g5 828c2ecf20Sopenharmony_ci sllx %g7, %g6, %g7 838c2ecf20Sopenharmony_ci srlx %g4, REAL_HPAGE_SHIFT, %g6 848c2ecf20Sopenharmony_ci sub %g7, 1, %g7 858c2ecf20Sopenharmony_ci and %g6, %g7, %g6 868c2ecf20Sopenharmony_ci sllx %g6, 4, %g6 878c2ecf20Sopenharmony_ci add %g5, %g6, %g5 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci TSB_LOAD_QUAD(%g5, %g6) 908c2ecf20Sopenharmony_ci cmp %g6, %g2 918c2ecf20Sopenharmony_ci be,a,pt %xcc, tsb_tlb_reload 928c2ecf20Sopenharmony_ci mov %g7, %g5 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci /* No match, remember the huge page TSB entry address, 958c2ecf20Sopenharmony_ci * and restore %g6 and %g7. 968c2ecf20Sopenharmony_ci */ 978c2ecf20Sopenharmony_ci TRAP_LOAD_TRAP_BLOCK(%g7, %g6) 988c2ecf20Sopenharmony_ci srlx %g4, 22, %g6 998c2ecf20Sopenharmony_ci80: stx %g5, [%g7 + TRAP_PER_CPU_TSB_HUGE_TEMP] 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci#endif 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci ldx [%g7 + TRAP_PER_CPU_PGD_PADDR], %g7 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci /* At this point we have: 1068c2ecf20Sopenharmony_ci * %g1 -- TSB entry address 1078c2ecf20Sopenharmony_ci * %g3 -- FAULT_CODE_{D,I}TLB 1088c2ecf20Sopenharmony_ci * %g4 -- missing virtual address 1098c2ecf20Sopenharmony_ci * %g6 -- TAG TARGET (vaddr >> 22) 1108c2ecf20Sopenharmony_ci * %g7 -- page table physical address 1118c2ecf20Sopenharmony_ci * 1128c2ecf20Sopenharmony_ci * We know that both the base PAGE_SIZE TSB and the HPAGE_SIZE 1138c2ecf20Sopenharmony_ci * TSB both lack a matching entry. 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_citsb_miss_page_table_walk_sun4v_fastpath: 1168c2ecf20Sopenharmony_ci USER_PGTABLE_WALK_TL1(%g4, %g7, %g5, %g2, tsb_do_fault) 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci /* Valid PTE is now in %g5. */ 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) 1218c2ecf20Sopenharmony_ci sethi %uhi(_PAGE_PMD_HUGE | _PAGE_PUD_HUGE), %g7 1228c2ecf20Sopenharmony_ci sllx %g7, 32, %g7 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci andcc %g5, %g7, %g0 1258c2ecf20Sopenharmony_ci be,pt %xcc, 60f 1268c2ecf20Sopenharmony_ci nop 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci /* It is a huge page, use huge page TSB entry address we 1298c2ecf20Sopenharmony_ci * calculated above. If the huge page TSB has not been 1308c2ecf20Sopenharmony_ci * allocated, setup a trap stack and call hugetlb_setup() 1318c2ecf20Sopenharmony_ci * to do so, then return from the trap to replay the TLB 1328c2ecf20Sopenharmony_ci * miss. 1338c2ecf20Sopenharmony_ci * 1348c2ecf20Sopenharmony_ci * This is necessary to handle the case of transparent huge 1358c2ecf20Sopenharmony_ci * pages where we don't really have a non-atomic context 1368c2ecf20Sopenharmony_ci * in which to allocate the hugepage TSB hash table. When 1378c2ecf20Sopenharmony_ci * the 'mm' faults in the hugepage for the first time, we 1388c2ecf20Sopenharmony_ci * thus handle it here. This also makes sure that we can 1398c2ecf20Sopenharmony_ci * allocate the TSB hash table on the correct NUMA node. 1408c2ecf20Sopenharmony_ci */ 1418c2ecf20Sopenharmony_ci TRAP_LOAD_TRAP_BLOCK(%g7, %g2) 1428c2ecf20Sopenharmony_ci ldx [%g7 + TRAP_PER_CPU_TSB_HUGE_TEMP], %g1 1438c2ecf20Sopenharmony_ci cmp %g1, -1 1448c2ecf20Sopenharmony_ci bne,pt %xcc, 60f 1458c2ecf20Sopenharmony_ci nop 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci661: rdpr %pstate, %g5 1488c2ecf20Sopenharmony_ci wrpr %g5, PSTATE_AG | PSTATE_MG, %pstate 1498c2ecf20Sopenharmony_ci .section .sun4v_2insn_patch, "ax" 1508c2ecf20Sopenharmony_ci .word 661b 1518c2ecf20Sopenharmony_ci SET_GL(1) 1528c2ecf20Sopenharmony_ci nop 1538c2ecf20Sopenharmony_ci .previous 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci rdpr %tl, %g7 1568c2ecf20Sopenharmony_ci cmp %g7, 1 1578c2ecf20Sopenharmony_ci bne,pn %xcc, winfix_trampoline 1588c2ecf20Sopenharmony_ci mov %g3, %g4 1598c2ecf20Sopenharmony_ci ba,pt %xcc, etrap 1608c2ecf20Sopenharmony_ci rd %pc, %g7 1618c2ecf20Sopenharmony_ci call hugetlb_setup 1628c2ecf20Sopenharmony_ci add %sp, PTREGS_OFF, %o0 1638c2ecf20Sopenharmony_ci ba,pt %xcc, rtrap 1648c2ecf20Sopenharmony_ci nop 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci60: 1678c2ecf20Sopenharmony_ci#endif 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci /* At this point we have: 1708c2ecf20Sopenharmony_ci * %g1 -- TSB entry address 1718c2ecf20Sopenharmony_ci * %g3 -- FAULT_CODE_{D,I}TLB 1728c2ecf20Sopenharmony_ci * %g5 -- valid PTE 1738c2ecf20Sopenharmony_ci * %g6 -- TAG TARGET (vaddr >> 22) 1748c2ecf20Sopenharmony_ci */ 1758c2ecf20Sopenharmony_citsb_reload: 1768c2ecf20Sopenharmony_ci TSB_LOCK_TAG(%g1, %g2, %g7) 1778c2ecf20Sopenharmony_ci TSB_WRITE(%g1, %g5, %g6) 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci /* Finally, load TLB and return from trap. */ 1808c2ecf20Sopenharmony_citsb_tlb_reload: 1818c2ecf20Sopenharmony_ci cmp %g3, FAULT_CODE_DTLB 1828c2ecf20Sopenharmony_ci bne,pn %xcc, tsb_itlb_load 1838c2ecf20Sopenharmony_ci nop 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_citsb_dtlb_load: 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci661: stxa %g5, [%g0] ASI_DTLB_DATA_IN 1888c2ecf20Sopenharmony_ci retry 1898c2ecf20Sopenharmony_ci .section .sun4v_2insn_patch, "ax" 1908c2ecf20Sopenharmony_ci .word 661b 1918c2ecf20Sopenharmony_ci nop 1928c2ecf20Sopenharmony_ci nop 1938c2ecf20Sopenharmony_ci .previous 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci /* For sun4v the ASI_DTLB_DATA_IN store and the retry 1968c2ecf20Sopenharmony_ci * instruction get nop'd out and we get here to branch 1978c2ecf20Sopenharmony_ci * to the sun4v tlb load code. The registers are setup 1988c2ecf20Sopenharmony_ci * as follows: 1998c2ecf20Sopenharmony_ci * 2008c2ecf20Sopenharmony_ci * %g4: vaddr 2018c2ecf20Sopenharmony_ci * %g5: PTE 2028c2ecf20Sopenharmony_ci * %g6: TAG 2038c2ecf20Sopenharmony_ci * 2048c2ecf20Sopenharmony_ci * The sun4v TLB load wants the PTE in %g3 so we fix that 2058c2ecf20Sopenharmony_ci * up here. 2068c2ecf20Sopenharmony_ci */ 2078c2ecf20Sopenharmony_ci ba,pt %xcc, sun4v_dtlb_load 2088c2ecf20Sopenharmony_ci mov %g5, %g3 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_citsb_itlb_load: 2118c2ecf20Sopenharmony_ci /* Executable bit must be set. */ 2128c2ecf20Sopenharmony_ci661: sethi %hi(_PAGE_EXEC_4U), %g4 2138c2ecf20Sopenharmony_ci andcc %g5, %g4, %g0 2148c2ecf20Sopenharmony_ci .section .sun4v_2insn_patch, "ax" 2158c2ecf20Sopenharmony_ci .word 661b 2168c2ecf20Sopenharmony_ci andcc %g5, _PAGE_EXEC_4V, %g0 2178c2ecf20Sopenharmony_ci nop 2188c2ecf20Sopenharmony_ci .previous 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci be,pn %xcc, tsb_do_fault 2218c2ecf20Sopenharmony_ci nop 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci661: stxa %g5, [%g0] ASI_ITLB_DATA_IN 2248c2ecf20Sopenharmony_ci retry 2258c2ecf20Sopenharmony_ci .section .sun4v_2insn_patch, "ax" 2268c2ecf20Sopenharmony_ci .word 661b 2278c2ecf20Sopenharmony_ci nop 2288c2ecf20Sopenharmony_ci nop 2298c2ecf20Sopenharmony_ci .previous 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci /* For sun4v the ASI_ITLB_DATA_IN store and the retry 2328c2ecf20Sopenharmony_ci * instruction get nop'd out and we get here to branch 2338c2ecf20Sopenharmony_ci * to the sun4v tlb load code. The registers are setup 2348c2ecf20Sopenharmony_ci * as follows: 2358c2ecf20Sopenharmony_ci * 2368c2ecf20Sopenharmony_ci * %g4: vaddr 2378c2ecf20Sopenharmony_ci * %g5: PTE 2388c2ecf20Sopenharmony_ci * %g6: TAG 2398c2ecf20Sopenharmony_ci * 2408c2ecf20Sopenharmony_ci * The sun4v TLB load wants the PTE in %g3 so we fix that 2418c2ecf20Sopenharmony_ci * up here. 2428c2ecf20Sopenharmony_ci */ 2438c2ecf20Sopenharmony_ci ba,pt %xcc, sun4v_itlb_load 2448c2ecf20Sopenharmony_ci mov %g5, %g3 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci /* No valid entry in the page tables, do full fault 2478c2ecf20Sopenharmony_ci * processing. 2488c2ecf20Sopenharmony_ci */ 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci .globl tsb_do_fault 2518c2ecf20Sopenharmony_citsb_do_fault: 2528c2ecf20Sopenharmony_ci cmp %g3, FAULT_CODE_DTLB 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci661: rdpr %pstate, %g5 2558c2ecf20Sopenharmony_ci wrpr %g5, PSTATE_AG | PSTATE_MG, %pstate 2568c2ecf20Sopenharmony_ci .section .sun4v_2insn_patch, "ax" 2578c2ecf20Sopenharmony_ci .word 661b 2588c2ecf20Sopenharmony_ci SET_GL(1) 2598c2ecf20Sopenharmony_ci ldxa [%g0] ASI_SCRATCHPAD, %g4 2608c2ecf20Sopenharmony_ci .previous 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci bne,pn %xcc, tsb_do_itlb_fault 2638c2ecf20Sopenharmony_ci nop 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_citsb_do_dtlb_fault: 2668c2ecf20Sopenharmony_ci rdpr %tl, %g3 2678c2ecf20Sopenharmony_ci cmp %g3, 1 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci661: mov TLB_TAG_ACCESS, %g4 2708c2ecf20Sopenharmony_ci ldxa [%g4] ASI_DMMU, %g5 2718c2ecf20Sopenharmony_ci .section .sun4v_2insn_patch, "ax" 2728c2ecf20Sopenharmony_ci .word 661b 2738c2ecf20Sopenharmony_ci ldx [%g4 + HV_FAULT_D_ADDR_OFFSET], %g5 2748c2ecf20Sopenharmony_ci nop 2758c2ecf20Sopenharmony_ci .previous 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci /* Clear context ID bits. */ 2788c2ecf20Sopenharmony_ci srlx %g5, PAGE_SHIFT, %g5 2798c2ecf20Sopenharmony_ci sllx %g5, PAGE_SHIFT, %g5 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci be,pt %xcc, sparc64_realfault_common 2828c2ecf20Sopenharmony_ci mov FAULT_CODE_DTLB, %g4 2838c2ecf20Sopenharmony_ci ba,pt %xcc, winfix_trampoline 2848c2ecf20Sopenharmony_ci nop 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_citsb_do_itlb_fault: 2878c2ecf20Sopenharmony_ci rdpr %tpc, %g5 2888c2ecf20Sopenharmony_ci ba,pt %xcc, sparc64_realfault_common 2898c2ecf20Sopenharmony_ci mov FAULT_CODE_ITLB, %g4 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci .globl sparc64_realfault_common 2928c2ecf20Sopenharmony_cisparc64_realfault_common: 2938c2ecf20Sopenharmony_ci /* fault code in %g4, fault address in %g5, etrap will 2948c2ecf20Sopenharmony_ci * preserve these two values in %l4 and %l5 respectively 2958c2ecf20Sopenharmony_ci */ 2968c2ecf20Sopenharmony_ci ba,pt %xcc, etrap ! Save trap state 2978c2ecf20Sopenharmony_ci1: rd %pc, %g7 ! ... 2988c2ecf20Sopenharmony_ci stb %l4, [%g6 + TI_FAULT_CODE] ! Save fault code 2998c2ecf20Sopenharmony_ci stx %l5, [%g6 + TI_FAULT_ADDR] ! Save fault address 3008c2ecf20Sopenharmony_ci call do_sparc64_fault ! Call fault handler 3018c2ecf20Sopenharmony_ci add %sp, PTREGS_OFF, %o0 ! Compute pt_regs arg 3028c2ecf20Sopenharmony_ci ba,pt %xcc, rtrap ! Restore cpu state 3038c2ecf20Sopenharmony_ci nop ! Delay slot (fill me) 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ciwinfix_trampoline: 3068c2ecf20Sopenharmony_ci rdpr %tpc, %g3 ! Prepare winfixup TNPC 3078c2ecf20Sopenharmony_ci or %g3, 0x7c, %g3 ! Compute branch offset 3088c2ecf20Sopenharmony_ci wrpr %g3, %tnpc ! Write it into TNPC 3098c2ecf20Sopenharmony_ci done ! Trap return 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci /* Insert an entry into the TSB. 3128c2ecf20Sopenharmony_ci * 3138c2ecf20Sopenharmony_ci * %o0: TSB entry pointer (virt or phys address) 3148c2ecf20Sopenharmony_ci * %o1: tag 3158c2ecf20Sopenharmony_ci * %o2: pte 3168c2ecf20Sopenharmony_ci */ 3178c2ecf20Sopenharmony_ci .align 32 3188c2ecf20Sopenharmony_ci .globl __tsb_insert 3198c2ecf20Sopenharmony_ci__tsb_insert: 3208c2ecf20Sopenharmony_ci rdpr %pstate, %o5 3218c2ecf20Sopenharmony_ci wrpr %o5, PSTATE_IE, %pstate 3228c2ecf20Sopenharmony_ci TSB_LOCK_TAG(%o0, %g2, %g3) 3238c2ecf20Sopenharmony_ci TSB_WRITE(%o0, %o2, %o1) 3248c2ecf20Sopenharmony_ci wrpr %o5, %pstate 3258c2ecf20Sopenharmony_ci retl 3268c2ecf20Sopenharmony_ci nop 3278c2ecf20Sopenharmony_ci .size __tsb_insert, .-__tsb_insert 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci /* Flush the given TSB entry if it has the matching 3308c2ecf20Sopenharmony_ci * tag. 3318c2ecf20Sopenharmony_ci * 3328c2ecf20Sopenharmony_ci * %o0: TSB entry pointer (virt or phys address) 3338c2ecf20Sopenharmony_ci * %o1: tag 3348c2ecf20Sopenharmony_ci */ 3358c2ecf20Sopenharmony_ci .align 32 3368c2ecf20Sopenharmony_ci .globl tsb_flush 3378c2ecf20Sopenharmony_ci .type tsb_flush,#function 3388c2ecf20Sopenharmony_citsb_flush: 3398c2ecf20Sopenharmony_ci sethi %hi(TSB_TAG_LOCK_HIGH), %g2 3408c2ecf20Sopenharmony_ci1: TSB_LOAD_TAG(%o0, %g1) 3418c2ecf20Sopenharmony_ci srlx %g1, 32, %o3 3428c2ecf20Sopenharmony_ci andcc %o3, %g2, %g0 3438c2ecf20Sopenharmony_ci bne,pn %icc, 1b 3448c2ecf20Sopenharmony_ci nop 3458c2ecf20Sopenharmony_ci cmp %g1, %o1 3468c2ecf20Sopenharmony_ci mov 1, %o3 3478c2ecf20Sopenharmony_ci bne,pt %xcc, 2f 3488c2ecf20Sopenharmony_ci sllx %o3, TSB_TAG_INVALID_BIT, %o3 3498c2ecf20Sopenharmony_ci TSB_CAS_TAG(%o0, %g1, %o3) 3508c2ecf20Sopenharmony_ci cmp %g1, %o3 3518c2ecf20Sopenharmony_ci bne,pn %xcc, 1b 3528c2ecf20Sopenharmony_ci nop 3538c2ecf20Sopenharmony_ci2: retl 3548c2ecf20Sopenharmony_ci nop 3558c2ecf20Sopenharmony_ci .size tsb_flush, .-tsb_flush 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci /* Reload MMU related context switch state at 3588c2ecf20Sopenharmony_ci * schedule() time. 3598c2ecf20Sopenharmony_ci * 3608c2ecf20Sopenharmony_ci * %o0: page table physical address 3618c2ecf20Sopenharmony_ci * %o1: TSB base config pointer 3628c2ecf20Sopenharmony_ci * %o2: TSB huge config pointer, or NULL if none 3638c2ecf20Sopenharmony_ci * %o3: Hypervisor TSB descriptor physical address 3648c2ecf20Sopenharmony_ci * %o4: Secondary context to load, if non-zero 3658c2ecf20Sopenharmony_ci * 3668c2ecf20Sopenharmony_ci * We have to run this whole thing with interrupts 3678c2ecf20Sopenharmony_ci * disabled so that the current cpu doesn't change 3688c2ecf20Sopenharmony_ci * due to preemption. 3698c2ecf20Sopenharmony_ci */ 3708c2ecf20Sopenharmony_ci .align 32 3718c2ecf20Sopenharmony_ci .globl __tsb_context_switch 3728c2ecf20Sopenharmony_ci .type __tsb_context_switch,#function 3738c2ecf20Sopenharmony_ci__tsb_context_switch: 3748c2ecf20Sopenharmony_ci rdpr %pstate, %g1 3758c2ecf20Sopenharmony_ci wrpr %g1, PSTATE_IE, %pstate 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci brz,pn %o4, 1f 3788c2ecf20Sopenharmony_ci mov SECONDARY_CONTEXT, %o5 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci661: stxa %o4, [%o5] ASI_DMMU 3818c2ecf20Sopenharmony_ci .section .sun4v_1insn_patch, "ax" 3828c2ecf20Sopenharmony_ci .word 661b 3838c2ecf20Sopenharmony_ci stxa %o4, [%o5] ASI_MMU 3848c2ecf20Sopenharmony_ci .previous 3858c2ecf20Sopenharmony_ci flush %g6 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci1: 3888c2ecf20Sopenharmony_ci TRAP_LOAD_TRAP_BLOCK(%g2, %g3) 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci stx %o0, [%g2 + TRAP_PER_CPU_PGD_PADDR] 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci ldx [%o1 + TSB_CONFIG_REG_VAL], %o0 3938c2ecf20Sopenharmony_ci brz,pt %o2, 1f 3948c2ecf20Sopenharmony_ci mov -1, %g3 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci ldx [%o2 + TSB_CONFIG_REG_VAL], %g3 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci1: stx %g3, [%g2 + TRAP_PER_CPU_TSB_HUGE] 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci sethi %hi(tlb_type), %g2 4018c2ecf20Sopenharmony_ci lduw [%g2 + %lo(tlb_type)], %g2 4028c2ecf20Sopenharmony_ci cmp %g2, 3 4038c2ecf20Sopenharmony_ci bne,pt %icc, 50f 4048c2ecf20Sopenharmony_ci nop 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci /* Hypervisor TSB switch. */ 4078c2ecf20Sopenharmony_ci mov SCRATCHPAD_UTSBREG1, %o5 4088c2ecf20Sopenharmony_ci stxa %o0, [%o5] ASI_SCRATCHPAD 4098c2ecf20Sopenharmony_ci mov SCRATCHPAD_UTSBREG2, %o5 4108c2ecf20Sopenharmony_ci stxa %g3, [%o5] ASI_SCRATCHPAD 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci mov 2, %o0 4138c2ecf20Sopenharmony_ci cmp %g3, -1 4148c2ecf20Sopenharmony_ci move %xcc, 1, %o0 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci mov HV_FAST_MMU_TSB_CTXNON0, %o5 4178c2ecf20Sopenharmony_ci mov %o3, %o1 4188c2ecf20Sopenharmony_ci ta HV_FAST_TRAP 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci /* Finish up. */ 4218c2ecf20Sopenharmony_ci ba,pt %xcc, 9f 4228c2ecf20Sopenharmony_ci nop 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci /* SUN4U TSB switch. */ 4258c2ecf20Sopenharmony_ci50: mov TSB_REG, %o5 4268c2ecf20Sopenharmony_ci stxa %o0, [%o5] ASI_DMMU 4278c2ecf20Sopenharmony_ci membar #Sync 4288c2ecf20Sopenharmony_ci stxa %o0, [%o5] ASI_IMMU 4298c2ecf20Sopenharmony_ci membar #Sync 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci2: ldx [%o1 + TSB_CONFIG_MAP_VADDR], %o4 4328c2ecf20Sopenharmony_ci brz %o4, 9f 4338c2ecf20Sopenharmony_ci ldx [%o1 + TSB_CONFIG_MAP_PTE], %o5 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci sethi %hi(sparc64_highest_unlocked_tlb_ent), %g2 4368c2ecf20Sopenharmony_ci mov TLB_TAG_ACCESS, %g3 4378c2ecf20Sopenharmony_ci lduw [%g2 + %lo(sparc64_highest_unlocked_tlb_ent)], %g2 4388c2ecf20Sopenharmony_ci stxa %o4, [%g3] ASI_DMMU 4398c2ecf20Sopenharmony_ci membar #Sync 4408c2ecf20Sopenharmony_ci sllx %g2, 3, %g2 4418c2ecf20Sopenharmony_ci stxa %o5, [%g2] ASI_DTLB_DATA_ACCESS 4428c2ecf20Sopenharmony_ci membar #Sync 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci brz,pt %o2, 9f 4458c2ecf20Sopenharmony_ci nop 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci ldx [%o2 + TSB_CONFIG_MAP_VADDR], %o4 4488c2ecf20Sopenharmony_ci ldx [%o2 + TSB_CONFIG_MAP_PTE], %o5 4498c2ecf20Sopenharmony_ci mov TLB_TAG_ACCESS, %g3 4508c2ecf20Sopenharmony_ci stxa %o4, [%g3] ASI_DMMU 4518c2ecf20Sopenharmony_ci membar #Sync 4528c2ecf20Sopenharmony_ci sub %g2, (1 << 3), %g2 4538c2ecf20Sopenharmony_ci stxa %o5, [%g2] ASI_DTLB_DATA_ACCESS 4548c2ecf20Sopenharmony_ci membar #Sync 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci9: 4578c2ecf20Sopenharmony_ci wrpr %g1, %pstate 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci retl 4608c2ecf20Sopenharmony_ci nop 4618c2ecf20Sopenharmony_ci .size __tsb_context_switch, .-__tsb_context_switch 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci#define TSB_PASS_BITS ((1 << TSB_TAG_LOCK_BIT) | \ 4648c2ecf20Sopenharmony_ci (1 << TSB_TAG_INVALID_BIT)) 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci .align 32 4678c2ecf20Sopenharmony_ci .globl copy_tsb 4688c2ecf20Sopenharmony_ci .type copy_tsb,#function 4698c2ecf20Sopenharmony_cicopy_tsb: /* %o0=old_tsb_base, %o1=old_tsb_size 4708c2ecf20Sopenharmony_ci * %o2=new_tsb_base, %o3=new_tsb_size 4718c2ecf20Sopenharmony_ci * %o4=page_size_shift 4728c2ecf20Sopenharmony_ci */ 4738c2ecf20Sopenharmony_ci sethi %uhi(TSB_PASS_BITS), %g7 4748c2ecf20Sopenharmony_ci srlx %o3, 4, %o3 4758c2ecf20Sopenharmony_ci add %o0, %o1, %o1 /* end of old tsb */ 4768c2ecf20Sopenharmony_ci sllx %g7, 32, %g7 4778c2ecf20Sopenharmony_ci sub %o3, 1, %o3 /* %o3 == new tsb hash mask */ 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci mov %o4, %g1 /* page_size_shift */ 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci661: prefetcha [%o0] ASI_N, #one_read 4828c2ecf20Sopenharmony_ci .section .tsb_phys_patch, "ax" 4838c2ecf20Sopenharmony_ci .word 661b 4848c2ecf20Sopenharmony_ci prefetcha [%o0] ASI_PHYS_USE_EC, #one_read 4858c2ecf20Sopenharmony_ci .previous 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci90: andcc %o0, (64 - 1), %g0 4888c2ecf20Sopenharmony_ci bne 1f 4898c2ecf20Sopenharmony_ci add %o0, 64, %o5 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci661: prefetcha [%o5] ASI_N, #one_read 4928c2ecf20Sopenharmony_ci .section .tsb_phys_patch, "ax" 4938c2ecf20Sopenharmony_ci .word 661b 4948c2ecf20Sopenharmony_ci prefetcha [%o5] ASI_PHYS_USE_EC, #one_read 4958c2ecf20Sopenharmony_ci .previous 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci1: TSB_LOAD_QUAD(%o0, %g2) /* %g2/%g3 == TSB entry */ 4988c2ecf20Sopenharmony_ci andcc %g2, %g7, %g0 /* LOCK or INVALID set? */ 4998c2ecf20Sopenharmony_ci bne,pn %xcc, 80f /* Skip it */ 5008c2ecf20Sopenharmony_ci sllx %g2, 22, %o4 /* TAG --> VADDR */ 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci /* This can definitely be computed faster... */ 5038c2ecf20Sopenharmony_ci srlx %o0, 4, %o5 /* Build index */ 5048c2ecf20Sopenharmony_ci and %o5, 511, %o5 /* Mask index */ 5058c2ecf20Sopenharmony_ci sllx %o5, %g1, %o5 /* Put into vaddr position */ 5068c2ecf20Sopenharmony_ci or %o4, %o5, %o4 /* Full VADDR. */ 5078c2ecf20Sopenharmony_ci srlx %o4, %g1, %o4 /* Shift down to create index */ 5088c2ecf20Sopenharmony_ci and %o4, %o3, %o4 /* Mask with new_tsb_nents-1 */ 5098c2ecf20Sopenharmony_ci sllx %o4, 4, %o4 /* Shift back up into tsb ent offset */ 5108c2ecf20Sopenharmony_ci TSB_STORE(%o2 + %o4, %g2) /* Store TAG */ 5118c2ecf20Sopenharmony_ci add %o4, 0x8, %o4 /* Advance to TTE */ 5128c2ecf20Sopenharmony_ci TSB_STORE(%o2 + %o4, %g3) /* Store TTE */ 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci80: add %o0, 16, %o0 5158c2ecf20Sopenharmony_ci cmp %o0, %o1 5168c2ecf20Sopenharmony_ci bne,pt %xcc, 90b 5178c2ecf20Sopenharmony_ci nop 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci retl 5208c2ecf20Sopenharmony_ci nop 5218c2ecf20Sopenharmony_ci .size copy_tsb, .-copy_tsb 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci /* Set the invalid bit in all TSB entries. */ 5248c2ecf20Sopenharmony_ci .align 32 5258c2ecf20Sopenharmony_ci .globl tsb_init 5268c2ecf20Sopenharmony_ci .type tsb_init,#function 5278c2ecf20Sopenharmony_citsb_init: /* %o0 = TSB vaddr, %o1 = size in bytes */ 5288c2ecf20Sopenharmony_ci prefetch [%o0 + 0x000], #n_writes 5298c2ecf20Sopenharmony_ci mov 1, %g1 5308c2ecf20Sopenharmony_ci prefetch [%o0 + 0x040], #n_writes 5318c2ecf20Sopenharmony_ci sllx %g1, TSB_TAG_INVALID_BIT, %g1 5328c2ecf20Sopenharmony_ci prefetch [%o0 + 0x080], #n_writes 5338c2ecf20Sopenharmony_ci1: prefetch [%o0 + 0x0c0], #n_writes 5348c2ecf20Sopenharmony_ci stx %g1, [%o0 + 0x00] 5358c2ecf20Sopenharmony_ci stx %g1, [%o0 + 0x10] 5368c2ecf20Sopenharmony_ci stx %g1, [%o0 + 0x20] 5378c2ecf20Sopenharmony_ci stx %g1, [%o0 + 0x30] 5388c2ecf20Sopenharmony_ci prefetch [%o0 + 0x100], #n_writes 5398c2ecf20Sopenharmony_ci stx %g1, [%o0 + 0x40] 5408c2ecf20Sopenharmony_ci stx %g1, [%o0 + 0x50] 5418c2ecf20Sopenharmony_ci stx %g1, [%o0 + 0x60] 5428c2ecf20Sopenharmony_ci stx %g1, [%o0 + 0x70] 5438c2ecf20Sopenharmony_ci prefetch [%o0 + 0x140], #n_writes 5448c2ecf20Sopenharmony_ci stx %g1, [%o0 + 0x80] 5458c2ecf20Sopenharmony_ci stx %g1, [%o0 + 0x90] 5468c2ecf20Sopenharmony_ci stx %g1, [%o0 + 0xa0] 5478c2ecf20Sopenharmony_ci stx %g1, [%o0 + 0xb0] 5488c2ecf20Sopenharmony_ci prefetch [%o0 + 0x180], #n_writes 5498c2ecf20Sopenharmony_ci stx %g1, [%o0 + 0xc0] 5508c2ecf20Sopenharmony_ci stx %g1, [%o0 + 0xd0] 5518c2ecf20Sopenharmony_ci stx %g1, [%o0 + 0xe0] 5528c2ecf20Sopenharmony_ci stx %g1, [%o0 + 0xf0] 5538c2ecf20Sopenharmony_ci subcc %o1, 0x100, %o1 5548c2ecf20Sopenharmony_ci bne,pt %xcc, 1b 5558c2ecf20Sopenharmony_ci add %o0, 0x100, %o0 5568c2ecf20Sopenharmony_ci retl 5578c2ecf20Sopenharmony_ci nop 5588c2ecf20Sopenharmony_ci nop 5598c2ecf20Sopenharmony_ci nop 5608c2ecf20Sopenharmony_ci .size tsb_init, .-tsb_init 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci .globl NGtsb_init 5638c2ecf20Sopenharmony_ci .type NGtsb_init,#function 5648c2ecf20Sopenharmony_ciNGtsb_init: 5658c2ecf20Sopenharmony_ci rd %asi, %g2 5668c2ecf20Sopenharmony_ci mov 1, %g1 5678c2ecf20Sopenharmony_ci wr %g0, ASI_BLK_INIT_QUAD_LDD_P, %asi 5688c2ecf20Sopenharmony_ci sllx %g1, TSB_TAG_INVALID_BIT, %g1 5698c2ecf20Sopenharmony_ci1: stxa %g1, [%o0 + 0x00] %asi 5708c2ecf20Sopenharmony_ci stxa %g1, [%o0 + 0x10] %asi 5718c2ecf20Sopenharmony_ci stxa %g1, [%o0 + 0x20] %asi 5728c2ecf20Sopenharmony_ci stxa %g1, [%o0 + 0x30] %asi 5738c2ecf20Sopenharmony_ci stxa %g1, [%o0 + 0x40] %asi 5748c2ecf20Sopenharmony_ci stxa %g1, [%o0 + 0x50] %asi 5758c2ecf20Sopenharmony_ci stxa %g1, [%o0 + 0x60] %asi 5768c2ecf20Sopenharmony_ci stxa %g1, [%o0 + 0x70] %asi 5778c2ecf20Sopenharmony_ci stxa %g1, [%o0 + 0x80] %asi 5788c2ecf20Sopenharmony_ci stxa %g1, [%o0 + 0x90] %asi 5798c2ecf20Sopenharmony_ci stxa %g1, [%o0 + 0xa0] %asi 5808c2ecf20Sopenharmony_ci stxa %g1, [%o0 + 0xb0] %asi 5818c2ecf20Sopenharmony_ci stxa %g1, [%o0 + 0xc0] %asi 5828c2ecf20Sopenharmony_ci stxa %g1, [%o0 + 0xd0] %asi 5838c2ecf20Sopenharmony_ci stxa %g1, [%o0 + 0xe0] %asi 5848c2ecf20Sopenharmony_ci stxa %g1, [%o0 + 0xf0] %asi 5858c2ecf20Sopenharmony_ci subcc %o1, 0x100, %o1 5868c2ecf20Sopenharmony_ci bne,pt %xcc, 1b 5878c2ecf20Sopenharmony_ci add %o0, 0x100, %o0 5888c2ecf20Sopenharmony_ci membar #Sync 5898c2ecf20Sopenharmony_ci retl 5908c2ecf20Sopenharmony_ci wr %g2, 0x0, %asi 5918c2ecf20Sopenharmony_ci .size NGtsb_init, .-NGtsb_init 592