Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
1965aae3 PA |
2 | #ifndef _ASM_X86_PGTABLE_2LEVEL_H |
3 | #define _ASM_X86_PGTABLE_2LEVEL_H | |
1da177e4 | 4 | |
1da177e4 | 5 | #define pte_ERROR(e) \ |
c767a54b | 6 | pr_err("%s:%d: bad pte %08lx\n", __FILE__, __LINE__, (e).pte_low) |
1da177e4 | 7 | #define pgd_ERROR(e) \ |
c767a54b | 8 | pr_err("%s:%d: bad pgd %08lx\n", __FILE__, __LINE__, pgd_val(e)) |
1da177e4 LT |
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 | */ | |
3dc494e8 JF |
15 | static inline void native_set_pte(pte_t *ptep , pte_t pte) |
16 | { | |
17 | *ptep = pte; | |
18 | } | |
4891645e | 19 | |
3dc494e8 JF |
20 | static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd) |
21 | { | |
22 | *pmdp = pmd; | |
23 | } | |
da181a8b | 24 | |
a00cc7d9 MW |
25 | static inline void native_set_pud(pud_t *pudp, pud_t pud) |
26 | { | |
27 | } | |
28 | ||
4891645e JF |
29 | static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) |
30 | { | |
31 | native_set_pte(ptep, pte); | |
32 | } | |
1da177e4 | 33 | |
4891645e JF |
34 | static inline void native_pmd_clear(pmd_t *pmdp) |
35 | { | |
36 | native_set_pmd(pmdp, __pmd(0)); | |
37 | } | |
6e5882cf | 38 | |
a00cc7d9 MW |
39 | static inline void native_pud_clear(pud_t *pudp) |
40 | { | |
41 | } | |
42 | ||
65e05d15 JP |
43 | static inline void native_pte_clear(struct mm_struct *mm, |
44 | unsigned long addr, pte_t *xp) | |
c2c1accd | 45 | { |
4891645e | 46 | *xp = native_make_pte(0); |
c2c1accd ZA |
47 | } |
48 | ||
142dd975 | 49 | #ifdef CONFIG_SMP |
3dc494e8 JF |
50 | static inline pte_t native_ptep_get_and_clear(pte_t *xp) |
51 | { | |
52 | return __pte(xchg(&xp->pte_low, 0)); | |
53 | } | |
142dd975 ZA |
54 | #else |
55 | #define native_ptep_get_and_clear(xp) native_local_ptep_get_and_clear(xp) | |
56 | #endif | |
6049742d | 57 | |
f2d6bfe9 JW |
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 | ||
a00cc7d9 MW |
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 | ||
5305ca10 CG |
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 | ||
93c0eac4 DH |
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 | */ | |
0a191362 | 95 | #define SWP_TYPE_BITS 5 |
93c0eac4 DH |
96 | #define _SWP_TYPE_MASK ((1U << SWP_TYPE_BITS) - 1) |
97 | #define _SWP_TYPE_SHIFT (_PAGE_BIT_PRESENT + 1) | |
1796316a | 98 | #define SWP_OFFSET_SHIFT (_PAGE_BIT_PROTNONE + 1) |
1796316a | 99 | |
93c0eac4 | 100 | #define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > 5) |
1796316a | 101 | |
93c0eac4 DH |
102 | #define __swp_type(x) (((x).val >> _SWP_TYPE_SHIFT) \ |
103 | & _SWP_TYPE_MASK) | |
1796316a JB |
104 | #define __swp_offset(x) ((x).val >> SWP_OFFSET_SHIFT) |
105 | #define __swp_entry(type, offset) ((swp_entry_t) { \ | |
93c0eac4 | 106 | (((type) & _SWP_TYPE_MASK) << _SWP_TYPE_SHIFT) \ |
1796316a | 107 | | ((offset) << SWP_OFFSET_SHIFT) }) |
1da177e4 | 108 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_low }) |
c8e5393a | 109 | #define __swp_entry_to_pte(x) ((pte_t) { .pte = (x).val }) |
1da177e4 | 110 | |
93c0eac4 DH |
111 | /* We borrow bit 7 to store the exclusive marker in swap PTEs. */ |
112 | #define _PAGE_SWP_EXCLUSIVE _PAGE_PSE | |
113 | ||
6b28baca AK |
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 | ||
1965aae3 | 131 | #endif /* _ASM_X86_PGTABLE_2LEVEL_H */ |