|
12 | 12 | #include <asm/pgalloc.h>
|
13 | 13 |
|
14 | 14 | extern pgd_t early_pg_dir[PTRS_PER_PGD];
|
15 |
| -asmlinkage void __init kasan_early_init(void) |
16 |
| -{ |
17 |
| - uintptr_t i; |
18 |
| - pgd_t *pgd = early_pg_dir + pgd_index(KASAN_SHADOW_START); |
19 |
| - |
20 |
| - BUILD_BUG_ON(KASAN_SHADOW_OFFSET != |
21 |
| - KASAN_SHADOW_END - (1UL << (64 - KASAN_SHADOW_SCALE_SHIFT))); |
22 |
| - |
23 |
| - for (i = 0; i < PTRS_PER_PTE; ++i) |
24 |
| - set_pte(kasan_early_shadow_pte + i, |
25 |
| - mk_pte(virt_to_page(kasan_early_shadow_page), |
26 |
| - PAGE_KERNEL)); |
27 |
| - |
28 |
| - for (i = 0; i < PTRS_PER_PMD; ++i) |
29 |
| - set_pmd(kasan_early_shadow_pmd + i, |
30 |
| - pfn_pmd(PFN_DOWN |
31 |
| - (__pa((uintptr_t) kasan_early_shadow_pte)), |
32 |
| - __pgprot(_PAGE_TABLE))); |
33 |
| - |
34 |
| - for (i = KASAN_SHADOW_START; i < KASAN_SHADOW_END; |
35 |
| - i += PGDIR_SIZE, ++pgd) |
36 |
| - set_pgd(pgd, |
37 |
| - pfn_pgd(PFN_DOWN |
38 |
| - (__pa(((uintptr_t) kasan_early_shadow_pmd))), |
39 |
| - __pgprot(_PAGE_TABLE))); |
40 |
| - |
41 |
| - /* init for swapper_pg_dir */ |
42 |
| - pgd = pgd_offset_k(KASAN_SHADOW_START); |
43 |
| - |
44 |
| - for (i = KASAN_SHADOW_START; i < KASAN_SHADOW_END; |
45 |
| - i += PGDIR_SIZE, ++pgd) |
46 |
| - set_pgd(pgd, |
47 |
| - pfn_pgd(PFN_DOWN |
48 |
| - (__pa(((uintptr_t) kasan_early_shadow_pmd))), |
49 |
| - __pgprot(_PAGE_TABLE))); |
50 |
| - |
51 |
| - local_flush_tlb_all(); |
52 |
| -} |
53 | 15 |
|
54 | 16 | static void __init kasan_populate_pte(pmd_t *pmd, unsigned long vaddr, unsigned long end)
|
55 | 17 | {
|
@@ -108,39 +70,88 @@ static void __init kasan_populate_pmd(pgd_t *pgd, unsigned long vaddr, unsigned
|
108 | 70 | set_pgd(pgd, pfn_pgd(PFN_DOWN(__pa(base_pmd)), PAGE_TABLE));
|
109 | 71 | }
|
110 | 72 |
|
111 |
| -static void __init kasan_populate_pgd(unsigned long vaddr, unsigned long end) |
| 73 | +static void __init kasan_populate_pgd(pgd_t *pgdp, |
| 74 | + unsigned long vaddr, unsigned long end, |
| 75 | + bool early) |
112 | 76 | {
|
113 | 77 | phys_addr_t phys_addr;
|
114 |
| - pgd_t *pgdp = pgd_offset_k(vaddr); |
115 | 78 | unsigned long next;
|
116 | 79 |
|
117 | 80 | do {
|
118 | 81 | next = pgd_addr_end(vaddr, end);
|
119 | 82 |
|
120 |
| - /* |
121 |
| - * pgdp can't be none since kasan_early_init initialized all KASAN |
122 |
| - * shadow region with kasan_early_shadow_pmd: if this is stillthe case, |
123 |
| - * that means we can try to allocate a hugepage as a replacement. |
124 |
| - */ |
125 |
| - if (pgd_page_vaddr(*pgdp) == (unsigned long)lm_alias(kasan_early_shadow_pmd) && |
126 |
| - IS_ALIGNED(vaddr, PGDIR_SIZE) && (next - vaddr) >= PGDIR_SIZE) { |
127 |
| - phys_addr = memblock_phys_alloc(PGDIR_SIZE, PGDIR_SIZE); |
128 |
| - if (phys_addr) { |
129 |
| - set_pgd(pgdp, pfn_pgd(PFN_DOWN(phys_addr), PAGE_KERNEL)); |
| 83 | + if (IS_ALIGNED(vaddr, PGDIR_SIZE) && (next - vaddr) >= PGDIR_SIZE) { |
| 84 | + if (early) { |
| 85 | + phys_addr = __pa((uintptr_t)kasan_early_shadow_pgd_next); |
| 86 | + set_pgd(pgdp, pfn_pgd(PFN_DOWN(phys_addr), PAGE_TABLE)); |
130 | 87 | continue;
|
| 88 | + } else if (pgd_page_vaddr(*pgdp) == |
| 89 | + (unsigned long)lm_alias(kasan_early_shadow_pgd_next)) { |
| 90 | + /* |
| 91 | + * pgdp can't be none since kasan_early_init |
| 92 | + * initialized all KASAN shadow region with |
| 93 | + * kasan_early_shadow_pud: if this is still the |
| 94 | + * case, that means we can try to allocate a |
| 95 | + * hugepage as a replacement. |
| 96 | + */ |
| 97 | + phys_addr = memblock_phys_alloc(PGDIR_SIZE, PGDIR_SIZE); |
| 98 | + if (phys_addr) { |
| 99 | + set_pgd(pgdp, pfn_pgd(PFN_DOWN(phys_addr), PAGE_KERNEL)); |
| 100 | + continue; |
| 101 | + } |
131 | 102 | }
|
132 | 103 | }
|
133 | 104 |
|
134 | 105 | kasan_populate_pmd(pgdp, vaddr, next);
|
135 | 106 | } while (pgdp++, vaddr = next, vaddr != end);
|
136 | 107 | }
|
137 | 108 |
|
| 109 | +asmlinkage void __init kasan_early_init(void) |
| 110 | +{ |
| 111 | + uintptr_t i; |
| 112 | + |
| 113 | + BUILD_BUG_ON(KASAN_SHADOW_OFFSET != |
| 114 | + KASAN_SHADOW_END - (1UL << (64 - KASAN_SHADOW_SCALE_SHIFT))); |
| 115 | + |
| 116 | + for (i = 0; i < PTRS_PER_PTE; ++i) |
| 117 | + set_pte(kasan_early_shadow_pte + i, |
| 118 | + mk_pte(virt_to_page(kasan_early_shadow_page), |
| 119 | + PAGE_KERNEL)); |
| 120 | + |
| 121 | + for (i = 0; i < PTRS_PER_PMD; ++i) |
| 122 | + set_pmd(kasan_early_shadow_pmd + i, |
| 123 | + pfn_pmd(PFN_DOWN |
| 124 | + (__pa((uintptr_t)kasan_early_shadow_pte)), |
| 125 | + PAGE_TABLE)); |
| 126 | + |
| 127 | + if (pgtable_l4_enabled) { |
| 128 | + for (i = 0; i < PTRS_PER_PUD; ++i) |
| 129 | + set_pud(kasan_early_shadow_pud + i, |
| 130 | + pfn_pud(PFN_DOWN |
| 131 | + (__pa(((uintptr_t)kasan_early_shadow_pmd))), |
| 132 | + PAGE_TABLE)); |
| 133 | + } |
| 134 | + |
| 135 | + kasan_populate_pgd(early_pg_dir + pgd_index(KASAN_SHADOW_START), |
| 136 | + KASAN_SHADOW_START, KASAN_SHADOW_END, true); |
| 137 | + |
| 138 | + local_flush_tlb_all(); |
| 139 | +} |
| 140 | + |
| 141 | +void __init kasan_swapper_init(void) |
| 142 | +{ |
| 143 | + kasan_populate_pgd(pgd_offset_k(KASAN_SHADOW_START), |
| 144 | + KASAN_SHADOW_START, KASAN_SHADOW_END, true); |
| 145 | + |
| 146 | + local_flush_tlb_all(); |
| 147 | +} |
| 148 | + |
138 | 149 | static void __init kasan_populate(void *start, void *end)
|
139 | 150 | {
|
140 | 151 | unsigned long vaddr = (unsigned long)start & PAGE_MASK;
|
141 | 152 | unsigned long vend = PAGE_ALIGN((unsigned long)end);
|
142 | 153 |
|
143 |
| - kasan_populate_pgd(vaddr, vend); |
| 154 | + kasan_populate_pgd(pgd_offset_k(vaddr), vaddr, vend, false); |
144 | 155 |
|
145 | 156 | local_flush_tlb_all();
|
146 | 157 | memset(start, KASAN_SHADOW_INIT, end - start);
|
|
0 commit comments