summaryrefslogtreecommitdiff
path: root/arch/riscv/include/asm/pgtable.h
diff options
context:
space:
mode:
authorPalmer Dabbelt <palmer@rivosinc.com>2023-03-09 15:46:40 -0800
committerPalmer Dabbelt <palmer@rivosinc.com>2023-03-09 18:13:45 -0800
commit4a4c459872f154acf872dfa6baf5d1edabd52323 (patch)
treeadba067144e374f7bff2061c644e8cc7313e80b2 /arch/riscv/include/asm/pgtable.h
parentfe15c26ee26efa11741a7b632e9f23b01aca4cc6 (diff)
parentce173474cf19fe7fbe8f0fc74e3c81ec9c3d9807 (diff)
Merge patch series "riscv, mm: detect svnapot cpu support at runtime"
Qinglin Pan <panqinglin00@gmail.com> says: Svnapot is a RISC-V extension for marking contiguous 4K pages as a non-4K page. This patch set is for using Svnapot in hugetlb fs and huge vmap. This patchset adds a Kconfig item for using Svnapot in "Platform type"->"SVNAPOT extension support". Its default value is on, and people can set it off if they don't allow kernel to detect Svnapot hardware support and leverage it. Tested on: - qemu rv64 with "Svnapot support" off and svnapot=true. - qemu rv64 with "Svnapot support" on and svnapot=true. - qemu rv64 with "Svnapot support" off and svnapot=false. - qemu rv64 with "Svnapot support" on and svnapot=false. * b4-shazam-merge: riscv: mm: support Svnapot in huge vmap riscv: mm: support Svnapot in hugetlb page riscv: mm: modify pte format for Svnapot Link: https://lore.kernel.org/r/20230209131647.17245-1-panqinglin00@gmail.com [Palmer: fix up the feature ordering in the merge] Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
Diffstat (limited to 'arch/riscv/include/asm/pgtable.h')
-rw-r--r--arch/riscv/include/asm/pgtable.h39
1 files changed, 38 insertions, 1 deletions
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index ab05f892d317..3303fc03d724 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -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))