/* SPDX-License-Identifier: GPL-2.0-only */ #ifndef _ASMPOWERPC_MMU_H_ #define _ASMPOWERPC_MMU_H_ #include bool mmu_enabled(void); void mmu_enable(pgd_t *pgtable); void mmu_disable(void); static inline void tlbie(unsigned long rb, unsigned long rs, int ric, int prs, int r) { /* MMU is radix (>= POWER9), so can use P9 tlbie directly */ asm volatile( " .machine push \n" " .machine power9 \n" " ptesync \n" " tlbie %0,%1,%2,%3,%4 \n" " eieio \n" " tlbsync \n" " ptesync \n" " .machine pop " :: "r"(rb), "r"(rs), "i"(ric), "i"(prs), "i"(r) : "memory"); } static inline void tlbiel(unsigned long rb, unsigned long rs, int ric, int prs, int r) { asm volatile( " .machine push \n" " .machine power9 \n" " ptesync \n" " tlbiel %0,%1,%2,%3,%4 \n" " ptesync \n" " .machine pop " :: "r"(rb), "r"(rs), "i"(ric), "i"(prs), "i"(r) : "memory"); } static inline void flush_tlb_page(uintptr_t vaddr) { unsigned long rb; unsigned long rs = (1ULL << 32); /* pid */ unsigned long ap; /* AP should come from dt (for pseries, at least) */ if (PAGE_SIZE == SZ_4K) ap = 0; else if (PAGE_SIZE == SZ_64K) ap = 5; else if (PAGE_SIZE == SZ_2M) ap = 1; else if (PAGE_SIZE == SZ_1G) ap = 2; else assert(0); rb = vaddr & ~((1UL << 12) - 1); rb |= ap << 5; tlbie(rb, rs, 0, 1, 1); } static inline void flush_tlb_page_local(uintptr_t vaddr) { unsigned long rb; unsigned long rs = (1ULL << 32); /* pid */ unsigned long ap; /* AP should come from dt (for pseries, at least) */ if (PAGE_SIZE == SZ_4K) ap = 0; else if (PAGE_SIZE == SZ_64K) ap = 5; else if (PAGE_SIZE == SZ_2M) ap = 1; else if (PAGE_SIZE == SZ_1G) ap = 2; else assert(0); rb = vaddr & ~((1UL << 12) - 1); rb |= ap << 5; tlbiel(rb, rs, 0, 1, 1); } #endif