xref: /linux/arch/arm/include/asm/kfence.h (revision 75969686ec0df23157afe24dc818d7bddb087d78)
1*75969686SWang Kefeng /* SPDX-License-Identifier: GPL-2.0 */
2*75969686SWang Kefeng 
3*75969686SWang Kefeng #ifndef __ASM_ARM_KFENCE_H
4*75969686SWang Kefeng #define __ASM_ARM_KFENCE_H
5*75969686SWang Kefeng 
6*75969686SWang Kefeng #include <linux/kfence.h>
7*75969686SWang Kefeng 
8*75969686SWang Kefeng #include <asm/pgalloc.h>
9*75969686SWang Kefeng #include <asm/set_memory.h>
10*75969686SWang Kefeng 
11*75969686SWang Kefeng static inline int split_pmd_page(pmd_t *pmd, unsigned long addr)
12*75969686SWang Kefeng {
13*75969686SWang Kefeng 	int i;
14*75969686SWang Kefeng 	unsigned long pfn = PFN_DOWN(__pa(addr));
15*75969686SWang Kefeng 	pte_t *pte = pte_alloc_one_kernel(&init_mm);
16*75969686SWang Kefeng 
17*75969686SWang Kefeng 	if (!pte)
18*75969686SWang Kefeng 		return -ENOMEM;
19*75969686SWang Kefeng 
20*75969686SWang Kefeng 	for (i = 0; i < PTRS_PER_PTE; i++)
21*75969686SWang Kefeng 		set_pte_ext(pte + i, pfn_pte(pfn + i, PAGE_KERNEL), 0);
22*75969686SWang Kefeng 	pmd_populate_kernel(&init_mm, pmd, pte);
23*75969686SWang Kefeng 
24*75969686SWang Kefeng 	flush_tlb_kernel_range(addr, addr + PMD_SIZE);
25*75969686SWang Kefeng 	return 0;
26*75969686SWang Kefeng }
27*75969686SWang Kefeng 
28*75969686SWang Kefeng static inline bool arch_kfence_init_pool(void)
29*75969686SWang Kefeng {
30*75969686SWang Kefeng 	unsigned long addr;
31*75969686SWang Kefeng 	pmd_t *pmd;
32*75969686SWang Kefeng 
33*75969686SWang Kefeng 	for (addr = (unsigned long)__kfence_pool; is_kfence_address((void *)addr);
34*75969686SWang Kefeng 	     addr += PAGE_SIZE) {
35*75969686SWang Kefeng 		pmd = pmd_off_k(addr);
36*75969686SWang Kefeng 
37*75969686SWang Kefeng 		if (pmd_leaf(*pmd)) {
38*75969686SWang Kefeng 			if (split_pmd_page(pmd, addr & PMD_MASK))
39*75969686SWang Kefeng 				return false;
40*75969686SWang Kefeng 		}
41*75969686SWang Kefeng 	}
42*75969686SWang Kefeng 
43*75969686SWang Kefeng 	return true;
44*75969686SWang Kefeng }
45*75969686SWang Kefeng 
46*75969686SWang Kefeng static inline bool kfence_protect_page(unsigned long addr, bool protect)
47*75969686SWang Kefeng {
48*75969686SWang Kefeng 	set_memory_valid(addr, 1, !protect);
49*75969686SWang Kefeng 
50*75969686SWang Kefeng 	return true;
51*75969686SWang Kefeng }
52*75969686SWang Kefeng 
53*75969686SWang Kefeng #endif /* __ASM_ARM_KFENCE_H */
54