Commit 912efda3 authored by Nikita Panov's avatar Nikita Panov Committed by Denis Darvish
Browse files

arm64: make KASAN aware about kernel replication

kunpeng inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IBOJU2



-------------------------------------------------

Acked-by: default avatarArtem Kuzin <artem.kuzin@huawei.com>
Acked-by: default avatarAlexander Grubnikov <alexander.grubnikov@huawei.com>
Acked-by: default avatarIlya Hanov <ilya.hanov@huawei-partners.com>
Acked-by: default avatarDenis Darvish <darvish.denis@huawei.com>
Signed-off-by: default avatarNikita Panov <panov.nikita@huawei.com>
parent 9dd4c324
Loading
Loading
Loading
Loading
+65 −3
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <linux/memblock.h>
#include <linux/start_kernel.h>
#include <linux/mm.h>
#include <linux/numa_kernel_replication.h>

#include <asm/mmu_context.h>
#include <asm/kernel-pgtable.h>
@@ -59,6 +60,24 @@ static phys_addr_t __init kasan_alloc_raw_page(int node)
	return __pa(p);
}

static void __init __kasan_pmd_populate(pmd_t *pmdp, phys_addr_t pte_phys, unsigned long addr)
{
#ifdef CONFIG_KERNEL_REPLICATION
	if (get_propagation_level() == PMD_PROPAGATION) {
		int nid;
		pmd_t *target;

		for_each_memory_node(nid) {
			target = (pmd_t *)pgd_offset_pgd(per_node_pgd(&init_mm, nid), addr);
			__pmd_populate(target, pte_phys, PMD_TYPE_TABLE);
		}
	} else
		__pmd_populate(pmdp, pte_phys, PMD_TYPE_TABLE);
#else
	__pmd_populate(pmdp, pte_phys, PMD_TYPE_TABLE);
#endif /* CONFIG_KERNEL_REPLICATION */
}

static pte_t *__init kasan_pte_offset(pmd_t *pmdp, unsigned long addr, int node,
				      bool early)
{
@@ -66,13 +85,31 @@ static pte_t *__init kasan_pte_offset(pmd_t *pmdp, unsigned long addr, int node,
		phys_addr_t pte_phys = early ?
				__pa_symbol(kasan_early_shadow_pte)
					: kasan_alloc_zeroed_page(node);
		__pmd_populate(pmdp, pte_phys, PMD_TYPE_TABLE);
		__kasan_pmd_populate(pmdp, pte_phys, PMD_TYPE_TABLE);
	}

	return early ? pte_offset_kimg(pmdp, addr)
		     : pte_offset_kernel(pmdp, addr);
}

static void __init __kasan_pud_populate(pud_t *pudp, phys_addr_t pmd_phys, unsigned long addr)
{
#ifdef CONFIG_KERNEL_REPLICATION
	if (get_propagation_level() == PUD_PROPAGATION) {
		int nid;
		pud_t *target;

		for_each_memory_node(nid) {
			target = (pud_t *)pgd_offset_pgd(per_node_pgd(&init_mm, nid), addr);
			__pud_populate(target, pmd_phys, PMD_TYPE_TABLE);
		}
	} else
		__pud_populate(pudp, pmd_phys, PMD_TYPE_TABLE);
#else
	__pud_populate(pudp, pmd_phys, PMD_TYPE_TABLE);
#endif /* CONFIG_KERNEL_REPLICATION */
}

static pmd_t *__init kasan_pmd_offset(pud_t *pudp, unsigned long addr, int node,
				      bool early)
{
@@ -80,12 +117,30 @@ static pmd_t *__init kasan_pmd_offset(pud_t *pudp, unsigned long addr, int node,
		phys_addr_t pmd_phys = early ?
				__pa_symbol(kasan_early_shadow_pmd)
					: kasan_alloc_zeroed_page(node);
		__pud_populate(pudp, pmd_phys, PUD_TYPE_TABLE);
		__kasan_pud_populate(pudp, pmd_phys, PUD_TYPE_TABLE);
	}

	return early ? pmd_offset_kimg(pudp, addr) : pmd_offset(pudp, addr);
}

static void __init __kasan_p4d_populate(p4d_t *p4dp, phys_addr_t pud_phys, unsigned long addr)
{
#ifdef CONFIG_KERNEL_REPLICATION
	if (get_propagation_level() == P4D_PROPAGATION) {
		int nid;
		p4d_t *target;

		for_each_memory_node(nid) {
			target = (p4d_t *)pgd_offset_pgd(per_node_pgd(&init_mm, nid), addr);
			__p4d_populate(target, pud_phys, PMD_TYPE_TABLE);
		}
	} else
		__p4d_populate(p4dp, pud_phys, PMD_TYPE_TABLE);
#else
	__p4d_populate(p4dp, pud_phys, PMD_TYPE_TABLE);
#endif /* CONFIG_KERNEL_REPLICATION */
}

static pud_t *__init kasan_pud_offset(p4d_t *p4dp, unsigned long addr, int node,
				      bool early)
{
@@ -93,7 +148,7 @@ static pud_t *__init kasan_pud_offset(p4d_t *p4dp, unsigned long addr, int node,
		phys_addr_t pud_phys = early ?
				__pa_symbol(kasan_early_shadow_pud)
					: kasan_alloc_zeroed_page(node);
		__p4d_populate(p4dp, pud_phys, P4D_TYPE_TABLE);
		__kasan_p4d_populate(p4dp, pud_phys, addr);
	}

	return early ? pud_offset_kimg(p4dp, addr) : pud_offset(p4dp, addr);
@@ -245,7 +300,14 @@ static void __init kasan_init_shadow(void)
	kasan_populate_early_shadow(kasan_mem_to_shadow((void *)PAGE_END),
				   (void *)mod_shadow_start);

#ifdef CONFIG_KERNEL_REPLICATION
	/*
	 * If Kernel replication is enabled,
	 * VMALLOC_START != MODULES_END
	 */
#else
	BUILD_BUG_ON(VMALLOC_START != MODULES_END);
#endif /* CONFIG_KERNEL_REPLICATION */
	kasan_populate_early_shadow((void *)vmalloc_shadow_end,
				    (void *)KASAN_SHADOW_END);