diff mbox series

[v3,08/12] mm/debug_vm_pgtable: Use struct pgtable_debug_args in PMD modifying tests

Message ID 20210719130613.334901-9-gshan@redhat.com (mailing list archive)
State New
Headers show
Series mm/debug_vm_pgtable: Enhancements | expand

Commit Message

Gavin Shan July 19, 2021, 1:06 p.m. UTC
This uses struct pgtable_debug_args in PMD modifying tests. The allocated
huge page is used when set_pmd_at() is used. The corresponding tests
are skipped if the huge page doesn't exist. Besides, the unused variable
@pmd_aligned in debug_vm_pgtable() is dropped.

Signed-off-by: Gavin Shan <gshan@redhat.com>
---
 mm/debug_vm_pgtable.c | 102 ++++++++++++++++++++----------------------
 1 file changed, 48 insertions(+), 54 deletions(-)

Comments

Anshuman Khandual July 22, 2021, 5:45 a.m. UTC | #1
On 7/19/21 6:36 PM, Gavin Shan wrote:
> This uses struct pgtable_debug_args in PMD modifying tests. The allocated
> huge page is used when set_pmd_at() is used. The corresponding tests
> are skipped if the huge page doesn't exist. Besides, the unused variable
> @pmd_aligned in debug_vm_pgtable() is dropped.

Please dont drop @pmd_aligned just yet.

