1 // SPDX-License-Identifier: GPL-2.0
3 #define DISABLE_BRANCH_PROFILING
5 #include <linux/kasan.h>
6 #include <linux/printk.h>
7 #include <linux/memblock.h>
8 #include <linux/sched/task.h>
9 #include <asm/pgalloc.h>
10 #include <asm/text-patching.h>
11 #include <mm/mmu_decl.h>
13 static pgprot_t __init
kasan_prot_ro(void)
15 if (early_mmu_has_feature(MMU_FTR_HPTE_TABLE
))
18 return PAGE_KERNEL_RO
;
21 static void __init
kasan_populate_pte(pte_t
*ptep
, pgprot_t prot
)
23 unsigned long va
= (unsigned long)kasan_early_shadow_page
;
24 phys_addr_t pa
= __pa(kasan_early_shadow_page
);
27 for (i
= 0; i
< PTRS_PER_PTE
; i
++, ptep
++)
28 __set_pte_at(&init_mm
, va
, ptep
, pfn_pte(PHYS_PFN(pa
), prot
), 1);
31 int __init
kasan_init_shadow_page_tables(unsigned long k_start
, unsigned long k_end
)
34 unsigned long k_cur
, k_next
;
36 pmd
= pmd_off_k(k_start
);
38 for (k_cur
= k_start
; k_cur
!= k_end
; k_cur
= k_next
, pmd
++) {
41 k_next
= pgd_addr_end(k_cur
, k_end
);
42 if ((void *)pmd_page_vaddr(*pmd
) != kasan_early_shadow_pte
)
45 new = memblock_alloc(PTE_FRAG_SIZE
, PTE_FRAG_SIZE
);
49 kasan_populate_pte(new, PAGE_KERNEL
);
50 pmd_populate_kernel(&init_mm
, pmd
, new);
55 int __init __weak
kasan_init_region(void *start
, size_t size
)
57 unsigned long k_start
= (unsigned long)kasan_mem_to_shadow(start
);
58 unsigned long k_end
= (unsigned long)kasan_mem_to_shadow(start
+ size
);
63 ret
= kasan_init_shadow_page_tables(k_start
, k_end
);
67 k_start
= k_start
& PAGE_MASK
;
68 block
= memblock_alloc(k_end
- k_start
, PAGE_SIZE
);
72 for (k_cur
= k_start
& PAGE_MASK
; k_cur
< k_end
; k_cur
+= PAGE_SIZE
) {
73 pmd_t
*pmd
= pmd_off_k(k_cur
);
74 void *va
= block
+ k_cur
- k_start
;
75 pte_t pte
= pfn_pte(PHYS_PFN(__pa(va
)), PAGE_KERNEL
);
77 __set_pte_at(&init_mm
, k_cur
, pte_offset_kernel(pmd
, k_cur
), pte
, 0);
79 flush_tlb_kernel_range(k_start
, k_end
);
84 kasan_update_early_region(unsigned long k_start
, unsigned long k_end
, pte_t pte
)
88 for (k_cur
= k_start
; k_cur
!= k_end
; k_cur
+= PAGE_SIZE
) {
89 pmd_t
*pmd
= pmd_off_k(k_cur
);
90 pte_t
*ptep
= pte_offset_kernel(pmd
, k_cur
);
92 if (pte_page(*ptep
) != virt_to_page(lm_alias(kasan_early_shadow_page
)))
95 __set_pte_at(&init_mm
, k_cur
, ptep
, pte
, 0);
98 flush_tlb_kernel_range(k_start
, k_end
);
101 static void __init
kasan_remap_early_shadow_ro(void)
103 pgprot_t prot
= kasan_prot_ro();
104 phys_addr_t pa
= __pa(kasan_early_shadow_page
);
106 kasan_populate_pte(kasan_early_shadow_pte
, prot
);
108 kasan_update_early_region(KASAN_SHADOW_START
, KASAN_SHADOW_END
,
109 pfn_pte(PHYS_PFN(pa
), prot
));
112 static void __init
kasan_unmap_early_shadow_vmalloc(void)
114 unsigned long k_start
= (unsigned long)kasan_mem_to_shadow((void *)VMALLOC_START
);
115 unsigned long k_end
= (unsigned long)kasan_mem_to_shadow((void *)VMALLOC_END
);
117 kasan_update_early_region(k_start
, k_end
, __pte(0));
120 k_start
= (unsigned long)kasan_mem_to_shadow((void *)MODULES_VADDR
);
121 k_end
= (unsigned long)kasan_mem_to_shadow((void *)MODULES_END
);
122 kasan_update_early_region(k_start
, k_end
, __pte(0));
126 void __init
kasan_mmu_init(void)
130 if (early_mmu_has_feature(MMU_FTR_HPTE_TABLE
)) {
131 ret
= kasan_init_shadow_page_tables(KASAN_SHADOW_START
, KASAN_SHADOW_END
);
134 panic("kasan: kasan_init_shadow_page_tables() failed");
138 void __init
kasan_init(void)
140 phys_addr_t base
, end
;
144 for_each_mem_range(i
, &base
, &end
) {
145 phys_addr_t top
= min(end
, total_lowmem
);
150 ret
= kasan_init_region(__va(base
), top
- base
);
152 panic("kasan: kasan_init_region() failed");
155 if (IS_ENABLED(CONFIG_KASAN_VMALLOC
)) {
156 ret
= kasan_init_shadow_page_tables(KASAN_SHADOW_START
, KASAN_SHADOW_END
);
159 panic("kasan: kasan_init_shadow_page_tables() failed");
162 kasan_remap_early_shadow_ro();
164 clear_page(kasan_early_shadow_page
);
166 /* At this point kasan is fully initialized. Enable error messages */
167 init_task
.kasan_depth
= 0;
168 pr_info("KASAN init done\n");
171 void __init
kasan_late_init(void)
173 if (IS_ENABLED(CONFIG_KASAN_VMALLOC
))
174 kasan_unmap_early_shadow_vmalloc();
177 void __init
kasan_early_init(void)
179 unsigned long addr
= KASAN_SHADOW_START
;
180 unsigned long end
= KASAN_SHADOW_END
;
182 pmd_t
*pmd
= pmd_off_k(addr
);
184 BUILD_BUG_ON(KASAN_SHADOW_START
& ~PGDIR_MASK
);
186 kasan_populate_pte(kasan_early_shadow_pte
, PAGE_KERNEL
);
189 next
= pgd_addr_end(addr
, end
);
190 pmd_populate_kernel(&init_mm
, pmd
, kasan_early_shadow_pte
);
191 } while (pmd
++, addr
= next
, addr
!= end
);