|
13 | 13 |
|
14 | 14 | static pgd_t kasan_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE); |
15 | 15 |
|
| 16 | +#ifdef __PAGETABLE_P4D_FOLDED |
| 17 | +#define __pgd_none(early, pgd) (0) |
| 18 | +#else |
| 19 | +#define __pgd_none(early, pgd) (early ? (pgd_val(pgd) == 0) : \ |
| 20 | +(__pa(pgd_val(pgd)) == (unsigned long)__pa(kasan_early_shadow_p4d))) |
| 21 | +#endif |
| 22 | + |
16 | 23 | #ifdef __PAGETABLE_PUD_FOLDED |
17 | 24 | #define __p4d_none(early, p4d) (0) |
18 | 25 | #else |
@@ -142,6 +149,19 @@ static pud_t *__init kasan_pud_offset(p4d_t *p4dp, unsigned long addr, int node, |
142 | 149 | return pud_offset(p4dp, addr); |
143 | 150 | } |
144 | 151 |
|
| 152 | +static p4d_t *__init kasan_p4d_offset(pgd_t *pgdp, unsigned long addr, int node, bool early) |
| 153 | +{ |
| 154 | + if (__pgd_none(early, pgdp_get(pgdp))) { |
| 155 | + phys_addr_t p4d_phys = early ? |
| 156 | + __pa_symbol(kasan_early_shadow_p4d) : kasan_alloc_zeroed_page(node); |
| 157 | + if (!early) |
| 158 | + memcpy(__va(p4d_phys), kasan_early_shadow_p4d, sizeof(kasan_early_shadow_p4d)); |
| 159 | + pgd_populate(&init_mm, pgdp, (p4d_t *)__va(p4d_phys)); |
| 160 | + } |
| 161 | + |
| 162 | + return p4d_offset(pgdp, addr); |
| 163 | +} |
| 164 | + |
145 | 165 | static void __init kasan_pte_populate(pmd_t *pmdp, unsigned long addr, |
146 | 166 | unsigned long end, int node, bool early) |
147 | 167 | { |
@@ -178,19 +198,19 @@ static void __init kasan_pud_populate(p4d_t *p4dp, unsigned long addr, |
178 | 198 | do { |
179 | 199 | next = pud_addr_end(addr, end); |
180 | 200 | kasan_pmd_populate(pudp, addr, next, node, early); |
181 | | - } while (pudp++, addr = next, addr != end); |
| 201 | + } while (pudp++, addr = next, addr != end && __pud_none(early, READ_ONCE(*pudp))); |
182 | 202 | } |
183 | 203 |
|
184 | 204 | static void __init kasan_p4d_populate(pgd_t *pgdp, unsigned long addr, |
185 | 205 | unsigned long end, int node, bool early) |
186 | 206 | { |
187 | 207 | unsigned long next; |
188 | | - p4d_t *p4dp = p4d_offset(pgdp, addr); |
| 208 | + p4d_t *p4dp = kasan_p4d_offset(pgdp, addr, node, early); |
189 | 209 |
|
190 | 210 | do { |
191 | 211 | next = p4d_addr_end(addr, end); |
192 | 212 | kasan_pud_populate(p4dp, addr, next, node, early); |
193 | | - } while (p4dp++, addr = next, addr != end); |
| 213 | + } while (p4dp++, addr = next, addr != end && __p4d_none(early, READ_ONCE(*p4dp))); |
194 | 214 | } |
195 | 215 |
|
196 | 216 | static void __init kasan_pgd_populate(unsigned long addr, unsigned long end, |
|
0 commit comments