162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef __SPARC_MMAN_H__
362306a36Sopenharmony_ci#define __SPARC_MMAN_H__
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <uapi/asm/mman.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef __ASSEMBLY__
862306a36Sopenharmony_ci#define arch_mmap_check(addr,len,flags)	sparc_mmap_check(addr,len)
962306a36Sopenharmony_ciint sparc_mmap_check(unsigned long addr, unsigned long len);
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#ifdef CONFIG_SPARC64
1262306a36Sopenharmony_ci#include <asm/adi_64.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cistatic inline void ipi_set_tstate_mcde(void *arg)
1562306a36Sopenharmony_ci{
1662306a36Sopenharmony_ci	struct mm_struct *mm = arg;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	/* Set TSTATE_MCDE for the task using address map that ADI has been
1962306a36Sopenharmony_ci	 * enabled on if the task is running. If not, it will be set
2062306a36Sopenharmony_ci	 * automatically at the next context switch
2162306a36Sopenharmony_ci	 */
2262306a36Sopenharmony_ci	if (current->mm == mm) {
2362306a36Sopenharmony_ci		struct pt_regs *regs;
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci		regs = task_pt_regs(current);
2662306a36Sopenharmony_ci		regs->tstate |= TSTATE_MCDE;
2762306a36Sopenharmony_ci	}
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#define arch_calc_vm_prot_bits(prot, pkey) sparc_calc_vm_prot_bits(prot)
3162306a36Sopenharmony_cistatic inline unsigned long sparc_calc_vm_prot_bits(unsigned long prot)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	if (adi_capable() && (prot & PROT_ADI)) {
3462306a36Sopenharmony_ci		struct pt_regs *regs;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci		if (!current->mm->context.adi) {
3762306a36Sopenharmony_ci			regs = task_pt_regs(current);
3862306a36Sopenharmony_ci			regs->tstate |= TSTATE_MCDE;
3962306a36Sopenharmony_ci			current->mm->context.adi = true;
4062306a36Sopenharmony_ci			on_each_cpu_mask(mm_cpumask(current->mm),
4162306a36Sopenharmony_ci					 ipi_set_tstate_mcde, current->mm, 0);
4262306a36Sopenharmony_ci		}
4362306a36Sopenharmony_ci		return VM_SPARC_ADI;
4462306a36Sopenharmony_ci	} else {
4562306a36Sopenharmony_ci		return 0;
4662306a36Sopenharmony_ci	}
4762306a36Sopenharmony_ci}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#define arch_validate_prot(prot, addr) sparc_validate_prot(prot, addr)
5062306a36Sopenharmony_cistatic inline int sparc_validate_prot(unsigned long prot, unsigned long addr)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM | PROT_ADI))
5362306a36Sopenharmony_ci		return 0;
5462306a36Sopenharmony_ci	return 1;
5562306a36Sopenharmony_ci}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci#define arch_validate_flags(vm_flags) arch_validate_flags(vm_flags)
5862306a36Sopenharmony_ci/* arch_validate_flags() - Ensure combination of flags is valid for a
5962306a36Sopenharmony_ci *	VMA.
6062306a36Sopenharmony_ci */
6162306a36Sopenharmony_cistatic inline bool arch_validate_flags(unsigned long vm_flags)
6262306a36Sopenharmony_ci{
6362306a36Sopenharmony_ci	/* If ADI is being enabled on this VMA, check for ADI
6462306a36Sopenharmony_ci	 * capability on the platform and ensure VMA is suitable
6562306a36Sopenharmony_ci	 * for ADI
6662306a36Sopenharmony_ci	 */
6762306a36Sopenharmony_ci	if (vm_flags & VM_SPARC_ADI) {
6862306a36Sopenharmony_ci		if (!adi_capable())
6962306a36Sopenharmony_ci			return false;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci		/* ADI can not be enabled on PFN mapped pages */
7262306a36Sopenharmony_ci		if (vm_flags & (VM_PFNMAP | VM_MIXEDMAP))
7362306a36Sopenharmony_ci			return false;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci		/* Mergeable pages can become unmergeable
7662306a36Sopenharmony_ci		 * if ADI is enabled on them even if they
7762306a36Sopenharmony_ci		 * have identical data on them. This can be
7862306a36Sopenharmony_ci		 * because ADI enabled pages with identical
7962306a36Sopenharmony_ci		 * data may still not have identical ADI
8062306a36Sopenharmony_ci		 * tags on them. Disallow ADI on mergeable
8162306a36Sopenharmony_ci		 * pages.
8262306a36Sopenharmony_ci		 */
8362306a36Sopenharmony_ci		if (vm_flags & VM_MERGEABLE)
8462306a36Sopenharmony_ci			return false;
8562306a36Sopenharmony_ci	}
8662306a36Sopenharmony_ci	return true;
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci#endif /* CONFIG_SPARC64 */
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci#endif /* __ASSEMBLY__ */
9162306a36Sopenharmony_ci#endif /* __SPARC_MMAN_H__ */
92