Merge patch series "riscv, mm: detect svnapot cpu support at runtime"
[platform/kernel/linux-starfive.git] / arch / riscv / include / asm / pgtable.h
index ab05f89..3303fc0 100644 (file)
@@ -264,10 +264,47 @@ static inline pte_t pud_pte(pud_t pud)
        return __pte(pud_val(pud));
 }
 
+#ifdef CONFIG_RISCV_ISA_SVNAPOT
+
+static __always_inline bool has_svnapot(void)
+{
+       return riscv_has_extension_likely(RISCV_ISA_EXT_SVNAPOT);
+}
+
+static inline unsigned long pte_napot(pte_t pte)
+{
+       return pte_val(pte) & _PAGE_NAPOT;
+}
+
+static inline pte_t pte_mknapot(pte_t pte, unsigned int order)
+{
+       int pos = order - 1 + _PAGE_PFN_SHIFT;
+       unsigned long napot_bit = BIT(pos);
+       unsigned long napot_mask = ~GENMASK(pos, _PAGE_PFN_SHIFT);
+
+       return __pte((pte_val(pte) & napot_mask) | napot_bit | _PAGE_NAPOT);
+}
+
+#else
+
+static __always_inline bool has_svnapot(void) { return false; }
+
+static inline unsigned long pte_napot(pte_t pte)
+{
+       return 0;
+}
+
+#endif /* CONFIG_RISCV_ISA_SVNAPOT */
+
 /* Yields the page frame number (PFN) of a page table entry */
 static inline unsigned long pte_pfn(pte_t pte)
 {
-       return __page_val_to_pfn(pte_val(pte));
+       unsigned long res  = __page_val_to_pfn(pte_val(pte));
+
+       if (has_svnapot() && pte_napot(pte))
+               res = res & (res - 1UL);
+
+       return res;
 }
 
 #define pte_page(x)     pfn_to_page(pte_pfn(x))