Skip to content

Commit 3169fc9

Browse files
mrutland-armAlex Shi
authored andcommitted
arm64: mm: add functions to walk page tables by PA
To allow us to walk tables allocated into the fixmap, we need to acquire the physical address of a page, rather than the virtual address in the linear map. This patch adds new p??_page_paddr and p??_offset_phys functions to acquire the physical address of a next-level table, and changes p??_offset* into macros which simply convert this to a linear map VA. This renders p??_page_vaddr unused, and hence they are removed. At the pgd level, a new pgd_offset_raw function is added to find the relevant PGD entry given the base of a PGD and a virtual address. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Tested-by: Jeremy Linton <jeremy.linton@arm.com> Cc: Laura Abbott <labbott@fedoraproject.org> Cc: Will Deacon <will.deacon@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> (cherry picked from commit dca56dca7124709f3dfca81afe61b4d98eb9cacf) Signed-off-by: Alex Shi <alex.shi@linaro.org>
1 parent 03f3f03 commit 3169fc9

1 file changed

Lines changed: 23 additions & 16 deletions

File tree

arch/arm64/include/asm/pgtable.h

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -415,15 +415,16 @@ static inline void pmd_clear(pmd_t *pmdp)
415415
set_pmd(pmdp, __pmd(0));
416416
}
417417

418-
static inline pte_t *pmd_page_vaddr(pmd_t pmd)
418+
static inline phys_addr_t pmd_page_paddr(pmd_t pmd)
419419
{
420-
return __va(pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK);
420+
return pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK;
421421
}
422422

423423
/* Find an entry in the third-level page table. */
424424
#define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
425425

426-
#define pte_offset_kernel(dir,addr) (pmd_page_vaddr(*(dir)) + pte_index(addr))
426+
#define pte_offset_phys(dir,addr) (pmd_page_paddr(*(dir)) + pte_index(addr) * sizeof(pte_t))
427+
#define pte_offset_kernel(dir,addr) ((pte_t *)__va(pte_offset_phys((dir), (addr))))
427428

428429
#define pte_offset_map(dir,addr) pte_offset_kernel((dir), (addr))
429430
#define pte_offset_map_nested(dir,addr) pte_offset_kernel((dir), (addr))
@@ -458,21 +459,23 @@ static inline void pud_clear(pud_t *pudp)
458459
set_pud(pudp, __pud(0));
459460
}
460461

461-
static inline pmd_t *pud_page_vaddr(pud_t pud)
462+
static inline phys_addr_t pud_page_paddr(pud_t pud)
462463
{
463-
return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK);
464+
return pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK;
464465
}
465466

466467
/* Find an entry in the second-level page table. */
467468
#define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
468469

469-
static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
470-
{
471-
return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr);
472-
}
470+
#define pmd_offset_phys(dir, addr) (pud_page_paddr(*(dir)) + pmd_index(addr) * sizeof(pmd_t))
471+
#define pmd_offset(dir, addr) ((pmd_t *)__va(pmd_offset_phys((dir), (addr))))
473472

474473
#define pud_page(pud) pfn_to_page(__phys_to_pfn(pud_val(pud) & PHYS_MASK))
475474

475+
#else
476+
477+
#define pud_page_paddr(pud) ({ BUILD_BUG(); 0; })
478+
476479
#endif /* CONFIG_PGTABLE_LEVELS > 2 */
477480

478481
#if CONFIG_PGTABLE_LEVELS > 3
@@ -494,29 +497,33 @@ static inline void pgd_clear(pgd_t *pgdp)
494497
set_pgd(pgdp, __pgd(0));
495498
}
496499

497-
static inline pud_t *pgd_page_vaddr(pgd_t pgd)
500+
static inline phys_addr_t pgd_page_paddr(pgd_t pgd)
498501
{
499-
return __va(pgd_val(pgd) & PHYS_MASK & (s32)PAGE_MASK);
502+
return pgd_val(pgd) & PHYS_MASK & (s32)PAGE_MASK;
500503
}
501504

502505
/* Find an entry in the frst-level page table. */
503506
#define pud_index(addr) (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
504507

505-
static inline pud_t *pud_offset(pgd_t *pgd, unsigned long addr)
506-
{
507-
return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(addr);
508-
}
508+
#define pud_offset_phys(dir, addr) (pgd_page_paddr(*(dir)) + pud_index(addr) * sizeof(pud_t))
509+
#define pud_offset(dir, addr) ((pud_t *)__va(pud_offset_phys((dir), (addr))))
509510

510511
#define pgd_page(pgd) pfn_to_page(__phys_to_pfn(pgd_val(pgd) & PHYS_MASK))
511512

513+
#else
514+
515+
#define pgd_page_paddr(pgd) ({ BUILD_BUG(); 0;})
516+
512517
#endif /* CONFIG_PGTABLE_LEVELS > 3 */
513518

514519
#define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd_val(pgd))
515520

516521
/* to find an entry in a page-table-directory */
517522
#define pgd_index(addr) (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
518523

519-
#define pgd_offset(mm, addr) ((mm)->pgd+pgd_index(addr))
524+
#define pgd_offset_raw(pgd, addr) ((pgd) + pgd_index(addr))
525+
526+
#define pgd_offset(mm, addr) (pgd_offset_raw((mm)->pgd, (addr)))
520527

521528
/* to find an entry in a kernel page-table-directory */
522529
#define pgd_offset_k(addr) pgd_offset(&init_mm, addr)

0 commit comments

Comments
 (0)