arch/arm64/include/asm/pgtable.h

Source file repositories/reference/linux-study-clean/arch/arm64/include/asm/pgtable.h

File Facts

System
Linux kernel
Corpus path
arch/arm64/include/asm/pgtable.h
Extension
.h
Size
58879 bytes
Lines
1983
Domain
Architecture Layer
Bucket
arch/arm64
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

static inline void arch_enter_lazy_mmu_mode(void) {}

static inline void arch_flush_lazy_mmu_mode(void)
{
	if (test_and_clear_thread_flag(TIF_LAZY_MMU_PENDING))
		emit_pte_barriers();
}

static inline void arch_leave_lazy_mmu_mode(void)
{
	arch_flush_lazy_mmu_mode();
}

#ifdef CONFIG_TRANSPARENT_HUGEPAGE
#define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE

/* Set stride and tlb_level in flush_*_tlb_range */
#define flush_pmd_tlb_range(vma, addr, end)	\
	__flush_tlb_range(vma, addr, end, PMD_SIZE, 2, TLBF_NONE)
#define flush_pud_tlb_range(vma, addr, end)	\
	__flush_tlb_range(vma, addr, end, PUD_SIZE, 1, TLBF_NONE)
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */

/*
 * We use local TLB invalidation instruction when reusing page in
 * write protection fault handler to avoid TLBI broadcast in the hot
 * path.  This will cause spurious page faults if stale read-only TLB
 * entries exist.
 */
#define flush_tlb_fix_spurious_fault(vma, address, ptep)	\
	__flush_tlb_page(vma, address, TLBF_NOBROADCAST | TLBF_NONOTIFY)

#define flush_tlb_fix_spurious_fault_pmd(vma, address, pmdp)			\
	__flush_tlb_range(vma, address, address + PMD_SIZE, PMD_SIZE, 2,	\
			  TLBF_NOBROADCAST | TLBF_NONOTIFY | TLBF_NOWALKCACHE)

#define pte_ERROR(e)	\
	pr_err("%s:%d: bad pte %016llx.\n", __FILE__, __LINE__, pte_val(e))

#ifdef CONFIG_ARM64_PA_BITS_52
static inline phys_addr_t __pte_to_phys(pte_t pte)
{
	pte_val(pte) &= ~PTE_MAYBE_SHARED;
	return (pte_val(pte) & PTE_ADDR_LOW) |
		((pte_val(pte) & PTE_ADDR_HIGH) << PTE_ADDR_HIGH_SHIFT);
}
static inline pteval_t __phys_to_pte_val(phys_addr_t phys)
{
	return (phys | (phys >> PTE_ADDR_HIGH_SHIFT)) & PHYS_TO_PTE_ADDR_MASK;
}
#else
static inline phys_addr_t __pte_to_phys(pte_t pte)
{
	return pte_val(pte) & PTE_ADDR_LOW;
}

static inline pteval_t __phys_to_pte_val(phys_addr_t phys)
{
	return phys;
}
#endif

#define pte_pfn(pte)		(__pte_to_phys(pte) >> PAGE_SHIFT)
#define pfn_pte(pfn,prot)	\
	__pte(__phys_to_pte_val((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))

#define pte_none(pte)		(!pte_val(pte))
#define pte_page(pte)		(pfn_to_page(pte_pfn(pte)))

/*
 * The following only work if pte_present(). Undefined behaviour otherwise.
 */
#define pte_present(pte)	(pte_valid(pte) || pte_present_invalid(pte))
#define pte_young(pte)		(!!(pte_val(pte) & PTE_AF))
#define pte_special(pte)	(!!(pte_val(pte) & PTE_SPECIAL))
#define pte_write(pte)		(!!(pte_val(pte) & PTE_WRITE))
#define pte_rdonly(pte)		(!!(pte_val(pte) & PTE_RDONLY))
#define pte_user(pte)		(!!(pte_val(pte) & PTE_USER))
#define pte_user_exec(pte)	(!(pte_val(pte) & PTE_UXN))
#define pte_cont(pte)		(!!(pte_val(pte) & PTE_CONT))
#define pte_tagged(pte)		((pte_val(pte) & PTE_ATTRINDX_MASK) == \
				 PTE_ATTRINDX(MT_NORMAL_TAGGED))

#define pte_cont_addr_end(addr, end)						\
({	unsigned long __boundary = ((addr) + CONT_PTE_SIZE) & CONT_PTE_MASK;	\
	(__boundary - 1 < (end) - 1) ? __boundary : (end);			\
})

#define pmd_cont_addr_end(addr, end)						\
({	unsigned long __boundary = ((addr) + CONT_PMD_SIZE) & CONT_PMD_MASK;	\

Annotation

Implementation Notes