190cbac0eSChristophe Leroy /* SPDX-License-Identifier: GPL-2.0 */
290cbac0eSChristophe Leroy /*
390cbac0eSChristophe Leroy * powerpc KFENCE support.
490cbac0eSChristophe Leroy *
590cbac0eSChristophe Leroy * Copyright (C) 2020 CS GROUP France
690cbac0eSChristophe Leroy */
790cbac0eSChristophe Leroy
890cbac0eSChristophe Leroy #ifndef __ASM_POWERPC_KFENCE_H
990cbac0eSChristophe Leroy #define __ASM_POWERPC_KFENCE_H
1090cbac0eSChristophe Leroy
1190cbac0eSChristophe Leroy #include <linux/mm.h>
1290cbac0eSChristophe Leroy #include <asm/pgtable.h>
1390cbac0eSChristophe Leroy
14a5edf981SNicholas Miehlbradt #ifdef CONFIG_PPC64_ELF_ABI_V1
15a5edf981SNicholas Miehlbradt #define ARCH_FUNC_PREFIX "."
16a5edf981SNicholas Miehlbradt #endif
17a5edf981SNicholas Miehlbradt
1890cbac0eSChristophe Leroy extern bool kfence_early_init;
1990cbac0eSChristophe Leroy extern bool kfence_disabled;
2090cbac0eSChristophe Leroy
disable_kfence(void)2190cbac0eSChristophe Leroy static inline void disable_kfence(void)
2290cbac0eSChristophe Leroy {
23a5edf981SNicholas Miehlbradt kfence_disabled = true;
24a5edf981SNicholas Miehlbradt }
25a5edf981SNicholas Miehlbradt
arch_kfence_init_pool(void)26*58b6fed8SLinus Walleij static inline bool arch_kfence_init_pool(void)
27a5edf981SNicholas Miehlbradt {
28a5edf981SNicholas Miehlbradt return !kfence_disabled;
29a5edf981SNicholas Miehlbradt }
30a5edf981SNicholas Miehlbradt
kfence_early_init_enabled(void)31a5edf981SNicholas Miehlbradt static inline bool kfence_early_init_enabled(void)
32a5edf981SNicholas Miehlbradt {
3390cbac0eSChristophe Leroy return IS_ENABLED(CONFIG_KFENCE) && kfence_early_init;
3490cbac0eSChristophe Leroy }
3590cbac0eSChristophe Leroy
3690cbac0eSChristophe Leroy #ifdef CONFIG_PPC64
kfence_protect_page(unsigned long addr,bool protect)3790cbac0eSChristophe Leroy static inline bool kfence_protect_page(unsigned long addr, bool protect)
3890cbac0eSChristophe Leroy {
3990cbac0eSChristophe Leroy struct page *page = virt_to_page((void *)addr);
4090cbac0eSChristophe Leroy
4190cbac0eSChristophe Leroy __kernel_map_pages(page, 1, !protect);
4290cbac0eSChristophe Leroy
4390cbac0eSChristophe Leroy return true;
4490cbac0eSChristophe Leroy }
4590cbac0eSChristophe Leroy #else
kfence_protect_page(unsigned long addr,bool protect)46a5edf981SNicholas Miehlbradt static inline bool kfence_protect_page(unsigned long addr, bool protect)
4790cbac0eSChristophe Leroy {
4890cbac0eSChristophe Leroy pte_t *kpte = virt_to_kpte(addr);
49
50 if (protect) {
51 pte_update(&init_mm, addr, kpte, _PAGE_PRESENT, 0, 0);
52 flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
53 } else {
54 pte_update(&init_mm, addr, kpte, 0, _PAGE_PRESENT, 0);
55 }
56
57 return true;
58 }
59 #endif
60
61 #endif /* __ASM_POWERPC_KFENCE_H */
62