// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2019 Andes Technology Corporation

#include <linux/pfn.h>
#include <linux/init_task.h>
#include <linux/kasan.h>
#include <linux/kernel.h>
#include <linux/memblock.h>
#include <linux/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/fixmap.h>
#include <asm/pgalloc.h>

/*
 * Kasan shadow region must lie at a fixed address across sv39, sv48 and sv57
 * which is right before the kernel.
 *
 * For sv39, the region is aligned on PGDIR_SIZE so we only need to populate
 * the page global directory with kasan_early_shadow_pmd.
 *
 * For sv48 and sv57, the region is not aligned on PGDIR_SIZE so the mapping
 * must be divided as follows:
 * - the first PGD entry, although incomplete, is populated with
 *   kasan_early_shadow_pud/p4d
 * - the PGD entries in the middle are populated with kasan_early_shadow_pud/p4d
 * - the last PGD entry is shared with the kernel mapping so populated at the
 *   lower levels pud/p4d
 *
 * In addition, when shallow populating a kasan region (for example vmalloc),
 * this region may also not be aligned on PGDIR size, so we must go down to the
 * pud level too.
 */

extern pgd_t early_pg_dir[PTRS_PER_PGD];

static void __init kasan_populate_pte(pmd_t *pmd, unsigned long vaddr, unsigned long end)
{
	phys_addr_t phys_addr;
	pte_t *ptep, *base_pte;

	if (pmd_none(*pmd))
		base_pte = memblock_alloc(PTRS_PER_PTE * sizeof(pte_t), PAGE_SIZE);
	else
		base_pte = (pte_t *)pmd_page_vaddr(*pmd);

	ptep = base_pte + pte_index(vaddr);

	do {
		if (pte_none(*ptep)) {
			phys_addr = memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
			set_pte(ptep, pfn_pte(PFN_DOWN(phys_addr), PAGE_KERNEL));
		}
	} while (ptep++, vaddr += PAGE_SIZE, vaddr != end);

	set_pmd(pmd, pfn_pmd(PFN_DOWN(__pa(base_pte)), PAGE_TABLE));
}

static void __init kasan_populate_pmd(pud_t *pud, unsigned long vaddr, unsigned long end)
{
	phys_addr_t phys_addr;
	pmd_t *pmdp, *base_pmd;
	unsigned long next;

	if (pud_none(*pud)) {
		base_pmd = memblock_alloc(PTRS_PER_PMD * sizeof(pmd_t), PAGE_SIZE);
	} else {
		base_pmd = (pmd_t *)pud_pgtable(*pud);
		if (base_pmd == lm_alias(kasan_early_shadow_pmd))
			base_pmd = memblock_alloc(PTRS_PER_PMD * sizeof(pmd_t), PAGE_SIZE);
	}

	pmdp = base_pmd + pmd_index(vaddr);

	do {
		next = pmd_addr_end(vaddr, end);

		if (pmd_none(*pmdp) && IS_ALIGNED(vaddr, PMD_SIZE) && (next - vaddr) >= PMD_SIZE) {
			phys_addr = memblock_phys_alloc(PMD_SIZE, PMD_SIZE);
			if (phys_addr) {
				set_pmd(pmdp, pfn_pmd(PFN_DOWN(phys_addr), PAGE_KERNEL));
				continue;
			}
		}

		kasan_populate_pte(pmdp, vaddr, next);
	} while (pmdp++, vaddr = next, vaddr != end);

	/*
	 * Wait for the whole PGD to be populated before setting the PGD in
	 * the page table, otherwise, if we did set the PGD before populating
	 * it entirely, memblock could allocate a page at a physical address
	 * where KASAN is not populated yet and then we'd get a page fault.
	 */
	set_pud(pud, pfn_pud(PFN_DOWN(__pa(base_pmd)), PAGE_TABLE));
}

