Commit | Line | Data |
---|---|---|
b0b5e9b1 AK |
1 | #ifndef _ASM_POWERPC_PGTABLE_RADIX_H |
2 | #define _ASM_POWERPC_PGTABLE_RADIX_H | |
3 | ||
4 | #ifndef __ASSEMBLY__ | |
5 | #include <asm/cmpxchg.h> | |
6 | #endif | |
7 | ||
8 | #ifdef CONFIG_PPC_64K_PAGES | |
9 | #include <asm/book3s/64/radix-64k.h> | |
10 | #else | |
11 | #include <asm/book3s/64/radix-4k.h> | |
12 | #endif | |
13 | ||
14 | /* An empty PTE can still have a R or C writeback */ | |
15 | #define RADIX_PTE_NONE_MASK (_PAGE_DIRTY | _PAGE_ACCESSED) | |
16 | ||
17 | /* Bits to set in a RPMD/RPUD/RPGD */ | |
18 | #define RADIX_PMD_VAL_BITS (0x8000000000000000UL | RADIX_PTE_INDEX_SIZE) | |
19 | #define RADIX_PUD_VAL_BITS (0x8000000000000000UL | RADIX_PMD_INDEX_SIZE) | |
20 | #define RADIX_PGD_VAL_BITS (0x8000000000000000UL | RADIX_PUD_INDEX_SIZE) | |
21 | ||
22 | /* Don't have anything in the reserved bits and leaf bits */ | |
23 | #define RADIX_PMD_BAD_BITS 0x60000000000000e0UL | |
24 | #define RADIX_PUD_BAD_BITS 0x60000000000000e0UL | |
25 | #define RADIX_PGD_BAD_BITS 0x60000000000000e0UL | |
26 | ||
27 | /* | |
28 | * Size of EA range mapped by our pagetables. | |
29 | */ | |
30 | #define RADIX_PGTABLE_EADDR_SIZE (RADIX_PTE_INDEX_SIZE + RADIX_PMD_INDEX_SIZE + \ | |
31 | RADIX_PUD_INDEX_SIZE + RADIX_PGD_INDEX_SIZE + PAGE_SHIFT) | |
32 | #define RADIX_PGTABLE_RANGE (ASM_CONST(1) << RADIX_PGTABLE_EADDR_SIZE) | |
33 | ||
34 | #ifndef __ASSEMBLY__ | |
35 | #define RADIX_PTE_TABLE_SIZE (sizeof(pte_t) << RADIX_PTE_INDEX_SIZE) | |
36 | #define RADIX_PMD_TABLE_SIZE (sizeof(pmd_t) << RADIX_PMD_INDEX_SIZE) | |
37 | #define RADIX_PUD_TABLE_SIZE (sizeof(pud_t) << RADIX_PUD_INDEX_SIZE) | |
38 | #define RADIX_PGD_TABLE_SIZE (sizeof(pgd_t) << RADIX_PGD_INDEX_SIZE) | |
39 | ||
40 | static inline unsigned long radix__pte_update(struct mm_struct *mm, | |
41 | unsigned long addr, | |
42 | pte_t *ptep, unsigned long clr, | |
43 | unsigned long set, | |
44 | int huge) | |
45 | { | |
46 | pte_t pte; | |
47 | unsigned long old_pte, new_pte; | |
48 | ||
49 | do { | |
50 | pte = READ_ONCE(*ptep); | |
51 | old_pte = pte_val(pte); | |
52 | new_pte = (old_pte | set) & ~clr; | |
53 | ||
54 | } while (!pte_xchg(ptep, __pte(old_pte), __pte(new_pte))); | |
55 | ||
56 | /* We already do a sync in cmpxchg, is ptesync needed ?*/ | |
57 | asm volatile("ptesync" : : : "memory"); | |
58 | /* huge pages use the old page table lock */ | |
59 | if (!huge) | |
60 | assert_pte_locked(mm, addr); | |
61 | ||
62 | return old_pte; | |
63 | } | |
64 | ||
65 | /* | |
66 | * Set the dirty and/or accessed bits atomically in a linux PTE, this | |
67 | * function doesn't need to invalidate tlb. | |
68 | */ | |
69 | static inline void radix__ptep_set_access_flags(pte_t *ptep, pte_t entry) | |
70 | { | |
71 | pte_t pte; | |
72 | unsigned long old_pte, new_pte; | |
73 | unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_ACCESSED | | |
74 | _PAGE_RW | _PAGE_EXEC); | |
75 | do { | |
76 | pte = READ_ONCE(*ptep); | |
77 | old_pte = pte_val(pte); | |
78 | new_pte = old_pte | set; | |
79 | ||
80 | } while (!pte_xchg(ptep, __pte(old_pte), __pte(new_pte))); | |
81 | ||
82 | /* We already do a sync in cmpxchg, is ptesync needed ?*/ | |
83 | asm volatile("ptesync" : : : "memory"); | |
84 | } | |
85 | ||
86 | static inline int radix__pte_same(pte_t pte_a, pte_t pte_b) | |
87 | { | |
88 | return ((pte_raw(pte_a) ^ pte_raw(pte_b)) == 0); | |
89 | } | |
90 | ||
91 | static inline int radix__pte_none(pte_t pte) | |
92 | { | |
93 | return (pte_val(pte) & ~RADIX_PTE_NONE_MASK) == 0; | |
94 | } | |
95 | ||
96 | static inline void radix__set_pte_at(struct mm_struct *mm, unsigned long addr, | |
97 | pte_t *ptep, pte_t pte, int percpu) | |
98 | { | |
99 | *ptep = pte; | |
100 | asm volatile("ptesync" : : : "memory"); | |
101 | } | |
102 | ||
103 | static inline int radix__pmd_bad(pmd_t pmd) | |
104 | { | |
105 | return !!(pmd_val(pmd) & RADIX_PMD_BAD_BITS); | |
106 | } | |
107 | ||
108 | static inline int radix__pmd_same(pmd_t pmd_a, pmd_t pmd_b) | |
109 | { | |
110 | return ((pmd_raw(pmd_a) ^ pmd_raw(pmd_b)) == 0); | |
111 | } | |
112 | ||
113 | static inline int radix__pud_bad(pud_t pud) | |
114 | { | |
115 | return !!(pud_val(pud) & RADIX_PUD_BAD_BITS); | |
116 | } | |
117 | ||
118 | ||
119 | static inline int radix__pgd_bad(pgd_t pgd) | |
120 | { | |
121 | return !!(pgd_val(pgd) & RADIX_PGD_BAD_BITS); | |
122 | } | |
123 | ||
6cc1a0ee AK |
124 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
125 | ||
126 | static inline int radix__pmd_trans_huge(pmd_t pmd) | |
127 | { | |
128 | return !!(pmd_val(pmd) & _PAGE_PTE); | |
129 | } | |
130 | ||
131 | #endif | |
132 | ||
b0b5e9b1 AK |
133 | #endif /* __ASSEMBLY__ */ |
134 | #endif |