^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #ifndef _ASM_PGTABLE_INVERT_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #define _ASM_PGTABLE_INVERT_H 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #ifndef __ASSEMBLY__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * A clear pte value is special, and doesn't get inverted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Note that even users that only pass a pgprot_t (rather
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * than a full pte) won't trigger the special zero case,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * because even PAGE_NONE has _PAGE_PROTNONE | _PAGE_ACCESSED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * set. So the all zero case really is limited to just the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * cleared page table entry case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static inline bool __pte_needs_invert(u64 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) return val && !(val & _PAGE_PRESENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* Get a mask to xor with the page table entry to get the correct pfn. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static inline u64 protnone_mask(u64 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) return __pte_needs_invert(val) ? ~0ull : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static inline u64 flip_protnone_guard(u64 oldval, u64 val, u64 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * When a PTE transitions from NONE to !NONE or vice-versa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * invert the PFN part to stop speculation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * pte_pfn undoes this when needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (__pte_needs_invert(oldval) != __pte_needs_invert(val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) val = (val & ~mask) | (~val & mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #endif /* __ASSEMBLY__ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #endif