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