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 <mm/mmu_decl.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ciint __init kasan_init_region(void *start, size_t size)
1062306a36Sopenharmony_ci{
1162306a36Sopenharmony_ci	unsigned long k_start = (unsigned long)kasan_mem_to_shadow(start);
1262306a36Sopenharmony_ci	unsigned long k_end = (unsigned long)kasan_mem_to_shadow(start + size);
1362306a36Sopenharmony_ci	unsigned long k_nobat = k_start;
1462306a36Sopenharmony_ci	unsigned long k_cur;
1562306a36Sopenharmony_ci	phys_addr_t phys;
1662306a36Sopenharmony_ci	int ret;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	while (k_nobat < k_end) {
1962306a36Sopenharmony_ci		unsigned int k_size = bat_block_size(k_nobat, k_end);
2062306a36Sopenharmony_ci		int idx = find_free_bat();
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci		if (idx == -1)
2362306a36Sopenharmony_ci			break;
2462306a36Sopenharmony_ci		if (k_size < SZ_128K)
2562306a36Sopenharmony_ci			break;
2662306a36Sopenharmony_ci		phys = memblock_phys_alloc_range(k_size, k_size, 0,
2762306a36Sopenharmony_ci						 MEMBLOCK_ALLOC_ANYWHERE);
2862306a36Sopenharmony_ci		if (!phys)
2962306a36Sopenharmony_ci			break;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci		setbat(idx, k_nobat, phys, k_size, PAGE_KERNEL);
3262306a36Sopenharmony_ci		k_nobat += k_size;
3362306a36Sopenharmony_ci	}
3462306a36Sopenharmony_ci	if (k_nobat != k_start)
3562306a36Sopenharmony_ci		update_bats();
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	if (k_nobat < k_end) {
3862306a36Sopenharmony_ci		phys = memblock_phys_alloc_range(k_end - k_nobat, PAGE_SIZE, 0,
3962306a36Sopenharmony_ci						 MEMBLOCK_ALLOC_ANYWHERE);
4062306a36Sopenharmony_ci		if (!phys)
4162306a36Sopenharmony_ci			return -ENOMEM;
4262306a36Sopenharmony_ci	}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	ret = kasan_init_shadow_page_tables(k_start, k_end);
4562306a36Sopenharmony_ci	if (ret)
4662306a36Sopenharmony_ci		return ret;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	kasan_update_early_region(k_start, k_nobat, __pte(0));
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	for (k_cur = k_nobat; k_cur < k_end; k_cur += PAGE_SIZE) {
5162306a36Sopenharmony_ci		pmd_t *pmd = pmd_off_k(k_cur);
5262306a36Sopenharmony_ci		pte_t pte = pfn_pte(PHYS_PFN(phys + k_cur - k_nobat), PAGE_KERNEL);
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci		__set_pte_at(&init_mm, k_cur, pte_offset_kernel(pmd, k_cur), pte, 0);
5562306a36Sopenharmony_ci	}
5662306a36Sopenharmony_ci	flush_tlb_kernel_range(k_start, k_end);
5762306a36Sopenharmony_ci	memset(kasan_mem_to_shadow(start), 0, k_end - k_start);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	return 0;
6062306a36Sopenharmony_ci}
61