Re: [PATCH V3 2/4] mm/debug_vm_pgtable: Add tests validating advanced arch page table helpers
On 06/27/2020 12:56 PM, Christophe Leroy wrote: > > > Le 15/06/2020 à 05:37, Anshuman Khandual a écrit : >> This adds new tests validating for these following arch advanced page table >> helpers. These tests create and test specific mapping types at various page >> table levels. >> >> 1. pxxp_set_wrprotect() >> 2. pxxp_get_and_clear() >> 3. pxxp_set_access_flags() >> 4. pxxp_get_and_clear_full() >> 5. pxxp_test_and_clear_young() >> 6. pxx_leaf() >> 7. pxx_set_huge() >> 8. pxx_(clear|mk)_savedwrite() >> 9. huge_pxxp_xxx() >> >> Cc: Andrew Morton >> Cc: Mike Rapoport >> Cc: Vineet Gupta >> Cc: Catalin Marinas >> Cc: Will Deacon >> Cc: Benjamin Herrenschmidt >> Cc: Paul Mackerras >> Cc: Michael Ellerman >> Cc: Heiko Carstens >> Cc: Vasily Gorbik >> Cc: Christian Borntraeger >> Cc: Thomas Gleixner >> Cc: Ingo Molnar >> Cc: Borislav Petkov >> Cc: "H. Peter Anvin" >> Cc: Kirill A. Shutemov >> Cc: Paul Walmsley >> Cc: Palmer Dabbelt >> Cc: linux-snps-...@lists.infradead.org >> Cc: linux-arm-ker...@lists.infradead.org >> Cc: linuxppc-dev@lists.ozlabs.org >> Cc: linux-s...@vger.kernel.org >> Cc: linux-ri...@lists.infradead.org >> Cc: x...@kernel.org >> Cc: linux...@kvack.org >> Cc: linux-a...@vger.kernel.org >> Cc: linux-ker...@vger.kernel.org >> Suggested-by: Catalin Marinas >> Signed-off-by: Anshuman Khandual >> --- >> mm/debug_vm_pgtable.c | 306 ++ >> 1 file changed, 306 insertions(+) >> >> diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c >> index ffa163d4c63c..e3f9f8317a98 100644 >> --- a/mm/debug_vm_pgtable.c >> +++ b/mm/debug_vm_pgtable.c >> @@ -21,6 +21,7 @@ >> #include >> #include >> #include >> +#include >> #include >> #include >> #include >> @@ -28,6 +29,7 @@ >> #include >> #include >> #include >> +#include >> #define VMFLAGS (VM_READ|VM_WRITE|VM_EXEC) >> @@ -55,6 +57,54 @@ static void __init pte_basic_tests(unsigned long pfn, >> pgprot_t prot) >> WARN_ON(pte_write(pte_wrprotect(pte_mkwrite(pte; >> } >> +static void __init pte_advanced_tests(struct mm_struct *mm, >> + struct vm_area_struct *vma, pte_t *ptep, >> + unsigned long pfn, unsigned long vaddr, pgprot_t prot) > > Align args properly. > >> +{ >> + pte_t pte = pfn_pte(pfn, prot); >> + >> + pte = pfn_pte(pfn, prot); >> + set_pte_at(mm, vaddr, ptep, pte); >> + ptep_set_wrprotect(mm, vaddr, ptep); >> + pte = READ_ONCE(*ptep); >> + WARN_ON(pte_write(pte)); >> + >> + pte = pfn_pte(pfn, prot); >> + set_pte_at(mm, vaddr, ptep, pte); >> + ptep_get_and_clear(mm, vaddr, ptep); >> + pte = READ_ONCE(*ptep); >> + WARN_ON(!pte_none(pte)); >> + >> + pte = pfn_pte(pfn, prot); >> + pte = pte_wrprotect(pte); >> + pte = pte_mkclean(pte); >> + set_pte_at(mm, vaddr, ptep, pte); >> + pte = pte_mkwrite(pte); >> + pte = pte_mkdirty(pte); >> + ptep_set_access_flags(vma, vaddr, ptep, pte, 1); >> + pte = READ_ONCE(*ptep); >> + WARN_ON(!(pte_write(pte) && pte_dirty(pte))); >> + >> + pte = pfn_pte(pfn, prot); >> + set_pte_at(mm, vaddr, ptep, pte); >> + ptep_get_and_clear_full(mm, vaddr, ptep, 1); >> + pte = READ_ONCE(*ptep); >> + WARN_ON(!pte_none(pte)); >> + >> + pte = pte_mkyoung(pte); >> + set_pte_at(mm, vaddr, ptep, pte); >> + ptep_test_and_clear_young(vma, vaddr, ptep); >> + pte = READ_ONCE(*ptep); >> + WARN_ON(pte_young(pte)); >> +} >> + >> +static void __init pte_savedwrite_tests(unsigned long pfn, pgprot_t prot) >> +{ >> + pte_t pte = pfn_pte(pfn, prot); >> + >> + WARN_ON(!pte_savedwrite(pte_mk_savedwrite(pte_clear_savedwrite(pte; >> + WARN_ON(pte_savedwrite(pte_clear_savedwrite(pte_mk_savedwrite(pte; >> +} >> #ifdef CONFIG_TRANSPARENT_HUGEPAGE >> static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot) >> { >> @@ -77,6 +127,89 @@ static void __init pmd_basic_tests(unsigned long pfn, >> pgprot_t prot) >> WARN_ON(!pmd_bad(pmd_mkhuge(pmd))); >> } >> +static void __init pmd_advanced_tests(struct mm_struct *mm, >> + struct vm_area_struct *vma, pmd_t *pmdp, >> + unsigned long pfn, unsigned long vaddr, pgprot_t prot) > > Align args properly > >> +{ >> + pmd_t pmd = pfn_pmd(pfn, prot); >> + >> + if (!has_transparent_hugepage()) >> + return; >> + >> + /* Align the address wrt HPAGE_PMD_SIZE */ >> + vaddr = (vaddr & HPAGE_PMD_MASK) + HPAGE_PMD_SIZE; >> + >> + pmd = pfn_pmd(pfn, prot); >> + set_pmd_at(mm, vaddr, pmdp, pmd); >> + pmdp_set_wrprotect(mm, vaddr, pmdp); >> + pmd = READ_ONCE(*pmdp); >> + WARN_ON(pmd_write(pmd)); >> + >> + pmd = pfn_pmd(pfn, prot); >> + set_pmd_at(mm, vaddr, pmdp, pmd); >> + pmdp_huge_get_and_clear(mm, vaddr, pmdp); >> + pmd = READ_ONCE(*pmdp); >> + WARN_ON(!pmd_none(pmd)); >> + >> + pmd = pfn_pmd(pfn, prot); >> + pmd = pmd_wrprotect(pmd); >> + pmd = pmd_mkclean(pmd); >> + set_pmd_at(mm,
Re: [PATCH V3 2/4] mm/debug_vm_pgtable: Add tests validating advanced arch page table helpers
On 06/27/2020 12:48 PM, Christophe Leroy wrote: > Le 15/06/2020 à 05:37, Anshuman Khandual a écrit : >> This adds new tests validating for these following arch advanced page table >> helpers. These tests create and test specific mapping types at various page >> table levels. >> >> 1. pxxp_set_wrprotect() >> 2. pxxp_get_and_clear() >> 3. pxxp_set_access_flags() >> 4. pxxp_get_and_clear_full() >> 5. pxxp_test_and_clear_young() >> 6. pxx_leaf() >> 7. pxx_set_huge() >> 8. pxx_(clear|mk)_savedwrite() >> 9. huge_pxxp_xxx() >> >> Cc: Andrew Morton >> Cc: Mike Rapoport >> Cc: Vineet Gupta >> Cc: Catalin Marinas >> Cc: Will Deacon >> Cc: Benjamin Herrenschmidt >> Cc: Paul Mackerras >> Cc: Michael Ellerman >> Cc: Heiko Carstens >> Cc: Vasily Gorbik >> Cc: Christian Borntraeger >> Cc: Thomas Gleixner >> Cc: Ingo Molnar >> Cc: Borislav Petkov >> Cc: "H. Peter Anvin" >> Cc: Kirill A. Shutemov >> Cc: Paul Walmsley >> Cc: Palmer Dabbelt >> Cc: linux-snps-...@lists.infradead.org >> Cc: linux-arm-ker...@lists.infradead.org >> Cc: linuxppc-dev@lists.ozlabs.org >> Cc: linux-s...@vger.kernel.org >> Cc: linux-ri...@lists.infradead.org >> Cc: x...@kernel.org >> Cc: linux...@kvack.org >> Cc: linux-a...@vger.kernel.org >> Cc: linux-ker...@vger.kernel.org >> Suggested-by: Catalin Marinas >> Signed-off-by: Anshuman Khandual >> --- >> mm/debug_vm_pgtable.c | 306 ++ >> 1 file changed, 306 insertions(+) >> >> diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c >> index ffa163d4c63c..e3f9f8317a98 100644 >> --- a/mm/debug_vm_pgtable.c >> +++ b/mm/debug_vm_pgtable.c >> @@ -21,6 +21,7 @@ >> #include >> #include >> #include >> +#include >> #include >> #include >> #include >> @@ -28,6 +29,7 @@ >> #include >> #include >> #include >> +#include >> #define VMFLAGS (VM_READ|VM_WRITE|VM_EXEC) >> @@ -55,6 +57,54 @@ static void __init pte_basic_tests(unsigned long pfn, >> pgprot_t prot) >> WARN_ON(pte_write(pte_wrprotect(pte_mkwrite(pte; >> } >> +static void __init pte_advanced_tests(struct mm_struct *mm, >> + struct vm_area_struct *vma, pte_t *ptep, >> + unsigned long pfn, unsigned long vaddr, pgprot_t prot) >> +{ >> + pte_t pte = pfn_pte(pfn, prot); >> + >> + pte = pfn_pte(pfn, prot); >> + set_pte_at(mm, vaddr, ptep, pte); >> + ptep_set_wrprotect(mm, vaddr, ptep); >> + pte = READ_ONCE(*ptep); > > same > >> + WARN_ON(pte_write(pte)); >> + >> + pte = pfn_pte(pfn, prot); >> + set_pte_at(mm, vaddr, ptep, pte); >> + ptep_get_and_clear(mm, vaddr, ptep); >> + pte = READ_ONCE(*ptep); > > same > >> + WARN_ON(!pte_none(pte)); >> + >> + pte = pfn_pte(pfn, prot); >> + pte = pte_wrprotect(pte); >> + pte = pte_mkclean(pte); >> + set_pte_at(mm, vaddr, ptep, pte); >> + pte = pte_mkwrite(pte); >> + pte = pte_mkdirty(pte); >> + ptep_set_access_flags(vma, vaddr, ptep, pte, 1); >> + pte = READ_ONCE(*ptep); > > same > >> + WARN_ON(!(pte_write(pte) && pte_dirty(pte))); >> + >> + pte = pfn_pte(pfn, prot); >> + set_pte_at(mm, vaddr, ptep, pte); >> + ptep_get_and_clear_full(mm, vaddr, ptep, 1); >> + pte = READ_ONCE(*ptep); > > same > >> + WARN_ON(!pte_none(pte)); >> + >> + pte = pte_mkyoung(pte); >> + set_pte_at(mm, vaddr, ptep, pte); >> + ptep_test_and_clear_young(vma, vaddr, ptep); >> + pte = READ_ONCE(*ptep); > > same > >> + WARN_ON(pte_young(pte)); >> +} >> + >> +static void __init pte_savedwrite_tests(unsigned long pfn, pgprot_t prot) >> +{ >> + pte_t pte = pfn_pte(pfn, prot); >> + >> + WARN_ON(!pte_savedwrite(pte_mk_savedwrite(pte_clear_savedwrite(pte; >> + WARN_ON(pte_savedwrite(pte_clear_savedwrite(pte_mk_savedwrite(pte; >> +} >> #ifdef CONFIG_TRANSPARENT_HUGEPAGE >> static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot) >> { >> @@ -77,6 +127,89 @@ static void __init pmd_basic_tests(unsigned long pfn, >> pgprot_t prot) >> WARN_ON(!pmd_bad(pmd_mkhuge(pmd))); >> } >> +static void __init pmd_advanced_tests(struct mm_struct *mm, >> + struct vm_area_struct *vma, pmd_t *pmdp, >> + unsigned long pfn, unsigned long vaddr, pgprot_t prot) >> +{ >> + pmd_t pmd = pfn_pmd(pfn, prot); >> + >> + if (!has_transparent_hugepage()) >> + return; >> + >> + /* Align the address wrt HPAGE_PMD_SIZE */ >> + vaddr = (vaddr & HPAGE_PMD_MASK) + HPAGE_PMD_SIZE; >> + >> + pmd = pfn_pmd(pfn, prot); >> + set_pmd_at(mm, vaddr, pmdp, pmd); >> + pmdp_set_wrprotect(mm, vaddr, pmdp); >> + pmd = READ_ONCE(*pmdp); >> + WARN_ON(pmd_write(pmd)); >> + >> + pmd = pfn_pmd(pfn, prot); >> + set_pmd_at(mm, vaddr, pmdp, pmd); >> + pmdp_huge_get_and_clear(mm, vaddr, pmdp); >> + pmd = READ_ONCE(*pmdp); >> + WARN_ON(!pmd_none(pmd)); >> + >> + pmd = pfn_pmd(pfn, prot); >> + pmd = pmd_wrprotect(pmd); >> + pmd = pmd_mkclean(pmd); >> + set_pmd_at(mm,
[PATCH V3 2/4] mm/debug_vm_pgtable: Add tests validating advanced arch page table helpers
This adds new tests validating for these following arch advanced page table helpers. These tests create and test specific mapping types at various page table levels. 1. pxxp_set_wrprotect() 2. pxxp_get_and_clear() 3. pxxp_set_access_flags() 4. pxxp_get_and_clear_full() 5. pxxp_test_and_clear_young() 6. pxx_leaf() 7. pxx_set_huge() 8. pxx_(clear|mk)_savedwrite() 9. huge_pxxp_xxx() Cc: Andrew Morton Cc: Mike Rapoport Cc: Vineet Gupta Cc: Catalin Marinas Cc: Will Deacon Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: Heiko Carstens Cc: Vasily Gorbik Cc: Christian Borntraeger Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: "H. Peter Anvin" Cc: Kirill A. Shutemov Cc: Paul Walmsley Cc: Palmer Dabbelt Cc: linux-snps-...@lists.infradead.org Cc: linux-arm-ker...@lists.infradead.org Cc: linuxppc-dev@lists.ozlabs.org Cc: linux-s...@vger.kernel.org Cc: linux-ri...@lists.infradead.org Cc: x...@kernel.org Cc: linux...@kvack.org Cc: linux-a...@vger.kernel.org Cc: linux-ker...@vger.kernel.org Suggested-by: Catalin Marinas Signed-off-by: Anshuman Khandual --- mm/debug_vm_pgtable.c | 306 ++ 1 file changed, 306 insertions(+) diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c index ffa163d4c63c..e3f9f8317a98 100644 --- a/mm/debug_vm_pgtable.c +++ b/mm/debug_vm_pgtable.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #define VMFLAGS(VM_READ|VM_WRITE|VM_EXEC) @@ -55,6 +57,54 @@ static void __init pte_basic_tests(unsigned long pfn, pgprot_t prot) WARN_ON(pte_write(pte_wrprotect(pte_mkwrite(pte; } +static void __init pte_advanced_tests(struct mm_struct *mm, + struct vm_area_struct *vma, pte_t *ptep, + unsigned long pfn, unsigned long vaddr, pgprot_t prot) +{ + pte_t pte = pfn_pte(pfn, prot); + + pte = pfn_pte(pfn, prot); + set_pte_at(mm, vaddr, ptep, pte); + ptep_set_wrprotect(mm, vaddr, ptep); + pte = READ_ONCE(*ptep); + WARN_ON(pte_write(pte)); + + pte = pfn_pte(pfn, prot); + set_pte_at(mm, vaddr, ptep, pte); + ptep_get_and_clear(mm, vaddr, ptep); + pte = READ_ONCE(*ptep); + WARN_ON(!pte_none(pte)); + + pte = pfn_pte(pfn, prot); + pte = pte_wrprotect(pte); + pte = pte_mkclean(pte); + set_pte_at(mm, vaddr, ptep, pte); + pte = pte_mkwrite(pte); + pte = pte_mkdirty(pte); + ptep_set_access_flags(vma, vaddr, ptep, pte, 1); + pte = READ_ONCE(*ptep); + WARN_ON(!(pte_write(pte) && pte_dirty(pte))); + + pte = pfn_pte(pfn, prot); + set_pte_at(mm, vaddr, ptep, pte); + ptep_get_and_clear_full(mm, vaddr, ptep, 1); + pte = READ_ONCE(*ptep); + WARN_ON(!pte_none(pte)); + + pte = pte_mkyoung(pte); + set_pte_at(mm, vaddr, ptep, pte); + ptep_test_and_clear_young(vma, vaddr, ptep); + pte = READ_ONCE(*ptep); + WARN_ON(pte_young(pte)); +} + +static void __init pte_savedwrite_tests(unsigned long pfn, pgprot_t prot) +{ + pte_t pte = pfn_pte(pfn, prot); + + WARN_ON(!pte_savedwrite(pte_mk_savedwrite(pte_clear_savedwrite(pte; + WARN_ON(pte_savedwrite(pte_clear_savedwrite(pte_mk_savedwrite(pte; +} #ifdef CONFIG_TRANSPARENT_HUGEPAGE static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot) { @@ -77,6 +127,89 @@ static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot) WARN_ON(!pmd_bad(pmd_mkhuge(pmd))); } +static void __init pmd_advanced_tests(struct mm_struct *mm, + struct vm_area_struct *vma, pmd_t *pmdp, + unsigned long pfn, unsigned long vaddr, pgprot_t prot) +{ + pmd_t pmd = pfn_pmd(pfn, prot); + + if (!has_transparent_hugepage()) + return; + + /* Align the address wrt HPAGE_PMD_SIZE */ + vaddr = (vaddr & HPAGE_PMD_MASK) + HPAGE_PMD_SIZE; + + pmd = pfn_pmd(pfn, prot); + set_pmd_at(mm, vaddr, pmdp, pmd); + pmdp_set_wrprotect(mm, vaddr, pmdp); + pmd = READ_ONCE(*pmdp); + WARN_ON(pmd_write(pmd)); + + pmd = pfn_pmd(pfn, prot); + set_pmd_at(mm, vaddr, pmdp, pmd); + pmdp_huge_get_and_clear(mm, vaddr, pmdp); + pmd = READ_ONCE(*pmdp); + WARN_ON(!pmd_none(pmd)); + + pmd = pfn_pmd(pfn, prot); + pmd = pmd_wrprotect(pmd); + pmd = pmd_mkclean(pmd); + set_pmd_at(mm, vaddr, pmdp, pmd); + pmd = pmd_mkwrite(pmd); + pmd = pmd_mkdirty(pmd); + pmdp_set_access_flags(vma, vaddr, pmdp, pmd, 1); + pmd = READ_ONCE(*pmdp); + WARN_ON(!(pmd_write(pmd) && pmd_dirty(pmd))); + + pmd = pmd_mkhuge(pfn_pmd(pfn, prot)); + set_pmd_at(mm, vaddr, pmdp, pmd); + pmdp_huge_get_and_clear_full(vma, vaddr, pmdp, 1); + pmd = READ_ONCE(*pmdp); +