> 
> Signed-off-by: Gavin Shan <gshan@redhat.com>
> ---
>  mm/debug_vm_pgtable.c | 102 ++++++++++++++++++++----------------------
>  1 file changed, 48 insertions(+), 54 deletions(-)
> 
> diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c
> index eb6dda88e0d9..cec3cbf99a6b 100644
> --- a/mm/debug_vm_pgtable.c
> +++ b/mm/debug_vm_pgtable.c
> @@ -213,54 +213,54 @@ static void __init pmd_basic_tests(struct pgtable_debug_args *args, int idx)
>  	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, pgtable_t pgtable)
> +static void __init pmd_advanced_tests(struct pgtable_debug_args *args)
>  {
>  	pmd_t pmd;
> +	unsigned long vaddr = (args->vaddr & HPAGE_PMD_MASK);
>  
>  	if (!has_transparent_hugepage())
>  		return;
>  
>  	pr_debug("Validating PMD advanced\n");
> -	/* Align the address wrt HPAGE_PMD_SIZE */
> -	vaddr &= HPAGE_PMD_MASK;

Please just leave these unchanged. If has_transparent_hugepage() evaluates
negative, it skips the masking operation. As mentioned earlier please avoid
changing the test in any manner during these transition patches.

> +	if (args->pmd_pfn == ULONG_MAX) {
> +		pr_debug("%s: Skipped\n", __func__);
> +		return;
> +	}

Just return. Please dont call out "Skipped".

>  
> -	pgtable_trans_huge_deposit(mm, pmdp, pgtable);
> +	pgtable_trans_huge_deposit(args->mm, args->pmdp, args->start_ptep);
>  
> -	pmd = pfn_pmd(pfn, prot);
> -	set_pmd_at(mm, vaddr, pmdp, pmd);
> -	pmdp_set_wrprotect(mm, vaddr, pmdp);
> -	pmd = READ_ONCE(*pmdp);
> +	pmd = pfn_pmd(args->pmd_pfn, args->page_prot);
> +	set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
> +	pmdp_set_wrprotect(args->mm, vaddr, args->pmdp);
> +	pmd = READ_ONCE(*(args->pmdp));
>  	WARN_ON(pmd_write(pmd));
> -	pmdp_huge_get_and_clear(mm, vaddr, pmdp);
> -	pmd = READ_ONCE(*pmdp);
> +	pmdp_huge_get_and_clear(args->mm, vaddr, args->pmdp);
> +	pmd = READ_ONCE(*(args->pmdp));
>  	WARN_ON(!pmd_none(pmd));
>  
> -	pmd = pfn_pmd(pfn, prot);
> +	pmd = pfn_pmd(args->pmd_pfn, args->page_prot);
>  	pmd = pmd_wrprotect(pmd);
>  	pmd = pmd_mkclean(pmd);
> -	set_pmd_at(mm, vaddr, pmdp, pmd);
> +	set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
>  	pmd = pmd_mkwrite(pmd);
>  	pmd = pmd_mkdirty(pmd);
> -	pmdp_set_access_flags(vma, vaddr, pmdp, pmd, 1);
> -	pmd = READ_ONCE(*pmdp);
> +	pmdp_set_access_flags(args->vma, vaddr, args->pmdp, pmd, 1);
> +	pmd = READ_ONCE(*(args->pmdp));
>  	WARN_ON(!(pmd_write(pmd) && pmd_dirty(pmd)));
> -	pmdp_huge_get_and_clear_full(vma, vaddr, pmdp, 1);
> -	pmd = READ_ONCE(*pmdp);
> +	pmdp_huge_get_and_clear_full(args->vma, vaddr, args->pmdp, 1);
> +	pmd = READ_ONCE(*(args->pmdp));
>  	WARN_ON(!pmd_none(pmd));
>  
> -	pmd = pmd_mkhuge(pfn_pmd(pfn, prot));
> +	pmd = pmd_mkhuge(pfn_pmd(args->pmd_pfn, args->page_prot));
>  	pmd = pmd_mkyoung(pmd);
> -	set_pmd_at(mm, vaddr, pmdp, pmd);
> -	pmdp_test_and_clear_young(vma, vaddr, pmdp);
> -	pmd = READ_ONCE(*pmdp);
> +	set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
> +	pmdp_test_and_clear_young(args->vma, vaddr, args->pmdp);
> +	pmd = READ_ONCE(*(args->pmdp));
>  	WARN_ON(pmd_young(pmd));
>  
>  	/*  Clear the pte entries  */
> -	pmdp_huge_get_and_clear(mm, vaddr, pmdp);
> -	pgtable = pgtable_trans_huge_withdraw(mm, pmdp);
> +	pmdp_huge_get_and_clear(args->mm, vaddr, args->pmdp);
> +	pgtable_trans_huge_withdraw(args->mm, args->pmdp);
>  }
>  
>  static void __init pmd_leaf_tests(struct pgtable_debug_args *args)
> @@ -417,12 +417,7 @@ static void __init pud_leaf_tests(struct pgtable_debug_args *args) { }
>  #else  /* !CONFIG_TRANSPARENT_HUGEPAGE */
>  static void __init pmd_basic_tests(struct pgtable_debug_args *args, int idx) { }
>  static void __init pud_basic_tests(struct pgtable_debug_args *args, int idx) { }
> -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, pgtable_t pgtable)
> -{
> -}
> +static void __init pmd_advanced_tests(struct pgtable_debug_args *args) { }
>  static void __init pud_advanced_tests(struct mm_struct *mm,
>  				      struct vm_area_struct *vma, pud_t *pudp,
>  				      unsigned long pfn, unsigned long vaddr,
> @@ -435,11 +430,11 @@ static void __init pmd_savedwrite_tests(struct pgtable_debug_args *args) { }
>  #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
>  
>  #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
> -static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
> +static void __init pmd_huge_tests(struct pgtable_debug_args *args)
>  {
>  	pmd_t pmd;
>  
> -	if (!arch_vmap_pmd_supported(prot))
> +	if (!arch_vmap_pmd_supported(args->page_prot))
>  		return;
>  
>  	pr_debug("Validating PMD huge\n");
> @@ -447,10 +442,11 @@ static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
>  	 * X86 defined pmd_set_huge() verifies that the given
>  	 * PMD is not a populated non-leaf entry.
>  	 */
> -	WRITE_ONCE(*pmdp, __pmd(0));
> -	WARN_ON(!pmd_set_huge(pmdp, __pfn_to_phys(pfn), prot));
> -	WARN_ON(!pmd_clear_huge(pmdp));
> -	pmd = READ_ONCE(*pmdp);
> +	WRITE_ONCE(*(args->pmdp), __pmd(0));

Possible extra braces.

> +	WARN_ON(!pmd_set_huge(args->pmdp, __pfn_to_phys(args->fixed_pmd_pfn),
> +			      args->page_prot));

Dont break the line.

> +	WARN_ON(!pmd_clear_huge(args->pmdp));
> +	pmd = READ_ONCE(*(args->pmdp));
>  	WARN_ON(!pmd_none(pmd));
>  }
>  
> @@ -473,7 +469,7 @@ static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot)
>  	WARN_ON(!pud_none(pud));
>  }
>  #else /* !CONFIG_HAVE_ARCH_HUGE_VMAP */
> -static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot) { }
> +static void __init pmd_huge_tests(struct pgtable_debug_args *args) { }
>  static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot) { }
>  #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
>  
> @@ -640,20 +636,19 @@ static void __init pte_clear_tests(struct pgtable_debug_args *args)
>  	WARN_ON(!pte_none(pte));
>  }
>  
> -static void __init pmd_clear_tests(struct mm_struct *mm, pmd_t *pmdp)
> +static void __init pmd_clear_tests(struct pgtable_debug_args *args)
>  {
> -	pmd_t pmd = READ_ONCE(*pmdp);
> +	pmd_t pmd = READ_ONCE(*(args->pmdp));
>  
>  	pr_debug("Validating PMD clear\n");
>  	pmd = __pmd(pmd_val(pmd) | RANDOM_ORVALUE);
> -	WRITE_ONCE(*pmdp, pmd);
> -	pmd_clear(pmdp);
> -	pmd = READ_ONCE(*pmdp);
> +	WRITE_ONCE(*(args->pmdp), pmd);
> +	pmd_clear(args->pmdp);
> +	pmd = READ_ONCE(*(args->pmdp));
>  	WARN_ON(!pmd_none(pmd));
>  }
>  
> -static void __init pmd_populate_tests(struct mm_struct *mm, pmd_t *pmdp,
> -				      pgtable_t pgtable)
> +static void __init pmd_populate_tests(struct pgtable_debug_args *args)
>  {
>  	pmd_t pmd;
>  
> @@ -662,8 +657,8 @@ static void __init pmd_populate_tests(struct mm_struct *mm, pmd_t *pmdp,
>  	 * This entry points to next level page table page.
>  	 * Hence this must not qualify as pmd_bad().
>  	 */
> -	pmd_populate(mm, pmdp, pgtable);
> -	pmd = READ_ONCE(*pmdp);
> +	pmd_populate(args->mm, args->pmdp, args->start_ptep);
> +	pmd = READ_ONCE(*(args->pmdp));
>  	WARN_ON(pmd_bad(pmd));
>  }
>  
> @@ -1159,7 +1154,7 @@ static int __init debug_vm_pgtable(void)
>  	pgtable_t saved_ptep;
>  	pgprot_t prot;
>  	phys_addr_t paddr;
> -	unsigned long vaddr, pmd_aligned;
> +	unsigned long vaddr;
>  	unsigned long pud_aligned;
>  	spinlock_t *ptl = NULL;
>  	int idx, ret;
> @@ -1194,7 +1189,6 @@ static int __init debug_vm_pgtable(void)
>  	 */
>  	paddr = __pa_symbol(&start_kernel);
>  
> -	pmd_aligned = (paddr & PMD_MASK) >> PAGE_SHIFT;

Please dont drop these just yet and wait until [PATCH 11/12].

>  	pud_aligned = (paddr & PUD_MASK) >> PAGE_SHIFT;
>  
>  	pgdp = pgd_offset(mm, vaddr);
> @@ -1281,11 +1275,11 @@ static int __init debug_vm_pgtable(void)
>  	pte_advanced_tests(&args);
>  	spin_unlock(ptl);
>  
> -	ptl = pmd_lock(mm, pmdp);
> -	pmd_clear_tests(mm, pmdp);
> -	pmd_advanced_tests(mm, vma, pmdp, pmd_aligned, vaddr, prot, saved_ptep);
> -	pmd_huge_tests(pmdp, pmd_aligned, prot);
> -	pmd_populate_tests(mm, pmdp, saved_ptep);
> +	ptl = pmd_lock(args.mm, args.pmdp);
> +	pmd_clear_tests(&args);
> +	pmd_advanced_tests(&args);
> +	pmd_huge_tests(&args);
> +	pmd_populate_tests(&args);
>  	spin_unlock(ptl);
>  
>  	ptl = pud_lock(mm, pudp);
>
Gavin Shan July 22, 2021, 6:41 a.m. UTC | #2
Hi Anshuman,

On 7/22/21 3:45 PM, Anshuman Khandual wrote:
> On 7/19/21 6:36 PM, Gavin Shan wrote:
>> This uses struct pgtable_debug_args in PMD modifying tests. The allocated
>> huge page is used when set_pmd_at() is used. The corresponding tests
>> are skipped if the huge page doesn't exist. Besides, the unused variable
>> @pmd_aligned in debug_vm_pgtable() is dropped.
> 
> Please dont drop @pmd_aligned just yet.
> 

We need do so. Otherwise, there is build warning to complain
something like 'unused variable' after this patch is applied.

>>
>> Signed-off-by: Gavin Shan <gshan@redhat.com>
>> ---
>>   mm/debug_vm_pgtable.c | 102 ++++++++++++++++++++----------------------
>>   1 file changed, 48 insertions(+), 54 deletions(-)
>>
>> diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c
>> index eb6dda88e0d9..cec3cbf99a6b 100644
>> --- a/mm/debug_vm_pgtable.c
>> +++ b/mm/debug_vm_pgtable.c
>> @@ -213,54 +213,54 @@ static void __init pmd_basic_tests(struct pgtable_debug_args *args, int idx)
>>   	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, pgtable_t pgtable)
>> +static void __init pmd_advanced_tests(struct pgtable_debug_args *args)
>>   {
>>   	pmd_t pmd;
>> +	unsigned long vaddr = (args->vaddr & HPAGE_PMD_MASK);
>>   
>>   	if (!has_transparent_hugepage())
>>   		return;
>>   
>>   	pr_debug("Validating PMD advanced\n");
>> -	/* Align the address wrt HPAGE_PMD_SIZE */
>> -	vaddr &= HPAGE_PMD_MASK;
> 
> Please just leave these unchanged. If has_transparent_hugepage() evaluates
> negative, it skips the masking operation. As mentioned earlier please avoid
> changing the test in any manner during these transition patches.
> 

Ok.

>> +	if (args->pmd_pfn == ULONG_MAX) {
>> +		pr_debug("%s: Skipped\n", __func__);
>> +		return;
>> +	}
> 
> Just return. Please dont call out "Skipped".
> 

Ok.

>>   
>> -	pgtable_trans_huge_deposit(mm, pmdp, pgtable);
>> +	pgtable_trans_huge_deposit(args->mm, args->pmdp, args->start_ptep);
>>   
>> -	pmd = pfn_pmd(pfn, prot);
>> -	set_pmd_at(mm, vaddr, pmdp, pmd);
>> -	pmdp_set_wrprotect(mm, vaddr, pmdp);
>> -	pmd = READ_ONCE(*pmdp);
>> +	pmd = pfn_pmd(args->pmd_pfn, args->page_prot);
>> +	set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
>> +	pmdp_set_wrprotect(args->mm, vaddr, args->pmdp);
>> +	pmd = READ_ONCE(*(args->pmdp));
>>   	WARN_ON(pmd_write(pmd));
>> -	pmdp_huge_get_and_clear(mm, vaddr, pmdp);
>> -	pmd = READ_ONCE(*pmdp);
>> +	pmdp_huge_get_and_clear(args->mm, vaddr, args->pmdp);
>> +	pmd = READ_ONCE(*(args->pmdp));
>>   	WARN_ON(!pmd_none(pmd));
>>   
>> -	pmd = pfn_pmd(pfn, prot);
>> +	pmd = pfn_pmd(args->pmd_pfn, args->page_prot);
>>   	pmd = pmd_wrprotect(pmd);
>>   	pmd = pmd_mkclean(pmd);
>> -	set_pmd_at(mm, vaddr, pmdp, pmd);
>> +	set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
>>   	pmd = pmd_mkwrite(pmd);
>>   	pmd = pmd_mkdirty(pmd);
>> -	pmdp_set_access_flags(vma, vaddr, pmdp, pmd, 1);
>> -	pmd = READ_ONCE(*pmdp);
>> +	pmdp_set_access_flags(args->vma, vaddr, args->pmdp, pmd, 1);
>> +	pmd = READ_ONCE(*(args->pmdp));
>>   	WARN_ON(!(pmd_write(pmd) && pmd_dirty(pmd)));
>> -	pmdp_huge_get_and_clear_full(vma, vaddr, pmdp, 1);
>> -	pmd = READ_ONCE(*pmdp);
>> +	pmdp_huge_get_and_clear_full(args->vma, vaddr, args->pmdp, 1);
>> +	pmd = READ_ONCE(*(args->pmdp));
>>   	WARN_ON(!pmd_none(pmd));
>>   
>> -	pmd = pmd_mkhuge(pfn_pmd(pfn, prot));
>> +	pmd = pmd_mkhuge(pfn_pmd(args->pmd_pfn, args->page_prot));
>>   	pmd = pmd_mkyoung(pmd);
>> -	set_pmd_at(mm, vaddr, pmdp, pmd);
>> -	pmdp_test_and_clear_young(vma, vaddr, pmdp);
>> -	pmd = READ_ONCE(*pmdp);
>> +	set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
>> +	pmdp_test_and_clear_young(args->vma, vaddr, args->pmdp);
>> +	pmd = READ_ONCE(*(args->pmdp));
>>   	WARN_ON(pmd_young(pmd));
>>   
>>   	/*  Clear the pte entries  */
>> -	pmdp_huge_get_and_clear(mm, vaddr, pmdp);
>> -	pgtable = pgtable_trans_huge_withdraw(mm, pmdp);
>> +	pmdp_huge_get_and_clear(args->mm, vaddr, args->pmdp);
>> +	pgtable_trans_huge_withdraw(args->mm, args->pmdp);
>>   }
>>   
>>   static void __init pmd_leaf_tests(struct pgtable_debug_args *args)
>> @@ -417,12 +417,7 @@ static void __init pud_leaf_tests(struct pgtable_debug_args *args) { }
>>   #else  /* !CONFIG_TRANSPARENT_HUGEPAGE */
>>   static void __init pmd_basic_tests(struct pgtable_debug_args *args, int idx) { }
>>   static void __init pud_basic_tests(struct pgtable_debug_args *args, int idx) { }
>> -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, pgtable_t pgtable)
>> -{
>> -}
>> +static void __init pmd_advanced_tests(struct pgtable_debug_args *args) { }
>>   static void __init pud_advanced_tests(struct mm_struct *mm,
>>   				      struct vm_area_struct *vma, pud_t *pudp,
>>   				      unsigned long pfn, unsigned long vaddr,
>> @@ -435,11 +430,11 @@ static void __init pmd_savedwrite_tests(struct pgtable_debug_args *args) { }
>>   #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
>>   
>>   #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
>> -static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
>> +static void __init pmd_huge_tests(struct pgtable_debug_args *args)
>>   {
>>   	pmd_t pmd;
>>   
>> -	if (!arch_vmap_pmd_supported(prot))
>> +	if (!arch_vmap_pmd_supported(args->page_prot))
>>   		return;
>>   
>>   	pr_debug("Validating PMD huge\n");
>> @@ -447,10 +442,11 @@ static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
>>   	 * X86 defined pmd_set_huge() verifies that the given
>>   	 * PMD is not a populated non-leaf entry.
>>   	 */
>> -	WRITE_ONCE(*pmdp, __pmd(0));
>> -	WARN_ON(!pmd_set_huge(pmdp, __pfn_to_phys(pfn), prot));
>> -	WARN_ON(!pmd_clear_huge(pmdp));
>> -	pmd = READ_ONCE(*pmdp);
>> +	WRITE_ONCE(*(args->pmdp), __pmd(0));
> 
> Possible extra braces.
> 

Will drop it in v4, thanks!

>> +	WARN_ON(!pmd_set_huge(args->pmdp, __pfn_to_phys(args->fixed_pmd_pfn),
>> +			      args->page_prot));
> 
> Dont break the line.
> 

Ok.

>> +	WARN_ON(!pmd_clear_huge(args->pmdp));
>> +	pmd = READ_ONCE(*(args->pmdp));
>>   	WARN_ON(!pmd_none(pmd));
>>   }
>>   
>> @@ -473,7 +469,7 @@ static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot)
>>   	WARN_ON(!pud_none(pud));
>>   }
>>   #else /* !CONFIG_HAVE_ARCH_HUGE_VMAP */
>> -static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot) { }
>> +static void __init pmd_huge_tests(struct pgtable_debug_args *args) { }
>>   static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot) { }
>>   #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
>>   
>> @@ -640,20 +636,19 @@ static void __init pte_clear_tests(struct pgtable_debug_args *args)
>>   	WARN_ON(!pte_none(pte));
>>   }
>>   
>> -static void __init pmd_clear_tests(struct mm_struct *mm, pmd_t *pmdp)
>> +static void __init pmd_clear_tests(struct pgtable_debug_args *args)
>>   {
>> -	pmd_t pmd = READ_ONCE(*pmdp);
>> +	pmd_t pmd = READ_ONCE(*(args->pmdp));
>>   
>>   	pr_debug("Validating PMD clear\n");
>>   	pmd = __pmd(pmd_val(pmd) | RANDOM_ORVALUE);
>> -	WRITE_ONCE(*pmdp, pmd);
>> -	pmd_clear(pmdp);
>> -	pmd = READ_ONCE(*pmdp);
>> +	WRITE_ONCE(*(args->pmdp), pmd);
>> +	pmd_clear(args->pmdp);
>> +	pmd = READ_ONCE(*(args->pmdp));
>>   	WARN_ON(!pmd_none(pmd));
>>   }
>>   
>> -static void __init pmd_populate_tests(struct mm_struct *mm, pmd_t *pmdp,
>> -				      pgtable_t pgtable)
>> +static void __init pmd_populate_tests(struct pgtable_debug_args *args)
>>   {
>>   	pmd_t pmd;
>>   
>> @@ -662,8 +657,8 @@ static void __init pmd_populate_tests(struct mm_struct *mm, pmd_t *pmdp,
>>   	 * This entry points to next level page table page.
>>   	 * Hence this must not qualify as pmd_bad().
>>   	 */
>> -	pmd_populate(mm, pmdp, pgtable);
>> -	pmd = READ_ONCE(*pmdp);
>> +	pmd_populate(args->mm, args->pmdp, args->start_ptep);
>> +	pmd = READ_ONCE(*(args->pmdp));
>>   	WARN_ON(pmd_bad(pmd));
>>   }
>>   
>> @@ -1159,7 +1154,7 @@ static int __init debug_vm_pgtable(void)
>>   	pgtable_t saved_ptep;
>>   	pgprot_t prot;
>>   	phys_addr_t paddr;
>> -	unsigned long vaddr, pmd_aligned;
>> +	unsigned long vaddr;
>>   	unsigned long pud_aligned;
>>   	spinlock_t *ptl = NULL;
>>   	int idx, ret;
>> @@ -1194,7 +1189,6 @@ static int __init debug_vm_pgtable(void)
>>   	 */
>>   	paddr = __pa_symbol(&start_kernel);
>>   
>> -	pmd_aligned = (paddr & PMD_MASK) >> PAGE_SHIFT;
> 
> Please dont drop these just yet and wait until [PATCH 11/12].
> 

Otherwise, it causes build warning: 'unused variable'.

>>   	pud_aligned = (paddr & PUD_MASK) >> PAGE_SHIFT;
>>   
>>   	pgdp = pgd_offset(mm, vaddr);
>> @@ -1281,11 +1275,11 @@ static int __init debug_vm_pgtable(void)
>>   	pte_advanced_tests(&args);
>>   	spin_unlock(ptl);
>>   
>> -	ptl = pmd_lock(mm, pmdp);
>> -	pmd_clear_tests(mm, pmdp);
>> -	pmd_advanced_tests(mm, vma, pmdp, pmd_aligned, vaddr, prot, saved_ptep);
>> -	pmd_huge_tests(pmdp, pmd_aligned, prot);
>> -	pmd_populate_tests(mm, pmdp, saved_ptep);
>> +	ptl = pmd_lock(args.mm, args.pmdp);
>> +	pmd_clear_tests(&args);
>> +	pmd_advanced_tests(&args);
>> +	pmd_huge_tests(&args);
>> +	pmd_populate_tests(&args);
>>   	spin_unlock(ptl);
>>   
>>   	ptl = pud_lock(mm, pudp);
>>
> 

Thanks,
Gavin
Anshuman Khandual July 22, 2021, 7:11 a.m. UTC | #3
On 7/22/21 12:11 PM, Gavin Shan wrote:
> Hi Anshuman,
> 
> On 7/22/21 3:45 PM, Anshuman Khandual wrote:
>> On 7/19/21 6:36 PM, Gavin Shan wrote:
>>> This uses struct pgtable_debug_args in PMD modifying tests. The allocated
>>> huge page is used when set_pmd_at() is used. The corresponding tests
>>> are skipped if the huge page doesn't exist. Besides, the unused variable
>>> @pmd_aligned in debug_vm_pgtable() is dropped.
>>
>> Please dont drop @pmd_aligned just yet.
>>
> 
> We need do so. Otherwise, there is build warning to complain
> something like 'unused variable' after this patch is applied.
> 
>>>
>>> Signed-off-by: Gavin Shan <gshan@redhat.com>
>>> ---
>>>   mm/debug_vm_pgtable.c | 102 ++++++++++++++++++++----------------------
>>>   1 file changed, 48 insertions(+), 54 deletions(-)
>>>
>>> diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c
>>> index eb6dda88e0d9..cec3cbf99a6b 100644
>>> --- a/mm/debug_vm_pgtable.c
>>> +++ b/mm/debug_vm_pgtable.c
>>> @@ -213,54 +213,54 @@ static void __init pmd_basic_tests(struct pgtable_debug_args *args, int idx)
>>>       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, pgtable_t pgtable)
>>> +static void __init pmd_advanced_tests(struct pgtable_debug_args *args)
>>>   {
>>>       pmd_t pmd;
>>> +    unsigned long vaddr = (args->vaddr & HPAGE_PMD_MASK);
>>>         if (!has_transparent_hugepage())
>>>           return;
>>>         pr_debug("Validating PMD advanced\n");
>>> -    /* Align the address wrt HPAGE_PMD_SIZE */
>>> -    vaddr &= HPAGE_PMD_MASK;
>>
>> Please just leave these unchanged. If has_transparent_hugepage() evaluates
>> negative, it skips the masking operation. As mentioned earlier please avoid
>> changing the test in any manner during these transition patches.
>>
> 
> Ok.
> 
>>> +    if (args->pmd_pfn == ULONG_MAX) {
>>> +        pr_debug("%s: Skipped\n", __func__);
>>> +        return;
>>> +    }
>>
>> Just return. Please dont call out "Skipped".
>>
> 
> Ok.
> 
>>>   -    pgtable_trans_huge_deposit(mm, pmdp, pgtable);
>>> +    pgtable_trans_huge_deposit(args->mm, args->pmdp, args->start_ptep);
>>>   -    pmd = pfn_pmd(pfn, prot);
>>> -    set_pmd_at(mm, vaddr, pmdp, pmd);
>>> -    pmdp_set_wrprotect(mm, vaddr, pmdp);
>>> -    pmd = READ_ONCE(*pmdp);
>>> +    pmd = pfn_pmd(args->pmd_pfn, args->page_prot);
>>> +    set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
>>> +    pmdp_set_wrprotect(args->mm, vaddr, args->pmdp);
>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>       WARN_ON(pmd_write(pmd));
>>> -    pmdp_huge_get_and_clear(mm, vaddr, pmdp);
>>> -    pmd = READ_ONCE(*pmdp);
>>> +    pmdp_huge_get_and_clear(args->mm, vaddr, args->pmdp);
>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>       WARN_ON(!pmd_none(pmd));
>>>   -    pmd = pfn_pmd(pfn, prot);
>>> +    pmd = pfn_pmd(args->pmd_pfn, args->page_prot);
>>>       pmd = pmd_wrprotect(pmd);
>>>       pmd = pmd_mkclean(pmd);
>>> -    set_pmd_at(mm, vaddr, pmdp, pmd);
>>> +    set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
>>>       pmd = pmd_mkwrite(pmd);
>>>       pmd = pmd_mkdirty(pmd);
>>> -    pmdp_set_access_flags(vma, vaddr, pmdp, pmd, 1);
>>> -    pmd = READ_ONCE(*pmdp);
>>> +    pmdp_set_access_flags(args->vma, vaddr, args->pmdp, pmd, 1);
>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>       WARN_ON(!(pmd_write(pmd) && pmd_dirty(pmd)));
>>> -    pmdp_huge_get_and_clear_full(vma, vaddr, pmdp, 1);
>>> -    pmd = READ_ONCE(*pmdp);
>>> +    pmdp_huge_get_and_clear_full(args->vma, vaddr, args->pmdp, 1);
>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>       WARN_ON(!pmd_none(pmd));
>>>   -    pmd = pmd_mkhuge(pfn_pmd(pfn, prot));
>>> +    pmd = pmd_mkhuge(pfn_pmd(args->pmd_pfn, args->page_prot));
>>>       pmd = pmd_mkyoung(pmd);
>>> -    set_pmd_at(mm, vaddr, pmdp, pmd);
>>> -    pmdp_test_and_clear_young(vma, vaddr, pmdp);
>>> -    pmd = READ_ONCE(*pmdp);
>>> +    set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
>>> +    pmdp_test_and_clear_young(args->vma, vaddr, args->pmdp);
>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>       WARN_ON(pmd_young(pmd));
>>>         /*  Clear the pte entries  */
>>> -    pmdp_huge_get_and_clear(mm, vaddr, pmdp);
>>> -    pgtable = pgtable_trans_huge_withdraw(mm, pmdp);
>>> +    pmdp_huge_get_and_clear(args->mm, vaddr, args->pmdp);
>>> +    pgtable_trans_huge_withdraw(args->mm, args->pmdp);
>>>   }
>>>     static void __init pmd_leaf_tests(struct pgtable_debug_args *args)
>>> @@ -417,12 +417,7 @@ static void __init pud_leaf_tests(struct pgtable_debug_args *args) { }
>>>   #else  /* !CONFIG_TRANSPARENT_HUGEPAGE */
>>>   static void __init pmd_basic_tests(struct pgtable_debug_args *args, int idx) { }
>>>   static void __init pud_basic_tests(struct pgtable_debug_args *args, int idx) { }
>>> -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, pgtable_t pgtable)
>>> -{
>>> -}
>>> +static void __init pmd_advanced_tests(struct pgtable_debug_args *args) { }
>>>   static void __init pud_advanced_tests(struct mm_struct *mm,
>>>                         struct vm_area_struct *vma, pud_t *pudp,
>>>                         unsigned long pfn, unsigned long vaddr,
>>> @@ -435,11 +430,11 @@ static void __init pmd_savedwrite_tests(struct pgtable_debug_args *args) { }
>>>   #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
>>>     #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
>>> -static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
>>> +static void __init pmd_huge_tests(struct pgtable_debug_args *args)
>>>   {
>>>       pmd_t pmd;
>>>   -    if (!arch_vmap_pmd_supported(prot))
>>> +    if (!arch_vmap_pmd_supported(args->page_prot))
>>>           return;
>>>         pr_debug("Validating PMD huge\n");
>>> @@ -447,10 +442,11 @@ static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
>>>        * X86 defined pmd_set_huge() verifies that the given
>>>        * PMD is not a populated non-leaf entry.
>>>        */
>>> -    WRITE_ONCE(*pmdp, __pmd(0));
>>> -    WARN_ON(!pmd_set_huge(pmdp, __pfn_to_phys(pfn), prot));
>>> -    WARN_ON(!pmd_clear_huge(pmdp));
>>> -    pmd = READ_ONCE(*pmdp);
>>> +    WRITE_ONCE(*(args->pmdp), __pmd(0));
>>
>> Possible extra braces.
>>
> 
> Will drop it in v4, thanks!
> 
>>> +    WARN_ON(!pmd_set_huge(args->pmdp, __pfn_to_phys(args->fixed_pmd_pfn),
>>> +                  args->page_prot));
>>
>> Dont break the line.
>>
> 
> Ok.
> 
>>> +    WARN_ON(!pmd_clear_huge(args->pmdp));
>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>       WARN_ON(!pmd_none(pmd));
>>>   }
>>>   @@ -473,7 +469,7 @@ static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot)
>>>       WARN_ON(!pud_none(pud));
>>>   }
>>>   #else /* !CONFIG_HAVE_ARCH_HUGE_VMAP */
>>> -static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot) { }
>>> +static void __init pmd_huge_tests(struct pgtable_debug_args *args) { }
>>>   static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot) { }
>>>   #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
>>>   @@ -640,20 +636,19 @@ static void __init pte_clear_tests(struct pgtable_debug_args *args)
>>>       WARN_ON(!pte_none(pte));
>>>   }
>>>   -static void __init pmd_clear_tests(struct mm_struct *mm, pmd_t *pmdp)
>>> +static void __init pmd_clear_tests(struct pgtable_debug_args *args)
>>>   {
>>> -    pmd_t pmd = READ_ONCE(*pmdp);
>>> +    pmd_t pmd = READ_ONCE(*(args->pmdp));
>>>         pr_debug("Validating PMD clear\n");
>>>       pmd = __pmd(pmd_val(pmd) | RANDOM_ORVALUE);
>>> -    WRITE_ONCE(*pmdp, pmd);
>>> -    pmd_clear(pmdp);
>>> -    pmd = READ_ONCE(*pmdp);
>>> +    WRITE_ONCE(*(args->pmdp), pmd);
>>> +    pmd_clear(args->pmdp);
>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>       WARN_ON(!pmd_none(pmd));
>>>   }
>>>   -static void __init pmd_populate_tests(struct mm_struct *mm, pmd_t *pmdp,
>>> -                      pgtable_t pgtable)
>>> +static void __init pmd_populate_tests(struct pgtable_debug_args *args)
>>>   {
>>>       pmd_t pmd;
>>>   @@ -662,8 +657,8 @@ static void __init pmd_populate_tests(struct mm_struct *mm, pmd_t *pmdp,
>>>        * This entry points to next level page table page.
>>>        * Hence this must not qualify as pmd_bad().
>>>        */
>>> -    pmd_populate(mm, pmdp, pgtable);
>>> -    pmd = READ_ONCE(*pmdp);
>>> +    pmd_populate(args->mm, args->pmdp, args->start_ptep);
>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>       WARN_ON(pmd_bad(pmd));
>>>   }
>>>   @@ -1159,7 +1154,7 @@ static int __init debug_vm_pgtable(void)
>>>       pgtable_t saved_ptep;
>>>       pgprot_t prot;
>>>       phys_addr_t paddr;
>>> -    unsigned long vaddr, pmd_aligned;
>>> +    unsigned long vaddr;
>>>       unsigned long pud_aligned;
>>>       spinlock_t *ptl = NULL;
>>>       int idx, ret;
>>> @@ -1194,7 +1189,6 @@ static int __init debug_vm_pgtable(void)
>>>        */
>>>       paddr = __pa_symbol(&start_kernel);
>>>   -    pmd_aligned = (paddr & PMD_MASK) >> PAGE_SHIFT;
>>
>> Please dont drop these just yet and wait until [PATCH 11/12].
>>
> 
> Otherwise, it causes build warning: 'unused variable'.

Why ? Just the evaluation of 'pmd_aligned' from 'paddr' should
be enough to avoid such warning. 'pmd_aligned' need not be used
afterwards.
Gavin Shan July 23, 2021, 1 a.m. UTC | #4
Hi Anshuman,

On 7/22/21 5:11 PM, Anshuman Khandual wrote:
> On 7/22/21 12:11 PM, Gavin Shan wrote:
>> On 7/22/21 3:45 PM, Anshuman Khandual wrote:
>>> On 7/19/21 6:36 PM, Gavin Shan wrote:
>>>> This uses struct pgtable_debug_args in PMD modifying tests. The allocated
>>>> huge page is used when set_pmd_at() is used. The corresponding tests
>>>> are skipped if the huge page doesn't exist. Besides, the unused variable
>>>> @pmd_aligned in debug_vm_pgtable() is dropped.
>>>
>>> Please dont drop @pmd_aligned just yet.
>>>
>>
>> We need do so. Otherwise, there is build warning to complain
>> something like 'unused variable' after this patch is applied.
>>
>>>>
>>>> Signed-off-by: Gavin Shan <gshan@redhat.com>
>>>> ---
>>>>    mm/debug_vm_pgtable.c | 102 ++++++++++++++++++++----------------------
>>>>    1 file changed, 48 insertions(+), 54 deletions(-)
>>>>
>>>> diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c
>>>> index eb6dda88e0d9..cec3cbf99a6b 100644
>>>> --- a/mm/debug_vm_pgtable.c
>>>> +++ b/mm/debug_vm_pgtable.c
>>>> @@ -213,54 +213,54 @@ static void __init pmd_basic_tests(struct pgtable_debug_args *args, int idx)
>>>>        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, pgtable_t pgtable)
>>>> +static void __init pmd_advanced_tests(struct pgtable_debug_args *args)
>>>>    {
>>>>        pmd_t pmd;
>>>> +    unsigned long vaddr = (args->vaddr & HPAGE_PMD_MASK);
>>>>          if (!has_transparent_hugepage())
>>>>            return;
>>>>          pr_debug("Validating PMD advanced\n");
>>>> -    /* Align the address wrt HPAGE_PMD_SIZE */
>>>> -    vaddr &= HPAGE_PMD_MASK;
>>>
>>> Please just leave these unchanged. If has_transparent_hugepage() evaluates
>>> negative, it skips the masking operation. As mentioned earlier please avoid
>>> changing the test in any manner during these transition patches.
>>>
>>
>> Ok.
>>
>>>> +    if (args->pmd_pfn == ULONG_MAX) {
>>>> +        pr_debug("%s: Skipped\n", __func__);
>>>> +        return;
>>>> +    }
>>>
>>> Just return. Please dont call out "Skipped".
>>>
>>
>> Ok.
>>
>>>>    -    pgtable_trans_huge_deposit(mm, pmdp, pgtable);
>>>> +    pgtable_trans_huge_deposit(args->mm, args->pmdp, args->start_ptep);
>>>>    -    pmd = pfn_pmd(pfn, prot);
>>>> -    set_pmd_at(mm, vaddr, pmdp, pmd);
>>>> -    pmdp_set_wrprotect(mm, vaddr, pmdp);
>>>> -    pmd = READ_ONCE(*pmdp);
>>>> +    pmd = pfn_pmd(args->pmd_pfn, args->page_prot);
>>>> +    set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
>>>> +    pmdp_set_wrprotect(args->mm, vaddr, args->pmdp);
>>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>>        WARN_ON(pmd_write(pmd));
>>>> -    pmdp_huge_get_and_clear(mm, vaddr, pmdp);
>>>> -    pmd = READ_ONCE(*pmdp);
>>>> +    pmdp_huge_get_and_clear(args->mm, vaddr, args->pmdp);
>>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>>        WARN_ON(!pmd_none(pmd));
>>>>    -    pmd = pfn_pmd(pfn, prot);
>>>> +    pmd = pfn_pmd(args->pmd_pfn, args->page_prot);
>>>>        pmd = pmd_wrprotect(pmd);
>>>>        pmd = pmd_mkclean(pmd);
>>>> -    set_pmd_at(mm, vaddr, pmdp, pmd);
>>>> +    set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
>>>>        pmd = pmd_mkwrite(pmd);
>>>>        pmd = pmd_mkdirty(pmd);
>>>> -    pmdp_set_access_flags(vma, vaddr, pmdp, pmd, 1);
>>>> -    pmd = READ_ONCE(*pmdp);
>>>> +    pmdp_set_access_flags(args->vma, vaddr, args->pmdp, pmd, 1);
>>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>>        WARN_ON(!(pmd_write(pmd) && pmd_dirty(pmd)));
>>>> -    pmdp_huge_get_and_clear_full(vma, vaddr, pmdp, 1);
>>>> -    pmd = READ_ONCE(*pmdp);
>>>> +    pmdp_huge_get_and_clear_full(args->vma, vaddr, args->pmdp, 1);
>>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>>        WARN_ON(!pmd_none(pmd));
>>>>    -    pmd = pmd_mkhuge(pfn_pmd(pfn, prot));
>>>> +    pmd = pmd_mkhuge(pfn_pmd(args->pmd_pfn, args->page_prot));
>>>>        pmd = pmd_mkyoung(pmd);
>>>> -    set_pmd_at(mm, vaddr, pmdp, pmd);
>>>> -    pmdp_test_and_clear_young(vma, vaddr, pmdp);
>>>> -    pmd = READ_ONCE(*pmdp);
>>>> +    set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
>>>> +    pmdp_test_and_clear_young(args->vma, vaddr, args->pmdp);
>>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>>        WARN_ON(pmd_young(pmd));
>>>>          /*  Clear the pte entries  */
>>>> -    pmdp_huge_get_and_clear(mm, vaddr, pmdp);
>>>> -    pgtable = pgtable_trans_huge_withdraw(mm, pmdp);
>>>> +    pmdp_huge_get_and_clear(args->mm, vaddr, args->pmdp);
>>>> +    pgtable_trans_huge_withdraw(args->mm, args->pmdp);
>>>>    }
>>>>      static void __init pmd_leaf_tests(struct pgtable_debug_args *args)
>>>> @@ -417,12 +417,7 @@ static void __init pud_leaf_tests(struct pgtable_debug_args *args) { }
>>>>    #else  /* !CONFIG_TRANSPARENT_HUGEPAGE */
>>>>    static void __init pmd_basic_tests(struct pgtable_debug_args *args, int idx) { }
>>>>    static void __init pud_basic_tests(struct pgtable_debug_args *args, int idx) { }
>>>> -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, pgtable_t pgtable)
>>>> -{
>>>> -}
>>>> +static void __init pmd_advanced_tests(struct pgtable_debug_args *args) { }
>>>>    static void __init pud_advanced_tests(struct mm_struct *mm,
>>>>                          struct vm_area_struct *vma, pud_t *pudp,
>>>>                          unsigned long pfn, unsigned long vaddr,
>>>> @@ -435,11 +430,11 @@ static void __init pmd_savedwrite_tests(struct pgtable_debug_args *args) { }
>>>>    #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
>>>>      #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
>>>> -static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
>>>> +static void __init pmd_huge_tests(struct pgtable_debug_args *args)
>>>>    {
>>>>        pmd_t pmd;
>>>>    -    if (!arch_vmap_pmd_supported(prot))
>>>> +    if (!arch_vmap_pmd_supported(args->page_prot))
>>>>            return;
>>>>          pr_debug("Validating PMD huge\n");
>>>> @@ -447,10 +442,11 @@ static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
>>>>         * X86 defined pmd_set_huge() verifies that the given
>>>>         * PMD is not a populated non-leaf entry.
>>>>         */
>>>> -    WRITE_ONCE(*pmdp, __pmd(0));
>>>> -    WARN_ON(!pmd_set_huge(pmdp, __pfn_to_phys(pfn), prot));
>>>> -    WARN_ON(!pmd_clear_huge(pmdp));
>>>> -    pmd = READ_ONCE(*pmdp);
>>>> +    WRITE_ONCE(*(args->pmdp), __pmd(0));
>>>
>>> Possible extra braces.
>>>
>>
>> Will drop it in v4, thanks!
>>
>>>> +    WARN_ON(!pmd_set_huge(args->pmdp, __pfn_to_phys(args->fixed_pmd_pfn),
>>>> +                  args->page_prot));
>>>
>>> Dont break the line.
>>>
>>
>> Ok.
>>
>>>> +    WARN_ON(!pmd_clear_huge(args->pmdp));
>>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>>        WARN_ON(!pmd_none(pmd));
>>>>    }
>>>>    @@ -473,7 +469,7 @@ static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot)
>>>>        WARN_ON(!pud_none(pud));
>>>>    }
>>>>    #else /* !CONFIG_HAVE_ARCH_HUGE_VMAP */
>>>> -static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot) { }
>>>> +static void __init pmd_huge_tests(struct pgtable_debug_args *args) { }
>>>>    static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot) { }
>>>>    #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
>>>>    @@ -640,20 +636,19 @@ static void __init pte_clear_tests(struct pgtable_debug_args *args)
>>>>        WARN_ON(!pte_none(pte));
>>>>    }
>>>>    -static void __init pmd_clear_tests(struct mm_struct *mm, pmd_t *pmdp)
>>>> +static void __init pmd_clear_tests(struct pgtable_debug_args *args)
>>>>    {
>>>> -    pmd_t pmd = READ_ONCE(*pmdp);
>>>> +    pmd_t pmd = READ_ONCE(*(args->pmdp));
>>>>          pr_debug("Validating PMD clear\n");
>>>>        pmd = __pmd(pmd_val(pmd) | RANDOM_ORVALUE);
>>>> -    WRITE_ONCE(*pmdp, pmd);
>>>> -    pmd_clear(pmdp);
>>>> -    pmd = READ_ONCE(*pmdp);
>>>> +    WRITE_ONCE(*(args->pmdp), pmd);
>>>> +    pmd_clear(args->pmdp);
>>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>>        WARN_ON(!pmd_none(pmd));
>>>>    }
>>>>    -static void __init pmd_populate_tests(struct mm_struct *mm, pmd_t *pmdp,
>>>> -                      pgtable_t pgtable)
>>>> +static void __init pmd_populate_tests(struct pgtable_debug_args *args)
>>>>    {
>>>>        pmd_t pmd;
>>>>    @@ -662,8 +657,8 @@ static void __init pmd_populate_tests(struct mm_struct *mm, pmd_t *pmdp,
>>>>         * This entry points to next level page table page.
>>>>         * Hence this must not qualify as pmd_bad().
>>>>         */
>>>> -    pmd_populate(mm, pmdp, pgtable);
>>>> -    pmd = READ_ONCE(*pmdp);
>>>> +    pmd_populate(args->mm, args->pmdp, args->start_ptep);
>>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>>        WARN_ON(pmd_bad(pmd));
>>>>    }
>>>>    @@ -1159,7 +1154,7 @@ static int __init debug_vm_pgtable(void)
>>>>        pgtable_t saved_ptep;
>>>>        pgprot_t prot;
>>>>        phys_addr_t paddr;
>>>> -    unsigned long vaddr, pmd_aligned;
>>>> +    unsigned long vaddr;
>>>>        unsigned long pud_aligned;
>>>>        spinlock_t *ptl = NULL;
>>>>        int idx, ret;
>>>> @@ -1194,7 +1189,6 @@ static int __init debug_vm_pgtable(void)
>>>>         */
>>>>        paddr = __pa_symbol(&start_kernel);
>>>>    -    pmd_aligned = (paddr & PMD_MASK) >> PAGE_SHIFT;
>>>
>>> Please dont drop these just yet and wait until [PATCH 11/12].
>>>
>>
>> Otherwise, it causes build warning: 'unused variable'.
> 
> Why ? Just the evaluation of 'pmd_aligned' from 'paddr' should
> be enough to avoid such warning. 'pmd_aligned' need not be used
> afterwards.
> 

It's not enough to avoid the warning. I apply the patches till
this one (PATCH[v3 08/12]) and have additional code to keep
@pmd_aligned, then I run into build warning as below:

diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c
index cec3cbf99a6b..961c9bb6fc7c 100644
--- a/mm/debug_vm_pgtable.c
+++ b/mm/debug_vm_pgtable.c
@@ -1154,7 +1154,7 @@ static int __init debug_vm_pgtable(void)
         pgtable_t saved_ptep;
         pgprot_t prot;
         phys_addr_t paddr;
-       unsigned long vaddr;
+       unsigned long vaddr, pmd_aligned;
         unsigned long pud_aligned;
         spinlock_t *ptl = NULL;
         int idx, ret;
@@ -1189,6 +1189,7 @@ static int __init debug_vm_pgtable(void)
          */
         paddr = __pa_symbol(&start_kernel);
  
+       pmd_aligned = (paddr & PMD_MASK) >> PAGE_SHIFT;
         pud_aligned = (paddr & PUD_MASK) >> PAGE_SHIFT;
  
         pgdp = pgd_offset(mm, vaddr);

[gwshan@gshan l]$ make W=1 mm/debug_vm_pgtable.o
      :
mm/debug_vm_pgtable.c: In function ‘debug_vm_pgtable’:
mm/debug_vm_pgtable.c:1157:23: warning: variable ‘pmd_aligned’ set but not used [-Wunused-but-set-variable]
  1157 |  unsigned long vaddr, pmd_aligned;
       |                       ^~~~~~~~~~~


By the way, 0-day is trying to build kernel with "W=1". It means the
build warnings will be reported by 0-day if the unused variables aren't
dropped from individual patches. It makes the review a bit harder. However,
we still need to keep each individual patch complete to make 'git bisect'
friendly.

Thanks,
Gavin
Anshuman Khandual July 23, 2021, 2:33 a.m. UTC | #5
On 7/23/21 6:30 AM, Gavin Shan wrote:
> Hi Anshuman,
> 
> On 7/22/21 5:11 PM, Anshuman Khandual wrote:
>> On 7/22/21 12:11 PM, Gavin Shan wrote:
>>> On 7/22/21 3:45 PM, Anshuman Khandual wrote:
>>>> On 7/19/21 6:36 PM, Gavin Shan wrote:
>>>>> This uses struct pgtable_debug_args in PMD modifying tests. The allocated
>>>>> huge page is used when set_pmd_at() is used. The corresponding tests
>>>>> are skipped if the huge page doesn't exist. Besides, the unused variable
>>>>> @pmd_aligned in debug_vm_pgtable() is dropped.
>>>>
>>>> Please dont drop @pmd_aligned just yet.
>>>>
>>>
>>> We need do so. Otherwise, there is build warning to complain
>>> something like 'unused variable' after this patch is applied.
>>>
>>>>>
>>>>> Signed-off-by: Gavin Shan <gshan@redhat.com>
>>>>> ---
>>>>>    mm/debug_vm_pgtable.c | 102 ++++++++++++++++++++----------------------
>>>>>    1 file changed, 48 insertions(+), 54 deletions(-)
>>>>>
>>>>> diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c
>>>>> index eb6dda88e0d9..cec3cbf99a6b 100644
>>>>> --- a/mm/debug_vm_pgtable.c
>>>>> +++ b/mm/debug_vm_pgtable.c
>>>>> @@ -213,54 +213,54 @@ static void __init pmd_basic_tests(struct pgtable_debug_args *args, int idx)
>>>>>        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, pgtable_t pgtable)
>>>>> +static void __init pmd_advanced_tests(struct pgtable_debug_args *args)
>>>>>    {
>>>>>        pmd_t pmd;
>>>>> +    unsigned long vaddr = (args->vaddr & HPAGE_PMD_MASK);
>>>>>          if (!has_transparent_hugepage())
>>>>>            return;
>>>>>          pr_debug("Validating PMD advanced\n");
>>>>> -    /* Align the address wrt HPAGE_PMD_SIZE */
>>>>> -    vaddr &= HPAGE_PMD_MASK;
>>>>
>>>> Please just leave these unchanged. If has_transparent_hugepage() evaluates
>>>> negative, it skips the masking operation. As mentioned earlier please avoid
>>>> changing the test in any manner during these transition patches.
>>>>
>>>
>>> Ok.
>>>
>>>>> +    if (args->pmd_pfn == ULONG_MAX) {
>>>>> +        pr_debug("%s: Skipped\n", __func__);
>>>>> +        return;
>>>>> +    }
>>>>
>>>> Just return. Please dont call out "Skipped".
>>>>
>>>
>>> Ok.
>>>
>>>>>    -    pgtable_trans_huge_deposit(mm, pmdp, pgtable);
>>>>> +    pgtable_trans_huge_deposit(args->mm, args->pmdp, args->start_ptep);
>>>>>    -    pmd = pfn_pmd(pfn, prot);
>>>>> -    set_pmd_at(mm, vaddr, pmdp, pmd);
>>>>> -    pmdp_set_wrprotect(mm, vaddr, pmdp);
>>>>> -    pmd = READ_ONCE(*pmdp);
>>>>> +    pmd = pfn_pmd(args->pmd_pfn, args->page_prot);
>>>>> +    set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
>>>>> +    pmdp_set_wrprotect(args->mm, vaddr, args->pmdp);
>>>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>>>        WARN_ON(pmd_write(pmd));
>>>>> -    pmdp_huge_get_and_clear(mm, vaddr, pmdp);
>>>>> -    pmd = READ_ONCE(*pmdp);
>>>>> +    pmdp_huge_get_and_clear(args->mm, vaddr, args->pmdp);
>>>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>>>        WARN_ON(!pmd_none(pmd));
>>>>>    -    pmd = pfn_pmd(pfn, prot);
>>>>> +    pmd = pfn_pmd(args->pmd_pfn, args->page_prot);
>>>>>        pmd = pmd_wrprotect(pmd);
>>>>>        pmd = pmd_mkclean(pmd);
>>>>> -    set_pmd_at(mm, vaddr, pmdp, pmd);
>>>>> +    set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
>>>>>        pmd = pmd_mkwrite(pmd);
>>>>>        pmd = pmd_mkdirty(pmd);
>>>>> -    pmdp_set_access_flags(vma, vaddr, pmdp, pmd, 1);
>>>>> -    pmd = READ_ONCE(*pmdp);
>>>>> +    pmdp_set_access_flags(args->vma, vaddr, args->pmdp, pmd, 1);
>>>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>>>        WARN_ON(!(pmd_write(pmd) && pmd_dirty(pmd)));
>>>>> -    pmdp_huge_get_and_clear_full(vma, vaddr, pmdp, 1);
>>>>> -    pmd = READ_ONCE(*pmdp);
>>>>> +    pmdp_huge_get_and_clear_full(args->vma, vaddr, args->pmdp, 1);
>>>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>>>        WARN_ON(!pmd_none(pmd));
>>>>>    -    pmd = pmd_mkhuge(pfn_pmd(pfn, prot));
>>>>> +    pmd = pmd_mkhuge(pfn_pmd(args->pmd_pfn, args->page_prot));
>>>>>        pmd = pmd_mkyoung(pmd);
>>>>> -    set_pmd_at(mm, vaddr, pmdp, pmd);
>>>>> -    pmdp_test_and_clear_young(vma, vaddr, pmdp);
>>>>> -    pmd = READ_ONCE(*pmdp);
>>>>> +    set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
>>>>> +    pmdp_test_and_clear_young(args->vma, vaddr, args->pmdp);
>>>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>>>        WARN_ON(pmd_young(pmd));
>>>>>          /*  Clear the pte entries  */
>>>>> -    pmdp_huge_get_and_clear(mm, vaddr, pmdp);
>>>>> -    pgtable = pgtable_trans_huge_withdraw(mm, pmdp);
>>>>> +    pmdp_huge_get_and_clear(args->mm, vaddr, args->pmdp);
>>>>> +    pgtable_trans_huge_withdraw(args->mm, args->pmdp);
>>>>>    }
>>>>>      static void __init pmd_leaf_tests(struct pgtable_debug_args *args)
>>>>> @@ -417,12 +417,7 @@ static void __init pud_leaf_tests(struct pgtable_debug_args *args) { }
>>>>>    #else  /* !CONFIG_TRANSPARENT_HUGEPAGE */
>>>>>    static void __init pmd_basic_tests(struct pgtable_debug_args *args, int idx) { }
>>>>>    static void __init pud_basic_tests(struct pgtable_debug_args *args, int idx) { }
>>>>> -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, pgtable_t pgtable)
>>>>> -{
>>>>> -}
>>>>> +static void __init pmd_advanced_tests(struct pgtable_debug_args *args) { }
>>>>>    static void __init pud_advanced_tests(struct mm_struct *mm,
>>>>>                          struct vm_area_struct *vma, pud_t *pudp,
>>>>>                          unsigned long pfn, unsigned long vaddr,
>>>>> @@ -435,11 +430,11 @@ static void __init pmd_savedwrite_tests(struct pgtable_debug_args *args) { }
>>>>>    #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
>>>>>      #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
>>>>> -static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
>>>>> +static void __init pmd_huge_tests(struct pgtable_debug_args *args)
>>>>>    {
>>>>>        pmd_t pmd;
>>>>>    -    if (!arch_vmap_pmd_supported(prot))
>>>>> +    if (!arch_vmap_pmd_supported(args->page_prot))
>>>>>            return;
>>>>>          pr_debug("Validating PMD huge\n");
>>>>> @@ -447,10 +442,11 @@ static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
>>>>>         * X86 defined pmd_set_huge() verifies that the given
>>>>>         * PMD is not a populated non-leaf entry.
>>>>>         */
>>>>> -    WRITE_ONCE(*pmdp, __pmd(0));
>>>>> -    WARN_ON(!pmd_set_huge(pmdp, __pfn_to_phys(pfn), prot));
>>>>> -    WARN_ON(!pmd_clear_huge(pmdp));
>>>>> -    pmd = READ_ONCE(*pmdp);
>>>>> +    WRITE_ONCE(*(args->pmdp), __pmd(0));
>>>>
>>>> Possible extra braces.
>>>>
>>>
>>> Will drop it in v4, thanks!
>>>
>>>>> +    WARN_ON(!pmd_set_huge(args->pmdp, __pfn_to_phys(args->fixed_pmd_pfn),
>>>>> +                  args->page_prot));
>>>>
>>>> Dont break the line.
>>>>
>>>
>>> Ok.
>>>
>>>>> +    WARN_ON(!pmd_clear_huge(args->pmdp));
>>>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>>>        WARN_ON(!pmd_none(pmd));
>>>>>    }
>>>>>    @@ -473,7 +469,7 @@ static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot)
>>>>>        WARN_ON(!pud_none(pud));
>>>>>    }
>>>>>    #else /* !CONFIG_HAVE_ARCH_HUGE_VMAP */
>>>>> -static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot) { }
>>>>> +static void __init pmd_huge_tests(struct pgtable_debug_args *args) { }
>>>>>    static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot) { }
>>>>>    #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
>>>>>    @@ -640,20 +636,19 @@ static void __init pte_clear_tests(struct pgtable_debug_args *args)
>>>>>        WARN_ON(!pte_none(pte));
>>>>>    }
>>>>>    -static void __init pmd_clear_tests(struct mm_struct *mm, pmd_t *pmdp)
>>>>> +static void __init pmd_clear_tests(struct pgtable_debug_args *args)
>>>>>    {
>>>>> -    pmd_t pmd = READ_ONCE(*pmdp);
>>>>> +    pmd_t pmd = READ_ONCE(*(args->pmdp));
>>>>>          pr_debug("Validating PMD clear\n");
>>>>>        pmd = __pmd(pmd_val(pmd) | RANDOM_ORVALUE);
>>>>> -    WRITE_ONCE(*pmdp, pmd);
>>>>> -    pmd_clear(pmdp);
>>>>> -    pmd = READ_ONCE(*pmdp);
>>>>> +    WRITE_ONCE(*(args->pmdp), pmd);
>>>>> +    pmd_clear(args->pmdp);
>>>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>>>        WARN_ON(!pmd_none(pmd));
>>>>>    }
>>>>>    -static void __init pmd_populate_tests(struct mm_struct *mm, pmd_t *pmdp,
>>>>> -                      pgtable_t pgtable)
>>>>> +static void __init pmd_populate_tests(struct pgtable_debug_args *args)
>>>>>    {
>>>>>        pmd_t pmd;
>>>>>    @@ -662,8 +657,8 @@ static void __init pmd_populate_tests(struct mm_struct *mm, pmd_t *pmdp,
>>>>>         * This entry points to next level page table page.
>>>>>         * Hence this must not qualify as pmd_bad().
>>>>>         */
>>>>> -    pmd_populate(mm, pmdp, pgtable);
>>>>> -    pmd = READ_ONCE(*pmdp);
>>>>> +    pmd_populate(args->mm, args->pmdp, args->start_ptep);
>>>>> +    pmd = READ_ONCE(*(args->pmdp));
>>>>>        WARN_ON(pmd_bad(pmd));
>>>>>    }
>>>>>    @@ -1159,7 +1154,7 @@ static int __init debug_vm_pgtable(void)
>>>>>        pgtable_t saved_ptep;
>>>>>        pgprot_t prot;
>>>>>        phys_addr_t paddr;
>>>>> -    unsigned long vaddr, pmd_aligned;
>>>>> +    unsigned long vaddr;
>>>>>        unsigned long pud_aligned;
>>>>>        spinlock_t *ptl = NULL;
>>>>>        int idx, ret;
>>>>> @@ -1194,7 +1189,6 @@ static int __init debug_vm_pgtable(void)
>>>>>         */
>>>>>        paddr = __pa_symbol(&start_kernel);
>>>>>    -    pmd_aligned = (paddr & PMD_MASK) >> PAGE_SHIFT;
>>>>
>>>> Please dont drop these just yet and wait until [PATCH 11/12].
>>>>
>>>
>>> Otherwise, it causes build warning: 'unused variable'.
>>
>> Why ? Just the evaluation of 'pmd_aligned' from 'paddr' should
>> be enough to avoid such warning. 'pmd_aligned' need not be used
>> afterwards.
>>
> 
> It's not enough to avoid the warning. I apply the patches till
> this one (PATCH[v3 08/12]) and have additional code to keep
> @pmd_aligned, then I run into build warning as below:
> 
> diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c
> index cec3cbf99a6b..961c9bb6fc7c 100644
> --- a/mm/debug_vm_pgtable.c
> +++ b/mm/debug_vm_pgtable.c
> @@ -1154,7 +1154,7 @@ static int __init debug_vm_pgtable(void)
>         pgtable_t saved_ptep;
>         pgprot_t prot;
>         phys_addr_t paddr;
> -       unsigned long vaddr;
> +       unsigned long vaddr, pmd_aligned;
>         unsigned long pud_aligned;
>         spinlock_t *ptl = NULL;
>         int idx, ret;
> @@ -1189,6 +1189,7 @@ static int __init debug_vm_pgtable(void)
>          */
>         paddr = __pa_symbol(&start_kernel);
>  
> +       pmd_aligned = (paddr & PMD_MASK) >> PAGE_SHIFT;
>         pud_aligned = (paddr & PUD_MASK) >> PAGE_SHIFT;
>  
>         pgdp = pgd_offset(mm, vaddr);
> 
> [gwshan@gshan l]$ make W=1 mm/debug_vm_pgtable.o
>      :
> mm/debug_vm_pgtable.c: In function ‘debug_vm_pgtable’:
> mm/debug_vm_pgtable.c:1157:23: warning: variable ‘pmd_aligned’ set but not used [-Wunused-but-set-variable]
>  1157 |  unsigned long vaddr, pmd_aligned;
>       |                       ^~~~~~~~~~~
> 
> 
> By the way, 0-day is trying to build kernel with "W=1". It means the
> build warnings will be reported by 0-day if the unused variables aren't
> dropped from individual patches. It makes the review a bit harder. However,

It is not about keeping the review process simple. But rather the proposed
patch changing as much what is really required and nothing else.

> we still need to keep each individual patch complete to make 'git bisect'
> friendly.

With W=1 if this throws up a build error, I guess we dont have choice here.
We need to keep the build clean for each individual patch applies.
diff mbox series

Patch

diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c
index eb6dda88e0d9..cec3cbf99a6b 100644
--- a/mm/debug_vm_pgtable.c
+++ b/mm/debug_vm_pgtable.c
@@ -213,54 +213,54 @@  static void __init pmd_basic_tests(struct pgtable_debug_args *args, int idx)
 	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, pgtable_t pgtable)
