blob: 299775cf6f15e97421cc1ace5673c97ec7e54bbc [file] [log] [blame]
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