Commit 46a6b987 authored by Huacai Chen's avatar Huacai Chen Committed by Wen Zhiwei
Browse files

LoongArch: Make KASAN work with 5-level page-tables

stable inclusion
from stable-v6.6.63
commit 32fc8cedcba673096694804a908a2d95110113f5
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBI1RP

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=32fc8cedcba673096694804a908a2d95110113f5



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

commit a410656643ce4844ba9875aa4e87a7779308259b upstream.

Make KASAN work with 5-level page-tables, including:
1. Implement and use __pgd_none() and kasan_p4d_offset().
2. As done in kasan_pmd_populate() and kasan_pte_populate(), restrict
   the loop conditions of kasan_p4d_populate() and kasan_pud_populate()
   to avoid unnecessary population.

Cc: stable@vger.kernel.org
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarWen Zhiwei <wenzhiwei@kylinos.cn>
parent 9ac07865
Loading
Loading
Loading
Loading
+23 −3
Original line number Diff line number Diff line
@@ -13,6 +13,13 @@

static pgd_t kasan_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE);

#ifdef __PAGETABLE_P4D_FOLDED
#define __pgd_none(early, pgd) (0)
#else
#define __pgd_none(early, pgd) (early ? (pgd_val(pgd) == 0) : \
(__pa(pgd_val(pgd)) == (unsigned long)__pa(kasan_early_shadow_p4d)))
#endif

#ifdef __PAGETABLE_PUD_FOLDED
#define __p4d_none(early, p4d) (0)
#else
@@ -142,6 +149,19 @@ static pud_t *__init kasan_pud_offset(p4d_t *p4dp, unsigned long addr, int node,
	return pud_offset(p4dp, addr);
}

static p4d_t *__init kasan_p4d_offset(pgd_t *pgdp, unsigned long addr, int node, bool early)
{
	if (__pgd_none(early, pgdp_get(pgdp))) {
		phys_addr_t p4d_phys = early ?
			__pa_symbol(kasan_early_shadow_p4d) : kasan_alloc_zeroed_page(node);
		if (!early)
			memcpy(__va(p4d_phys), kasan_early_shadow_p4d, sizeof(kasan_early_shadow_p4d));
		pgd_populate(&init_mm, pgdp, (p4d_t *)__va(p4d_phys));
	}

	return p4d_offset(pgdp, addr);
}

static void __init kasan_pte_populate(pmd_t *pmdp, unsigned long addr,
				      unsigned long end, int node, bool early)
{
@@ -178,19 +198,19 @@ static void __init kasan_pud_populate(p4d_t *p4dp, unsigned long addr,
	do {
		next = pud_addr_end(addr, end);
		kasan_pmd_populate(pudp, addr, next, node, early);
	} while (pudp++, addr = next, addr != end);
	} while (pudp++, addr = next, addr != end && __pud_none(early, READ_ONCE(*pudp)));
}

static void __init kasan_p4d_populate(pgd_t *pgdp, unsigned long addr,
					    unsigned long end, int node, bool early)
{
	unsigned long next;
	p4d_t *p4dp = p4d_offset(pgdp, addr);
	p4d_t *p4dp = kasan_p4d_offset(pgdp, addr, node, early);

	do {
		next = p4d_addr_end(addr, end);
		kasan_pud_populate(p4dp, addr, next, node, early);
	} while (p4dp++, addr = next, addr != end);
	} while (p4dp++, addr = next, addr != end && __p4d_none(early, READ_ONCE(*p4dp)));
}

static void __init kasan_pgd_populate(unsigned long addr, unsigned long end,