From 399e44118e1d171984a5e4a0ef3118ed24824fcd Mon Sep 17 00:00:00 2001 From: Qingqing Zhou Date: Mon, 1 Mar 2021 16:02:44 +0800 Subject: [PATCH] pci_iomap: fix page fault issue on vmalloc with section mapping In this case, CONFIG_SMP and CONFIG_LPAE are both not enabled, CONFIG_ENABLE_VMALLOC_SAVING is enabled. The paddr|size|addr satisfies PMD_SIZE alignment, will create section mapping not page mapping, non-LPAE arm32 uses 2-level page table, including pgd and pte, before remapping it will do unmapping which clears init_mm->pgd of corresponding addr and memcpy into [VMALLOC_START, VMALLOC_END) part of current->active_mm->pgd, but this memcpy misses to sync other vmalloc areas outside [VMALLC_START, VMALLOC_END) with vmalloc saving feature, the pgd part of addr in other vmalloc areas is not synced and still holds the stale mappings, if request addrs fall into other vmalloc areas, then page fault happens for them. So need to consider other vmalloc areas outside [VMALLOC_START, VMALLOC_END) with vmalloc saving feature, change into [PAGE_OFFSET, VMALLOC_END) to include all vmalloc areas, then all pgds of vmalloc addrs in current->active_mm->pgd will be synced on unmapping, the pgds of request addrs are cleared, then do_traslation_fault will be called for zero pgd value, it calls copy_pmd to sync the pgds from init_mm->pgd to current->active_mm->pgd for request addrs on remapping. Change-Id: Ia283d409a20c8fc9951434078332a3badf0f9ed0 Signed-off-by: Qingqing Zhou --- arch/arm/mm/iomap.c | 3 +-- arch/arm/mm/ioremap.c | 7 +++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/iomap.c b/arch/arm/mm/iomap.c index 091ddc56827e..290660d6d567 100644 --- a/arch/arm/mm/iomap.c +++ b/arch/arm/mm/iomap.c @@ -35,8 +35,7 @@ EXPORT_SYMBOL(pcibios_min_mem); void pci_iounmap(struct pci_dev *dev, void __iomem *addr) { - if ((unsigned long)addr >= VMALLOC_START && - (unsigned long)addr < VMALLOC_END) + if (is_vmalloc_addr(addr)) iounmap(addr); } EXPORT_SYMBOL(pci_iounmap); diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 60da4db46f77..3696097982db 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -120,10 +120,17 @@ void __check_vmalloc_seq(struct mm_struct *mm) do { seq = init_mm.context.vmalloc_seq; +#ifdef CONFIG_ENABLE_VMALLOC_SAVING + memcpy(pgd_offset(mm, PAGE_OFFSET), + pgd_offset_k(PAGE_OFFSET), + sizeof(pgd_t) * (pgd_index(VMALLOC_END) - + pgd_index(PAGE_OFFSET))); +#else memcpy(pgd_offset(mm, VMALLOC_START), pgd_offset_k(VMALLOC_START), sizeof(pgd_t) * (pgd_index(VMALLOC_END) - pgd_index(VMALLOC_START))); +#endif mm->context.vmalloc_seq = seq; } while (seq != init_mm.context.vmalloc_seq); }