+static void __init pmd_advanced_tests(struct pgtable_debug_args *args)
 {
 	pmd_t pmd;
+	unsigned long vaddr = (args->vaddr & HPAGE_PMD_MASK);
 
 	if (!has_transparent_hugepage())
 		return;
 
 	pr_debug("Validating PMD advanced\n");
-	/* Align the address wrt HPAGE_PMD_SIZE */
-	vaddr &= HPAGE_PMD_MASK;
+	if (args->pmd_pfn == ULONG_MAX) {
+		pr_debug("%s: Skipped\n", __func__);
+		return;
+	}
 
-	pgtable_trans_huge_deposit(mm, pmdp, pgtable);
+	pgtable_trans_huge_deposit(args->mm, args->pmdp, args->start_ptep);
 
-	pmd = pfn_pmd(pfn, prot);
-	set_pmd_at(mm, vaddr, pmdp, pmd);
-	pmdp_set_wrprotect(mm, vaddr, pmdp);
-	pmd = READ_ONCE(*pmdp);
+	pmd = pfn_pmd(args->pmd_pfn, args->page_prot);
+	set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
+	pmdp_set_wrprotect(args->mm, vaddr, args->pmdp);
+	pmd = READ_ONCE(*(args->pmdp));
 	WARN_ON(pmd_write(pmd));
-	pmdp_huge_get_and_clear(mm, vaddr, pmdp);
-	pmd = READ_ONCE(*pmdp);
+	pmdp_huge_get_and_clear(args->mm, vaddr, args->pmdp);
+	pmd = READ_ONCE(*(args->pmdp));
 	WARN_ON(!pmd_none(pmd));
 
-	pmd = pfn_pmd(pfn, prot);
+	pmd = pfn_pmd(args->pmd_pfn, args->page_prot);
 	pmd = pmd_wrprotect(pmd);
 	pmd = pmd_mkclean(pmd);
-	set_pmd_at(mm, vaddr, pmdp, pmd);
+	set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
 	pmd = pmd_mkwrite(pmd);
 	pmd = pmd_mkdirty(pmd);
-	pmdp_set_access_flags(vma, vaddr, pmdp, pmd, 1);
-	pmd = READ_ONCE(*pmdp);
+	pmdp_set_access_flags(args->vma, vaddr, args->pmdp, pmd, 1);
+	pmd = READ_ONCE(*(args->pmdp));
 	WARN_ON(!(pmd_write(pmd) && pmd_dirty(pmd)));
-	pmdp_huge_get_and_clear_full(vma, vaddr, pmdp, 1);
-	pmd = READ_ONCE(*pmdp);
+	pmdp_huge_get_and_clear_full(args->vma, vaddr, args->pmdp, 1);
+	pmd = READ_ONCE(*(args->pmdp));
 	WARN_ON(!pmd_none(pmd));
 
-	pmd = pmd_mkhuge(pfn_pmd(pfn, prot));
+	pmd = pmd_mkhuge(pfn_pmd(args->pmd_pfn, args->page_prot));
 	pmd = pmd_mkyoung(pmd);
-	set_pmd_at(mm, vaddr, pmdp, pmd);
-	pmdp_test_and_clear_young(vma, vaddr, pmdp);
-	pmd = READ_ONCE(*pmdp);
+	set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
+	pmdp_test_and_clear_young(args->vma, vaddr, args->pmdp);
+	pmd = READ_ONCE(*(args->pmdp));
 	WARN_ON(pmd_young(pmd));
 
 	/*  Clear the pte entries  */
-	pmdp_huge_get_and_clear(mm, vaddr, pmdp);
-	pgtable = pgtable_trans_huge_withdraw(mm, pmdp);
+	pmdp_huge_get_and_clear(args->mm, vaddr, args->pmdp);
+	pgtable_trans_huge_withdraw(args->mm, args->pmdp);
 }
 
 static void __init pmd_leaf_tests(struct pgtable_debug_args *args)
