xref: /kernel/linux/linux-5.10/arch/sparc/kernel/tsb.S (revision 8c2ecf20)
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