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:
committed by
Gerrit - the friendly Code Review server
parent
e904060a40
commit
467cc1dae3
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user