Message ID | 20230710083914.18336-5-yangyicong@huawei.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | arm64: support batched/deferred tlb shootdown during page reclamation/migration | expand |
On Mon, Jul 10, 2023 at 04:39:14PM +0800, Yicong Yang wrote: > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig > index 7856c3a3e35a..f0ce8208c57f 100644 > --- a/arch/arm64/Kconfig > +++ b/arch/arm64/Kconfig > @@ -96,6 +96,7 @@ config ARM64 > select ARCH_SUPPORTS_NUMA_BALANCING > select ARCH_SUPPORTS_PAGE_TABLE_CHECK > select ARCH_SUPPORTS_PER_VMA_LOCK > + select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH if EXPERT I don't want EXPERT to turn on a feature that's not selectable by the user. This would lead to different performance behaviour based on EXPERT. Just select it unconditionally. > diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h > index 412a3b9a3c25..4bb9cec62e26 100644 > --- a/arch/arm64/include/asm/tlbflush.h > +++ b/arch/arm64/include/asm/tlbflush.h > @@ -254,17 +254,23 @@ static inline void flush_tlb_mm(struct mm_struct *mm) > dsb(ish); > } > > -static inline void flush_tlb_page_nosync(struct vm_area_struct *vma, > - unsigned long uaddr) > +static inline void __flush_tlb_page_nosync(struct mm_struct *mm, > + unsigned long uaddr) > { > unsigned long addr; > > dsb(ishst); > - addr = __TLBI_VADDR(uaddr, ASID(vma->vm_mm)); > + addr = __TLBI_VADDR(uaddr, ASID(mm)); > __tlbi(vale1is, addr); > __tlbi_user(vale1is, addr); > } > > +static inline void flush_tlb_page_nosync(struct vm_area_struct *vma, > + unsigned long uaddr) > +{ > + return __flush_tlb_page_nosync(vma->vm_mm, uaddr); > +} > + > static inline void flush_tlb_page(struct vm_area_struct *vma, > unsigned long uaddr) > { > @@ -272,6 +278,42 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, > dsb(ish); > } > > +#ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH If it's selected unconditionally, we won't need this #ifdef here. > + > +static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm) > +{ > +#ifdef CONFIG_ARM64_WORKAROUND_REPEAT_TLBI > + /* > + * TLB flush deferral is not required on systems, which are affected with "affected by" and drop the comma before "which".
On 2023/7/16 23:11, Catalin Marinas wrote: > On Mon, Jul 10, 2023 at 04:39:14PM +0800, Yicong Yang wrote: >> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig >> index 7856c3a3e35a..f0ce8208c57f 100644 >> --- a/arch/arm64/Kconfig >> +++ b/arch/arm64/Kconfig >> @@ -96,6 +96,7 @@ config ARM64 >> select ARCH_SUPPORTS_NUMA_BALANCING >> select ARCH_SUPPORTS_PAGE_TABLE_CHECK >> select ARCH_SUPPORTS_PER_VMA_LOCK >> + select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH if EXPERT > > I don't want EXPERT to turn on a feature that's not selectable by the > user. This would lead to different performance behaviour based on > EXPERT. Just select it unconditionally. Got it. will drop it and address the comment below. Thanks. > >> diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h >> index 412a3b9a3c25..4bb9cec62e26 100644 >> --- a/arch/arm64/include/asm/tlbflush.h >> +++ b/arch/arm64/include/asm/tlbflush.h >> @@ -254,17 +254,23 @@ static inline void flush_tlb_mm(struct mm_struct *mm) >> dsb(ish); >> } >> >> -static inline void flush_tlb_page_nosync(struct vm_area_struct *vma, >> - unsigned long uaddr) >> +static inline void __flush_tlb_page_nosync(struct mm_struct *mm, >> + unsigned long uaddr) >> { >> unsigned long addr; >> >> dsb(ishst); >> - addr = __TLBI_VADDR(uaddr, ASID(vma->vm_mm)); >> + addr = __TLBI_VADDR(uaddr, ASID(mm)); >> __tlbi(vale1is, addr); >> __tlbi_user(vale1is, addr); >> } >> >> +static inline void flush_tlb_page_nosync(struct vm_area_struct *vma, >> + unsigned long uaddr) >> +{ >> + return __flush_tlb_page_nosync(vma->vm_mm, uaddr); >> +} >> + >> static inline void flush_tlb_page(struct vm_area_struct *vma, >> unsigned long uaddr) >> { >> @@ -272,6 +278,42 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, >> dsb(ish); >> } >> >> +#ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH > > If it's selected unconditionally, we won't need this #ifdef here. > >> + >> +static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm) >> +{ >> +#ifdef CONFIG_ARM64_WORKAROUND_REPEAT_TLBI >> + /* >> + * TLB flush deferral is not required on systems, which are affected with > > "affected by" and drop the comma before "which". >
diff --git a/Documentation/features/vm/TLB/arch-support.txt b/Documentation/features/vm/TLB/arch-support.txt index 7f049c251a79..76208db88f3b 100644 --- a/Documentation/features/vm/TLB/arch-support.txt +++ b/Documentation/features/vm/TLB/arch-support.txt @@ -9,7 +9,7 @@ | alpha: | TODO | | arc: | TODO | | arm: | TODO | - | arm64: | N/A | + | arm64: | ok | | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 7856c3a3e35a..f0ce8208c57f 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -96,6 +96,7 @@ config ARM64 select ARCH_SUPPORTS_NUMA_BALANCING select ARCH_SUPPORTS_PAGE_TABLE_CHECK select ARCH_SUPPORTS_PER_VMA_LOCK + select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH if EXPERT select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT select ARCH_WANT_DEFAULT_BPF_JIT select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT diff --git a/arch/arm64/include/asm/tlbbatch.h b/arch/arm64/include/asm/tlbbatch.h new file mode 100644 index 000000000000..fedb0b87b8db --- /dev/null +++ b/arch/arm64/include/asm/tlbbatch.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ARCH_ARM64_TLBBATCH_H +#define _ARCH_ARM64_TLBBATCH_H + +struct arch_tlbflush_unmap_batch { + /* + * For arm64, HW can do tlb shootdown, so we don't + * need to record cpumask for sending IPI + */ +}; + +#endif /* _ARCH_ARM64_TLBBATCH_H */ diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h index 412a3b9a3c25..4bb9cec62e26 100644 --- a/arch/arm64/include/asm/tlbflush.h +++ b/arch/arm64/include/asm/tlbflush.h @@ -254,17 +254,23 @@ static inline void flush_tlb_mm(struct mm_struct *mm) dsb(ish); } -static inline void flush_tlb_page_nosync(struct vm_area_struct *vma, - unsigned long uaddr) +static inline void __flush_tlb_page_nosync(struct mm_struct *mm, + unsigned long uaddr) { unsigned long addr; dsb(ishst); - addr = __TLBI_VADDR(uaddr, ASID(vma->vm_mm)); + addr = __TLBI_VADDR(uaddr, ASID(mm)); __tlbi(vale1is, addr); __tlbi_user(vale1is, addr); } +static inline void flush_tlb_page_nosync(struct vm_area_struct *vma, + unsigned long uaddr) +{ + return __flush_tlb_page_nosync(vma->vm_mm, uaddr); +} + static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) { @@ -272,6 +278,42 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, dsb(ish); } +#ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH + +static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm) +{ +#ifdef CONFIG_ARM64_WORKAROUND_REPEAT_TLBI + /* + * TLB flush deferral is not required on systems, which are affected with + * ARM64_WORKAROUND_REPEAT_TLBI, as __tlbi()/__tlbi_user() implementation + * will have two consecutive TLBI instructions with a dsb(ish) in between + * defeating the purpose (i.e save overall 'dsb ish' cost). + */ + if (unlikely(cpus_have_const_cap(ARM64_WORKAROUND_REPEAT_TLBI))) + return false; +#endif + return true; +} + +static inline void arch_tlbbatch_add_pending(struct arch_tlbflush_unmap_batch *batch, + struct mm_struct *mm, + unsigned long uaddr) +{ + __flush_tlb_page_nosync(mm, uaddr); +} + +static inline void arch_flush_tlb_batched_pending(struct mm_struct *mm) +{ + dsb(ish); +} + +static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch) +{ + dsb(ish); +} + +#endif /* CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH */ + /* * This is meant to avoid soft lock-ups on large TLB flushing ranges and not * necessarily a performance improvement.