mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
mm: split 'tlb_flush_mmu()' into tlb flushing and memory freeing parts
The mmu-gather operation 'tlb_flush_mmu()' has done two things: the actual tlb flush operation, and the batched freeing of the pages that the TLB entries pointed at. This splits the operation into separate phases, so that the forced batched flushing done by zap_pte_range() can now do the actual TLB flush while still holding the page table lock, but delay the batched freeing of all the pages to after the lock has been dropped. This in turn allows us to avoid a race condition between set_page_dirty() (as called by zap_pte_range() when it finds a dirty shared memory pte) and page_mkclean(): because we now flush all the dirty page data from the TLB's while holding the pte lock, page_mkclean() will be held up walking the (recently cleaned) page tables until after the TLB entries have been flushed from all CPU's. Reported-by: Benjamin Herrenschmidt <[email protected]> Tested-by: Dave Hansen <[email protected]> Acked-by: Hugh Dickins <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Russell King - ARM Linux <[email protected]> Cc: Tony Luck <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
parent
9a60ee117b
commit
1cf35d4771
6 changed files with 111 additions and 33 deletions
|
|
@ -58,14 +58,26 @@ tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start
|
|||
extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
|
||||
unsigned long end);
|
||||
|
||||
static inline void
|
||||
tlb_flush_mmu_tlbonly(struct mmu_gather *tlb)
|
||||
{
|
||||
flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end);
|
||||
}
|
||||
|
||||
static inline void
|
||||
tlb_flush_mmu_free(struct mmu_gather *tlb)
|
||||
{
|
||||
init_tlb_gather(tlb);
|
||||
}
|
||||
|
||||
static inline void
|
||||
tlb_flush_mmu(struct mmu_gather *tlb)
|
||||
{
|
||||
if (!tlb->need_flush)
|
||||
return;
|
||||
|
||||
flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end);
|
||||
init_tlb_gather(tlb);
|
||||
tlb_flush_mmu_tlbonly(tlb);
|
||||
tlb_flush_mmu_free(tlb);
|
||||
}
|
||||
|
||||
/* tlb_finish_mmu
|
||||
|
|
|
|||
Loading…
Reference in a new issue