xref: /kernel/linux/linux-5.10/arch/sparc/kernel/ktlb.S (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/* arch/sparc64/kernel/ktlb.S: Kernel mapping TLB miss handling.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (C) 1995, 1997, 2005, 2008 David S. Miller <davem@davemloft.net>
58c2ecf20Sopenharmony_ci * Copyright (C) 1996 Eddie C. Dost        (ecd@brainaid.de)
68c2ecf20Sopenharmony_ci * Copyright (C) 1996 Miguel de Icaza      (miguel@nuclecu.unam.mx)
78c2ecf20Sopenharmony_ci * Copyright (C) 1996,98,99 Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/pgtable.h>
118c2ecf20Sopenharmony_ci#include <asm/head.h>
128c2ecf20Sopenharmony_ci#include <asm/asi.h>
138c2ecf20Sopenharmony_ci#include <asm/page.h>
148c2ecf20Sopenharmony_ci#include <asm/tsb.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci	.text
178c2ecf20Sopenharmony_ci	.align		32
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cikvmap_itlb:
208c2ecf20Sopenharmony_ci	/* g6: TAG TARGET */
218c2ecf20Sopenharmony_ci	mov		TLB_TAG_ACCESS, %g4
228c2ecf20Sopenharmony_ci	ldxa		[%g4] ASI_IMMU, %g4
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci	/* The kernel executes in context zero, therefore we do not
258c2ecf20Sopenharmony_ci	 * need to clear the context ID bits out of %g4 here.
268c2ecf20Sopenharmony_ci	 */
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	/* sun4v_itlb_miss branches here with the missing virtual
298c2ecf20Sopenharmony_ci	 * address already loaded into %g4
308c2ecf20Sopenharmony_ci	 */
318c2ecf20Sopenharmony_cikvmap_itlb_4v:
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	/* Catch kernel NULL pointer calls.  */
348c2ecf20Sopenharmony_ci	sethi		%hi(PAGE_SIZE), %g5
358c2ecf20Sopenharmony_ci	cmp		%g4, %g5
368c2ecf20Sopenharmony_ci	blu,pn		%xcc, kvmap_itlb_longpath
378c2ecf20Sopenharmony_ci	 nop
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	KERN_TSB_LOOKUP_TL1(%g4, %g6, %g5, %g1, %g2, %g3, kvmap_itlb_load)
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cikvmap_itlb_tsb_miss:
428c2ecf20Sopenharmony_ci	sethi		%hi(LOW_OBP_ADDRESS), %g5
438c2ecf20Sopenharmony_ci	cmp		%g4, %g5
448c2ecf20Sopenharmony_ci	blu,pn		%xcc, kvmap_itlb_vmalloc_addr
458c2ecf20Sopenharmony_ci	 mov		0x1, %g5
468c2ecf20Sopenharmony_ci	sllx		%g5, 32, %g5
478c2ecf20Sopenharmony_ci	cmp		%g4, %g5
488c2ecf20Sopenharmony_ci	blu,pn		%xcc, kvmap_itlb_obp
498c2ecf20Sopenharmony_ci	 nop
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_cikvmap_itlb_vmalloc_addr:
528c2ecf20Sopenharmony_ci	KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_itlb_longpath)
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	TSB_LOCK_TAG(%g1, %g2, %g7)
558c2ecf20Sopenharmony_ci	TSB_WRITE(%g1, %g5, %g6)
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	/* fallthrough to TLB load */
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cikvmap_itlb_load:
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci661:	stxa		%g5, [%g0] ASI_ITLB_DATA_IN
628c2ecf20Sopenharmony_ci	retry
638c2ecf20Sopenharmony_ci	.section	.sun4v_2insn_patch, "ax"
648c2ecf20Sopenharmony_ci	.word		661b
658c2ecf20Sopenharmony_ci	nop
668c2ecf20Sopenharmony_ci	nop
678c2ecf20Sopenharmony_ci	.previous
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	/* For sun4v the ASI_ITLB_DATA_IN store and the retry
708c2ecf20Sopenharmony_ci	 * instruction get nop'd out and we get here to branch
718c2ecf20Sopenharmony_ci	 * to the sun4v tlb load code.  The registers are setup
728c2ecf20Sopenharmony_ci	 * as follows:
738c2ecf20Sopenharmony_ci	 *
748c2ecf20Sopenharmony_ci	 * %g4: vaddr
758c2ecf20Sopenharmony_ci	 * %g5: PTE
768c2ecf20Sopenharmony_ci	 * %g6:	TAG
778c2ecf20Sopenharmony_ci	 *
788c2ecf20Sopenharmony_ci	 * The sun4v TLB load wants the PTE in %g3 so we fix that
798c2ecf20Sopenharmony_ci	 * up here.
808c2ecf20Sopenharmony_ci	 */
818c2ecf20Sopenharmony_ci	ba,pt		%xcc, sun4v_itlb_load
828c2ecf20Sopenharmony_ci	 mov		%g5, %g3
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cikvmap_itlb_longpath:
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci661:	rdpr	%pstate, %g5
878c2ecf20Sopenharmony_ci	wrpr	%g5, PSTATE_AG | PSTATE_MG, %pstate
888c2ecf20Sopenharmony_ci	.section .sun4v_2insn_patch, "ax"
898c2ecf20Sopenharmony_ci	.word	661b
908c2ecf20Sopenharmony_ci	SET_GL(1)
918c2ecf20Sopenharmony_ci	nop
928c2ecf20Sopenharmony_ci	.previous
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	rdpr	%tpc, %g5
958c2ecf20Sopenharmony_ci	ba,pt	%xcc, sparc64_realfault_common
968c2ecf20Sopenharmony_ci	 mov	FAULT_CODE_ITLB, %g4
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cikvmap_itlb_obp:
998c2ecf20Sopenharmony_ci	OBP_TRANS_LOOKUP(%g4, %g5, %g2, %g3, kvmap_itlb_longpath)
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	TSB_LOCK_TAG(%g1, %g2, %g7)
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	TSB_WRITE(%g1, %g5, %g6)
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	ba,pt		%xcc, kvmap_itlb_load
1068c2ecf20Sopenharmony_ci	 nop
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_cikvmap_dtlb_obp:
1098c2ecf20Sopenharmony_ci	OBP_TRANS_LOOKUP(%g4, %g5, %g2, %g3, kvmap_dtlb_longpath)
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	TSB_LOCK_TAG(%g1, %g2, %g7)
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	TSB_WRITE(%g1, %g5, %g6)
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	ba,pt		%xcc, kvmap_dtlb_load
1168c2ecf20Sopenharmony_ci	 nop
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cikvmap_linear_early:
1198c2ecf20Sopenharmony_ci	sethi		%hi(kern_linear_pte_xor), %g7
1208c2ecf20Sopenharmony_ci	ldx		[%g7 + %lo(kern_linear_pte_xor)], %g2
1218c2ecf20Sopenharmony_ci	ba,pt		%xcc, kvmap_dtlb_tsb4m_load
1228c2ecf20Sopenharmony_ci	 xor		%g2, %g4, %g5
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	.align		32
1258c2ecf20Sopenharmony_cikvmap_dtlb_tsb4m_load:
1268c2ecf20Sopenharmony_ci	TSB_LOCK_TAG(%g1, %g2, %g7)
1278c2ecf20Sopenharmony_ci	TSB_WRITE(%g1, %g5, %g6)
1288c2ecf20Sopenharmony_ci	ba,pt		%xcc, kvmap_dtlb_load
1298c2ecf20Sopenharmony_ci	 nop
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_cikvmap_dtlb:
1328c2ecf20Sopenharmony_ci	/* %g6: TAG TARGET */
1338c2ecf20Sopenharmony_ci	mov		TLB_TAG_ACCESS, %g4
1348c2ecf20Sopenharmony_ci	ldxa		[%g4] ASI_DMMU, %g4
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	/* The kernel executes in context zero, therefore we do not
1378c2ecf20Sopenharmony_ci	 * need to clear the context ID bits out of %g4 here.
1388c2ecf20Sopenharmony_ci	 */
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	/* sun4v_dtlb_miss branches here with the missing virtual
1418c2ecf20Sopenharmony_ci	 * address already loaded into %g4
1428c2ecf20Sopenharmony_ci	 */
1438c2ecf20Sopenharmony_cikvmap_dtlb_4v:
1448c2ecf20Sopenharmony_ci	brgez,pn	%g4, kvmap_dtlb_nonlinear
1458c2ecf20Sopenharmony_ci	 nop
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_PAGEALLOC
1488c2ecf20Sopenharmony_ci	/* Index through the base page size TSB even for linear
1498c2ecf20Sopenharmony_ci	 * mappings when using page allocation debugging.
1508c2ecf20Sopenharmony_ci	 */
1518c2ecf20Sopenharmony_ci	KERN_TSB_LOOKUP_TL1(%g4, %g6, %g5, %g1, %g2, %g3, kvmap_dtlb_load)
1528c2ecf20Sopenharmony_ci#else
1538c2ecf20Sopenharmony_ci	/* Correct TAG_TARGET is already in %g6, check 4mb TSB.  */
1548c2ecf20Sopenharmony_ci	KERN_TSB4M_LOOKUP_TL1(%g6, %g5, %g1, %g2, %g3, kvmap_dtlb_load)
1558c2ecf20Sopenharmony_ci#endif
1568c2ecf20Sopenharmony_ci	/* Linear mapping TSB lookup failed.  Fallthrough to kernel
1578c2ecf20Sopenharmony_ci	 * page table based lookup.
1588c2ecf20Sopenharmony_ci	 */
1598c2ecf20Sopenharmony_ci	.globl		kvmap_linear_patch
1608c2ecf20Sopenharmony_cikvmap_linear_patch:
1618c2ecf20Sopenharmony_ci	ba,a,pt		%xcc, kvmap_linear_early
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_cikvmap_dtlb_vmalloc_addr:
1648c2ecf20Sopenharmony_ci	KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_dtlb_longpath)
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	TSB_LOCK_TAG(%g1, %g2, %g7)
1678c2ecf20Sopenharmony_ci	TSB_WRITE(%g1, %g5, %g6)
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	/* fallthrough to TLB load */
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_cikvmap_dtlb_load:
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci661:	stxa		%g5, [%g0] ASI_DTLB_DATA_IN	! Reload TLB
1748c2ecf20Sopenharmony_ci	retry
1758c2ecf20Sopenharmony_ci	.section	.sun4v_2insn_patch, "ax"
1768c2ecf20Sopenharmony_ci	.word		661b
1778c2ecf20Sopenharmony_ci	nop
1788c2ecf20Sopenharmony_ci	nop
1798c2ecf20Sopenharmony_ci	.previous
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	/* For sun4v the ASI_DTLB_DATA_IN store and the retry
1828c2ecf20Sopenharmony_ci	 * instruction get nop'd out and we get here to branch
1838c2ecf20Sopenharmony_ci	 * to the sun4v tlb load code.  The registers are setup
1848c2ecf20Sopenharmony_ci	 * as follows:
1858c2ecf20Sopenharmony_ci	 *
1868c2ecf20Sopenharmony_ci	 * %g4: vaddr
1878c2ecf20Sopenharmony_ci	 * %g5: PTE
1888c2ecf20Sopenharmony_ci	 * %g6:	TAG
1898c2ecf20Sopenharmony_ci	 *
1908c2ecf20Sopenharmony_ci	 * The sun4v TLB load wants the PTE in %g3 so we fix that
1918c2ecf20Sopenharmony_ci	 * up here.
1928c2ecf20Sopenharmony_ci	 */
1938c2ecf20Sopenharmony_ci	ba,pt		%xcc, sun4v_dtlb_load
1948c2ecf20Sopenharmony_ci	 mov		%g5, %g3
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci#ifdef CONFIG_SPARSEMEM_VMEMMAP
1978c2ecf20Sopenharmony_cikvmap_vmemmap:
1988c2ecf20Sopenharmony_ci	KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_dtlb_longpath)
1998c2ecf20Sopenharmony_ci	ba,a,pt		%xcc, kvmap_dtlb_load
2008c2ecf20Sopenharmony_ci#endif
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_cikvmap_dtlb_nonlinear:
2038c2ecf20Sopenharmony_ci	/* Catch kernel NULL pointer derefs.  */
2048c2ecf20Sopenharmony_ci	sethi		%hi(PAGE_SIZE), %g5
2058c2ecf20Sopenharmony_ci	cmp		%g4, %g5
2068c2ecf20Sopenharmony_ci	bleu,pn		%xcc, kvmap_dtlb_longpath
2078c2ecf20Sopenharmony_ci	 nop
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci#ifdef CONFIG_SPARSEMEM_VMEMMAP
2108c2ecf20Sopenharmony_ci	/* Do not use the TSB for vmemmap.  */
2118c2ecf20Sopenharmony_ci	sethi		%hi(VMEMMAP_BASE), %g5
2128c2ecf20Sopenharmony_ci	ldx		[%g5 + %lo(VMEMMAP_BASE)], %g5
2138c2ecf20Sopenharmony_ci	cmp		%g4,%g5
2148c2ecf20Sopenharmony_ci	bgeu,pn		%xcc, kvmap_vmemmap
2158c2ecf20Sopenharmony_ci	 nop
2168c2ecf20Sopenharmony_ci#endif
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	KERN_TSB_LOOKUP_TL1(%g4, %g6, %g5, %g1, %g2, %g3, kvmap_dtlb_load)
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_cikvmap_dtlb_tsbmiss:
2218c2ecf20Sopenharmony_ci	sethi		%hi(MODULES_VADDR), %g5
2228c2ecf20Sopenharmony_ci	cmp		%g4, %g5
2238c2ecf20Sopenharmony_ci	blu,pn		%xcc, kvmap_dtlb_longpath
2248c2ecf20Sopenharmony_ci	 sethi		%hi(VMALLOC_END), %g5
2258c2ecf20Sopenharmony_ci	ldx		[%g5 + %lo(VMALLOC_END)], %g5
2268c2ecf20Sopenharmony_ci	cmp		%g4, %g5
2278c2ecf20Sopenharmony_ci	bgeu,pn		%xcc, kvmap_dtlb_longpath
2288c2ecf20Sopenharmony_ci	 nop
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_cikvmap_check_obp:
2318c2ecf20Sopenharmony_ci	sethi		%hi(LOW_OBP_ADDRESS), %g5
2328c2ecf20Sopenharmony_ci	cmp		%g4, %g5
2338c2ecf20Sopenharmony_ci	blu,pn		%xcc, kvmap_dtlb_vmalloc_addr
2348c2ecf20Sopenharmony_ci	 mov		0x1, %g5
2358c2ecf20Sopenharmony_ci	sllx		%g5, 32, %g5
2368c2ecf20Sopenharmony_ci	cmp		%g4, %g5
2378c2ecf20Sopenharmony_ci	blu,pn		%xcc, kvmap_dtlb_obp
2388c2ecf20Sopenharmony_ci	 nop
2398c2ecf20Sopenharmony_ci	ba,pt		%xcc, kvmap_dtlb_vmalloc_addr
2408c2ecf20Sopenharmony_ci	 nop
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_cikvmap_dtlb_longpath:
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci661:	rdpr	%pstate, %g5
2458c2ecf20Sopenharmony_ci	wrpr	%g5, PSTATE_AG | PSTATE_MG, %pstate
2468c2ecf20Sopenharmony_ci	.section .sun4v_2insn_patch, "ax"
2478c2ecf20Sopenharmony_ci	.word	661b
2488c2ecf20Sopenharmony_ci	SET_GL(1)
2498c2ecf20Sopenharmony_ci	ldxa		[%g0] ASI_SCRATCHPAD, %g5
2508c2ecf20Sopenharmony_ci	.previous
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	rdpr	%tl, %g3
2538c2ecf20Sopenharmony_ci	cmp	%g3, 1
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci661:	mov	TLB_TAG_ACCESS, %g4
2568c2ecf20Sopenharmony_ci	ldxa	[%g4] ASI_DMMU, %g5
2578c2ecf20Sopenharmony_ci	.section .sun4v_2insn_patch, "ax"
2588c2ecf20Sopenharmony_ci	.word	661b
2598c2ecf20Sopenharmony_ci	ldx	[%g5 + HV_FAULT_D_ADDR_OFFSET], %g5
2608c2ecf20Sopenharmony_ci	nop
2618c2ecf20Sopenharmony_ci	.previous
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	/* The kernel executes in context zero, therefore we do not
2648c2ecf20Sopenharmony_ci	 * need to clear the context ID bits out of %g5 here.
2658c2ecf20Sopenharmony_ci	 */
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	be,pt	%xcc, sparc64_realfault_common
2688c2ecf20Sopenharmony_ci	 mov	FAULT_CODE_DTLB, %g4
2698c2ecf20Sopenharmony_ci	ba,pt	%xcc, winfix_trampoline
2708c2ecf20Sopenharmony_ci	 nop
271