1*8ad8b727SNick Hu // SPDX-License-Identifier: GPL-2.0 2*8ad8b727SNick Hu // Copyright (C) 2019 Andes Technology Corporation 3*8ad8b727SNick Hu 4*8ad8b727SNick Hu #include <linux/pfn.h> 5*8ad8b727SNick Hu #include <linux/init_task.h> 6*8ad8b727SNick Hu #include <linux/kasan.h> 7*8ad8b727SNick Hu #include <linux/kernel.h> 8*8ad8b727SNick Hu #include <linux/memblock.h> 9*8ad8b727SNick Hu #include <asm/tlbflush.h> 10*8ad8b727SNick Hu #include <asm/pgtable.h> 11*8ad8b727SNick Hu #include <asm/fixmap.h> 12*8ad8b727SNick Hu 13*8ad8b727SNick Hu extern pgd_t early_pg_dir[PTRS_PER_PGD]; 14*8ad8b727SNick Hu asmlinkage void __init kasan_early_init(void) 15*8ad8b727SNick Hu { 16*8ad8b727SNick Hu uintptr_t i; 17*8ad8b727SNick Hu pgd_t *pgd = early_pg_dir + pgd_index(KASAN_SHADOW_START); 18*8ad8b727SNick Hu 19*8ad8b727SNick Hu for (i = 0; i < PTRS_PER_PTE; ++i) 20*8ad8b727SNick Hu set_pte(kasan_early_shadow_pte + i, 21*8ad8b727SNick Hu mk_pte(virt_to_page(kasan_early_shadow_page), 22*8ad8b727SNick Hu PAGE_KERNEL)); 23*8ad8b727SNick Hu 24*8ad8b727SNick Hu for (i = 0; i < PTRS_PER_PMD; ++i) 25*8ad8b727SNick Hu set_pmd(kasan_early_shadow_pmd + i, 26*8ad8b727SNick Hu pfn_pmd(PFN_DOWN(__pa((uintptr_t)kasan_early_shadow_pte)), 27*8ad8b727SNick Hu __pgprot(_PAGE_TABLE))); 28*8ad8b727SNick Hu 29*8ad8b727SNick Hu for (i = KASAN_SHADOW_START; i < KASAN_SHADOW_END; 30*8ad8b727SNick Hu i += PGDIR_SIZE, ++pgd) 31*8ad8b727SNick Hu set_pgd(pgd, 32*8ad8b727SNick Hu pfn_pgd(PFN_DOWN(__pa(((uintptr_t)kasan_early_shadow_pmd))), 33*8ad8b727SNick Hu __pgprot(_PAGE_TABLE))); 34*8ad8b727SNick Hu 35*8ad8b727SNick Hu /* init for swapper_pg_dir */ 36*8ad8b727SNick Hu pgd = pgd_offset_k(KASAN_SHADOW_START); 37*8ad8b727SNick Hu 38*8ad8b727SNick Hu for (i = KASAN_SHADOW_START; i < KASAN_SHADOW_END; 39*8ad8b727SNick Hu i += PGDIR_SIZE, ++pgd) 40*8ad8b727SNick Hu set_pgd(pgd, 41*8ad8b727SNick Hu pfn_pgd(PFN_DOWN(__pa(((uintptr_t)kasan_early_shadow_pmd))), 42*8ad8b727SNick Hu __pgprot(_PAGE_TABLE))); 43*8ad8b727SNick Hu 44*8ad8b727SNick Hu flush_tlb_all(); 45*8ad8b727SNick Hu } 46*8ad8b727SNick Hu 47*8ad8b727SNick Hu static void __init populate(void *start, void *end) 48*8ad8b727SNick Hu { 49*8ad8b727SNick Hu unsigned long i; 50*8ad8b727SNick Hu unsigned long vaddr = (unsigned long)start & PAGE_MASK; 51*8ad8b727SNick Hu unsigned long vend = PAGE_ALIGN((unsigned long)end); 52*8ad8b727SNick Hu unsigned long n_pages = (vend - vaddr) / PAGE_SIZE; 53*8ad8b727SNick Hu unsigned long n_pmds = 54*8ad8b727SNick Hu (n_pages % PTRS_PER_PTE) ? n_pages / PTRS_PER_PTE + 1 : 55*8ad8b727SNick Hu n_pages / PTRS_PER_PTE; 56*8ad8b727SNick Hu pgd_t *pgd = pgd_offset_k(vaddr); 57*8ad8b727SNick Hu pmd_t *pmd = memblock_alloc(n_pmds * sizeof(pmd_t), PAGE_SIZE); 58*8ad8b727SNick Hu pte_t *pte = memblock_alloc(n_pages * sizeof(pte_t), PAGE_SIZE); 59*8ad8b727SNick Hu 60*8ad8b727SNick Hu for (i = 0; i < n_pages; i++) { 61*8ad8b727SNick Hu phys_addr_t phys = memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE); 62*8ad8b727SNick Hu 63*8ad8b727SNick Hu set_pte(pte + i, pfn_pte(PHYS_PFN(phys), PAGE_KERNEL)); 64*8ad8b727SNick Hu } 65*8ad8b727SNick Hu 66*8ad8b727SNick Hu for (i = 0; i < n_pmds; ++pgd, i += PTRS_PER_PMD) 67*8ad8b727SNick Hu set_pgd(pgd, pfn_pgd(PFN_DOWN(__pa(((uintptr_t)(pmd + i)))), 68*8ad8b727SNick Hu __pgprot(_PAGE_TABLE))); 69*8ad8b727SNick Hu 70*8ad8b727SNick Hu for (i = 0; i < n_pages; ++pmd, i += PTRS_PER_PTE) 71*8ad8b727SNick Hu set_pmd(pmd, pfn_pmd(PFN_DOWN(__pa((uintptr_t)(pte + i))), 72*8ad8b727SNick Hu __pgprot(_PAGE_TABLE))); 73*8ad8b727SNick Hu 74*8ad8b727SNick Hu flush_tlb_all(); 75*8ad8b727SNick Hu memset(start, 0, end - start); 76*8ad8b727SNick Hu } 77*8ad8b727SNick Hu 78*8ad8b727SNick Hu void __init kasan_init(void) 79*8ad8b727SNick Hu { 80*8ad8b727SNick Hu struct memblock_region *reg; 81*8ad8b727SNick Hu unsigned long i; 82*8ad8b727SNick Hu 83*8ad8b727SNick Hu kasan_populate_early_shadow((void *)KASAN_SHADOW_START, 84*8ad8b727SNick Hu (void *)kasan_mem_to_shadow((void *)VMALLOC_END)); 85*8ad8b727SNick Hu 86*8ad8b727SNick Hu for_each_memblock(memory, reg) { 87*8ad8b727SNick Hu void *start = (void *)__va(reg->base); 88*8ad8b727SNick Hu void *end = (void *)__va(reg->base + reg->size); 89*8ad8b727SNick Hu 90*8ad8b727SNick Hu if (start >= end) 91*8ad8b727SNick Hu break; 92*8ad8b727SNick Hu 93*8ad8b727SNick Hu populate(kasan_mem_to_shadow(start), 94*8ad8b727SNick Hu kasan_mem_to_shadow(end)); 95*8ad8b727SNick Hu }; 96*8ad8b727SNick Hu 97*8ad8b727SNick Hu for (i = 0; i < PTRS_PER_PTE; i++) 98*8ad8b727SNick Hu set_pte(&kasan_early_shadow_pte[i], 99*8ad8b727SNick Hu mk_pte(virt_to_page(kasan_early_shadow_page), 100*8ad8b727SNick Hu __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_ACCESSED))); 101*8ad8b727SNick Hu 102*8ad8b727SNick Hu memset(kasan_early_shadow_page, 0, PAGE_SIZE); 103*8ad8b727SNick Hu init_task.kasan_depth = 0; 104*8ad8b727SNick Hu } 105