1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #ifndef _ASM_X86_PGTABLE_2LEVEL_H |
3 | #define _ASM_X86_PGTABLE_2LEVEL_H |
4 | |
5 | #define pte_ERROR(e) \ |
6 | pr_err("%s:%d: bad pte %08lx\n", __FILE__, __LINE__, (e).pte_low) |
7 | #define pgd_ERROR(e) \ |
8 | pr_err("%s:%d: bad pgd %08lx\n", __FILE__, __LINE__, pgd_val(e)) |
9 | |
10 | /* |
11 | * Certain architectures need to do special things when PTEs |
12 | * within a page table are directly modified. Thus, the following |
13 | * hook is made available. |
14 | */ |
15 | static inline void native_set_pte(pte_t *ptep , pte_t pte) |
16 | { |
17 | *ptep = pte; |
18 | } |
19 | |
20 | static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd) |
21 | { |
22 | *pmdp = pmd; |
23 | } |
24 | |
25 | static inline void native_set_pud(pud_t *pudp, pud_t pud) |
26 | { |
27 | } |
28 | |
29 | static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) |
30 | { |
31 | native_set_pte(ptep, pte); |
32 | } |
33 | |
34 | static inline void native_pmd_clear(pmd_t *pmdp) |
35 | { |
36 | native_set_pmd(pmdp, pmd: __pmd(val: 0)); |
37 | } |
38 | |
39 | static inline void native_pud_clear(pud_t *pudp) |
40 | { |
41 | } |
42 | |
43 | static inline void native_pte_clear(struct mm_struct *mm, |
44 | unsigned long addr, pte_t *xp) |
45 | { |
46 | *xp = native_make_pte(val: 0); |
47 | } |
48 | |
49 | #ifdef CONFIG_SMP |
50 | static inline pte_t native_ptep_get_and_clear(pte_t *xp) |
51 | { |
52 | return __pte(xchg(&xp->pte_low, 0)); |
53 | } |
54 | #else |
55 | #define native_ptep_get_and_clear(xp) native_local_ptep_get_and_clear(xp) |
56 | #endif |
57 | |
58 | #ifdef CONFIG_SMP |
59 | static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp) |
60 | { |
61 | return __pmd(xchg((pmdval_t *)xp, 0)); |
62 | } |
63 | #else |
64 | #define native_pmdp_get_and_clear(xp) native_local_pmdp_get_and_clear(xp) |
65 | #endif |
66 | |
67 | #ifdef CONFIG_SMP |
68 | static inline pud_t native_pudp_get_and_clear(pud_t *xp) |
69 | { |
70 | return __pud(xchg((pudval_t *)xp, 0)); |
71 | } |
72 | #else |
73 | #define native_pudp_get_and_clear(xp) native_local_pudp_get_and_clear(xp) |
74 | #endif |
75 | |
76 | /* Bit manipulation helper on pte/pgoff entry */ |
77 | static inline unsigned long pte_bitop(unsigned long value, unsigned int rightshift, |
78 | unsigned long mask, unsigned int leftshift) |
79 | { |
80 | return ((value >> rightshift) & mask) << leftshift; |
81 | } |
82 | |
83 | /* |
84 | * Encode/decode swap entries and swap PTEs. Swap PTEs are all PTEs that |
85 | * are !pte_none() && !pte_present(). |
86 | * |
87 | * Format of swap PTEs: |
88 | * |
89 | * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 |
90 | * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
91 | * <----------------- offset ------------------> 0 E <- type --> 0 |
92 | * |
93 | * E is the exclusive marker that is not stored in swap entries. |
94 | */ |
95 | #define SWP_TYPE_BITS 5 |
96 | #define _SWP_TYPE_MASK ((1U << SWP_TYPE_BITS) - 1) |
97 | #define _SWP_TYPE_SHIFT (_PAGE_BIT_PRESENT + 1) |
98 | #define SWP_OFFSET_SHIFT (_PAGE_BIT_PROTNONE + 1) |
99 | |
100 | #define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > 5) |
101 | |
102 | #define __swp_type(x) (((x).val >> _SWP_TYPE_SHIFT) \ |
103 | & _SWP_TYPE_MASK) |
104 | #define __swp_offset(x) ((x).val >> SWP_OFFSET_SHIFT) |
105 | #define __swp_entry(type, offset) ((swp_entry_t) { \ |
106 | (((type) & _SWP_TYPE_MASK) << _SWP_TYPE_SHIFT) \ |
107 | | ((offset) << SWP_OFFSET_SHIFT) }) |
108 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_low }) |
109 | #define __swp_entry_to_pte(x) ((pte_t) { .pte = (x).val }) |
110 | |
111 | /* We borrow bit 7 to store the exclusive marker in swap PTEs. */ |
112 | #define _PAGE_SWP_EXCLUSIVE _PAGE_PSE |
113 | |
114 | /* No inverted PFNs on 2 level page tables */ |
115 | |
116 | static inline u64 protnone_mask(u64 val) |
117 | { |
118 | return 0; |
119 | } |
120 | |
121 | static inline u64 flip_protnone_guard(u64 oldval, u64 val, u64 mask) |
122 | { |
123 | return val; |
124 | } |
125 | |
126 | static inline bool __pte_needs_invert(u64 val) |
127 | { |
128 | return false; |
129 | } |
130 | |
131 | #endif /* _ASM_X86_PGTABLE_2LEVEL_H */ |
132 | |