arch/mips/include/asm/pgtable.h

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

File Facts

System
Linux kernel
Corpus path
arch/mips/include/asm/pgtable.h
Extension
.h
Size
18670 bytes
Lines
761
Domain
Architecture Layer
Bucket
arch/mips
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

if(!raw_current_cpu_data.htw_seq++) {			\
			write_c0_pwctl(read_c0_pwctl() &		\
				       ~(1 << MIPS_PWCTL_PWEN_SHIFT));	\
			back_to_back_c0_hazard();			\
		}							\
		local_irq_restore(__flags);				\
	}								\
} while(0)

#define htw_start()							\
do {									\
	unsigned long __flags;						\
									\
	if (cpu_has_htw) {						\
		local_irq_save(__flags);				\
		if (!--raw_current_cpu_data.htw_seq) {			\
			write_c0_pwctl(read_c0_pwctl() |		\
				       (1 << MIPS_PWCTL_PWEN_SHIFT));	\
			back_to_back_c0_hazard();			\
		}							\
		local_irq_restore(__flags);				\
	}								\
} while(0)

#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)

#ifdef CONFIG_XPA
# define pte_none(pte)		(!(((pte).pte_high) & ~_PAGE_GLOBAL))
#else
# define pte_none(pte)		(!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL))
#endif

#define pte_present(pte)	((pte).pte_low & _PAGE_PRESENT)
#define pte_no_exec(pte)	((pte).pte_low & _PAGE_NO_EXEC)

static inline void set_pte(pte_t *ptep, pte_t pte)
{
	ptep->pte_high = pte.pte_high;
	smp_wmb();
	ptep->pte_low = pte.pte_low;

#ifdef CONFIG_XPA
	if (pte.pte_high & _PAGE_GLOBAL) {
#else
	if (pte.pte_low & _PAGE_GLOBAL) {
#endif
		pte_t *buddy = ptep_buddy(ptep);
		/*
		 * Make sure the buddy is global too (if it's !none,
		 * it better already be global)
		 */
		if (pte_none(*buddy)) {
			if (!IS_ENABLED(CONFIG_XPA))
				buddy->pte_low |= _PAGE_GLOBAL;
			buddy->pte_high |= _PAGE_GLOBAL;
		}
	}
}

static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
	pte_t null = __pte(0);

	htw_stop();
	/* Preserve global status for the pair */
	if (IS_ENABLED(CONFIG_XPA)) {
		if (ptep_buddy(ptep)->pte_high & _PAGE_GLOBAL)
			null.pte_high = _PAGE_GLOBAL;
	} else {
		if (ptep_buddy(ptep)->pte_low & _PAGE_GLOBAL)
			null.pte_low = null.pte_high = _PAGE_GLOBAL;
	}

	set_pte(ptep, null);
	htw_start();
}
#else

#define pte_none(pte)		(!(pte_val(pte) & ~_PAGE_GLOBAL))
#define pte_present(pte)	(pte_val(pte) & _PAGE_PRESENT)
#define pte_no_exec(pte)	(pte_val(pte) & _PAGE_NO_EXEC)

/*
 * Certain architectures need to do special things when pte's
 * within a page table are directly modified.  Thus, the following
 * hook is made available.
 */
static inline void set_pte(pte_t *ptep, pte_t pteval)
{
	*ptep = pteval;

Annotation

Implementation Notes