162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef __ASM_ASM_UACCESS_H
362306a36Sopenharmony_ci#define __ASM_ASM_UACCESS_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <asm/alternative-macros.h>
662306a36Sopenharmony_ci#include <asm/asm-extable.h>
762306a36Sopenharmony_ci#include <asm/assembler.h>
862306a36Sopenharmony_ci#include <asm/kernel-pgtable.h>
962306a36Sopenharmony_ci#include <asm/mmu.h>
1062306a36Sopenharmony_ci#include <asm/sysreg.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/*
1362306a36Sopenharmony_ci * User access enabling/disabling macros.
1462306a36Sopenharmony_ci */
1562306a36Sopenharmony_ci#ifdef CONFIG_ARM64_SW_TTBR0_PAN
1662306a36Sopenharmony_ci	.macro	__uaccess_ttbr0_disable, tmp1
1762306a36Sopenharmony_ci	mrs	\tmp1, ttbr1_el1			// swapper_pg_dir
1862306a36Sopenharmony_ci	bic	\tmp1, \tmp1, #TTBR_ASID_MASK
1962306a36Sopenharmony_ci	sub	\tmp1, \tmp1, #RESERVED_SWAPPER_OFFSET	// reserved_pg_dir
2062306a36Sopenharmony_ci	msr	ttbr0_el1, \tmp1			// set reserved TTBR0_EL1
2162306a36Sopenharmony_ci	add	\tmp1, \tmp1, #RESERVED_SWAPPER_OFFSET
2262306a36Sopenharmony_ci	msr	ttbr1_el1, \tmp1		// set reserved ASID
2362306a36Sopenharmony_ci	isb
2462306a36Sopenharmony_ci	.endm
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	.macro	__uaccess_ttbr0_enable, tmp1, tmp2
2762306a36Sopenharmony_ci	get_current_task \tmp1
2862306a36Sopenharmony_ci	ldr	\tmp1, [\tmp1, #TSK_TI_TTBR0]	// load saved TTBR0_EL1
2962306a36Sopenharmony_ci	mrs	\tmp2, ttbr1_el1
3062306a36Sopenharmony_ci	extr    \tmp2, \tmp2, \tmp1, #48
3162306a36Sopenharmony_ci	ror     \tmp2, \tmp2, #16
3262306a36Sopenharmony_ci	msr	ttbr1_el1, \tmp2		// set the active ASID
3362306a36Sopenharmony_ci	msr	ttbr0_el1, \tmp1		// set the non-PAN TTBR0_EL1
3462306a36Sopenharmony_ci	isb
3562306a36Sopenharmony_ci	.endm
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	.macro	uaccess_ttbr0_disable, tmp1, tmp2
3862306a36Sopenharmony_cialternative_if_not ARM64_HAS_PAN
3962306a36Sopenharmony_ci	save_and_disable_irq \tmp2		// avoid preemption
4062306a36Sopenharmony_ci	__uaccess_ttbr0_disable \tmp1
4162306a36Sopenharmony_ci	restore_irq \tmp2
4262306a36Sopenharmony_cialternative_else_nop_endif
4362306a36Sopenharmony_ci	.endm
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	.macro	uaccess_ttbr0_enable, tmp1, tmp2, tmp3
4662306a36Sopenharmony_cialternative_if_not ARM64_HAS_PAN
4762306a36Sopenharmony_ci	save_and_disable_irq \tmp3		// avoid preemption
4862306a36Sopenharmony_ci	__uaccess_ttbr0_enable \tmp1, \tmp2
4962306a36Sopenharmony_ci	restore_irq \tmp3
5062306a36Sopenharmony_cialternative_else_nop_endif
5162306a36Sopenharmony_ci	.endm
5262306a36Sopenharmony_ci#else
5362306a36Sopenharmony_ci	.macro	uaccess_ttbr0_disable, tmp1, tmp2
5462306a36Sopenharmony_ci	.endm
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	.macro	uaccess_ttbr0_enable, tmp1, tmp2, tmp3
5762306a36Sopenharmony_ci	.endm
5862306a36Sopenharmony_ci#endif
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci#define USER(l, x...)				\
6162306a36Sopenharmony_ci9999:	x;					\
6262306a36Sopenharmony_ci	_asm_extable_uaccess	9999b, l
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci/*
6562306a36Sopenharmony_ci * Generate the assembly for LDTR/STTR with exception table entries.
6662306a36Sopenharmony_ci * This is complicated as there is no post-increment or pair versions of the
6762306a36Sopenharmony_ci * unprivileged instructions, and USER() only works for single instructions.
6862306a36Sopenharmony_ci */
6962306a36Sopenharmony_ci	.macro user_ldp l, reg1, reg2, addr, post_inc
7062306a36Sopenharmony_ci8888:		ldtr	\reg1, [\addr];
7162306a36Sopenharmony_ci8889:		ldtr	\reg2, [\addr, #8];
7262306a36Sopenharmony_ci		add	\addr, \addr, \post_inc;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci		_asm_extable_uaccess	8888b, \l;
7562306a36Sopenharmony_ci		_asm_extable_uaccess	8889b, \l;
7662306a36Sopenharmony_ci	.endm
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	.macro user_stp l, reg1, reg2, addr, post_inc
7962306a36Sopenharmony_ci8888:		sttr	\reg1, [\addr];
8062306a36Sopenharmony_ci8889:		sttr	\reg2, [\addr, #8];
8162306a36Sopenharmony_ci		add	\addr, \addr, \post_inc;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci		_asm_extable_uaccess	8888b,\l;
8462306a36Sopenharmony_ci		_asm_extable_uaccess	8889b,\l;
8562306a36Sopenharmony_ci	.endm
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	.macro user_ldst l, inst, reg, addr, post_inc
8862306a36Sopenharmony_ci8888:		\inst		\reg, [\addr];
8962306a36Sopenharmony_ci		add		\addr, \addr, \post_inc;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci		_asm_extable_uaccess	8888b, \l;
9262306a36Sopenharmony_ci	.endm
9362306a36Sopenharmony_ci#endif
94