162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci#define DISABLE_BRANCH_PROFILING 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/kasan.h> 662306a36Sopenharmony_ci#include <linux/memblock.h> 762306a36Sopenharmony_ci#include <linux/hugetlb.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_cistatic int __init 1062306a36Sopenharmony_cikasan_init_shadow_8M(unsigned long k_start, unsigned long k_end, void *block) 1162306a36Sopenharmony_ci{ 1262306a36Sopenharmony_ci pmd_t *pmd = pmd_off_k(k_start); 1362306a36Sopenharmony_ci unsigned long k_cur, k_next; 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci for (k_cur = k_start; k_cur != k_end; k_cur = k_next, pmd += 2, block += SZ_8M) { 1662306a36Sopenharmony_ci pte_basic_t *new; 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci k_next = pgd_addr_end(k_cur, k_end); 1962306a36Sopenharmony_ci k_next = pgd_addr_end(k_next, k_end); 2062306a36Sopenharmony_ci if ((void *)pmd_page_vaddr(*pmd) != kasan_early_shadow_pte) 2162306a36Sopenharmony_ci continue; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci new = memblock_alloc(sizeof(pte_basic_t), SZ_4K); 2462306a36Sopenharmony_ci if (!new) 2562306a36Sopenharmony_ci return -ENOMEM; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci *new = pte_val(pte_mkhuge(pfn_pte(PHYS_PFN(__pa(block)), PAGE_KERNEL))); 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci hugepd_populate_kernel((hugepd_t *)pmd, (pte_t *)new, PAGE_SHIFT_8M); 3062306a36Sopenharmony_ci hugepd_populate_kernel((hugepd_t *)pmd + 1, (pte_t *)new, PAGE_SHIFT_8M); 3162306a36Sopenharmony_ci } 3262306a36Sopenharmony_ci return 0; 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ciint __init kasan_init_region(void *start, size_t size) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci unsigned long k_start = (unsigned long)kasan_mem_to_shadow(start); 3862306a36Sopenharmony_ci unsigned long k_end = (unsigned long)kasan_mem_to_shadow(start + size); 3962306a36Sopenharmony_ci unsigned long k_cur; 4062306a36Sopenharmony_ci int ret; 4162306a36Sopenharmony_ci void *block; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci block = memblock_alloc(k_end - k_start, SZ_8M); 4462306a36Sopenharmony_ci if (!block) 4562306a36Sopenharmony_ci return -ENOMEM; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci if (IS_ALIGNED(k_start, SZ_8M)) { 4862306a36Sopenharmony_ci kasan_init_shadow_8M(k_start, ALIGN_DOWN(k_end, SZ_8M), block); 4962306a36Sopenharmony_ci k_cur = ALIGN_DOWN(k_end, SZ_8M); 5062306a36Sopenharmony_ci if (k_cur == k_end) 5162306a36Sopenharmony_ci goto finish; 5262306a36Sopenharmony_ci } else { 5362306a36Sopenharmony_ci k_cur = k_start; 5462306a36Sopenharmony_ci } 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci ret = kasan_init_shadow_page_tables(k_start, k_end); 5762306a36Sopenharmony_ci if (ret) 5862306a36Sopenharmony_ci return ret; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci for (; k_cur < k_end; k_cur += PAGE_SIZE) { 6162306a36Sopenharmony_ci pmd_t *pmd = pmd_off_k(k_cur); 6262306a36Sopenharmony_ci void *va = block + k_cur - k_start; 6362306a36Sopenharmony_ci pte_t pte = pfn_pte(PHYS_PFN(__pa(va)), PAGE_KERNEL); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci if (k_cur < ALIGN_DOWN(k_end, SZ_512K)) 6662306a36Sopenharmony_ci pte = pte_mkhuge(pte); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci __set_pte_at(&init_mm, k_cur, pte_offset_kernel(pmd, k_cur), pte, 0); 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_cifinish: 7162306a36Sopenharmony_ci flush_tlb_kernel_range(k_start, k_end); 7262306a36Sopenharmony_ci return 0; 7362306a36Sopenharmony_ci} 74