18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef __SPARC_MMAN_H__
38c2ecf20Sopenharmony_ci#define __SPARC_MMAN_H__
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <uapi/asm/mman.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
88c2ecf20Sopenharmony_ci#define arch_mmap_check(addr,len,flags)	sparc_mmap_check(addr,len)
98c2ecf20Sopenharmony_ciint sparc_mmap_check(unsigned long addr, unsigned long len);
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#ifdef CONFIG_SPARC64
128c2ecf20Sopenharmony_ci#include <asm/adi_64.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_cistatic inline void ipi_set_tstate_mcde(void *arg)
158c2ecf20Sopenharmony_ci{
168c2ecf20Sopenharmony_ci	struct mm_struct *mm = arg;
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci	/* Set TSTATE_MCDE for the task using address map that ADI has been
198c2ecf20Sopenharmony_ci	 * enabled on if the task is running. If not, it will be set
208c2ecf20Sopenharmony_ci	 * automatically at the next context switch
218c2ecf20Sopenharmony_ci	 */
228c2ecf20Sopenharmony_ci	if (current->mm == mm) {
238c2ecf20Sopenharmony_ci		struct pt_regs *regs;
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci		regs = task_pt_regs(current);
268c2ecf20Sopenharmony_ci		regs->tstate |= TSTATE_MCDE;
278c2ecf20Sopenharmony_ci	}
288c2ecf20Sopenharmony_ci}
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#define arch_calc_vm_prot_bits(prot, pkey) sparc_calc_vm_prot_bits(prot)
318c2ecf20Sopenharmony_cistatic inline unsigned long sparc_calc_vm_prot_bits(unsigned long prot)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	if (adi_capable() && (prot & PROT_ADI)) {
348c2ecf20Sopenharmony_ci		struct pt_regs *regs;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci		if (!current->mm->context.adi) {
378c2ecf20Sopenharmony_ci			regs = task_pt_regs(current);
388c2ecf20Sopenharmony_ci			regs->tstate |= TSTATE_MCDE;
398c2ecf20Sopenharmony_ci			current->mm->context.adi = true;
408c2ecf20Sopenharmony_ci			on_each_cpu_mask(mm_cpumask(current->mm),
418c2ecf20Sopenharmony_ci					 ipi_set_tstate_mcde, current->mm, 0);
428c2ecf20Sopenharmony_ci		}
438c2ecf20Sopenharmony_ci		return VM_SPARC_ADI;
448c2ecf20Sopenharmony_ci	} else {
458c2ecf20Sopenharmony_ci		return 0;
468c2ecf20Sopenharmony_ci	}
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#define arch_vm_get_page_prot(vm_flags) sparc_vm_get_page_prot(vm_flags)
508c2ecf20Sopenharmony_cistatic inline pgprot_t sparc_vm_get_page_prot(unsigned long vm_flags)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	return (vm_flags & VM_SPARC_ADI) ? __pgprot(_PAGE_MCD_4V) : __pgprot(0);
538c2ecf20Sopenharmony_ci}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#define arch_validate_prot(prot, addr) sparc_validate_prot(prot, addr)
568c2ecf20Sopenharmony_cistatic inline int sparc_validate_prot(unsigned long prot, unsigned long addr)
578c2ecf20Sopenharmony_ci{
588c2ecf20Sopenharmony_ci	if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM | PROT_ADI))
598c2ecf20Sopenharmony_ci		return 0;
608c2ecf20Sopenharmony_ci	return 1;
618c2ecf20Sopenharmony_ci}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci#define arch_validate_flags(vm_flags) arch_validate_flags(vm_flags)
648c2ecf20Sopenharmony_ci/* arch_validate_flags() - Ensure combination of flags is valid for a
658c2ecf20Sopenharmony_ci *	VMA.
668c2ecf20Sopenharmony_ci */
678c2ecf20Sopenharmony_cistatic inline bool arch_validate_flags(unsigned long vm_flags)
688c2ecf20Sopenharmony_ci{
698c2ecf20Sopenharmony_ci	/* If ADI is being enabled on this VMA, check for ADI
708c2ecf20Sopenharmony_ci	 * capability on the platform and ensure VMA is suitable
718c2ecf20Sopenharmony_ci	 * for ADI
728c2ecf20Sopenharmony_ci	 */
738c2ecf20Sopenharmony_ci	if (vm_flags & VM_SPARC_ADI) {
748c2ecf20Sopenharmony_ci		if (!adi_capable())
758c2ecf20Sopenharmony_ci			return false;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci		/* ADI can not be enabled on PFN mapped pages */
788c2ecf20Sopenharmony_ci		if (vm_flags & (VM_PFNMAP | VM_MIXEDMAP))
798c2ecf20Sopenharmony_ci			return false;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci		/* Mergeable pages can become unmergeable
828c2ecf20Sopenharmony_ci		 * if ADI is enabled on them even if they
838c2ecf20Sopenharmony_ci		 * have identical data on them. This can be
848c2ecf20Sopenharmony_ci		 * because ADI enabled pages with identical
858c2ecf20Sopenharmony_ci		 * data may still not have identical ADI
868c2ecf20Sopenharmony_ci		 * tags on them. Disallow ADI on mergeable
878c2ecf20Sopenharmony_ci		 * pages.
888c2ecf20Sopenharmony_ci		 */
898c2ecf20Sopenharmony_ci		if (vm_flags & VM_MERGEABLE)
908c2ecf20Sopenharmony_ci			return false;
918c2ecf20Sopenharmony_ci	}
928c2ecf20Sopenharmony_ci	return true;
938c2ecf20Sopenharmony_ci}
948c2ecf20Sopenharmony_ci#endif /* CONFIG_SPARC64 */
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */
978c2ecf20Sopenharmony_ci#endif /* __SPARC_MMAN_H__ */
98