|
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