@@ -417,12 +417,7 @@  static void __init pud_leaf_tests(struct pgtable_debug_args *args) { }
 #else  /* !CONFIG_TRANSPARENT_HUGEPAGE */
 static void __init pmd_basic_tests(struct pgtable_debug_args *args, int idx) { }
 static void __init pud_basic_tests(struct pgtable_debug_args *args, int idx) { }
-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, pgtable_t pgtable)
-{
-}
+static void __init pmd_advanced_tests(struct pgtable_debug_args *args) { }
 static void __init pud_advanced_tests(struct mm_struct *mm,
 				      struct vm_area_struct *vma, pud_t *pudp,
 				      unsigned long pfn, unsigned long vaddr,
@@ -435,11 +430,11 @@  static void __init pmd_savedwrite_tests(struct pgtable_debug_args *args) { }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
 #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
-static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
+static void __init pmd_huge_tests(struct pgtable_debug_args *args)
 {
 	pmd_t pmd;
 
-	if (!arch_vmap_pmd_supported(prot))
+	if (!arch_vmap_pmd_supported(args->page_prot))
 		return;
 
 	pr_debug("Validating PMD huge\n");
@@ -447,10 +442,11 @@  static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
 	 * X86 defined pmd_set_huge() verifies that the given
 	 * PMD is not a populated non-leaf entry.
 	 */
-	WRITE_ONCE(*pmdp, __pmd(0));
-	WARN_ON(!pmd_set_huge(pmdp, __pfn_to_phys(pfn), prot));
-	WARN_ON(!pmd_clear_huge(pmdp));
-	pmd = READ_ONCE(*pmdp);
+	WRITE_ONCE(*(args->pmdp), __pmd(0));
+	WARN_ON(!pmd_set_huge(args->pmdp, __pfn_to_phys(args->fixed_pmd_pfn),
+			      args->page_prot));
+	WARN_ON(!pmd_clear_huge(args->pmdp));
+	pmd = READ_ONCE(*(args->pmdp));
 	WARN_ON(!pmd_none(pmd));
 }
 
@@ -473,7 +469,7 @@  static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot)
 	WARN_ON(!pud_none(pud));
 }
 #else /* !CONFIG_HAVE_ARCH_HUGE_VMAP */
