Commit 22a61c3c authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Will Deacon
Browse files

asm-generic/tlb: Track freeing of page-table directories in struct mmu_gather



Some architectures require different TLB invalidation instructions
depending on whether it is only the last-level of page table being
changed, or whether there are also changes to the intermediate
(directory) entries higher up the tree.

Add a new bit to the flags bitfield in struct mmu_gather so that the
architecture code can operate accordingly if it's the intermediate
levels being invalidated.

Acked-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarPeter Zijlstra <peterz@infradead.org>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
parent faaadaf3
Loading
Loading
Loading
Loading
+23 −8
Original line number Diff line number Diff line
@@ -99,12 +99,22 @@ struct mmu_gather {
#endif
	unsigned long		start;
	unsigned long		end;
	/* we are in the middle of an operation to clear
	 * a full mm and can make some optimizations */
	unsigned int		fullmm : 1,
	/* we have performed an operation which
	 * requires a complete flush of the tlb */
				need_flush_all : 1;
	/*
	 * we are in the middle of an operation to clear
	 * a full mm and can make some optimizations
	 */
	unsigned int		fullmm : 1;

	/*
	 * we have performed an operation which
	 * requires a complete flush of the tlb
	 */
	unsigned int		need_flush_all : 1;

	/*
	 * we have removed page directories
	 */
	unsigned int		freed_tables : 1;

	struct mmu_gather_batch *active;
	struct mmu_gather_batch	local;
@@ -139,6 +149,7 @@ static inline void __tlb_reset_range(struct mmu_gather *tlb)
		tlb->start = TASK_SIZE;
		tlb->end = 0;
	}
	tlb->freed_tables = 0;
}

static inline void tlb_flush_mmu_tlbonly(struct mmu_gather *tlb)
@@ -280,6 +291,7 @@ static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
#define pte_free_tlb(tlb, ptep, address)			\
	do {							\
		__tlb_adjust_range(tlb, address, PAGE_SIZE);	\
		tlb->freed_tables = 1;			\
		__pte_free_tlb(tlb, ptep, address);		\
	} while (0)
#endif
@@ -288,6 +300,7 @@ static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
#define pmd_free_tlb(tlb, pmdp, address)			\
	do {							\
		__tlb_adjust_range(tlb, address, PAGE_SIZE);	\
		tlb->freed_tables = 1;			\
		__pmd_free_tlb(tlb, pmdp, address);		\
	} while (0)
#endif
@@ -297,6 +310,7 @@ static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
#define pud_free_tlb(tlb, pudp, address)			\
	do {							\
		__tlb_adjust_range(tlb, address, PAGE_SIZE);	\
		tlb->freed_tables = 1;			\
		__pud_free_tlb(tlb, pudp, address);		\
	} while (0)
#endif
@@ -307,6 +321,7 @@ static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
#define p4d_free_tlb(tlb, pudp, address)			\
	do {							\
		__tlb_adjust_range(tlb, address, PAGE_SIZE);	\
		tlb->freed_tables = 1;			\
		__p4d_free_tlb(tlb, pudp, address);		\
	} while (0)
#endif