162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#define DISABLE_BRANCH_PROFILING 362306a36Sopenharmony_ci#define pr_fmt(fmt) "kasan: " fmt 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci/* cpu_feature_enabled() cannot be used this early */ 662306a36Sopenharmony_ci#define USE_EARLY_PGTABLE_L5 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/memblock.h> 962306a36Sopenharmony_ci#include <linux/kasan.h> 1062306a36Sopenharmony_ci#include <linux/kdebug.h> 1162306a36Sopenharmony_ci#include <linux/mm.h> 1262306a36Sopenharmony_ci#include <linux/sched.h> 1362306a36Sopenharmony_ci#include <linux/sched/task.h> 1462306a36Sopenharmony_ci#include <linux/vmalloc.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <asm/e820/types.h> 1762306a36Sopenharmony_ci#include <asm/pgalloc.h> 1862306a36Sopenharmony_ci#include <asm/tlbflush.h> 1962306a36Sopenharmony_ci#include <asm/sections.h> 2062306a36Sopenharmony_ci#include <asm/cpu_entry_area.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ciextern struct range pfn_mapped[E820_MAX_ENTRIES]; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic p4d_t tmp_p4d_table[MAX_PTRS_PER_P4D] __initdata __aligned(PAGE_SIZE); 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic __init void *early_alloc(size_t size, int nid, bool should_panic) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci void *ptr = memblock_alloc_try_nid(size, size, 2962306a36Sopenharmony_ci __pa(MAX_DMA_ADDRESS), MEMBLOCK_ALLOC_ACCESSIBLE, nid); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci if (!ptr && should_panic) 3262306a36Sopenharmony_ci panic("%pS: Failed to allocate page, nid=%d from=%lx\n", 3362306a36Sopenharmony_ci (void *)_RET_IP_, nid, __pa(MAX_DMA_ADDRESS)); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci return ptr; 3662306a36Sopenharmony_ci} 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic void __init kasan_populate_pmd(pmd_t *pmd, unsigned long addr, 3962306a36Sopenharmony_ci unsigned long end, int nid) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci pte_t *pte; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci if (pmd_none(*pmd)) { 4462306a36Sopenharmony_ci void *p; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci if (boot_cpu_has(X86_FEATURE_PSE) && 4762306a36Sopenharmony_ci ((end - addr) == PMD_SIZE) && 4862306a36Sopenharmony_ci IS_ALIGNED(addr, PMD_SIZE)) { 4962306a36Sopenharmony_ci p = early_alloc(PMD_SIZE, nid, false); 5062306a36Sopenharmony_ci if (p && pmd_set_huge(pmd, __pa(p), PAGE_KERNEL)) 5162306a36Sopenharmony_ci return; 5262306a36Sopenharmony_ci memblock_free(p, PMD_SIZE); 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci p = early_alloc(PAGE_SIZE, nid, true); 5662306a36Sopenharmony_ci pmd_populate_kernel(&init_mm, pmd, p); 5762306a36Sopenharmony_ci } 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci pte = pte_offset_kernel(pmd, addr); 6062306a36Sopenharmony_ci do { 6162306a36Sopenharmony_ci pte_t entry; 6262306a36Sopenharmony_ci void *p; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci if (!pte_none(*pte)) 6562306a36Sopenharmony_ci continue; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci p = early_alloc(PAGE_SIZE, nid, true); 6862306a36Sopenharmony_ci entry = pfn_pte(PFN_DOWN(__pa(p)), PAGE_KERNEL); 6962306a36Sopenharmony_ci set_pte_at(&init_mm, addr, pte, entry); 7062306a36Sopenharmony_ci } while (pte++, addr += PAGE_SIZE, addr != end); 7162306a36Sopenharmony_ci} 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic void __init kasan_populate_pud(pud_t *pud, unsigned long addr, 7462306a36Sopenharmony_ci unsigned long end, int nid) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci pmd_t *pmd; 7762306a36Sopenharmony_ci unsigned long next; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (pud_none(*pud)) { 8062306a36Sopenharmony_ci void *p; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci if (boot_cpu_has(X86_FEATURE_GBPAGES) && 8362306a36Sopenharmony_ci ((end - addr) == PUD_SIZE) && 8462306a36Sopenharmony_ci IS_ALIGNED(addr, PUD_SIZE)) { 8562306a36Sopenharmony_ci p = early_alloc(PUD_SIZE, nid, false); 8662306a36Sopenharmony_ci if (p && pud_set_huge(pud, __pa(p), PAGE_KERNEL)) 8762306a36Sopenharmony_ci return; 8862306a36Sopenharmony_ci memblock_free(p, PUD_SIZE); 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci p = early_alloc(PAGE_SIZE, nid, true); 9262306a36Sopenharmony_ci pud_populate(&init_mm, pud, p); 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci pmd = pmd_offset(pud, addr); 9662306a36Sopenharmony_ci do { 9762306a36Sopenharmony_ci next = pmd_addr_end(addr, end); 9862306a36Sopenharmony_ci if (!pmd_large(*pmd)) 9962306a36Sopenharmony_ci kasan_populate_pmd(pmd, addr, next, nid); 10062306a36Sopenharmony_ci } while (pmd++, addr = next, addr != end); 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic void __init kasan_populate_p4d(p4d_t *p4d, unsigned long addr, 10462306a36Sopenharmony_ci unsigned long end, int nid) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci pud_t *pud; 10762306a36Sopenharmony_ci unsigned long next; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci if (p4d_none(*p4d)) { 11062306a36Sopenharmony_ci void *p = early_alloc(PAGE_SIZE, nid, true); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci p4d_populate(&init_mm, p4d, p); 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci pud = pud_offset(p4d, addr); 11662306a36Sopenharmony_ci do { 11762306a36Sopenharmony_ci next = pud_addr_end(addr, end); 11862306a36Sopenharmony_ci if (!pud_large(*pud)) 11962306a36Sopenharmony_ci kasan_populate_pud(pud, addr, next, nid); 12062306a36Sopenharmony_ci } while (pud++, addr = next, addr != end); 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistatic void __init kasan_populate_pgd(pgd_t *pgd, unsigned long addr, 12462306a36Sopenharmony_ci unsigned long end, int nid) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci void *p; 12762306a36Sopenharmony_ci p4d_t *p4d; 12862306a36Sopenharmony_ci unsigned long next; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci if (pgd_none(*pgd)) { 13162306a36Sopenharmony_ci p = early_alloc(PAGE_SIZE, nid, true); 13262306a36Sopenharmony_ci pgd_populate(&init_mm, pgd, p); 13362306a36Sopenharmony_ci } 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci p4d = p4d_offset(pgd, addr); 13662306a36Sopenharmony_ci do { 13762306a36Sopenharmony_ci next = p4d_addr_end(addr, end); 13862306a36Sopenharmony_ci kasan_populate_p4d(p4d, addr, next, nid); 13962306a36Sopenharmony_ci } while (p4d++, addr = next, addr != end); 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic void __init kasan_populate_shadow(unsigned long addr, unsigned long end, 14362306a36Sopenharmony_ci int nid) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci pgd_t *pgd; 14662306a36Sopenharmony_ci unsigned long next; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci addr = addr & PAGE_MASK; 14962306a36Sopenharmony_ci end = round_up(end, PAGE_SIZE); 15062306a36Sopenharmony_ci pgd = pgd_offset_k(addr); 15162306a36Sopenharmony_ci do { 15262306a36Sopenharmony_ci next = pgd_addr_end(addr, end); 15362306a36Sopenharmony_ci kasan_populate_pgd(pgd, addr, next, nid); 15462306a36Sopenharmony_ci } while (pgd++, addr = next, addr != end); 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cistatic void __init map_range(struct range *range) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci unsigned long start; 16062306a36Sopenharmony_ci unsigned long end; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci start = (unsigned long)kasan_mem_to_shadow(pfn_to_kaddr(range->start)); 16362306a36Sopenharmony_ci end = (unsigned long)kasan_mem_to_shadow(pfn_to_kaddr(range->end)); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci kasan_populate_shadow(start, end, early_pfn_to_nid(range->start)); 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic void __init clear_pgds(unsigned long start, 16962306a36Sopenharmony_ci unsigned long end) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci pgd_t *pgd; 17262306a36Sopenharmony_ci /* See comment in kasan_init() */ 17362306a36Sopenharmony_ci unsigned long pgd_end = end & PGDIR_MASK; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci for (; start < pgd_end; start += PGDIR_SIZE) { 17662306a36Sopenharmony_ci pgd = pgd_offset_k(start); 17762306a36Sopenharmony_ci /* 17862306a36Sopenharmony_ci * With folded p4d, pgd_clear() is nop, use p4d_clear() 17962306a36Sopenharmony_ci * instead. 18062306a36Sopenharmony_ci */ 18162306a36Sopenharmony_ci if (pgtable_l5_enabled()) 18262306a36Sopenharmony_ci pgd_clear(pgd); 18362306a36Sopenharmony_ci else 18462306a36Sopenharmony_ci p4d_clear(p4d_offset(pgd, start)); 18562306a36Sopenharmony_ci } 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci pgd = pgd_offset_k(start); 18862306a36Sopenharmony_ci for (; start < end; start += P4D_SIZE) 18962306a36Sopenharmony_ci p4d_clear(p4d_offset(pgd, start)); 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic inline p4d_t *early_p4d_offset(pgd_t *pgd, unsigned long addr) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci unsigned long p4d; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci if (!pgtable_l5_enabled()) 19762306a36Sopenharmony_ci return (p4d_t *)pgd; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci p4d = pgd_val(*pgd) & PTE_PFN_MASK; 20062306a36Sopenharmony_ci p4d += __START_KERNEL_map - phys_base; 20162306a36Sopenharmony_ci return (p4d_t *)p4d + p4d_index(addr); 20262306a36Sopenharmony_ci} 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic void __init kasan_early_p4d_populate(pgd_t *pgd, 20562306a36Sopenharmony_ci unsigned long addr, 20662306a36Sopenharmony_ci unsigned long end) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci pgd_t pgd_entry; 20962306a36Sopenharmony_ci p4d_t *p4d, p4d_entry; 21062306a36Sopenharmony_ci unsigned long next; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci if (pgd_none(*pgd)) { 21362306a36Sopenharmony_ci pgd_entry = __pgd(_KERNPG_TABLE | 21462306a36Sopenharmony_ci __pa_nodebug(kasan_early_shadow_p4d)); 21562306a36Sopenharmony_ci set_pgd(pgd, pgd_entry); 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci p4d = early_p4d_offset(pgd, addr); 21962306a36Sopenharmony_ci do { 22062306a36Sopenharmony_ci next = p4d_addr_end(addr, end); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci if (!p4d_none(*p4d)) 22362306a36Sopenharmony_ci continue; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci p4d_entry = __p4d(_KERNPG_TABLE | 22662306a36Sopenharmony_ci __pa_nodebug(kasan_early_shadow_pud)); 22762306a36Sopenharmony_ci set_p4d(p4d, p4d_entry); 22862306a36Sopenharmony_ci } while (p4d++, addr = next, addr != end && p4d_none(*p4d)); 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic void __init kasan_map_early_shadow(pgd_t *pgd) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci /* See comment in kasan_init() */ 23462306a36Sopenharmony_ci unsigned long addr = KASAN_SHADOW_START & PGDIR_MASK; 23562306a36Sopenharmony_ci unsigned long end = KASAN_SHADOW_END; 23662306a36Sopenharmony_ci unsigned long next; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci pgd += pgd_index(addr); 23962306a36Sopenharmony_ci do { 24062306a36Sopenharmony_ci next = pgd_addr_end(addr, end); 24162306a36Sopenharmony_ci kasan_early_p4d_populate(pgd, addr, next); 24262306a36Sopenharmony_ci } while (pgd++, addr = next, addr != end); 24362306a36Sopenharmony_ci} 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistatic void __init kasan_shallow_populate_p4ds(pgd_t *pgd, 24662306a36Sopenharmony_ci unsigned long addr, 24762306a36Sopenharmony_ci unsigned long end) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci p4d_t *p4d; 25062306a36Sopenharmony_ci unsigned long next; 25162306a36Sopenharmony_ci void *p; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci p4d = p4d_offset(pgd, addr); 25462306a36Sopenharmony_ci do { 25562306a36Sopenharmony_ci next = p4d_addr_end(addr, end); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci if (p4d_none(*p4d)) { 25862306a36Sopenharmony_ci p = early_alloc(PAGE_SIZE, NUMA_NO_NODE, true); 25962306a36Sopenharmony_ci p4d_populate(&init_mm, p4d, p); 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci } while (p4d++, addr = next, addr != end); 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistatic void __init kasan_shallow_populate_pgds(void *start, void *end) 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci unsigned long addr, next; 26762306a36Sopenharmony_ci pgd_t *pgd; 26862306a36Sopenharmony_ci void *p; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci addr = (unsigned long)start; 27162306a36Sopenharmony_ci pgd = pgd_offset_k(addr); 27262306a36Sopenharmony_ci do { 27362306a36Sopenharmony_ci next = pgd_addr_end(addr, (unsigned long)end); 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci if (pgd_none(*pgd)) { 27662306a36Sopenharmony_ci p = early_alloc(PAGE_SIZE, NUMA_NO_NODE, true); 27762306a36Sopenharmony_ci pgd_populate(&init_mm, pgd, p); 27862306a36Sopenharmony_ci } 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci /* 28162306a36Sopenharmony_ci * we need to populate p4ds to be synced when running in 28262306a36Sopenharmony_ci * four level mode - see sync_global_pgds_l4() 28362306a36Sopenharmony_ci */ 28462306a36Sopenharmony_ci kasan_shallow_populate_p4ds(pgd, addr, next); 28562306a36Sopenharmony_ci } while (pgd++, addr = next, addr != (unsigned long)end); 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_civoid __init kasan_early_init(void) 28962306a36Sopenharmony_ci{ 29062306a36Sopenharmony_ci int i; 29162306a36Sopenharmony_ci pteval_t pte_val = __pa_nodebug(kasan_early_shadow_page) | 29262306a36Sopenharmony_ci __PAGE_KERNEL | _PAGE_ENC; 29362306a36Sopenharmony_ci pmdval_t pmd_val = __pa_nodebug(kasan_early_shadow_pte) | _KERNPG_TABLE; 29462306a36Sopenharmony_ci pudval_t pud_val = __pa_nodebug(kasan_early_shadow_pmd) | _KERNPG_TABLE; 29562306a36Sopenharmony_ci p4dval_t p4d_val = __pa_nodebug(kasan_early_shadow_pud) | _KERNPG_TABLE; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci /* Mask out unsupported __PAGE_KERNEL bits: */ 29862306a36Sopenharmony_ci pte_val &= __default_kernel_pte_mask; 29962306a36Sopenharmony_ci pmd_val &= __default_kernel_pte_mask; 30062306a36Sopenharmony_ci pud_val &= __default_kernel_pte_mask; 30162306a36Sopenharmony_ci p4d_val &= __default_kernel_pte_mask; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci for (i = 0; i < PTRS_PER_PTE; i++) 30462306a36Sopenharmony_ci kasan_early_shadow_pte[i] = __pte(pte_val); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci for (i = 0; i < PTRS_PER_PMD; i++) 30762306a36Sopenharmony_ci kasan_early_shadow_pmd[i] = __pmd(pmd_val); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci for (i = 0; i < PTRS_PER_PUD; i++) 31062306a36Sopenharmony_ci kasan_early_shadow_pud[i] = __pud(pud_val); 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci for (i = 0; pgtable_l5_enabled() && i < PTRS_PER_P4D; i++) 31362306a36Sopenharmony_ci kasan_early_shadow_p4d[i] = __p4d(p4d_val); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci kasan_map_early_shadow(early_top_pgt); 31662306a36Sopenharmony_ci kasan_map_early_shadow(init_top_pgt); 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_cistatic unsigned long kasan_mem_to_shadow_align_down(unsigned long va) 32062306a36Sopenharmony_ci{ 32162306a36Sopenharmony_ci unsigned long shadow = (unsigned long)kasan_mem_to_shadow((void *)va); 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci return round_down(shadow, PAGE_SIZE); 32462306a36Sopenharmony_ci} 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_cistatic unsigned long kasan_mem_to_shadow_align_up(unsigned long va) 32762306a36Sopenharmony_ci{ 32862306a36Sopenharmony_ci unsigned long shadow = (unsigned long)kasan_mem_to_shadow((void *)va); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci return round_up(shadow, PAGE_SIZE); 33162306a36Sopenharmony_ci} 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_civoid __init kasan_populate_shadow_for_vaddr(void *va, size_t size, int nid) 33462306a36Sopenharmony_ci{ 33562306a36Sopenharmony_ci unsigned long shadow_start, shadow_end; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci shadow_start = kasan_mem_to_shadow_align_down((unsigned long)va); 33862306a36Sopenharmony_ci shadow_end = kasan_mem_to_shadow_align_up((unsigned long)va + size); 33962306a36Sopenharmony_ci kasan_populate_shadow(shadow_start, shadow_end, nid); 34062306a36Sopenharmony_ci} 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_civoid __init kasan_init(void) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci unsigned long shadow_cea_begin, shadow_cea_per_cpu_begin, shadow_cea_end; 34562306a36Sopenharmony_ci int i; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci memcpy(early_top_pgt, init_top_pgt, sizeof(early_top_pgt)); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci /* 35062306a36Sopenharmony_ci * We use the same shadow offset for 4- and 5-level paging to 35162306a36Sopenharmony_ci * facilitate boot-time switching between paging modes. 35262306a36Sopenharmony_ci * As result in 5-level paging mode KASAN_SHADOW_START and 35362306a36Sopenharmony_ci * KASAN_SHADOW_END are not aligned to PGD boundary. 35462306a36Sopenharmony_ci * 35562306a36Sopenharmony_ci * KASAN_SHADOW_START doesn't share PGD with anything else. 35662306a36Sopenharmony_ci * We claim whole PGD entry to make things easier. 35762306a36Sopenharmony_ci * 35862306a36Sopenharmony_ci * KASAN_SHADOW_END lands in the last PGD entry and it collides with 35962306a36Sopenharmony_ci * bunch of things like kernel code, modules, EFI mapping, etc. 36062306a36Sopenharmony_ci * We need to take extra steps to not overwrite them. 36162306a36Sopenharmony_ci */ 36262306a36Sopenharmony_ci if (pgtable_l5_enabled()) { 36362306a36Sopenharmony_ci void *ptr; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci ptr = (void *)pgd_page_vaddr(*pgd_offset_k(KASAN_SHADOW_END)); 36662306a36Sopenharmony_ci memcpy(tmp_p4d_table, (void *)ptr, sizeof(tmp_p4d_table)); 36762306a36Sopenharmony_ci set_pgd(&early_top_pgt[pgd_index(KASAN_SHADOW_END)], 36862306a36Sopenharmony_ci __pgd(__pa(tmp_p4d_table) | _KERNPG_TABLE)); 36962306a36Sopenharmony_ci } 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci load_cr3(early_top_pgt); 37262306a36Sopenharmony_ci __flush_tlb_all(); 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci clear_pgds(KASAN_SHADOW_START & PGDIR_MASK, KASAN_SHADOW_END); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci kasan_populate_early_shadow((void *)(KASAN_SHADOW_START & PGDIR_MASK), 37762306a36Sopenharmony_ci kasan_mem_to_shadow((void *)PAGE_OFFSET)); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci for (i = 0; i < E820_MAX_ENTRIES; i++) { 38062306a36Sopenharmony_ci if (pfn_mapped[i].end == 0) 38162306a36Sopenharmony_ci break; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci map_range(&pfn_mapped[i]); 38462306a36Sopenharmony_ci } 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci shadow_cea_begin = kasan_mem_to_shadow_align_down(CPU_ENTRY_AREA_BASE); 38762306a36Sopenharmony_ci shadow_cea_per_cpu_begin = kasan_mem_to_shadow_align_up(CPU_ENTRY_AREA_PER_CPU); 38862306a36Sopenharmony_ci shadow_cea_end = kasan_mem_to_shadow_align_up(CPU_ENTRY_AREA_BASE + 38962306a36Sopenharmony_ci CPU_ENTRY_AREA_MAP_SIZE); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci kasan_populate_early_shadow( 39262306a36Sopenharmony_ci kasan_mem_to_shadow((void *)PAGE_OFFSET + MAXMEM), 39362306a36Sopenharmony_ci kasan_mem_to_shadow((void *)VMALLOC_START)); 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci /* 39662306a36Sopenharmony_ci * If we're in full vmalloc mode, don't back vmalloc space with early 39762306a36Sopenharmony_ci * shadow pages. Instead, prepopulate pgds/p4ds so they are synced to 39862306a36Sopenharmony_ci * the global table and we can populate the lower levels on demand. 39962306a36Sopenharmony_ci */ 40062306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) 40162306a36Sopenharmony_ci kasan_shallow_populate_pgds( 40262306a36Sopenharmony_ci kasan_mem_to_shadow((void *)VMALLOC_START), 40362306a36Sopenharmony_ci kasan_mem_to_shadow((void *)VMALLOC_END)); 40462306a36Sopenharmony_ci else 40562306a36Sopenharmony_ci kasan_populate_early_shadow( 40662306a36Sopenharmony_ci kasan_mem_to_shadow((void *)VMALLOC_START), 40762306a36Sopenharmony_ci kasan_mem_to_shadow((void *)VMALLOC_END)); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci kasan_populate_early_shadow( 41062306a36Sopenharmony_ci kasan_mem_to_shadow((void *)VMALLOC_END + 1), 41162306a36Sopenharmony_ci (void *)shadow_cea_begin); 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci /* 41462306a36Sopenharmony_ci * Populate the shadow for the shared portion of the CPU entry area. 41562306a36Sopenharmony_ci * Shadows for the per-CPU areas are mapped on-demand, as each CPU's 41662306a36Sopenharmony_ci * area is randomly placed somewhere in the 512GiB range and mapping 41762306a36Sopenharmony_ci * the entire 512GiB range is prohibitively expensive. 41862306a36Sopenharmony_ci */ 41962306a36Sopenharmony_ci kasan_populate_shadow(shadow_cea_begin, 42062306a36Sopenharmony_ci shadow_cea_per_cpu_begin, 0); 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci kasan_populate_early_shadow((void *)shadow_cea_end, 42362306a36Sopenharmony_ci kasan_mem_to_shadow((void *)__START_KERNEL_map)); 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci kasan_populate_shadow((unsigned long)kasan_mem_to_shadow(_stext), 42662306a36Sopenharmony_ci (unsigned long)kasan_mem_to_shadow(_end), 42762306a36Sopenharmony_ci early_pfn_to_nid(__pa(_stext))); 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci kasan_populate_early_shadow(kasan_mem_to_shadow((void *)MODULES_END), 43062306a36Sopenharmony_ci (void *)KASAN_SHADOW_END); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci load_cr3(init_top_pgt); 43362306a36Sopenharmony_ci __flush_tlb_all(); 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci /* 43662306a36Sopenharmony_ci * kasan_early_shadow_page has been used as early shadow memory, thus 43762306a36Sopenharmony_ci * it may contain some garbage. Now we can clear and write protect it, 43862306a36Sopenharmony_ci * since after the TLB flush no one should write to it. 43962306a36Sopenharmony_ci */ 44062306a36Sopenharmony_ci memset(kasan_early_shadow_page, 0, PAGE_SIZE); 44162306a36Sopenharmony_ci for (i = 0; i < PTRS_PER_PTE; i++) { 44262306a36Sopenharmony_ci pte_t pte; 44362306a36Sopenharmony_ci pgprot_t prot; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci prot = __pgprot(__PAGE_KERNEL_RO | _PAGE_ENC); 44662306a36Sopenharmony_ci pgprot_val(prot) &= __default_kernel_pte_mask; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci pte = __pte(__pa(kasan_early_shadow_page) | pgprot_val(prot)); 44962306a36Sopenharmony_ci set_pte(&kasan_early_shadow_pte[i], pte); 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci /* Flush TLBs again to be sure that write protection applied. */ 45262306a36Sopenharmony_ci __flush_tlb_all(); 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci init_task.kasan_depth = 0; 45562306a36Sopenharmony_ci pr_info("KernelAddressSanitizer initialized\n"); 45662306a36Sopenharmony_ci} 457