提交 b104fad3 编写于 作者: Y Yu Zhao 提交者: YuLinjia

mm: x86, arm64: add arch_has_hw_pte_young()

mainline inclusion
from mainline-v6.1-rc1
commit e1fd09e3
category: feature
bugzilla: https://gitee.com/openeuler/open-source-summer/issues/I55Z0L
CVE: NA
Reference: https://android-review.googlesource.com/c/kernel/common/+/2050906/10

The MGLRU in the mainline version combines many other new features,
especially folio. While this commit uses the version of MGLRU that did
not have folio before, so there will be some differences in the code
focusing on folio/page, and the core algorithm is consistent.

----------------------------------------------------------------------

Some architectures automatically set the accessed bit in PTEs, e.g.,
x86 and arm64 v8.2. On architectures that do not have this capability,
clearing the accessed bit in a PTE usually triggers a page fault
following the TLB miss of this PTE (to emulate the accessed bit).

Being aware of this capability can help make better decisions, e.g.,
whether to spread the work out over a period of time to reduce bursty
page faults when trying to clear the accessed bit in many PTEs.

Note that theoretically this capability can be unreliable, e.g.,
hotplugged CPUs might be different from builtin ones. Therefore it
should not be used in architecture-independent code that involves
correctness, e.g., to determine whether TLB flushes are required (in
combination with the accessed bit).

Link: https://lore.kernel.org/r/20220309021230.721028-2-yuzhao@google.com/Signed-off-by: NYu Zhao <yuzhao@google.com>
Reviewed-by: NBarry Song <baohua@kernel.org>
Acked-by: NBrian Geffon <bgeffon@google.com>
Acked-by: NJan Alexander Steffens (heftig) <heftig@archlinux.org>
Acked-by: NOleksandr Natalenko <oleksandr@natalenko.name>
Acked-by: NSteven Barrett <steven@liquorix.net>
Acked-by: NSuleiman Souhlal <suleiman@google.com>
Acked-by: NWill Deacon <will@kernel.org>
Tested-by: NDaniel Byrne <djbyrne@mtu.edu>
Tested-by: NDonald Carr <d@chaos-reins.com>
Tested-by: NHolger Hoffstätte <holger@applied-asynchrony.com>
Tested-by: NKonstantin Kharlamov <Hi-Angel@yandex.ru>
Tested-by: NShuang Zhai <szhai2@cs.rochester.edu>
Tested-by: NSofia Trinh <sofia.trinh@edi.works>
Tested-by: NVaibhav Jain <vaibhav@linux.ibm.com>
Bug: 227651406
Signed-off-by: NKalesh Singh <kaleshsingh@google.com>
Change-Id: Ie81175d7e0d239f688d31487b298cf9b4fb66707
Signed-off-by: NYuLinjia <3110442349@qq.com>
上级 dbd67bc0
...@@ -1030,13 +1030,13 @@ static inline void update_mmu_cache(struct vm_area_struct *vma, ...@@ -1030,13 +1030,13 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
* page after fork() + CoW for pfn mappings. We don't always have a * page after fork() + CoW for pfn mappings. We don't always have a
* hardware-managed access flag on arm64. * hardware-managed access flag on arm64.
*/ */
static inline bool arch_faults_on_old_pte(void) #define arch_has_hw_pte_young cpu_has_hw_af
{
WARN_ON(preemptible());
return !cpu_has_hw_af(); /*
} * Experimentally, it's cheap to set the access flag in hardware and we
#define arch_faults_on_old_pte arch_faults_on_old_pte * benefit from prefaulting mappings as 'old' to start with.
*/
#define arch_wants_old_prefaulted_pte cpu_has_hw_af
static inline pgprot_t arch_filter_pgprot(pgprot_t prot) static inline pgprot_t arch_filter_pgprot(pgprot_t prot)
{ {
......
...@@ -1412,10 +1412,10 @@ static inline bool arch_has_pfn_modify_check(void) ...@@ -1412,10 +1412,10 @@ static inline bool arch_has_pfn_modify_check(void)
return boot_cpu_has_bug(X86_BUG_L1TF); return boot_cpu_has_bug(X86_BUG_L1TF);
} }
#define arch_faults_on_old_pte arch_faults_on_old_pte #define arch_has_hw_pte_young arch_has_hw_pte_young
static inline bool arch_faults_on_old_pte(void) static inline bool arch_has_hw_pte_young(void)
{ {
return false; return true;
} }
#ifdef CONFIG_PAGE_TABLE_CHECK #ifdef CONFIG_PAGE_TABLE_CHECK
......
...@@ -242,6 +242,19 @@ static inline int pmdp_clear_flush_young(struct vm_area_struct *vma, ...@@ -242,6 +242,19 @@ static inline int pmdp_clear_flush_young(struct vm_area_struct *vma,
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
#endif #endif
#ifndef arch_has_hw_pte_young
/*
* Return whether the accessed bit is supported on the local CPU.
*
* This stub assumes accessing through an old PTE triggers a page fault.
* Architectures that automatically set the access bit should overwrite it.
*/
static inline bool arch_has_hw_pte_young(void)
{
return false;
}
#endif
#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR #ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR
static inline pte_t ptep_get_and_clear(struct mm_struct *mm, static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
unsigned long address, unsigned long address,
......
...@@ -122,15 +122,15 @@ int randomize_va_space __read_mostly = ...@@ -122,15 +122,15 @@ int randomize_va_space __read_mostly =
2; 2;
#endif #endif
#ifndef arch_faults_on_old_pte #ifndef arch_wants_old_prefaulted_pte
static inline bool arch_faults_on_old_pte(void) static inline bool arch_wants_old_prefaulted_pte(void)
{ {
/* /*
* Those arches which don't have hw access flag feature need to * Transitioning a PTE from 'old' to 'young' can be expensive on
* implement their own helper. By default, "true" means pagefault * some architectures, even if it's performed in hardware. By
* will be hit on old pte. * default, "false" means prefaulted entries will be 'young'.
*/ */
return true; return false;
} }
#endif #endif
...@@ -2674,7 +2674,7 @@ static inline bool cow_user_page(struct page *dst, struct page *src, ...@@ -2674,7 +2674,7 @@ static inline bool cow_user_page(struct page *dst, struct page *src,
* On architectures with software "accessed" bits, we would * On architectures with software "accessed" bits, we would
* take a double page fault, so mark it accessed here. * take a double page fault, so mark it accessed here.
*/ */
if (arch_faults_on_old_pte() && !pte_young(vmf->orig_pte)) { if (!arch_has_hw_pte_young() && !pte_young(vmf->orig_pte)) {
pte_t entry; pte_t entry;
vmf->pte = pte_offset_map_lock(mm, vmf->pmd, addr, &vmf->ptl); vmf->pte = pte_offset_map_lock(mm, vmf->pmd, addr, &vmf->ptl);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册