static void __init kasan_populate_pud(pgd_t *pgd,
				      unsigned long vaddr, unsigned long end,
				      bool early)
{
	phys_addr_t phys_addr;
	pud_t *pudp, *base_pud;
	unsigned long next;

	if (early) {
		/*
		 * We can't use pgd_page_vaddr here as it would return a linear
		 * mapping address but it is not mapped yet, but when populating
		 * early_pg_dir, we need the physical address and when populating
		 * swapper_pg_dir, we need the kernel virtual address so use
		 * pt_ops facility.
		 */
		base_pud = pt_ops.get_pud_virt(pfn_to_phys(_pgd_pfn(*pgd)));
	} else if (pgd_none(*pgd)) {
		base_pud = memblock_alloc(PTRS_PER_PUD * sizeof(pud_t), PAGE_SIZE);
		memcpy(base_pud, (void *)kasan_early_shadow_pud,
			sizeof(pud_t) * PTRS_PER_PUD);
	} else {
		base_pud = (pud_t *)pgd_page_vaddr(*pgd);
		if (base_pud == lm_alias(kasan_early_shadow_pud)) {
			base_pud = memblock_alloc(PTRS_PER_PUD * sizeof(pud_t), PAGE_SIZE);
			memcpy(base_pud, (void *)kasan_early_shadow_pud,
			       sizeof(pud_t) * PTRS_PER_PUD);
		}
	}

	pudp = base_pud + pud_index(vaddr);

	do {
		next = pud_addr_end(vaddr, end);

		if (pud_none(*pudp) && IS_ALIGNED(vaddr, PUD_SIZE) && (next - vaddr) >= PUD_SIZE) {
			if (early) {
				phys_addr = __pa(((uintptr_t)kasan_early_shadow_pmd));
				set_pud(pudp, pfn_pud(PFN_DOWN(phys_addr), PAGE_TABLE));
				continue;
			} else {
				phys_addr = memblock_phys_alloc(PUD_SIZE, PUD_SIZE);
				if (phys_addr) {
					set_pud(pudp, pfn_pud(PFN_DOWN(phys_addr), PAGE_KERNEL));
					continue;
				}
			}
		}

		kasan_populate_pmd(pudp, vaddr, next);
	} while (pudp++, vaddr = next, vaddr != end);

	/*
	 * Wait for the whole PGD to be populated before setting the PGD in
	 * the page table, otherwise, if we did set the PGD before populating
	 * it entirely, memblock could allocate a page at a physical address
	 * where KASAN is not populated yet and then we'd get a page fault.
	 */
	if (!early)
		set_pgd(pgd, pfn_pgd(PFN_DOWN(__pa(base_pud)), PAGE_TABLE));
}

static void __init kasan_populate_p4d(pgd_t *pgd,
				      unsigned long vaddr, unsigned long end,
				      bool early)
{
	phys_addr_t phys_addr;
	p4d_t *p4dp, *base_p4d;
	unsigned long next;

	if (early) {
		/*
		 * We can't use pgd_page_vaddr here as it would return a linear
		 * mapping address but it is not mapped yet, but when populating
		 * early_pg_dir, we need the physical address and when populating
		 * swapper_pg_dir, we need the kernel virtual address so use
		 * pt_ops facility.
		 */
		base_p4d = pt_ops.get_p4d_virt(pfn_to_phys(_pgd_pfn(*pgd)));
	} else {
		base_p4d = (p4d_t *)pgd_page_vaddr(*pgd);
		if (base_p4d == lm_alias(kasan_early_shadow_p4d)) {
			base_p4d = memblock_alloc(PTRS_PER_PUD * sizeof(p4d_t), PAGE_SIZE);
			memcpy(base_p4d, (void *)kasan_early_shadow_p4d,
				sizeof(p4d_t) * PTRS_PER_P4D);
		}
	}

	p4dp = base_p4d + p4d_index(vaddr);

	do {
		next = p4d_addr_end(vaddr, end);

		if (p4d_none(*p4dp) && IS_ALIGNED(vaddr, P4D_SIZE) && (next - vaddr) >= P4D_SIZE) {
			if (early) {
				phys_addr = __pa(((uintptr_t)kasan_early_shadow_pud));
				set_p4d(p4dp, pfn_p4d(PFN_DOWN(phys_addr), PAGE_TABLE));
				continue;
			} else {
				phys_addr = memblock_phys_alloc(P4D_SIZE, P4D_SIZE);
				if (phys_addr) {
					set_p4d(p4dp, pfn_p4d(PFN_DOWN(phys_addr), PAGE_KERNEL));
					continue;
				}
			}
		}

		kasan_populate_pud((pgd_t *)p4dp, vaddr, next, early);
	} while (p4dp++, vaddr = next, vaddr != end);

	/*
	 * Wait for the whole P4D to be populated before setting the P4D in
	 * the page table, otherwise, if we did set the P4D before populating
	 * it entirely, memblock could allocate a page at a physical address
	 * where KASAN is not populated yet and then we'd get a page fault.
	 */
	if (!early)
		set_pgd(pgd, pfn_pgd(PFN_DOWN(__pa(base_p4d)), PAGE_TABLE));
}