-static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot) { }
+static void __init pmd_huge_tests(struct pgtable_debug_args *args) { }
 static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot) { }
 #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
 
@@ -640,20 +636,19 @@  static void __init pte_clear_tests(struct pgtable_debug_args *args)
 	WARN_ON(!pte_none(pte));
 }
 
-static void __init pmd_clear_tests(struct mm_struct *mm, pmd_t *pmdp)
+static void __init pmd_clear_tests(struct pgtable_debug_args *args)
 {
-	pmd_t pmd = READ_ONCE(*pmdp);
+	pmd_t pmd = READ_ONCE(*(args->pmdp));
 
 	pr_debug("Validating PMD clear\n");
 	pmd = __pmd(pmd_val(pmd) | RANDOM_ORVALUE);
-	WRITE_ONCE(*pmdp, pmd);
-	pmd_clear(pmdp);
-	pmd = READ_ONCE(*pmdp);
+	WRITE_ONCE(*(args->pmdp), pmd);
+	pmd_clear(args->pmdp);
+	pmd = READ_ONCE(*(args->pmdp));
 	WARN_ON(!pmd_none(pmd));
 }
 
-static void __init pmd_populate_tests(struct mm_struct *mm, pmd_t *pmdp,
-				      pgtable_t pgtable)
+static void __init pmd_populate_tests(struct pgtable_debug_args *args)
 {
 	pmd_t pmd;
 
@@ -662,8 +657,8 @@  static void __init pmd_populate_tests(struct mm_struct *mm, pmd_t *pmdp,
 	 * This entry points to next level page table page.
 	 * Hence this must not qualify as pmd_bad().
 	 */
-	pmd_populate(mm, pmdp, pgtable);
-	pmd = READ_ONCE(*pmdp);
+	pmd_populate(args->mm, args->pmdp, args->start_ptep);
+	pmd = READ_ONCE(*(args->pmdp));
 	WARN_ON(pmd_bad(pmd));
 }
 
@@ -1159,7 +1154,7 @@  static int __init debug_vm_pgtable(void)
 	pgtable_t saved_ptep;
 	pgprot_t prot;
 	phys_addr_t paddr;
-	unsigned long vaddr, pmd_aligned;
+	unsigned long vaddr;
 	unsigned long pud_aligned;
 	spinlock_t *ptl = NULL;
 	int idx, ret;
@@ -1194,7 +1189,6 @@  static int __init debug_vm_pgtable(void)
 	 */
 	paddr = __pa_symbol(&start_kernel);
 
-	pmd_aligned = (paddr & PMD_MASK) >> PAGE_SHIFT;
 	pud_aligned = (paddr & PUD_MASK) >> PAGE_SHIFT;
 
 	pgdp = pgd_offset(mm, vaddr);
@@ -1281,11 +1275,11 @@  static int __init debug_vm_pgtable(void)
 	pte_advanced_tests(&args);
 	spin_unlock(ptl);
 
-	ptl = pmd_lock(mm, pmdp);
-	pmd_clear_tests(mm, pmdp);
-	pmd_advanced_tests(mm, vma, pmdp, pmd_aligned, vaddr, prot, saved_ptep);
-	pmd_huge_tests(pmdp, pmd_aligned, prot);
-	pmd_populate_tests(mm, pmdp, saved_ptep);
+	ptl = pmd_lock(args.mm, args.pmdp);
+	pmd_clear_tests(&args);
+	pmd_advanced_tests(&args);
+	pmd_huge_tests(&args);
+	pmd_populate_tests(&args);
 	spin_unlock(ptl);
 
 	ptl = pud_lock(mm, pudp);