Unverified Commit 2c312616 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!9166 A Solution to Re-enable hugetlb vmemmap optimize on ARM64

Merge Pull Request from: @ci-robot 
 
PR sync from: Nanyong Sun <sunnanyong@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/BDSOU2I6VSLV57DEDNU4FYZT2YOL3GMT/ 
HVO was previously disabled on arm64 [1] due to the lack of necessary
BBM(break-before-make) logic when changing page tables.
This set of patches fix this by adding necessary BBM sequence when
changing page table, and supporting vmemmap page fault handling to
fixup kernel address translation fault if vmemmap is concurrently accessed.

I have tested this patch set with concurrently accessing the vmemmap
address when do BBM and can recover by vmemmap fault handler. Also
tested under the config of 2/3/4 pgtable levels with 4K/64K page size
and all works well.

[1] commit 060a2c92 ("arm64: mm: hugetlb: Disable HUGETLB_PAGE_OPTIMIZE_VMEMMAP")

Mark Rutland (1):
  arm64: mm: kfence: only handle translation faults

Nanyong Sun (2):
  mm: HVO: introduce helper function to update and flush pgtable
  arm64: mm: HVO: support BBM of vmemmap pgtable safely

Wang Kefeng (1):
  ARM: 9278/1: kfence: only handle translation faults


-- 
2.25.1
 
https://gitee.com/openeuler/kernel/issues/I8YLWW 
 
Link:https://gitee.com/openeuler/kernel/pulls/9166

 

Reviewed-by: default avatarKefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents f6a96ed9 499b9106
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -118,6 +118,19 @@ static inline bool is_write_fault(unsigned int fsr)
	return (fsr & FSR_WRITE) && !(fsr & FSR_CM);
}

static inline bool is_translation_fault(unsigned int fsr)
{
	int fs = fsr_fs(fsr);
#ifdef CONFIG_ARM_LPAE
	if ((fs & FS_MMU_NOLL_MASK) == FS_TRANS_NOLL)
		return true;
#else
	if (fs == FS_L1_TRANS || fs == FS_L2_TRANS)
		return true;
#endif
	return false;
}

static void die_kernel_fault(const char *msg, struct mm_struct *mm,
			     unsigned long addr, unsigned int fsr,
			     struct pt_regs *regs)
@@ -153,7 +166,8 @@ __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
	if (addr < PAGE_SIZE) {
		msg = "NULL pointer dereference";
	} else {
		if (kfence_handle_page_fault(addr, is_write_fault(fsr), regs))
		if (is_translation_fault(fsr) &&
		    kfence_handle_page_fault(addr, is_write_fault(fsr), regs))
			return;

		msg = "paging request";
@@ -221,7 +235,7 @@ static inline bool is_permission_fault(unsigned int fsr)
{
	int fs = fsr_fs(fsr);
#ifdef CONFIG_ARM_LPAE
	if ((fs & FS_PERM_NOLL_MASK) == FS_PERM_NOLL)
	if ((fs & FS_MMU_NOLL_MASK) == FS_PERM_NOLL)
		return true;
#else
	if (fs == FS_L1_PERM || fs == FS_L2_PERM)
+6 −3
Original line number Diff line number Diff line
@@ -14,8 +14,9 @@

#ifdef CONFIG_ARM_LPAE
#define FSR_FS_AEA		17
#define FS_TRANS_NOLL		0x4
#define FS_PERM_NOLL		0xC
#define FS_PERM_NOLL_MASK	0x3C
#define FS_MMU_NOLL_MASK	0x3C

static inline int fsr_fs(unsigned int fsr)
{
@@ -23,6 +24,8 @@ static inline int fsr_fs(unsigned int fsr)
}
#else
#define FSR_FS_AEA		22
#define FS_L1_TRANS		0x5
#define FS_L2_TRANS		0x7
#define FS_L1_PERM		0xD
#define FS_L2_PERM		0xF

+4 −0
Original line number Diff line number Diff line
@@ -112,6 +112,10 @@
#define ESR_ELx_FSC_SERROR	(0x11)
#define ESR_ELx_FSC_ACCESS	(0x08)
#define ESR_ELx_FSC_FAULT	(0x04)
#define ESR_ELx_FSC_FAULT_L0    (0x04)
#define ESR_ELx_FSC_FAULT_L1    (0x05)
#define ESR_ELx_FSC_FAULT_L2    (0x06)
#define ESR_ELx_FSC_FAULT_L3    (0x07)
#define ESR_ELx_FSC_PERM	(0x0C)

/* ISS field definitions for Data Aborts */
+6 −0
Original line number Diff line number Diff line
@@ -1038,6 +1038,12 @@ static inline pgprot_t arch_filter_pgprot(pgprot_t prot)
	return PAGE_READONLY_EXEC;
}

#ifdef CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP
void vmemmap_update_pmd(unsigned long addr, pmd_t *pmdp, pte_t *ptep);
#define vmemmap_update_pmd vmemmap_update_pmd
void vmemmap_update_pte(unsigned long addr, pte_t *ptep, pte_t pte);
#define vmemmap_update_pte vmemmap_update_pte
#endif

#endif /* !__ASSEMBLY__ */

+16 −0
Original line number Diff line number Diff line
@@ -441,6 +441,22 @@ static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr)
	dsb(ish);
	isb();
}

#ifdef CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP
static inline void vmemmap_flush_tlb_all(void)
{
	/* do nothing, already flushed tlb in every single BBM */
}
#define vmemmap_flush_tlb_all vmemmap_flush_tlb_all

static inline void vmemmap_flush_tlb_range(unsigned long start,
					   unsigned long end)
{
	/* do nothing, already flushed tlb in every single BBM */
}
#define vmemmap_flush_tlb_range vmemmap_flush_tlb_range
#endif

#endif

#endif
Loading