#define kasan_early_shadow_pgd_next			(pgtable_l5_enabled ?	\
				(uintptr_t)kasan_early_shadow_p4d :		\
							(pgtable_l4_enabled ?	\
				(uintptr_t)kasan_early_shadow_pud :		\
				(uintptr_t)kasan_early_shadow_pmd))
#define kasan_populate_pgd_next(pgdp, vaddr, next, early)			\
		(pgtable_l5_enabled ?						\
		kasan_populate_p4d(pgdp, vaddr, next, early) :			\
		(pgtable_l4_enabled ?						\
			kasan_populate_pud(pgdp, vaddr, next, early) :		\
			kasan_populate_pmd((pud_t *)pgdp, vaddr, next)))

static void __init kasan_populate_pgd(pgd_t *pgdp,
				      unsigned long vaddr, unsigned long end,
				      bool early)
{
	phys_addr_t phys_addr;
	unsigned long next;

	do {
		next = pgd_addr_end(vaddr, end);

		if (IS_ALIGNED(vaddr, PGDIR_SIZE) && (next - vaddr) >= PGDIR_SIZE) {
			if (early) {
				phys_addr = __pa((uintptr_t)kasan_early_shadow_pgd_next);
				set_pgd(pgdp, pfn_pgd(PFN_DOWN(phys_addr), PAGE_TABLE));
				continue;
			} else if (pgd_page_vaddr(*pgdp) ==
				   (unsigned long)lm_alias(kasan_early_shadow_pgd_next)) {
				/*
				 * pgdp can't be none since kasan_early_init
				 * initialized all KASAN shadow region with
				 * kasan_early_shadow_pud: if this is still the
				 * case, that means we can try to allocate a
				 * hugepage as a replacement.
				 */
				phys_addr = memblock_phys_alloc(PGDIR_SIZE, PGDIR_SIZE);
				if (phys_addr) {
					set_pgd(pgdp, pfn_pgd(PFN_DOWN(phys_addr), PAGE_KERNEL));
					continue;
				}
			}
		}

		kasan_populate_pgd_next(pgdp, vaddr, next, early);
	} while (pgdp++, vaddr = next, vaddr != end);
}

