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 <qqzhou@codeaurora.org>
This commit is contained in:
Qingqing Zhou
2021-03-01 16:02:44 +08:00
committed by Gerrit - the friendly Code Review server
parent e904060a40
commit 467cc1dae3
2 changed files with 8 additions and 2 deletions

View File

@@ -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);

View File

@@ -119,10 +119,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);
}