File: /usr/src/linux/include/asm-s390x/pgtable.h
1 /*
2 * include/asm-s390/pgtable.h
3 *
4 * S390 64bit version
5 * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
6 * Author(s): Hartmut Penner (hp@de.ibm.com)
7 * Ulrich Weigand (weigand@de.ibm.com)
8 * Martin Schwidefsky (schwidefsky@de.ibm.com)
9 *
10 * Derived from "include/asm-i386/pgtable.h"
11 */
12
13 #ifndef _ASM_S390_PGTABLE_H
14 #define _ASM_S390_PGTABLE_H
15
16 /*
17 * The Linux memory management assumes a three-level page table setup. On
18 * the S390, we use that, but "fold" the mid level into the top-level page
19 * table, so that we physically have the same two-level page table as the
20 * S390 mmu expects.
21 *
22 * This file contains the functions and defines necessary to modify and use
23 * the S390 page table tree.
24 */
25 #ifndef __ASSEMBLY__
26 #include <asm/processor.h>
27 #include <linux/threads.h>
28
29 extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));
30 extern void paging_init(void);
31
32 /* Caches aren't brain-dead on S390. */
33 #define flush_cache_all() do { } while (0)
34 #define flush_cache_mm(mm) do { } while (0)
35 #define flush_cache_range(mm, start, end) do { } while (0)
36 #define flush_cache_page(vma, vmaddr) do { } while (0)
37 #define flush_page_to_ram(page) do { } while (0)
38 #define flush_dcache_page(page) do { } while (0)
39 #define flush_icache_range(start, end) do { } while (0)
40 #define flush_icache_page(vma,pg) do { } while (0)
41
42 /*
43 * The S390 doesn't have any external MMU info: the kernel page
44 * tables contain all the necessary information.
45 */
46 #define update_mmu_cache(vma, address, pte) do { } while (0)
47
48 /*
49 * ZERO_PAGE is a global shared page that is always zero: used
50 * for zero-mapped memory areas etc..
51 */
52 extern char empty_zero_page[PAGE_SIZE];
53 #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
54 #endif /* !__ASSEMBLY__ */
55
56 /*
57 * Certain architectures need to do special things when PTEs
58 * within a page table are directly modified. Thus, the following
59 * hook is made available.
60 */
61 #define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
62
63 /*
64 * PMD_SHIFT determines the size of the area a second-level page
65 * table can map
66 */
67 #define PMD_SHIFT 21
68 #define PMD_SIZE (1UL << PMD_SHIFT)
69 #define PMD_MASK (~(PMD_SIZE-1))
70
71 /* PGDIR_SHIFT determines what a third-level page table entry can map */
72 #define PGDIR_SHIFT 31
73 #define PGDIR_SIZE (1UL << PGDIR_SHIFT)
74 #define PGDIR_MASK (~(PGDIR_SIZE-1))
75
76 /*
77 * entries per page directory level: the S390 is two to five-level,
78 * currently we use a 3 level lookup
79 */
80 #define PTRS_PER_PTE 512
81 #define PTRS_PER_PMD 1024
82 #define PTRS_PER_PGD 2048
83
84 /*
85 * pgd entries used up by user/kernel:
86 */
87 #define USER_PTRS_PER_PGD 2048
88 #define USER_PGD_PTRS 2048
89 #define KERNEL_PGD_PTRS 2048
90 #define FIRST_USER_PGD_NR 0
91
92 #define pte_ERROR(e) \
93 printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
94 #define pmd_ERROR(e) \
95 printk("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e))
96 #define pgd_ERROR(e) \
97 printk("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e))
98
99 #ifndef __ASSEMBLY__
100 /*
101 * Just any arbitrary offset to the start of the vmalloc VM area: the
102 * current 8MB value just means that there will be a 8MB "hole" after the
103 * physical memory until the kernel virtual memory starts. That means that
104 * any out-of-bounds memory accesses will hopefully be caught.
105 * The vmalloc() routines leaves a hole of 4kB between each vmalloced
106 * area for the same reason. ;)
107 */
108 #define VMALLOC_OFFSET (8*1024*1024)
109 #define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) \
110 & ~(VMALLOC_OFFSET-1))
111 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
112 #define VMALLOC_END (0x40000000000L)
113
114
115 /*
116 * A pagetable entry of S390 has following format:
117 * | PFRA |0IP0| OS |
118 * 0000000000111111111122222222223333333333444444444455555555556666
119 * 0123456789012345678901234567890123456789012345678901234567890123
120 *
121 * I Page-Invalid Bit: Page is not available for address-translation
122 * P Page-Protection Bit: Store access not possible for page
123 *
124 * A segmenttable entry of S390 has following format:
125 * | P-table origin | TT
126 * 0000000000111111111122222222223333333333444444444455555555556666
127 * 0123456789012345678901234567890123456789012345678901234567890123
128 *
129 * I Segment-Invalid Bit: Segment is not available for address-translation
130 * C Common-Segment Bit: Segment is not private (PoP 3-30)
131 * P Page-Protection Bit: Store access not possible for page
132 * TT Type 00
133 *
134 * A region table entry of S390 has following format:
135 * | S-table origin | TF TTTL
136 * 0000000000111111111122222222223333333333444444444455555555556666
137 * 0123456789012345678901234567890123456789012345678901234567890123
138 *
139 * I Segment-Invalid Bit: Segment is not available for address-translation
140 * TT Type 01
141 * TF
142 * TL Table lenght
143 *
144 * The regiontable origin of S390 has following format:
145 * | region table origon | DTTL
146 * 0000000000111111111122222222223333333333444444444455555555556666
147 * 0123456789012345678901234567890123456789012345678901234567890123
148 *
149 * X Space-Switch event:
150 * G Segment-Invalid Bit:
151 * P Private-Space Bit:
152 * S Storage-Alteration:
153 * R Real space
154 * TL Table-Length:
155 *
156 * A storage key has the following format:
157 * | ACC |F|R|C|0|
158 * 0 3 4 5 6 7
159 * ACC: access key
160 * F : fetch protection bit
161 * R : referenced bit
162 * C : changed bit
163 */
164
165 /* Bits in the page table entry */
166 #define _PAGE_PRESENT 0x001 /* Software */
167 #define _PAGE_RO 0x200 /* HW read-only */
168 #define _PAGE_INVALID 0x400 /* HW invalid */
169
170 /* Bits in the segment table entry */
171 #define _PMD_ENTRY_INV 0x20 /* invalid segment table entry */
172 #define _PMD_ENTRY 0x00
173
174 /* Bits in the region third table entry */
175 #define _PGD_ENTRY_INV 0x20 /* invalid region table entry */
176 #define _PGD_ENTRY 0x07
177
178 /*
179 * User and kernel page directory
180 */
181 #define _REGION_THIRD 0x4
182 #define _REGION_THIRD_LEN 0x3
183 #define _REGION_TABLE (_REGION_THIRD|_REGION_THIRD_LEN|0x40)
184
185 /* Bits in the storage key */
186 #define _PAGE_CHANGED 0x02 /* HW changed bit */
187 #define _PAGE_REFERENCED 0x04 /* HW referenced bit */
188
189 /*
190 * No mapping available
191 */
192 #define PAGE_INVALID __pgprot(_PAGE_INVALID)
193 #define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_INVALID)
194 #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_RO)
195 #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_RO)
196 #define PAGE_SHARED __pgprot(_PAGE_PRESENT )
197 #define PAGE_KERNEL __pgprot(_PAGE_PRESENT )
198
199 /*
200 * The S390 can't do page protection for execute, and considers that the
201 * same are read. Also, write permissions imply read permissions. This is
202 * the closest we can get..
203 */
204 #define __P000 PAGE_NONE
205 #define __P001 PAGE_READONLY
206 #define __P010 PAGE_COPY
207 #define __P011 PAGE_COPY
208 #define __P100 PAGE_READONLY
209 #define __P101 PAGE_READONLY
210 #define __P110 PAGE_COPY
211 #define __P111 PAGE_COPY
212
213 #define __S000 PAGE_NONE
214 #define __S001 PAGE_READONLY
215 #define __S010 PAGE_SHARED
216 #define __S011 PAGE_SHARED
217 #define __S100 PAGE_READONLY
218 #define __S101 PAGE_READONLY
219 #define __S110 PAGE_SHARED
220 #define __S111 PAGE_SHARED
221
222 /*
223 * Permanent address of a page.
224 */
225 #define page_address(page) ((page)->virtual)
226 #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
227
228 /*
229 * pgd/pmd/pte query functions
230 */
231 extern inline int pgd_present(pgd_t pgd)
232 {
233 return (pgd_val(pgd) & ~PAGE_MASK) == _PGD_ENTRY;
234 }
235
236 extern inline int pgd_none(pgd_t pgd)
237 {
238 return pgd_val(pgd) & _PGD_ENTRY_INV;
239 }
240
241 extern inline int pgd_bad(pgd_t pgd)
242 {
243 return (pgd_val(pgd) & (~PAGE_MASK & ~_PGD_ENTRY_INV)) != _PGD_ENTRY;
244 }
245
246 extern inline int pmd_present(pmd_t pmd)
247 {
248 return (pmd_val(pmd) & ~PAGE_MASK) == _PMD_ENTRY;
249 }
250
251 extern inline int pmd_none(pmd_t pmd)
252 {
253 return pmd_val(pmd) & _PMD_ENTRY_INV;
254 }
255
256 extern inline int pmd_bad(pmd_t pmd)
257 {
258 return (pmd_val(pmd) & (~PAGE_MASK & ~_PMD_ENTRY_INV)) != _PMD_ENTRY;
259 }
260
261 extern inline int pte_present(pte_t pte)
262 {
263 return pte_val(pte) & _PAGE_PRESENT;
264 }
265
266 extern inline int pte_none(pte_t pte)
267 {
268 return ((pte_val(pte) &
269 (_PAGE_INVALID | _PAGE_RO | _PAGE_PRESENT)) == _PAGE_INVALID);
270 }
271
272 #define pte_same(a,b) (pte_val(a) == pte_val(b))
273
274 /*
275 * query functions pte_write/pte_dirty/pte_young only work if
276 * pte_present() is true. Undefined behaviour if not..
277 */
278 extern inline int pte_write(pte_t pte)
279 {
280 return (pte_val(pte) & _PAGE_RO) == 0;
281 }
282
283 extern inline int pte_dirty(pte_t pte)
284 {
285 int skey;
286
287 asm volatile ("iske %0,%1" : "=d" (skey) : "a" (pte_val(pte)));
288 return skey & _PAGE_CHANGED;
289 }
290
291 extern inline int pte_young(pte_t pte)
292 {
293 int skey;
294
295 asm volatile ("iske %0,%1" : "=d" (skey) : "a" (pte_val(pte)));
296 return skey & _PAGE_REFERENCED;
297 }
298
299 /*
300 * pgd/pmd/pte modification functions
301 */
302 extern inline void pgd_clear(pgd_t * pgdp)
303 {
304 pgd_val(*pgdp) = _PGD_ENTRY_INV | _PGD_ENTRY;
305 }
306
307 extern inline void pmd_clear(pmd_t * pmdp)
308 {
309 pmd_val(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY;
310 pmd_val1(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY;
311 }
312
313 extern inline void pte_clear(pte_t *ptep)
314 {
315 pte_val(*ptep) = _PAGE_INVALID;
316 }
317
318 #define PTE_INIT(x) pte_clear(x)
319
320 /*
321 * The following pte_modification functions only work if
322 * pte_present() is true. Undefined behaviour if not..
323 */
324 extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
325 {
326 pte_val(pte) = (pte_val(pte) & PAGE_MASK) | pgprot_val(newprot);
327 return pte;
328 }
329
330 extern inline pte_t pte_wrprotect(pte_t pte)
331 {
332 pte_val(pte) |= _PAGE_RO;
333 return pte;
334 }
335
336 extern inline pte_t pte_mkwrite(pte_t pte)
337 {
338 pte_val(pte) &= ~_PAGE_RO;
339 return pte;
340 }
341
342 extern inline pte_t pte_mkclean(pte_t pte)
343 {
344 /* We can't clear the changed bit atomically. The iske/and/sske
345 * sequence has a race condition with the page referenced bit.
346 * At the moment pte_mkclean is always followed by a pte_mkold.
347 * So its safe to ignore the problem for now. Hope this will
348 * never change ... */
349 asm volatile ("sske %0,%1"
350 : : "d" (0), "a" (pte_val(pte)));
351 return pte;
352 }
353
354 extern inline pte_t pte_mkdirty(pte_t pte)
355 {
356 /* We can't set the changed bit atomically either. For now we
357 * set (!) the page referenced bit. */
358 asm volatile ("sske %0,%1"
359 : : "d" (_PAGE_CHANGED|_PAGE_REFERENCED),
360 "a" (pte_val(pte)));
361 return pte;
362 }
363
364 extern inline pte_t pte_mkold(pte_t pte)
365 {
366 asm volatile ("rrbe 0,%0" : : "a" (pte_val(pte)) : "cc" );
367 return pte;
368 }
369
370 extern inline pte_t pte_mkyoung(pte_t pte)
371 {
372 /* To set the referenced bit we read the first word from the real
373 * page with a special instruction: load using real address (lura).
374 * Isn't S/390 a nice architecture ?! */
375 asm volatile ("lura 0,%0" : : "a" (pte_val(pte) & PAGE_MASK) : "0" );
376 return pte;
377 }
378
379 static inline int ptep_test_and_clear_young(pte_t *ptep)
380 {
381 int ccode;
382
383 asm volatile ("rrbe 0,%1\n\t"
384 "ipm %0\n\t"
385 "srl %0,28\n\t"
386 : "=d" (ccode) : "a" (pte_val(*ptep)) : "cc" );
387 return ccode & 2;
388 }
389
390 static inline int ptep_test_and_clear_dirty(pte_t *ptep)
391 {
392 int skey;
393
394 asm volatile ("iske %0,%1" : "=d" (skey) : "a" (*ptep));
395 if ((skey & _PAGE_CHANGED) == 0)
396 return 0;
397 /* We can't clear the changed bit atomically. For now we
398 * clear (!) the page referenced bit. */
399 asm volatile ("sske %0,%1"
400 : : "d" (0), "a" (*ptep));
401 return 1;
402 }
403
404 static inline pte_t ptep_get_and_clear(pte_t *ptep)
405 {
406 pte_t pte = *ptep;
407 pte_clear(ptep);
408 return pte;
409 }
410
411 static inline void ptep_set_wrprotect(pte_t *ptep)
412 {
413 pte_t old_pte = *ptep;
414 set_pte(ptep, pte_wrprotect(old_pte));
415 }
416
417 static inline void ptep_mkdirty(pte_t *ptep)
418 {
419 pte_mkdirty(*ptep);
420 }
421
422 /*
423 * Conversion functions: convert a page and protection to a page entry,
424 * and a page entry and page directory to the page they refer to.
425 */
426 extern inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
427 {
428 pte_t __pte;
429 pte_val(__pte) = physpage + pgprot_val(pgprot);
430 return __pte;
431 }
432 #define mk_pte(page,pgprot) mk_pte_phys(__pa(((page)-mem_map)<<PAGE_SHIFT),pgprot)
433
434 #define pte_page(x) (mem_map+(unsigned long)((pte_val(x) >> PAGE_SHIFT)))
435
436 #define pmd_page(pmd) \
437 ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
438
439 /* to find an entry in a page-table-directory */
440 #define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
441 #define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
442
443 #define pgd_page(pmd) \
444 ((unsigned long) __va(pgd_val(pmd) & PAGE_MASK))
445
446 /* to find an entry in a kernel page-table-directory */
447 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
448
449 /* Find an entry in the second-level page table.. */
450 #define pmd_offset(dir,addr) \
451 ((pmd_t *) pgd_page(*(dir)) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)))
452
453 /* Find an entry in the third-level page table.. */
454 #define pte_offset(dir,addr) \
455 ((pte_t *) pmd_page(*(dir)) + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
456
457 /*
458 * A page-table entry has some bits we have to treat in a special way.
459 * Bits 52 and bit 55 have to be zero, otherwise an specification
460 * exception will occur instead of a page translation exception. The
461 * specifiation exception has the bad habit not to store necessary
462 * information in the lowcore.
463 * Bit 53 and bit 54 are the page invalid bit and the page protection
464 * bit. We set both to indicate a swapped page.
465 * Bit 63 is used as the software page present bit. If a page is
466 * swapped this obviously has to be zero.
467 * This leaves the bits 0-51 and bits 56-62 to store type and offset.
468 * We use the 7 bits from 56-62 for the type and the 52 bits from 0-51
469 * for the offset.
470 * | offset |0110|type |0
471 * 0000000000111111111122222222223333333333444444444455555555556666
472 * 0123456789012345678901234567890123456789012345678901234567890123
473 */
474 extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
475 {
476 pte_t pte;
477 pte_val(pte) = (type << 1) | (offset << 12) | _PAGE_INVALID | _PAGE_RO;
478 pte_val(pte) &= 0xfffffffffffff6fe; /* better to be paranoid */
479 return pte;
480 }
481
482 #define SWP_TYPE(entry) (((entry).val >> 1) & 0x3f)
483 #define SWP_OFFSET(entry) ((entry).val >> 12)
484 #define SWP_ENTRY(type,offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) })
485
486 #define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
487 #define swp_entry_to_pte(x) ((pte_t) { (x).val })
488
489 #endif /* !__ASSEMBLY__ */
490
491 /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
492 #define PageSkip(page) (0)
493 #define kern_addr_valid(addr) (1)
494
495 #endif /* _S390_PAGE_H */
496
497