| From e2298470038dc227add4f65cc139643f43b47b1c Mon Sep 17 00:00:00 2001 |
| From: Yu Zhao <yuzhao@google.com> |
| Date: Sat, 26 Jun 2021 22:17:27 -0600 |
| Subject: [PATCH] CHROMIUM: mm: multigenerational lru: add |
| arch_has_hw_pte_young() |
| |
| Add arch_has_hw_pte_young() to indicate whether the h/w accessed bit |
| is supported. For those CPUs that don't, e.g., arm64 v8.0, we skip |
| walk_mm_list() and solely rely on lru_gen_scan_around(). This still |
| retains ~80% of the performance improvement. |
| |
| BUG=b:123039911 |
| TEST=Built |
| |
| Signed-off-by: Yu Zhao <yuzhao@google.com> |
| Change-Id: I32e1380bc5966b4cb3ba5a9796c95af61fa8fc4a |
| Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2991720 |
| Tested-by: Yu Zhao <yuzhao@chromium.org> |
| Reviewed-by: Sonny Rao <sonnyrao@chromium.org> |
| Reviewed-by: Yu Zhao <yuzhao@chromium.org> |
| Commit-Queue: Yu Zhao <yuzhao@chromium.org> |
| --- |
| arch/arm64/include/asm/cpufeature.h | 6 ++++++ |
| arch/arm64/include/asm/pgtable.h | 6 ++++++ |
| arch/arm64/kernel/cpufeature.c | 10 ++++++++++ |
| arch/x86/include/asm/pgtable.h | 6 ++++++ |
| include/linux/pgtable.h | 7 +++++++ |
| mm/vmscan.c | 8 ++++++++ |
| 6 files changed, 43 insertions(+) |
| |
| diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h |
| index 9bb9d11750d7..e6654a708077 100644 |
| --- a/arch/arm64/include/asm/cpufeature.h |
| +++ b/arch/arm64/include/asm/cpufeature.h |
| @@ -776,6 +776,12 @@ static inline bool system_supports_tlb_range(void) |
| cpus_have_const_cap(ARM64_HAS_TLB_RANGE); |
| } |
| |
| +static inline bool system_has_hw_af(void) |
| +{ |
| + return IS_ENABLED(CONFIG_ARM64_HW_AFDBM) && |
| + cpus_have_const_cap(ARM64_HW_AF); |
| +} |
| + |
| extern int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt); |
| |
| static inline u32 id_aa64mmfr0_parange_to_phys_shift(int parange) |
| diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h |
| index f09bf5c02891..11dc392daf53 100644 |
| --- a/arch/arm64/include/asm/pgtable.h |
| +++ b/arch/arm64/include/asm/pgtable.h |
| @@ -1023,6 +1023,12 @@ static inline pgprot_t arch_filter_pgprot(pgprot_t prot) |
| } |
| |
| |
| +static inline bool arch_has_hw_pte_young(void) |
| +{ |
| + return system_has_hw_af(); |
| +} |
| +#define arch_has_hw_pte_young arch_has_hw_pte_young |
| + |
| #endif /* !__ASSEMBLY__ */ |
| |
| #endif /* __ASM_PGTABLE_H */ |
| diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c |
| index 0ead8bfedf20..772b39d14c63 100644 |
| --- a/arch/arm64/kernel/cpufeature.c |
| +++ b/arch/arm64/kernel/cpufeature.c |
| @@ -2126,6 +2126,16 @@ static const struct arm64_cpu_capabilities arm64_features[] = { |
| .matches = has_hw_dbm, |
| .cpu_enable = cpu_enable_hw_dbm, |
| }, |
| + { |
| + .desc = "Hardware update of the Access flag", |
| + .type = ARM64_CPUCAP_SYSTEM_FEATURE, |
| + .capability = ARM64_HW_AF, |
| + .sys_reg = SYS_ID_AA64MMFR1_EL1, |
| + .sign = FTR_UNSIGNED, |
| + .field_pos = ID_AA64MMFR1_HADBS_SHIFT, |
| + .min_field_value = 1, |
| + .matches = has_cpuid_feature, |
| + }, |
| #endif |
| { |
| .desc = "CRC32 instructions", |
| diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h |
| index 448cd01eb3ec..a434590c8f61 100644 |
| --- a/arch/x86/include/asm/pgtable.h |
| +++ b/arch/x86/include/asm/pgtable.h |
| @@ -1403,6 +1403,12 @@ static inline bool arch_faults_on_old_pte(void) |
| return false; |
| } |
| |
| +static inline bool arch_has_hw_pte_young(void) |
| +{ |
| + return true; |
| +} |
| +#define arch_has_hw_pte_young arch_has_hw_pte_young |
| + |
| #endif /* __ASSEMBLY__ */ |
| |
| #endif /* _ASM_X86_PGTABLE_H */ |
| diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h |
| index d147480cdefc..cf31044565a3 100644 |
| --- a/include/linux/pgtable.h |
| +++ b/include/linux/pgtable.h |
| @@ -258,6 +258,13 @@ static inline int pmdp_clear_flush_young(struct vm_area_struct *vma, |
| #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ |
| #endif |
| |
| +#ifndef arch_has_hw_pte_young |
| +static inline bool arch_has_hw_pte_young(void) |
| +{ |
| + return false; |
| +} |
| +#endif |
| + |
| #ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR |
| static inline pte_t ptep_get_and_clear(struct mm_struct *mm, |
| unsigned long address, |
| diff --git a/mm/vmscan.c b/mm/vmscan.c |
| index 798b356acba1..2a25f488aa98 100644 |
| --- a/mm/vmscan.c |
| +++ b/mm/vmscan.c |
| @@ -4537,6 +4537,11 @@ static long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, int s |
| if (get_hi_wmark(max_seq, min_seq, swappiness) > MIN_NR_GENS) |
| return nr_to_scan; |
| |
| + if (!arch_has_hw_pte_young()) { |
| + inc_max_seq(lruvec, max_seq); |
| + return nr_to_scan; |
| + } |
| + |
| /* kswapd uses lru_gen_age_node() */ |
| if (current_is_kswapd()) |
| return 0; |
| @@ -4625,6 +4630,9 @@ static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) |
| |
| VM_BUG_ON(!current_is_kswapd()); |
| |
| + if (!arch_has_hw_pte_young()) |
| + return; |
| + |
| memcg = mem_cgroup_iter(NULL, NULL, NULL); |
| do { |
| struct lruvec *lruvec = mem_cgroup_lruvec(memcg, pgdat); |
| -- |
| 2.32.0.402.g57bb445576-goog |
| |