lkml.org 
[lkml]   [2022]   [Nov]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
SubjectRe: [PATCH v2] mm: introduce arch_has_hw_nonleaf_pmd_young()
From
Hi,

On 24.11.22 15:08, Geert Uytterhoeven wrote:
> Hi Jürgen,
>
> On Wed, Nov 23, 2022 at 7:53 AM Juergen Gross <jgross@suse.com> wrote:
>> When running as a Xen PV guests commit eed9a328aa1a ("mm: x86: add
>> CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG") can cause a protection violation
>> in pmdp_test_and_clear_young():
>>
>> BUG: unable to handle page fault for address: ffff8880083374d0
>> #PF: supervisor write access in kernel mode
>> #PF: error_code(0x0003) - permissions violation
>> PGD 3026067 P4D 3026067 PUD 3027067 PMD 7fee5067 PTE 8010000008337065
>> Oops: 0003 [#1] PREEMPT SMP NOPTI
>> CPU: 7 PID: 158 Comm: kswapd0 Not tainted 6.1.0-rc5-20221118-doflr+ #1
>> RIP: e030:pmdp_test_and_clear_young+0x25/0x40
>>
>> This happens because the Xen hypervisor can't emulate direct writes to
>> page table entries other than PTEs.
>>
>> This can easily be fixed by introducing arch_has_hw_nonleaf_pmd_young()
>> similar to arch_has_hw_pte_young() and test that instead of
>> CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG.
>>
>> Fixes: eed9a328aa1a ("mm: x86: add CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG")
>> Reported-by: Sander Eikelenboom <linux@eikelenboom.it>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
>> Acked-by: Yu Zhao <yuzhao@google.com>
>> Tested-by: Sander Eikelenboom <linux@eikelenboom.it>
>> ---
>> V2:
>> - correct function name in commit message to match patch
>
> Thanks for your patch, which is now commit 3f85e711d5af4fb4 ("mm:
> introduce arch_has_hw_nonleaf_pmd_young()") in next-20221124.
>
> noreply@ellerman.id.au reported a build failure for m68k/allmodconfig,
> which I have bisected to this commit.
>
>> --- a/mm/vmscan.c
>> +++ b/mm/vmscan.c
>
>> @@ -4073,14 +4073,14 @@ static void walk_pmd_range(pud_t *pud, unsigned long start, unsigned long end,
>> #endif
>> walk->mm_stats[MM_NONLEAF_TOTAL]++;
>>
>> -#ifdef CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG
>> - if (get_cap(LRU_GEN_NONLEAF_YOUNG)) {
>> + if (arch_has_hw_nonleaf_pmd_young() &&
>> + get_cap(LRU_GEN_NONLEAF_YOUNG)) {
>> if (!pmd_young(val))
>
> mm/vmscan.c:4102:30: error: implicit declaration of function
> 'pmd_young'; did you mean 'pte_young'?
> [-Werror=implicit-function-declaration]
>
> pmd_young() seems to be defined only on a handful of architectures.

What would be the preferred fix for that?

I could offer:

- use V1 of the patch
- add the #ifdefs again to this patch (which would be kind of weird)
- use the attached patch


Juergen

From 9f16c75dfbff994c01a003e4701f5bdd48cbfc3f Mon Sep 17 00:00:00 2001
From: Juergen Gross <jgross@suse.com>
Date: Thu, 24 Nov 2022 15:18:03 +0100
Subject: [PATCH] mm: add dummy pmd_young() for architectures not having it

In order to avoid #ifdeffery add a dummy pmd_young() implementation as
a fallback.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
arch/loongarch/include/asm/pgtable.h | 1 +
arch/mips/include/asm/pgtable.h | 1 +
arch/riscv/include/asm/pgtable.h | 1 +
arch/s390/include/asm/pgtable.h | 1 +
arch/sparc/include/asm/pgtable_64.h | 1 +
arch/x86/include/asm/pgtable.h | 1 +
include/linux/pgtable.h | 7 +++++++
7 files changed, 13 insertions(+)

diff --git a/arch/loongarch/include/asm/pgtable.h b/arch/loongarch/include/asm/pgtable.h
index 946704bee599..10e0bd9009e2 100644
--- a/arch/loongarch/include/asm/pgtable.h
+++ b/arch/loongarch/include/asm/pgtable.h
@@ -482,6 +482,7 @@ static inline pmd_t pmd_mkdirty(pmd_t pmd)
return pmd;
}

+#define pmd_young pmd_young
static inline int pmd_young(pmd_t pmd)
{
return !!(pmd_val(pmd) & _PAGE_ACCESSED);
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
index 6caec386ad2f..4678627673df 100644
--- a/arch/mips/include/asm/pgtable.h
+++ b/arch/mips/include/asm/pgtable.h
@@ -622,6 +622,7 @@ static inline pmd_t pmd_mkdirty(pmd_t pmd)
return pmd;
}

+#define pmd_young pmd_young
static inline int pmd_young(pmd_t pmd)
{
return !!(pmd_val(pmd) & _PAGE_ACCESSED);
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 7ec936910a96..92ec2d9d7273 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -600,6 +600,7 @@ static inline int pmd_dirty(pmd_t pmd)
return pte_dirty(pmd_pte(pmd));
}

+#define pmd_young pmd_young
static inline int pmd_young(pmd_t pmd)
{
return pte_young(pmd_pte(pmd));
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index f1cb9391190d..11e901286414 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -763,6 +763,7 @@ static inline int pmd_dirty(pmd_t pmd)
return (pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY) != 0;
}

+#define pmd_young pmd_young
static inline int pmd_young(pmd_t pmd)
{
return (pmd_val(pmd) & _SEGMENT_ENTRY_YOUNG) != 0;
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index a779418ceba9..3bc9736bddb1 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -693,6 +693,7 @@ static inline unsigned long pmd_dirty(pmd_t pmd)
return pte_dirty(pte);
}

+#define pmd_young pmd_young
static inline unsigned long pmd_young(pmd_t pmd)
{
pte_t pte = __pte(pmd_val(pmd));
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 5059799bebe3..1d55af8d82b9 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -139,6 +139,7 @@ static inline int pmd_dirty(pmd_t pmd)
return pmd_flags(pmd) & _PAGE_DIRTY;
}

+#define pmd_young pmd_young
static inline int pmd_young(pmd_t pmd)
{
return pmd_flags(pmd) & _PAGE_ACCESSED;
diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h
index a108b60a6962..6b0d59269b33 100644
--- a/include/linux/pgtable.h
+++ b/include/linux/pgtable.h
@@ -165,6 +165,13 @@ static inline pte_t *virt_to_kpte(unsigned long vaddr)
return pmd_none(*pmd) ? NULL : pte_offset_kernel(pmd, vaddr);
}

+#ifndef pmd_young
+static inline int pmd_young(pmd_t pmd)
+{
+ return 0;
+}
+#endif
+
#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
extern int ptep_set_access_flags(struct vm_area_struct *vma,
unsigned long address, pte_t *ptep,
--
2.35.3
[unhandled content-type:application/pgp-keys][unhandled content-type:application/pgp-signature]
\
 
 \ /
  Last update: 2022-11-24 15:31    [W:0.068 / U:0.328 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site