Make the arm64 PMD/PUD PFN helpers use PTE-level pgprot_t as the basic format. pfn_pmd() and pfn_pud() now translate PTE-level attributes into block entries. pmd_pgprot() and pud_pgprot() translate block descriptor attributes back into PTE-level attributes. Remove mk_pmd_sect_prot() and mk_pud_sect_prot(). Signed-off-by: Yin Tirui --- arch/arm64/include/asm/pgtable.h | 48 ++++++++++++++++++++++---------- arch/arm64/mm/mmu.c | 4 +-- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 4dfa42b7d053..c3ee12e14f86 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -511,16 +511,6 @@ static inline pmd_t pte_pmd(pte_t pte) return __pmd(pte_val(pte)); } -static inline pgprot_t mk_pud_sect_prot(pgprot_t prot) -{ - return __pgprot((pgprot_val(prot) & ~PUD_TYPE_MASK) | PUD_TYPE_SECT); -} - -static inline pgprot_t mk_pmd_sect_prot(pgprot_t prot) -{ - return __pgprot((pgprot_val(prot) & ~PMD_TYPE_MASK) | PMD_TYPE_SECT); -} - static inline pte_t pte_swp_mkexclusive(pte_t pte) { return set_pte_bit(pte, __pgprot(PTE_SWP_EXCLUSIVE)); @@ -628,7 +618,13 @@ static inline pmd_t pmd_mkspecial(pmd_t pmd) #define __pmd_to_phys(pmd) __pte_to_phys(pmd_pte(pmd)) #define __phys_to_pmd_val(phys) __phys_to_pte_val(phys) #define pmd_pfn(pmd) ((__pmd_to_phys(pmd) & PMD_MASK) >> PAGE_SHIFT) -#define pfn_pmd(pfn,prot) __pmd(__phys_to_pmd_val((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)) +static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t prot) +{ + pmd_t pmd = __pmd(__phys_to_pmd_val((phys_addr_t)pfn << PAGE_SHIFT) | + pgprot_val(prot)); + + return pmd_mkhuge(pmd); +} #define pud_young(pud) pte_young(pud_pte(pud)) #define pud_mkyoung(pud) pte_pud(pte_mkyoung(pud_pte(pud))) @@ -652,22 +648,46 @@ static inline pud_t pud_mkhuge(pud_t pud) #define __pud_to_phys(pud) __pte_to_phys(pud_pte(pud)) #define __phys_to_pud_val(phys) __phys_to_pte_val(phys) #define pud_pfn(pud) ((__pud_to_phys(pud) & PUD_MASK) >> PAGE_SHIFT) -#define pfn_pud(pfn,prot) __pud(__phys_to_pud_val((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)) +static inline pud_t pfn_pud(unsigned long pfn, pgprot_t prot) +{ + pud_t pud = __pud(__phys_to_pud_val((phys_addr_t)pfn << PAGE_SHIFT) | + pgprot_val(prot)); + + return pud_mkhuge(pud); +} #define pmd_pgprot pmd_pgprot static inline pgprot_t pmd_pgprot(pmd_t pmd) { unsigned long pfn = pmd_pfn(pmd); + pmdval_t protval = pmd_val(pmd) ^ + __phys_to_pmd_val((phys_addr_t)pfn << PAGE_SHIFT); + + /* + * pgprot_t represents PTE-level attributes. Convert the PMD + * block descriptor type into a PTE page descriptor type. + */ + pmdval_t mask = PMD_TYPE_MASK & ~PTE_VALID; + pmdval_t val = PTE_TYPE_PAGE & ~PTE_VALID; - return __pgprot(pmd_val(pfn_pmd(pfn, __pgprot(0))) ^ pmd_val(pmd)); + return __pgprot((protval & ~mask) | val); } #define pud_pgprot pud_pgprot static inline pgprot_t pud_pgprot(pud_t pud) { unsigned long pfn = pud_pfn(pud); + pudval_t protval = pud_val(pud) ^ + __phys_to_pud_val((phys_addr_t)pfn << PAGE_SHIFT); + + /* + * pgprot_t represents PTE-level attributes. Convert the PUD + * block descriptor type into a PTE page descriptor type. + */ + pudval_t mask = PUD_TYPE_MASK & ~PTE_VALID; + pudval_t val = PTE_TYPE_PAGE & ~PTE_VALID; - return __pgprot(pud_val(pfn_pud(pfn, __pgprot(0))) ^ pud_val(pud)); + return __pgprot((protval & ~mask) | val); } static inline void __set_ptes_anysz(struct mm_struct *mm, unsigned long addr, diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index e5a42b7a0160..2dd99d595f19 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -1816,7 +1816,7 @@ void vmemmap_free(unsigned long start, unsigned long end, int pud_set_huge(pud_t *pudp, phys_addr_t phys, pgprot_t prot) { - pud_t new_pud = pfn_pud(__phys_to_pfn(phys), mk_pud_sect_prot(prot)); + pud_t new_pud = pfn_pud(__phys_to_pfn(phys), prot); /* Only allow permission changes for now */ if (!pgattr_change_is_safe(READ_ONCE(pud_val(*pudp)), @@ -1830,7 +1830,7 @@ int pud_set_huge(pud_t *pudp, phys_addr_t phys, pgprot_t prot) int pmd_set_huge(pmd_t *pmdp, phys_addr_t phys, pgprot_t prot) { - pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), mk_pmd_sect_prot(prot)); + pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), prot); /* Only allow permission changes for now */ if (!pgattr_change_is_safe(READ_ONCE(pmd_val(*pmdp)), -- 2.43.0