asmlinkage void __init kasan_early_init(void)
{
	uintptr_t i;

	BUILD_BUG_ON(KASAN_SHADOW_OFFSET !=
		KASAN_SHADOW_END - (1UL << (64 - KASAN_SHADOW_SCALE_SHIFT)));

	for (i = 0; i < PTRS_PER_PTE; ++i)
		set_pte(kasan_early_shadow_pte + i,
			pfn_pte(virt_to_pfn(kasan_early_shadow_page), PAGE_KERNEL));

	for (i = 0; i < PTRS_PER_PMD; ++i)
		set_pmd(kasan_early_shadow_pmd + i,
			pfn_pmd(PFN_DOWN
				(__pa((uintptr_t)kasan_early_shadow_pte)),
				PAGE_TABLE));

	if (pgtable_l4_enabled) {
		for (i = 0; i < PTRS_PER_PUD; ++i)
			set_pud(kasan_early_shadow_pud + i,
				pfn_pud(PFN_DOWN
					(__pa(((uintptr_t)kasan_early_shadow_pmd))),
					PAGE_TABLE));
	}

	if (pgtable_l5_enabled) {
		for (i = 0; i < PTRS_PER_P4D; ++i)
			set_p4d(kasan_early_shadow_p4d + i,
				pfn_p4d(PFN_DOWN
					(__pa(((uintptr_t)kasan_early_shadow_pud))),
					PAGE_TABLE));
	}

	kasan_populate_pgd(early_pg_dir + pgd_index(KASAN_SHADOW_START),
			   KASAN_SHADOW_START, KASAN_SHADOW_END, true);

	local_flush_tlb_all();
}

void __init kasan_swapper_init(void)
{
	kasan_populate_pgd(pgd_offset_k(KASAN_SHADOW_START),
			   KASAN_SHADOW_START, KASAN_SHADOW_END, true);

	local_flush_tlb_all();
}

static void __init kasan_populate(void *start, void *end)
{
	unsigned long vaddr = (unsigned long)start & PAGE_MASK;
	unsigned long vend = PAGE_ALIGN((unsigned long)end);

	kasan_populate_pgd(pgd_offset_k(vaddr), vaddr, vend, false);

	local_flush_tlb_all();
	memset(start, KASAN_SHADOW_INIT, end - start);
}

static void __init kasan_shallow_populate_pmd(pgd_t *pgdp,
					      unsigned long vaddr, unsigned long end)
{
	unsigned long next;
	pmd_t *pmdp, *base_pmd;
	bool is_kasan_pte;

	base_pmd = (pmd_t *)pgd_page_vaddr(*pgdp);
	pmdp = base_pmd + pmd_index(vaddr);

	do {
		next = pmd_addr_end(vaddr, end);
		is_kasan_pte = (pmd_pgtable(*pmdp) == lm_alias(kasan_early_shadow_pte));

		if (is_kasan_pte)
			pmd_clear(pmdp);
	} while (pmdp++, vaddr = next, vaddr != end);
}

static void __init kasan_shallow_populate_pud(pgd_t *pgdp,
					      unsigned long vaddr, unsigned long end)
{
	unsigned long next;
	pud_t *pudp, *base_pud;
	pmd_t *base_pmd;
	bool is_kasan_pmd;

	base_pud = (pud_t *)pgd_page_vaddr(*pgdp);
	pudp = base_pud + pud_index(vaddr);

	do {
		next = pud_addr_end(vaddr, end);
		is_kasan_pmd = (pud_pgtable(*pudp) == lm_alias(kasan_early_shadow_pmd));

		if (!is_kasan_pmd)
			continue;

		base_pmd = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
		set_pud(pudp, pfn_pud(PFN_DOWN(__pa(base_pmd)), PAGE_TABLE));

		if (IS_ALIGNED(vaddr, PUD_SIZE) && (next - vaddr) >= PUD_SIZE)
			continue;

		memcpy(base_pmd, (void *)kasan_early_shadow_pmd, PAGE_SIZE);
		kasan_shallow_populate_pmd((pgd_t *)pudp, vaddr, next);
	} while (pudp++, vaddr = next, vaddr != end);
}

