diff options
Diffstat (limited to 'arch/s390/include/asm/page.h')
-rw-r--r-- | arch/s390/include/asm/page.h | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index 3c987e9ec8d..81ee2776088 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h | |||
@@ -107,8 +107,8 @@ typedef pte_t *pgtable_t; | |||
107 | #define __pgd(x) ((pgd_t) { (x) } ) | 107 | #define __pgd(x) ((pgd_t) { (x) } ) |
108 | #define __pgprot(x) ((pgprot_t) { (x) } ) | 108 | #define __pgprot(x) ((pgprot_t) { (x) } ) |
109 | 109 | ||
110 | static inline void | 110 | static inline void page_set_storage_key(unsigned long addr, |
111 | page_set_storage_key(unsigned long addr, unsigned int skey, int mapped) | 111 | unsigned char skey, int mapped) |
112 | { | 112 | { |
113 | if (!mapped) | 113 | if (!mapped) |
114 | asm volatile(".insn rrf,0xb22b0000,%0,%1,8,0" | 114 | asm volatile(".insn rrf,0xb22b0000,%0,%1,8,0" |
@@ -117,15 +117,59 @@ page_set_storage_key(unsigned long addr, unsigned int skey, int mapped) | |||
117 | asm volatile("sske %0,%1" : : "d" (skey), "a" (addr)); | 117 | asm volatile("sske %0,%1" : : "d" (skey), "a" (addr)); |
118 | } | 118 | } |
119 | 119 | ||
120 | static inline unsigned int | 120 | static inline unsigned char page_get_storage_key(unsigned long addr) |
121 | page_get_storage_key(unsigned long addr) | ||
122 | { | 121 | { |
123 | unsigned int skey; | 122 | unsigned char skey; |
124 | 123 | ||
125 | asm volatile("iske %0,%1" : "=d" (skey) : "a" (addr), "0" (0)); | 124 | asm volatile("iske %0,%1" : "=d" (skey) : "a" (addr)); |
126 | return skey; | 125 | return skey; |
127 | } | 126 | } |
128 | 127 | ||
128 | static inline int page_reset_referenced(unsigned long addr) | ||
129 | { | ||
130 | unsigned int ipm; | ||
131 | |||
132 | asm volatile( | ||
133 | " rrbe 0,%1\n" | ||
134 | " ipm %0\n" | ||
135 | : "=d" (ipm) : "a" (addr) : "cc"); | ||
136 | return !!(ipm & 0x20000000); | ||
137 | } | ||
138 | |||
139 | /* Bits int the storage key */ | ||
140 | #define _PAGE_CHANGED 0x02 /* HW changed bit */ | ||
141 | #define _PAGE_REFERENCED 0x04 /* HW referenced bit */ | ||
142 | #define _PAGE_FP_BIT 0x08 /* HW fetch protection bit */ | ||
143 | #define _PAGE_ACC_BITS 0xf0 /* HW access control bits */ | ||
144 | |||
145 | /* | ||
146 | * Test and clear dirty bit in storage key. | ||
147 | * We can't clear the changed bit atomically. This is a potential | ||
148 | * race against modification of the referenced bit. This function | ||
149 | * should therefore only be called if it is not mapped in any | ||
150 | * address space. | ||
151 | */ | ||
152 | #define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY | ||
153 | static inline int page_test_and_clear_dirty(unsigned long pfn, int mapped) | ||
154 | { | ||
155 | unsigned char skey; | ||
156 | |||
157 | skey = page_get_storage_key(pfn << PAGE_SHIFT); | ||
158 | if (!(skey & _PAGE_CHANGED)) | ||
159 | return 0; | ||
160 | page_set_storage_key(pfn << PAGE_SHIFT, skey & ~_PAGE_CHANGED, mapped); | ||
161 | return 1; | ||
162 | } | ||
163 | |||
164 | /* | ||
165 | * Test and clear referenced bit in storage key. | ||
166 | */ | ||
167 | #define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG | ||
168 | static inline int page_test_and_clear_young(unsigned long pfn) | ||
169 | { | ||
170 | return page_reset_referenced(pfn << PAGE_SHIFT); | ||
171 | } | ||
172 | |||
129 | struct page; | 173 | struct page; |
130 | void arch_free_page(struct page *page, int order); | 174 | void arch_free_page(struct page *page, int order); |
131 | void arch_alloc_page(struct page *page, int order); | 175 | void arch_alloc_page(struct page *page, int order); |