[PATCH 02/11] riscv: mm: Increment PFN in place when splitting mappings

Samuel Holland posted 11 patches 3 weeks, 1 day ago
[PATCH 02/11] riscv: mm: Increment PFN in place when splitting mappings
Posted by Samuel Holland 3 weeks, 1 day ago
The current code separates page table entry values into a PFN and a
pgprot_t before incrementing the PFN and combining the two parts using
pfn_pXX(). On some hardware with custom page table formats or memory
aliases, the pfn_pXX() functions need to transform the PTE value, so
these functions would need to apply the opposite transformation when
breaking apart the PTE value.

However, both transformations can be avoided by incrementing the PFN in
place, as done by pte_advance_pfn() and set_ptes().

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
---

 arch/riscv/mm/pageattr.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/arch/riscv/mm/pageattr.c b/arch/riscv/mm/pageattr.c
index 271d01a5ba4d..335060adc1a6 100644
--- a/arch/riscv/mm/pageattr.c
+++ b/arch/riscv/mm/pageattr.c
@@ -109,9 +109,8 @@ static int __split_linear_mapping_pmd(pud_t *pudp,
 			continue;
 
 		if (pmd_leaf(pmdp_get(pmdp))) {
+			pte_t pte = pmd_pte(pmdp_get(pmdp));
 			struct page *pte_page;
-			unsigned long pfn = _pmd_pfn(pmdp_get(pmdp));
-			pgprot_t prot = __pgprot(pmd_val(pmdp_get(pmdp)) & ~_PAGE_PFN_MASK);
 			pte_t *ptep_new;
 			int i;
 
@@ -121,7 +120,7 @@ static int __split_linear_mapping_pmd(pud_t *pudp,
 
 			ptep_new = (pte_t *)page_address(pte_page);
 			for (i = 0; i < PTRS_PER_PTE; ++i, ++ptep_new)
-				set_pte(ptep_new, pfn_pte(pfn + i, prot));
+				set_pte(ptep_new, pte_advance_pfn(pte, i));
 
 			smp_wmb();
 
@@ -149,9 +148,8 @@ static int __split_linear_mapping_pud(p4d_t *p4dp,
 			continue;
 
 		if (pud_leaf(pudp_get(pudp))) {
+			pmd_t pmd = __pmd(pud_val(pudp_get(pudp)));
 			struct page *pmd_page;
-			unsigned long pfn = _pud_pfn(pudp_get(pudp));
-			pgprot_t prot = __pgprot(pud_val(pudp_get(pudp)) & ~_PAGE_PFN_MASK);
 			pmd_t *pmdp_new;
 			int i;
 
@@ -162,7 +160,8 @@ static int __split_linear_mapping_pud(p4d_t *p4dp,
 			pmdp_new = (pmd_t *)page_address(pmd_page);
 			for (i = 0; i < PTRS_PER_PMD; ++i, ++pmdp_new)
 				set_pmd(pmdp_new,
-					pfn_pmd(pfn + ((i * PMD_SIZE) >> PAGE_SHIFT), prot));
+					__pmd(pmd_val(pmd) +
+					      (i << (PMD_SHIFT - PAGE_SHIFT + PFN_PTE_SHIFT))));
 
 			smp_wmb();
 
@@ -198,9 +197,8 @@ static int __split_linear_mapping_p4d(pgd_t *pgdp,
 			continue;
 
 		if (p4d_leaf(p4dp_get(p4dp))) {
+			pud_t pud = __pud(p4d_val(p4dp_get(p4dp)));
 			struct page *pud_page;
-			unsigned long pfn = _p4d_pfn(p4dp_get(p4dp));
-			pgprot_t prot = __pgprot(p4d_val(p4dp_get(p4dp)) & ~_PAGE_PFN_MASK);
 			pud_t *pudp_new;
 			int i;
 
@@ -215,7 +213,8 @@ static int __split_linear_mapping_p4d(pgd_t *pgdp,
 			pudp_new = (pud_t *)page_address(pud_page);
 			for (i = 0; i < PTRS_PER_PUD; ++i, ++pudp_new)
 				set_pud(pudp_new,
-					pfn_pud(pfn + ((i * PUD_SIZE) >> PAGE_SHIFT), prot));
+					__pud(pud_val(pud) +
+					      (i << (PUD_SHIFT - PAGE_SHIFT + PFN_PTE_SHIFT))));
 
 			/*
 			 * Make sure the pud filling is not reordered with the
-- 
2.45.1
Re: [PATCH 02/11] riscv: mm: Increment PFN in place when splitting mappings
Posted by Alexandre Ghiti 2 weeks, 5 days ago
Hi Samuel,

On 02/11/2024 01:07, Samuel Holland wrote:
> The current code separates page table entry values into a PFN and a
> pgprot_t before incrementing the PFN and combining the two parts using
> pfn_pXX(). On some hardware with custom page table formats or memory
> aliases, the pfn_pXX() functions need to transform the PTE value, so
> these functions would need to apply the opposite transformation when
> breaking apart the PTE value.
>
> However, both transformations can be avoided by incrementing the PFN in
> place, as done by pte_advance_pfn() and set_ptes().
>
> Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
> ---
>
>   arch/riscv/mm/pageattr.c | 17 ++++++++---------
>   1 file changed, 8 insertions(+), 9 deletions(-)
>
> diff --git a/arch/riscv/mm/pageattr.c b/arch/riscv/mm/pageattr.c
> index 271d01a5ba4d..335060adc1a6 100644
> --- a/arch/riscv/mm/pageattr.c
> +++ b/arch/riscv/mm/pageattr.c
> @@ -109,9 +109,8 @@ static int __split_linear_mapping_pmd(pud_t *pudp,
>   			continue;
>   
>   		if (pmd_leaf(pmdp_get(pmdp))) {
> +			pte_t pte = pmd_pte(pmdp_get(pmdp));
>   			struct page *pte_page;
> -			unsigned long pfn = _pmd_pfn(pmdp_get(pmdp));
> -			pgprot_t prot = __pgprot(pmd_val(pmdp_get(pmdp)) & ~_PAGE_PFN_MASK);
>   			pte_t *ptep_new;
>   			int i;
>   
> @@ -121,7 +120,7 @@ static int __split_linear_mapping_pmd(pud_t *pudp,
>   
>   			ptep_new = (pte_t *)page_address(pte_page);
>   			for (i = 0; i < PTRS_PER_PTE; ++i, ++ptep_new)
> -				set_pte(ptep_new, pfn_pte(pfn + i, prot));
> +				set_pte(ptep_new, pte_advance_pfn(pte, i));
>   
>   			smp_wmb();
>   
> @@ -149,9 +148,8 @@ static int __split_linear_mapping_pud(p4d_t *p4dp,
>   			continue;
>   
>   		if (pud_leaf(pudp_get(pudp))) {
> +			pmd_t pmd = __pmd(pud_val(pudp_get(pudp)));


Nit: You could use pud_pte() here.


>   			struct page *pmd_page;
> -			unsigned long pfn = _pud_pfn(pudp_get(pudp));
> -			pgprot_t prot = __pgprot(pud_val(pudp_get(pudp)) & ~_PAGE_PFN_MASK);
>   			pmd_t *pmdp_new;
>   			int i;
>   
> @@ -162,7 +160,8 @@ static int __split_linear_mapping_pud(p4d_t *p4dp,
>   			pmdp_new = (pmd_t *)page_address(pmd_page);
>   			for (i = 0; i < PTRS_PER_PMD; ++i, ++pmdp_new)
>   				set_pmd(pmdp_new,
> -					pfn_pmd(pfn + ((i * PMD_SIZE) >> PAGE_SHIFT), prot));
> +					__pmd(pmd_val(pmd) +
> +					      (i << (PMD_SHIFT - PAGE_SHIFT + PFN_PTE_SHIFT))));


Nit: Here you could use pte_advance_pfn(pmd, i << (PMD_SHIFT - PAGE_SHIFT))


>   
>   			smp_wmb();
>   
> @@ -198,9 +197,8 @@ static int __split_linear_mapping_p4d(pgd_t *pgdp,
>   			continue;
>   
>   		if (p4d_leaf(p4dp_get(p4dp))) {
> +			pud_t pud = __pud(p4d_val(p4dp_get(p4dp)));
>   			struct page *pud_page;
> -			unsigned long pfn = _p4d_pfn(p4dp_get(p4dp));
> -			pgprot_t prot = __pgprot(p4d_val(p4dp_get(p4dp)) & ~_PAGE_PFN_MASK);
>   			pud_t *pudp_new;
>   			int i;
>   
> @@ -215,7 +213,8 @@ static int __split_linear_mapping_p4d(pgd_t *pgdp,
>   			pudp_new = (pud_t *)page_address(pud_page);
>   			for (i = 0; i < PTRS_PER_PUD; ++i, ++pudp_new)
>   				set_pud(pudp_new,
> -					pfn_pud(pfn + ((i * PUD_SIZE) >> PAGE_SHIFT), prot));
> +					__pud(pud_val(pud) +
> +					      (i << (PUD_SHIFT - PAGE_SHIFT + PFN_PTE_SHIFT))));


Nit: Ditto


>   
>   			/*
>   			 * Make sure the pud filling is not reordered with the


Other than the nits (which are up to you), you can add:

Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com>

Thanks,

Alex