diff options
Diffstat (limited to 'arch/s390/include/asm/page.h')
-rw-r--r-- | arch/s390/include/asm/page.h | 60 |
1 files changed, 54 insertions, 6 deletions
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index 3c987e9ec8d6..accb372ddc7e 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h | |||
@@ -90,6 +90,7 @@ static inline void copy_page(void *to, void *from) | |||
90 | */ | 90 | */ |
91 | 91 | ||
92 | typedef struct { unsigned long pgprot; } pgprot_t; | 92 | typedef struct { unsigned long pgprot; } pgprot_t; |
93 | typedef struct { unsigned long pgste; } pgste_t; | ||
93 | typedef struct { unsigned long pte; } pte_t; | 94 | typedef struct { unsigned long pte; } pte_t; |
94 | typedef struct { unsigned long pmd; } pmd_t; | 95 | typedef struct { unsigned long pmd; } pmd_t; |
95 | typedef struct { unsigned long pud; } pud_t; | 96 | typedef struct { unsigned long pud; } pud_t; |
@@ -97,18 +98,21 @@ typedef struct { unsigned long pgd; } pgd_t; | |||
97 | typedef pte_t *pgtable_t; | 98 | typedef pte_t *pgtable_t; |
98 | 99 | ||
99 | #define pgprot_val(x) ((x).pgprot) | 100 | #define pgprot_val(x) ((x).pgprot) |
101 | #define pgste_val(x) ((x).pgste) | ||
100 | #define pte_val(x) ((x).pte) | 102 | #define pte_val(x) ((x).pte) |
101 | #define pmd_val(x) ((x).pmd) | 103 | #define pmd_val(x) ((x).pmd) |
102 | #define pud_val(x) ((x).pud) | 104 | #define pud_val(x) ((x).pud) |
103 | #define pgd_val(x) ((x).pgd) | 105 | #define pgd_val(x) ((x).pgd) |
104 | 106 | ||
107 | #define __pgste(x) ((pgste_t) { (x) } ) | ||
105 | #define __pte(x) ((pte_t) { (x) } ) | 108 | #define __pte(x) ((pte_t) { (x) } ) |
106 | #define __pmd(x) ((pmd_t) { (x) } ) | 109 | #define __pmd(x) ((pmd_t) { (x) } ) |
110 | #define __pud(x) ((pud_t) { (x) } ) | ||
107 | #define __pgd(x) ((pgd_t) { (x) } ) | 111 | #define __pgd(x) ((pgd_t) { (x) } ) |
108 | #define __pgprot(x) ((pgprot_t) { (x) } ) | 112 | #define __pgprot(x) ((pgprot_t) { (x) } ) |
109 | 113 | ||
110 | static inline void | 114 | static inline void page_set_storage_key(unsigned long addr, |
111 | page_set_storage_key(unsigned long addr, unsigned int skey, int mapped) | 115 | unsigned char skey, int mapped) |
112 | { | 116 | { |
113 | if (!mapped) | 117 | if (!mapped) |
114 | asm volatile(".insn rrf,0xb22b0000,%0,%1,8,0" | 118 | asm volatile(".insn rrf,0xb22b0000,%0,%1,8,0" |
@@ -117,15 +121,59 @@ page_set_storage_key(unsigned long addr, unsigned int skey, int mapped) | |||
117 | asm volatile("sske %0,%1" : : "d" (skey), "a" (addr)); | 121 | asm volatile("sske %0,%1" : : "d" (skey), "a" (addr)); |
118 | } | 122 | } |
119 | 123 | ||
120 | static inline unsigned int | 124 | static inline unsigned char page_get_storage_key(unsigned long addr) |
121 | page_get_storage_key(unsigned long addr) | ||
122 | { | 125 | { |
123 | unsigned int skey; | 126 | unsigned char skey; |
124 | 127 | ||
125 | asm volatile("iske %0,%1" : "=d" (skey) : "a" (addr), "0" (0)); | 128 | asm volatile("iske %0,%1" : "=d" (skey) : "a" (addr)); |
126 | return skey; | 129 | return skey; |
127 | } | 130 | } |
128 | 131 | ||
132 | static inline int page_reset_referenced(unsigned long addr) | ||
133 | { | ||
134 | unsigned int ipm; | ||
135 | |||
136 | asm volatile( | ||
137 | " rrbe 0,%1\n" | ||
138 | " ipm %0\n" | ||
139 | : "=d" (ipm) : "a" (addr) : "cc"); | ||
140 | return !!(ipm & 0x20000000); | ||
141 | } | ||
142 | |||
143 | /* Bits int the storage key */ | ||
144 | #define _PAGE_CHANGED 0x02 /* HW changed bit */ | ||
145 | #define _PAGE_REFERENCED 0x04 /* HW referenced bit */ | ||
146 | #define _PAGE_FP_BIT 0x08 /* HW fetch protection bit */ | ||
147 | #define _PAGE_ACC_BITS 0xf0 /* HW access control bits */ | ||
148 | |||
149 | /* | ||
150 | * Test and clear dirty bit in storage key. | ||
151 | * We can't clear the changed bit atomically. This is a potential | ||
152 | * race against modification of the referenced bit. This function | ||
153 | * should therefore only be called if it is not mapped in any | ||
154 | * address space. | ||
155 | */ | ||
156 | #define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY | ||
157 | static inline int page_test_and_clear_dirty(unsigned long pfn, int mapped) | ||
158 | { | ||
159 | unsigned char skey; | ||
160 | |||
161 | skey = page_get_storage_key(pfn << PAGE_SHIFT); | ||
162 | if (!(skey & _PAGE_CHANGED)) | ||
163 | return 0; | ||
164 | page_set_storage_key(pfn << PAGE_SHIFT, skey & ~_PAGE_CHANGED, mapped); | ||
165 | return 1; | ||
166 | } | ||
167 | |||
168 | /* | ||
169 | * Test and clear referenced bit in storage key. | ||
170 | */ | ||
171 | #define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG | ||
172 | static inline int page_test_and_clear_young(unsigned long pfn) | ||
173 | { | ||
174 | return page_reset_referenced(pfn << PAGE_SHIFT); | ||
175 | } | ||
176 | |||
129 | struct page; | 177 | struct page; |
130 | void arch_free_page(struct page *page, int order); | 178 | void arch_free_page(struct page *page, int order); |
131 | void arch_alloc_page(struct page *page, int order); | 179 | void arch_alloc_page(struct page *page, int order); |