static void __init kasan_shallow_populate_p4d(pgd_t *pgdp,
					      unsigned long vaddr, unsigned long end)
{
	unsigned long next;
	p4d_t *p4dp, *base_p4d;
	pud_t *base_pud;
	bool is_kasan_pud;

	base_p4d = (p4d_t *)pgd_page_vaddr(*pgdp);
	p4dp = base_p4d + p4d_index(vaddr);

	do {
		next = p4d_addr_end(vaddr, end);
		is_kasan_pud = (p4d_pgtable(*p4dp) == lm_alias(kasan_early_shadow_pud));

		if (!is_kasan_pud)
			continue;

		base_pud = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
		set_p4d(p4dp, pfn_p4d(PFN_DOWN(__pa(base_pud)), PAGE_TABLE));

		if (IS_ALIGNED(vaddr, P4D_SIZE) && (next - vaddr) >= P4D_SIZE)
			continue;

		memcpy(base_pud, (void *)kasan_early_shadow_pud, PAGE_SIZE);
		kasan_shallow_populate_pud((pgd_t *)p4dp, vaddr, next);
	} while (p4dp++, vaddr = next, vaddr != end);
}

#define kasan_shallow_populate_pgd_next(pgdp, vaddr, next)			\
		(pgtable_l5_enabled ?						\
		kasan_shallow_populate_p4d(pgdp, vaddr, next) :			\
		(pgtable_l4_enabled ?						\
		kasan_shallow_populate_pud(pgdp, vaddr, next) :			\
		kasan_shallow_populate_pmd(pgdp, vaddr, next)))

static void __init kasan_shallow_populate_pgd(unsigned long vaddr, unsigned long end)
{
	unsigned long next;
	void *p;
	pgd_t *pgd_k = pgd_offset_k(vaddr);
	bool is_kasan_pgd_next;

	do {
		next = pgd_addr_end(vaddr, end);
		is_kasan_pgd_next = (pgd_page_vaddr(*pgd_k) ==
				     (unsigned long)lm_alias(kasan_early_shadow_pgd_next));

		if (is_kasan_pgd_next) {
			p = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
			set_pgd(pgd_k, pfn_pgd(PFN_DOWN(__pa(p)), PAGE_TABLE));
		}

		if (IS_ALIGNED(vaddr, PGDIR_SIZE) && (next - vaddr) >= PGDIR_SIZE)
			continue;

		memcpy(p, (void *)kasan_early_shadow_pgd_next, PAGE_SIZE);
		kasan_shallow_populate_pgd_next(pgd_k, vaddr, next);
	} while (pgd_k++, vaddr = next, vaddr != end);
}

static void __init kasan_shallow_populate(void *start, void *end)
{
	unsigned long vaddr = (unsigned long)start & PAGE_MASK;
	unsigned long vend = PAGE_ALIGN((unsigned long)end);

	kasan_shallow_populate_pgd(vaddr, vend);
	local_flush_tlb_all();
}

void __init kasan_init(void)
{
	phys_addr_t p_start, p_end;
	u64 i;

	if (IS_ENABLED(CONFIG_KASAN_VMALLOC))
		kasan_shallow_populate(
			(void *)kasan_mem_to_shadow((void *)VMALLOC_START),
			(void *)kasan_mem_to_shadow((void *)VMALLOC_END));

	/* Populate the linear mapping */
	for_each_mem_range(i, &p_start, &p_end) {
		void *start = (void *)__va(p_start);
		void *end = (void *)__va(p_end);

		if (start >= end)
			break;

		kasan_populate(kasan_mem_to_shadow(start), kasan_mem_to_shadow(end));
	}

	/* Populate kernel, BPF, modules mapping */
	kasan_populate(kasan_mem_to_shadow((const void *)MODULES_VADDR),
		       kasan_mem_to_shadow((const void *)MODULES_VADDR + SZ_2G));

	for (i = 0; i < PTRS_PER_PTE; i++)
		set_pte(&kasan_early_shadow_pte[i],
			mk_pte(virt_to_page(kasan_early_shadow_page),
			       __pgprot(_PAGE_PRESENT | _PAGE_READ |
					_PAGE_ACCESSED)));

	memset(kasan_early_shadow_page, KASAN_SHADOW_INIT, PAGE_SIZE);
	init_task.kasan_depth = 0;
}
