xref: /openbmc/linux/arch/riscv/include/asm/pgtable-64.h (revision ca2478a7d974f38d29d27acb42a952c7f168916e)
150acfb2bSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
207037db5SPalmer Dabbelt /*
307037db5SPalmer Dabbelt  * Copyright (C) 2012 Regents of the University of California
407037db5SPalmer Dabbelt  */
507037db5SPalmer Dabbelt 
607037db5SPalmer Dabbelt #ifndef _ASM_RISCV_PGTABLE_64_H
707037db5SPalmer Dabbelt #define _ASM_RISCV_PGTABLE_64_H
807037db5SPalmer Dabbelt 
9100631b4SHeiko Stuebner #include <linux/bits.h>
1007037db5SPalmer Dabbelt #include <linux/const.h>
11ff689fd2SHeiko Stuebner #include <asm/errata_list.h>
1207037db5SPalmer Dabbelt 
13e8a62cc2SAlexandre Ghiti extern bool pgtable_l4_enabled;
14d10efa21SQinglin Pan extern bool pgtable_l5_enabled;
15e8a62cc2SAlexandre Ghiti 
16e8a62cc2SAlexandre Ghiti #define PGDIR_SHIFT_L3  30
17e8a62cc2SAlexandre Ghiti #define PGDIR_SHIFT_L4  39
18d10efa21SQinglin Pan #define PGDIR_SHIFT_L5  48
19e8a62cc2SAlexandre Ghiti #define PGDIR_SIZE_L3   (_AC(1, UL) << PGDIR_SHIFT_L3)
20e8a62cc2SAlexandre Ghiti 
21d10efa21SQinglin Pan #define PGDIR_SHIFT     (pgtable_l5_enabled ? PGDIR_SHIFT_L5 : \
22d10efa21SQinglin Pan 		(pgtable_l4_enabled ? PGDIR_SHIFT_L4 : PGDIR_SHIFT_L3))
2307037db5SPalmer Dabbelt /* Size of region mapped by a page global directory */
2407037db5SPalmer Dabbelt #define PGDIR_SIZE      (_AC(1, UL) << PGDIR_SHIFT)
2507037db5SPalmer Dabbelt #define PGDIR_MASK      (~(PGDIR_SIZE - 1))
2607037db5SPalmer Dabbelt 
27d10efa21SQinglin Pan /* p4d is folded into pgd in case of 4-level page table */
2871fc3621SAlexandre Ghiti #define P4D_SHIFT_L3   30
2971fc3621SAlexandre Ghiti #define P4D_SHIFT_L4   39
3071fc3621SAlexandre Ghiti #define P4D_SHIFT_L5   39
3171fc3621SAlexandre Ghiti #define P4D_SHIFT      (pgtable_l5_enabled ? P4D_SHIFT_L5 : \
3271fc3621SAlexandre Ghiti 		(pgtable_l4_enabled ? P4D_SHIFT_L4 : P4D_SHIFT_L3))
33d10efa21SQinglin Pan #define P4D_SIZE       (_AC(1, UL) << P4D_SHIFT)
34d10efa21SQinglin Pan #define P4D_MASK       (~(P4D_SIZE - 1))
35d10efa21SQinglin Pan 
36e8a62cc2SAlexandre Ghiti /* pud is folded into pgd in case of 3-level page table */
37e8a62cc2SAlexandre Ghiti #define PUD_SHIFT      30
38e8a62cc2SAlexandre Ghiti #define PUD_SIZE       (_AC(1, UL) << PUD_SHIFT)
39e8a62cc2SAlexandre Ghiti #define PUD_MASK       (~(PUD_SIZE - 1))
40e8a62cc2SAlexandre Ghiti 
4107037db5SPalmer Dabbelt #define PMD_SHIFT       21
4207037db5SPalmer Dabbelt /* Size of region mapped by a page middle directory */
4307037db5SPalmer Dabbelt #define PMD_SIZE        (_AC(1, UL) << PMD_SHIFT)
4407037db5SPalmer Dabbelt #define PMD_MASK        (~(PMD_SIZE - 1))
4507037db5SPalmer Dabbelt 
46d10efa21SQinglin Pan /* Page 4th Directory entry */
47d10efa21SQinglin Pan typedef struct {
48d10efa21SQinglin Pan 	unsigned long p4d;
49d10efa21SQinglin Pan } p4d_t;
50d10efa21SQinglin Pan 
51d10efa21SQinglin Pan #define p4d_val(x)	((x).p4d)
52d10efa21SQinglin Pan #define __p4d(x)	((p4d_t) { (x) })
53d10efa21SQinglin Pan #define PTRS_PER_P4D	(PAGE_SIZE / sizeof(p4d_t))
54d10efa21SQinglin Pan 
55e8a62cc2SAlexandre Ghiti /* Page Upper Directory entry */
56e8a62cc2SAlexandre Ghiti typedef struct {
57e8a62cc2SAlexandre Ghiti 	unsigned long pud;
58e8a62cc2SAlexandre Ghiti } pud_t;
59e8a62cc2SAlexandre Ghiti 
60e8a62cc2SAlexandre Ghiti #define pud_val(x)      ((x).pud)
61e8a62cc2SAlexandre Ghiti #define __pud(x)        ((pud_t) { (x) })
62e8a62cc2SAlexandre Ghiti #define PTRS_PER_PUD    (PAGE_SIZE / sizeof(pud_t))
63e8a62cc2SAlexandre Ghiti 
6407037db5SPalmer Dabbelt /* Page Middle Directory entry */
6507037db5SPalmer Dabbelt typedef struct {
6607037db5SPalmer Dabbelt 	unsigned long pmd;
6707037db5SPalmer Dabbelt } pmd_t;
6807037db5SPalmer Dabbelt 
6907037db5SPalmer Dabbelt #define pmd_val(x)      ((x).pmd)
7007037db5SPalmer Dabbelt #define __pmd(x)        ((pmd_t) { (x) })
7107037db5SPalmer Dabbelt 
7207037db5SPalmer Dabbelt #define PTRS_PER_PMD    (PAGE_SIZE / sizeof(pmd_t))
7307037db5SPalmer Dabbelt 
74100631b4SHeiko Stuebner /*
75100631b4SHeiko Stuebner  * rv64 PTE format:
76100631b4SHeiko Stuebner  * | 63 | 62 61 | 60 54 | 53  10 | 9             8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
77100631b4SHeiko Stuebner  *   N      MT     RSV    PFN      reserved for SW   D   A   G   U   X   W   R   V
78100631b4SHeiko Stuebner  */
79100631b4SHeiko Stuebner #define _PAGE_PFN_MASK  GENMASK(53, 10)
80100631b4SHeiko Stuebner 
81ff689fd2SHeiko Stuebner /*
8223ad288aSQinglin Pan  * [63] Svnapot definitions:
8323ad288aSQinglin Pan  * 0 Svnapot disabled
8423ad288aSQinglin Pan  * 1 Svnapot enabled
8523ad288aSQinglin Pan  */
8623ad288aSQinglin Pan #define _PAGE_NAPOT_SHIFT	63
8723ad288aSQinglin Pan #define _PAGE_NAPOT		BIT(_PAGE_NAPOT_SHIFT)
8823ad288aSQinglin Pan /*
8923ad288aSQinglin Pan  * Only 64KB (order 4) napot ptes supported.
9023ad288aSQinglin Pan  */
9123ad288aSQinglin Pan #define NAPOT_CONT_ORDER_BASE 4
9223ad288aSQinglin Pan enum napot_cont_order {
9323ad288aSQinglin Pan 	NAPOT_CONT64KB_ORDER = NAPOT_CONT_ORDER_BASE,
9423ad288aSQinglin Pan 	NAPOT_ORDER_MAX,
9523ad288aSQinglin Pan };
9623ad288aSQinglin Pan 
9723ad288aSQinglin Pan #define for_each_napot_order(order)						\
9823ad288aSQinglin Pan 	for (order = NAPOT_CONT_ORDER_BASE; order < NAPOT_ORDER_MAX; order++)
9923ad288aSQinglin Pan #define for_each_napot_order_rev(order)						\
10023ad288aSQinglin Pan 	for (order = NAPOT_ORDER_MAX - 1;					\
10123ad288aSQinglin Pan 	     order >= NAPOT_CONT_ORDER_BASE; order--)
10223ad288aSQinglin Pan #define napot_cont_order(val)	(__builtin_ctzl((val.pte >> _PAGE_PFN_SHIFT) << 1))
10323ad288aSQinglin Pan 
10423ad288aSQinglin Pan #define napot_cont_shift(order)	((order) + PAGE_SHIFT)
10523ad288aSQinglin Pan #define napot_cont_size(order)	BIT(napot_cont_shift(order))
10623ad288aSQinglin Pan #define napot_cont_mask(order)	(~(napot_cont_size(order) - 1UL))
10723ad288aSQinglin Pan #define napot_pte_num(order)	BIT(order)
10823ad288aSQinglin Pan 
10923ad288aSQinglin Pan #ifdef CONFIG_RISCV_ISA_SVNAPOT
11023ad288aSQinglin Pan #define HUGE_MAX_HSTATE		(2 + (NAPOT_ORDER_MAX - NAPOT_CONT_ORDER_BASE))
11123ad288aSQinglin Pan #else
11223ad288aSQinglin Pan #define HUGE_MAX_HSTATE		2
11323ad288aSQinglin Pan #endif
11423ad288aSQinglin Pan 
11523ad288aSQinglin Pan /*
116ff689fd2SHeiko Stuebner  * [62:61] Svpbmt Memory Type definitions:
117ff689fd2SHeiko Stuebner  *
118ff689fd2SHeiko Stuebner  *  00 - PMA    Normal Cacheable, No change to implied PMA memory type
119ff689fd2SHeiko Stuebner  *  01 - NC     Non-cacheable, idempotent, weakly-ordered Main Memory
120ff689fd2SHeiko Stuebner  *  10 - IO     Non-cacheable, non-idempotent, strongly-ordered I/O memory
121ff689fd2SHeiko Stuebner  *  11 - Rsvd   Reserved for future standard use
122ff689fd2SHeiko Stuebner  */
123ff689fd2SHeiko Stuebner #define _PAGE_NOCACHE_SVPBMT	(1UL << 61)
124ff689fd2SHeiko Stuebner #define _PAGE_IO_SVPBMT		(1UL << 62)
125ff689fd2SHeiko Stuebner #define _PAGE_MTMASK_SVPBMT	(_PAGE_NOCACHE_SVPBMT | _PAGE_IO_SVPBMT)
126ff689fd2SHeiko Stuebner 
127a35707c3SHeiko Stuebner /*
128a35707c3SHeiko Stuebner  * [63:59] T-Head Memory Type definitions:
129a35707c3SHeiko Stuebner  *
130a35707c3SHeiko Stuebner  * 00000 - NC   Weakly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable
131a35707c3SHeiko Stuebner  * 01110 - PMA  Weakly-ordered, Cacheable, Bufferable, Shareable, Non-trustable
132a35707c3SHeiko Stuebner  * 10000 - IO   Strongly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable
133a35707c3SHeiko Stuebner  */
134a35707c3SHeiko Stuebner #define _PAGE_PMA_THEAD		((1UL << 62) | (1UL << 61) | (1UL << 60))
135a35707c3SHeiko Stuebner #define _PAGE_NOCACHE_THEAD	0UL
136a35707c3SHeiko Stuebner #define _PAGE_IO_THEAD		(1UL << 63)
137a35707c3SHeiko Stuebner #define _PAGE_MTMASK_THEAD	(_PAGE_PMA_THEAD | _PAGE_IO_THEAD | (1UL << 59))
138a35707c3SHeiko Stuebner 
riscv_page_mtmask(void)139ff689fd2SHeiko Stuebner static inline u64 riscv_page_mtmask(void)
140ff689fd2SHeiko Stuebner {
141ff689fd2SHeiko Stuebner 	u64 val;
142ff689fd2SHeiko Stuebner 
143ff689fd2SHeiko Stuebner 	ALT_SVPBMT(val, _PAGE_MTMASK);
144ff689fd2SHeiko Stuebner 	return val;
145ff689fd2SHeiko Stuebner }
146ff689fd2SHeiko Stuebner 
riscv_page_nocache(void)147ff689fd2SHeiko Stuebner static inline u64 riscv_page_nocache(void)
148ff689fd2SHeiko Stuebner {
149ff689fd2SHeiko Stuebner 	u64 val;
150ff689fd2SHeiko Stuebner 
151ff689fd2SHeiko Stuebner 	ALT_SVPBMT(val, _PAGE_NOCACHE);
152ff689fd2SHeiko Stuebner 	return val;
153ff689fd2SHeiko Stuebner }
154ff689fd2SHeiko Stuebner 
riscv_page_io(void)155ff689fd2SHeiko Stuebner static inline u64 riscv_page_io(void)
156ff689fd2SHeiko Stuebner {
157ff689fd2SHeiko Stuebner 	u64 val;
158ff689fd2SHeiko Stuebner 
159ff689fd2SHeiko Stuebner 	ALT_SVPBMT(val, _PAGE_IO);
160ff689fd2SHeiko Stuebner 	return val;
161ff689fd2SHeiko Stuebner }
162ff689fd2SHeiko Stuebner 
163ff689fd2SHeiko Stuebner #define _PAGE_NOCACHE		riscv_page_nocache()
164ff689fd2SHeiko Stuebner #define _PAGE_IO		riscv_page_io()
165ff689fd2SHeiko Stuebner #define _PAGE_MTMASK		riscv_page_mtmask()
166ff689fd2SHeiko Stuebner 
167ff689fd2SHeiko Stuebner /* Set of bits to preserve across pte_modify() */
168ff689fd2SHeiko Stuebner #define _PAGE_CHG_MASK  (~(unsigned long)(_PAGE_PRESENT | _PAGE_READ |	\
169ff689fd2SHeiko Stuebner 					  _PAGE_WRITE | _PAGE_EXEC |	\
170ff689fd2SHeiko Stuebner 					  _PAGE_USER | _PAGE_GLOBAL |	\
171ff689fd2SHeiko Stuebner 					  _PAGE_MTMASK))
172ff689fd2SHeiko Stuebner 
pud_present(pud_t pud)17307037db5SPalmer Dabbelt static inline int pud_present(pud_t pud)
17407037db5SPalmer Dabbelt {
17507037db5SPalmer Dabbelt 	return (pud_val(pud) & _PAGE_PRESENT);
17607037db5SPalmer Dabbelt }
17707037db5SPalmer Dabbelt 
pud_none(pud_t pud)17807037db5SPalmer Dabbelt static inline int pud_none(pud_t pud)
17907037db5SPalmer Dabbelt {
18007037db5SPalmer Dabbelt 	return (pud_val(pud) == 0);
18107037db5SPalmer Dabbelt }
18207037db5SPalmer Dabbelt 
pud_bad(pud_t pud)18307037db5SPalmer Dabbelt static inline int pud_bad(pud_t pud)
18407037db5SPalmer Dabbelt {
18507037db5SPalmer Dabbelt 	return !pud_present(pud);
18607037db5SPalmer Dabbelt }
18707037db5SPalmer Dabbelt 
188af6513eaSSteven Price #define pud_leaf	pud_leaf
pud_leaf(pud_t pud)189af6513eaSSteven Price static inline int pud_leaf(pud_t pud)
190af6513eaSSteven Price {
191f5397c3eSNanyong Sun 	return pud_present(pud) && (pud_val(pud) & _PAGE_LEAF);
192af6513eaSSteven Price }
193af6513eaSSteven Price 
pud_user(pud_t pud)1942c8a81dcSTong Tiangen static inline int pud_user(pud_t pud)
1952c8a81dcSTong Tiangen {
1962c8a81dcSTong Tiangen 	return pud_val(pud) & _PAGE_USER;
1972c8a81dcSTong Tiangen }
1982c8a81dcSTong Tiangen 
set_pud(pud_t * pudp,pud_t pud)19907037db5SPalmer Dabbelt static inline void set_pud(pud_t *pudp, pud_t pud)
20007037db5SPalmer Dabbelt {
201193b1fc1SAlexandre Ghiti 	WRITE_ONCE(*pudp, pud);
20207037db5SPalmer Dabbelt }
20307037db5SPalmer Dabbelt 
pud_clear(pud_t * pudp)20407037db5SPalmer Dabbelt static inline void pud_clear(pud_t *pudp)
20507037db5SPalmer Dabbelt {
20607037db5SPalmer Dabbelt 	set_pud(pudp, __pud(0));
20707037db5SPalmer Dabbelt }
20807037db5SPalmer Dabbelt 
pfn_pud(unsigned long pfn,pgprot_t prot)209e8a62cc2SAlexandre Ghiti static inline pud_t pfn_pud(unsigned long pfn, pgprot_t prot)
210e8a62cc2SAlexandre Ghiti {
211e8a62cc2SAlexandre Ghiti 	return __pud((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
212e8a62cc2SAlexandre Ghiti }
213e8a62cc2SAlexandre Ghiti 
_pud_pfn(pud_t pud)214e8a62cc2SAlexandre Ghiti static inline unsigned long _pud_pfn(pud_t pud)
215e8a62cc2SAlexandre Ghiti {
21688573389SAlexandre Ghiti 	return __page_val_to_pfn(pud_val(pud));
217e8a62cc2SAlexandre Ghiti }
218e8a62cc2SAlexandre Ghiti 
pud_pgtable(pud_t pud)2199cf6fa24SAneesh Kumar K.V static inline pmd_t *pud_pgtable(pud_t pud)
22007037db5SPalmer Dabbelt {
221100631b4SHeiko Stuebner 	return (pmd_t *)pfn_to_virt(__page_val_to_pfn(pud_val(pud)));
22207037db5SPalmer Dabbelt }
22307037db5SPalmer Dabbelt 
pud_page(pud_t pud)2248ad8b727SNick Hu static inline struct page *pud_page(pud_t pud)
2258ad8b727SNick Hu {
226100631b4SHeiko Stuebner 	return pfn_to_page(__page_val_to_pfn(pud_val(pud)));
2278ad8b727SNick Hu }
2288ad8b727SNick Hu 
229d10efa21SQinglin Pan #define mm_p4d_folded  mm_p4d_folded
mm_p4d_folded(struct mm_struct * mm)230d10efa21SQinglin Pan static inline bool mm_p4d_folded(struct mm_struct *mm)
231d10efa21SQinglin Pan {
232d10efa21SQinglin Pan 	if (pgtable_l5_enabled)
233d10efa21SQinglin Pan 		return false;
234d10efa21SQinglin Pan 
235d10efa21SQinglin Pan 	return true;
236d10efa21SQinglin Pan }
237d10efa21SQinglin Pan 
238e8a62cc2SAlexandre Ghiti #define mm_pud_folded  mm_pud_folded
mm_pud_folded(struct mm_struct * mm)239e8a62cc2SAlexandre Ghiti static inline bool mm_pud_folded(struct mm_struct *mm)
240e8a62cc2SAlexandre Ghiti {
241e8a62cc2SAlexandre Ghiti 	if (pgtable_l4_enabled)
242e8a62cc2SAlexandre Ghiti 		return false;
243e8a62cc2SAlexandre Ghiti 
244e8a62cc2SAlexandre Ghiti 	return true;
245e8a62cc2SAlexandre Ghiti }
246e8a62cc2SAlexandre Ghiti 
247e8a62cc2SAlexandre Ghiti #define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
248e8a62cc2SAlexandre Ghiti 
pfn_pmd(unsigned long pfn,pgprot_t prot)24907037db5SPalmer Dabbelt static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t prot)
25007037db5SPalmer Dabbelt {
251a35707c3SHeiko Stuebner 	unsigned long prot_val = pgprot_val(prot);
252a35707c3SHeiko Stuebner 
253a35707c3SHeiko Stuebner 	ALT_THEAD_PMA(prot_val);
254a35707c3SHeiko Stuebner 
255a35707c3SHeiko Stuebner 	return __pmd((pfn << _PAGE_PFN_SHIFT) | prot_val);
25607037db5SPalmer Dabbelt }
25707037db5SPalmer Dabbelt 
_pmd_pfn(pmd_t pmd)258671f9a3eSAnup Patel static inline unsigned long _pmd_pfn(pmd_t pmd)
259671f9a3eSAnup Patel {
260100631b4SHeiko Stuebner 	return __page_val_to_pfn(pmd_val(pmd));
261671f9a3eSAnup Patel }
262671f9a3eSAnup Patel 
2639eb4fcffSNanyong Sun #define mk_pmd(page, prot)    pfn_pmd(page_to_pfn(page), prot)
2649eb4fcffSNanyong Sun 
26507037db5SPalmer Dabbelt #define pmd_ERROR(e) \
26607037db5SPalmer Dabbelt 	pr_err("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e))
26707037db5SPalmer Dabbelt 
268e8a62cc2SAlexandre Ghiti #define pud_ERROR(e)   \
269e8a62cc2SAlexandre Ghiti 	pr_err("%s:%d: bad pud %016lx.\n", __FILE__, __LINE__, pud_val(e))
270e8a62cc2SAlexandre Ghiti 
271d10efa21SQinglin Pan #define p4d_ERROR(e)   \
272d10efa21SQinglin Pan 	pr_err("%s:%d: bad p4d %016lx.\n", __FILE__, __LINE__, p4d_val(e))
273d10efa21SQinglin Pan 
set_p4d(p4d_t * p4dp,p4d_t p4d)274e8a62cc2SAlexandre Ghiti static inline void set_p4d(p4d_t *p4dp, p4d_t p4d)
275e8a62cc2SAlexandre Ghiti {
276e8a62cc2SAlexandre Ghiti 	if (pgtable_l4_enabled)
277193b1fc1SAlexandre Ghiti 		WRITE_ONCE(*p4dp, p4d);
278e8a62cc2SAlexandre Ghiti 	else
279e8a62cc2SAlexandre Ghiti 		set_pud((pud_t *)p4dp, (pud_t){ p4d_val(p4d) });
280e8a62cc2SAlexandre Ghiti }
281e8a62cc2SAlexandre Ghiti 
p4d_none(p4d_t p4d)282e8a62cc2SAlexandre Ghiti static inline int p4d_none(p4d_t p4d)
283e8a62cc2SAlexandre Ghiti {
284e8a62cc2SAlexandre Ghiti 	if (pgtable_l4_enabled)
285e8a62cc2SAlexandre Ghiti 		return (p4d_val(p4d) == 0);
286e8a62cc2SAlexandre Ghiti 
287e8a62cc2SAlexandre Ghiti 	return 0;
288e8a62cc2SAlexandre Ghiti }
289e8a62cc2SAlexandre Ghiti 
p4d_present(p4d_t p4d)290e8a62cc2SAlexandre Ghiti static inline int p4d_present(p4d_t p4d)
291e8a62cc2SAlexandre Ghiti {
292e8a62cc2SAlexandre Ghiti 	if (pgtable_l4_enabled)
293e8a62cc2SAlexandre Ghiti 		return (p4d_val(p4d) & _PAGE_PRESENT);
294e8a62cc2SAlexandre Ghiti 
295e8a62cc2SAlexandre Ghiti 	return 1;
296e8a62cc2SAlexandre Ghiti }
297e8a62cc2SAlexandre Ghiti 
p4d_bad(p4d_t p4d)298e8a62cc2SAlexandre Ghiti static inline int p4d_bad(p4d_t p4d)
299e8a62cc2SAlexandre Ghiti {
300e8a62cc2SAlexandre Ghiti 	if (pgtable_l4_enabled)
301e8a62cc2SAlexandre Ghiti 		return !p4d_present(p4d);
302e8a62cc2SAlexandre Ghiti 
303e8a62cc2SAlexandre Ghiti 	return 0;
304e8a62cc2SAlexandre Ghiti }
305e8a62cc2SAlexandre Ghiti 
p4d_clear(p4d_t * p4d)306e8a62cc2SAlexandre Ghiti static inline void p4d_clear(p4d_t *p4d)
307e8a62cc2SAlexandre Ghiti {
308e8a62cc2SAlexandre Ghiti 	if (pgtable_l4_enabled)
309e8a62cc2SAlexandre Ghiti 		set_p4d(p4d, __p4d(0));
310e8a62cc2SAlexandre Ghiti }
311e8a62cc2SAlexandre Ghiti 
pfn_p4d(unsigned long pfn,pgprot_t prot)312d10efa21SQinglin Pan static inline p4d_t pfn_p4d(unsigned long pfn, pgprot_t prot)
313d10efa21SQinglin Pan {
314d10efa21SQinglin Pan 	return __p4d((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
315d10efa21SQinglin Pan }
316d10efa21SQinglin Pan 
_p4d_pfn(p4d_t p4d)317d10efa21SQinglin Pan static inline unsigned long _p4d_pfn(p4d_t p4d)
318d10efa21SQinglin Pan {
31988573389SAlexandre Ghiti 	return __page_val_to_pfn(p4d_val(p4d));
320d10efa21SQinglin Pan }
321d10efa21SQinglin Pan 
p4d_pgtable(p4d_t p4d)322e8a62cc2SAlexandre Ghiti static inline pud_t *p4d_pgtable(p4d_t p4d)
323e8a62cc2SAlexandre Ghiti {
324e8a62cc2SAlexandre Ghiti 	if (pgtable_l4_enabled)
32588573389SAlexandre Ghiti 		return (pud_t *)pfn_to_virt(__page_val_to_pfn(p4d_val(p4d)));
326e8a62cc2SAlexandre Ghiti 
327e8a62cc2SAlexandre Ghiti 	return (pud_t *)pud_pgtable((pud_t) { p4d_val(p4d) });
328e8a62cc2SAlexandre Ghiti }
329d10efa21SQinglin Pan #define p4d_page_vaddr(p4d)	((unsigned long)p4d_pgtable(p4d))
330e8a62cc2SAlexandre Ghiti 
p4d_page(p4d_t p4d)331e8a62cc2SAlexandre Ghiti static inline struct page *p4d_page(p4d_t p4d)
332e8a62cc2SAlexandre Ghiti {
33388573389SAlexandre Ghiti 	return pfn_to_page(__page_val_to_pfn(p4d_val(p4d)));
334e8a62cc2SAlexandre Ghiti }
335e8a62cc2SAlexandre Ghiti 
336e8a62cc2SAlexandre Ghiti #define pud_index(addr) (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
337e8a62cc2SAlexandre Ghiti 
338e8a62cc2SAlexandre Ghiti #define pud_offset pud_offset
339*e0316069SAlexandre Ghiti pud_t *pud_offset(p4d_t *p4d, unsigned long address);
340e8a62cc2SAlexandre Ghiti 
set_pgd(pgd_t * pgdp,pgd_t pgd)341d10efa21SQinglin Pan static inline void set_pgd(pgd_t *pgdp, pgd_t pgd)
342d10efa21SQinglin Pan {
343d10efa21SQinglin Pan 	if (pgtable_l5_enabled)
344193b1fc1SAlexandre Ghiti 		WRITE_ONCE(*pgdp, pgd);
345d10efa21SQinglin Pan 	else
346d10efa21SQinglin Pan 		set_p4d((p4d_t *)pgdp, (p4d_t){ pgd_val(pgd) });
347d10efa21SQinglin Pan }
348d10efa21SQinglin Pan 
pgd_none(pgd_t pgd)349d10efa21SQinglin Pan static inline int pgd_none(pgd_t pgd)
350d10efa21SQinglin Pan {
351d10efa21SQinglin Pan 	if (pgtable_l5_enabled)
352d10efa21SQinglin Pan 		return (pgd_val(pgd) == 0);
353d10efa21SQinglin Pan 
354d10efa21SQinglin Pan 	return 0;
355d10efa21SQinglin Pan }
356d10efa21SQinglin Pan 
pgd_present(pgd_t pgd)357d10efa21SQinglin Pan static inline int pgd_present(pgd_t pgd)
358d10efa21SQinglin Pan {
359d10efa21SQinglin Pan 	if (pgtable_l5_enabled)
360d10efa21SQinglin Pan 		return (pgd_val(pgd) & _PAGE_PRESENT);
361d10efa21SQinglin Pan 
362d10efa21SQinglin Pan 	return 1;
363d10efa21SQinglin Pan }
364d10efa21SQinglin Pan 
pgd_bad(pgd_t pgd)365d10efa21SQinglin Pan static inline int pgd_bad(pgd_t pgd)
366d10efa21SQinglin Pan {
367d10efa21SQinglin Pan 	if (pgtable_l5_enabled)
368d10efa21SQinglin Pan 		return !pgd_present(pgd);
369d10efa21SQinglin Pan 
370d10efa21SQinglin Pan 	return 0;
371d10efa21SQinglin Pan }
372d10efa21SQinglin Pan 
pgd_clear(pgd_t * pgd)373d10efa21SQinglin Pan static inline void pgd_clear(pgd_t *pgd)
374d10efa21SQinglin Pan {
375d10efa21SQinglin Pan 	if (pgtable_l5_enabled)
376d10efa21SQinglin Pan 		set_pgd(pgd, __pgd(0));
377d10efa21SQinglin Pan }
378d10efa21SQinglin Pan 
pgd_pgtable(pgd_t pgd)379d10efa21SQinglin Pan static inline p4d_t *pgd_pgtable(pgd_t pgd)
380d10efa21SQinglin Pan {
381d10efa21SQinglin Pan 	if (pgtable_l5_enabled)
38288573389SAlexandre Ghiti 		return (p4d_t *)pfn_to_virt(__page_val_to_pfn(pgd_val(pgd)));
383d10efa21SQinglin Pan 
384d10efa21SQinglin Pan 	return (p4d_t *)p4d_pgtable((p4d_t) { pgd_val(pgd) });
385d10efa21SQinglin Pan }
386d10efa21SQinglin Pan #define pgd_page_vaddr(pgd)	((unsigned long)pgd_pgtable(pgd))
387d10efa21SQinglin Pan 
pgd_page(pgd_t pgd)388d10efa21SQinglin Pan static inline struct page *pgd_page(pgd_t pgd)
389d10efa21SQinglin Pan {
39088573389SAlexandre Ghiti 	return pfn_to_page(__page_val_to_pfn(pgd_val(pgd)));
391d10efa21SQinglin Pan }
392d10efa21SQinglin Pan #define pgd_page(pgd)	pgd_page(pgd)
393d10efa21SQinglin Pan 
394d10efa21SQinglin Pan #define p4d_index(addr) (((addr) >> P4D_SHIFT) & (PTRS_PER_P4D - 1))
395d10efa21SQinglin Pan 
396d10efa21SQinglin Pan #define p4d_offset p4d_offset
397*e0316069SAlexandre Ghiti p4d_t *p4d_offset(pgd_t *pgd, unsigned long address);
398d10efa21SQinglin Pan 
39907037db5SPalmer Dabbelt #endif /* _ASM_RISCV_PGTABLE_64_H */
400