aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-s390/pgtable.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-s390/pgtable.h')
-rw-r--r--include/asm-s390/pgtable.h163
1 files changed, 143 insertions, 20 deletions
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index 2d968a69ed1f..13c16546eff5 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -40,6 +40,7 @@ struct mm_struct;
40 40
41extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096))); 41extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));
42extern void paging_init(void); 42extern void paging_init(void);
43extern void vmem_map_init(void);
43 44
44/* 45/*
45 * The S390 doesn't have any external MMU info: the kernel page 46 * The S390 doesn't have any external MMU info: the kernel page
@@ -107,23 +108,25 @@ extern char empty_zero_page[PAGE_SIZE];
107 * The vmalloc() routines leaves a hole of 4kB between each vmalloced 108 * The vmalloc() routines leaves a hole of 4kB between each vmalloced
108 * area for the same reason. ;) 109 * area for the same reason. ;)
109 */ 110 */
111extern unsigned long vmalloc_end;
110#define VMALLOC_OFFSET (8*1024*1024) 112#define VMALLOC_OFFSET (8*1024*1024)
111#define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) \ 113#define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) \
112 & ~(VMALLOC_OFFSET-1)) 114 & ~(VMALLOC_OFFSET-1))
115#define VMALLOC_END vmalloc_end
113 116
114/* 117/*
115 * We need some free virtual space to be able to do vmalloc. 118 * We need some free virtual space to be able to do vmalloc.
116 * VMALLOC_MIN_SIZE defines the minimum size of the vmalloc 119 * VMALLOC_MIN_SIZE defines the minimum size of the vmalloc
117 * area. On a machine with 2GB memory we make sure that we 120 * area. On a machine with 2GB memory we make sure that we
118 * have at least 128MB free space for vmalloc. On a machine 121 * have at least 128MB free space for vmalloc. On a machine
119 * with 4TB we make sure we have at least 1GB. 122 * with 4TB we make sure we have at least 128GB.
120 */ 123 */
121#ifndef __s390x__ 124#ifndef __s390x__
122#define VMALLOC_MIN_SIZE 0x8000000UL 125#define VMALLOC_MIN_SIZE 0x8000000UL
123#define VMALLOC_END 0x80000000UL 126#define VMALLOC_END_INIT 0x80000000UL
124#else /* __s390x__ */ 127#else /* __s390x__ */
125#define VMALLOC_MIN_SIZE 0x40000000UL 128#define VMALLOC_MIN_SIZE 0x2000000000UL
126#define VMALLOC_END 0x40000000000UL 129#define VMALLOC_END_INIT 0x40000000000UL
127#endif /* __s390x__ */ 130#endif /* __s390x__ */
128 131
129/* 132/*
@@ -221,6 +224,8 @@ extern char empty_zero_page[PAGE_SIZE];
221#define _PAGE_TYPE_FILE 0x601 /* bit 0x002 is used for offset !! */ 224#define _PAGE_TYPE_FILE 0x601 /* bit 0x002 is used for offset !! */
222#define _PAGE_TYPE_RO 0x200 225#define _PAGE_TYPE_RO 0x200
223#define _PAGE_TYPE_RW 0x000 226#define _PAGE_TYPE_RW 0x000
227#define _PAGE_TYPE_EX_RO 0x202
228#define _PAGE_TYPE_EX_RW 0x002
224 229
225/* 230/*
226 * PTE type bits are rather complicated. handle_pte_fault uses pte_present, 231 * PTE type bits are rather complicated. handle_pte_fault uses pte_present,
@@ -241,11 +246,13 @@ extern char empty_zero_page[PAGE_SIZE];
241 * _PAGE_TYPE_FILE 11?1 -> 11?1 246 * _PAGE_TYPE_FILE 11?1 -> 11?1
242 * _PAGE_TYPE_RO 0100 -> 1100 247 * _PAGE_TYPE_RO 0100 -> 1100
243 * _PAGE_TYPE_RW 0000 -> 1000 248 * _PAGE_TYPE_RW 0000 -> 1000
249 * _PAGE_TYPE_EX_RO 0110 -> 1110
250 * _PAGE_TYPE_EX_RW 0010 -> 1010
244 * 251 *
245 * pte_none is true for bits combinations 1000, 1100 252 * pte_none is true for bits combinations 1000, 1010, 1100, 1110
246 * pte_present is true for bits combinations 0000, 0010, 0100, 0110, 1001 253 * pte_present is true for bits combinations 0000, 0010, 0100, 0110, 1001
247 * pte_file is true for bits combinations 1101, 1111 254 * pte_file is true for bits combinations 1101, 1111
248 * swap pte is 1011 and 0001, 0011, 0101, 0111, 1010 and 1110 are invalid. 255 * swap pte is 1011 and 0001, 0011, 0101, 0111 are invalid.
249 */ 256 */
250 257
251#ifndef __s390x__ 258#ifndef __s390x__
@@ -310,33 +317,100 @@ extern char empty_zero_page[PAGE_SIZE];
310#define PAGE_NONE __pgprot(_PAGE_TYPE_NONE) 317#define PAGE_NONE __pgprot(_PAGE_TYPE_NONE)
311#define PAGE_RO __pgprot(_PAGE_TYPE_RO) 318#define PAGE_RO __pgprot(_PAGE_TYPE_RO)
312#define PAGE_RW __pgprot(_PAGE_TYPE_RW) 319#define PAGE_RW __pgprot(_PAGE_TYPE_RW)
320#define PAGE_EX_RO __pgprot(_PAGE_TYPE_EX_RO)
321#define PAGE_EX_RW __pgprot(_PAGE_TYPE_EX_RW)
313 322
314#define PAGE_KERNEL PAGE_RW 323#define PAGE_KERNEL PAGE_RW
315#define PAGE_COPY PAGE_RO 324#define PAGE_COPY PAGE_RO
316 325
317/* 326/*
318 * The S390 can't do page protection for execute, and considers that the 327 * Dependent on the EXEC_PROTECT option s390 can do execute protection.
319 * same are read. Also, write permissions imply read permissions. This is 328 * Write permission always implies read permission. In theory with a
320 * the closest we can get.. 329 * primary/secondary page table execute only can be implemented but
330 * it would cost an additional bit in the pte to distinguish all the
331 * different pte types. To avoid that execute permission currently
332 * implies read permission as well.
321 */ 333 */
322 /*xwr*/ 334 /*xwr*/
323#define __P000 PAGE_NONE 335#define __P000 PAGE_NONE
324#define __P001 PAGE_RO 336#define __P001 PAGE_RO
325#define __P010 PAGE_RO 337#define __P010 PAGE_RO
326#define __P011 PAGE_RO 338#define __P011 PAGE_RO
327#define __P100 PAGE_RO 339#define __P100 PAGE_EX_RO
328#define __P101 PAGE_RO 340#define __P101 PAGE_EX_RO
329#define __P110 PAGE_RO 341#define __P110 PAGE_EX_RO
330#define __P111 PAGE_RO 342#define __P111 PAGE_EX_RO
331 343
332#define __S000 PAGE_NONE 344#define __S000 PAGE_NONE
333#define __S001 PAGE_RO 345#define __S001 PAGE_RO
334#define __S010 PAGE_RW 346#define __S010 PAGE_RW
335#define __S011 PAGE_RW 347#define __S011 PAGE_RW
336#define __S100 PAGE_RO 348#define __S100 PAGE_EX_RO
337#define __S101 PAGE_RO 349#define __S101 PAGE_EX_RO
338#define __S110 PAGE_RW 350#define __S110 PAGE_EX_RW
339#define __S111 PAGE_RW 351#define __S111 PAGE_EX_RW
352
353#ifndef __s390x__
354# define PMD_SHADOW_SHIFT 1
355# define PGD_SHADOW_SHIFT 1
356#else /* __s390x__ */
357# define PMD_SHADOW_SHIFT 2
358# define PGD_SHADOW_SHIFT 2
359#endif /* __s390x__ */
360
361static inline struct page *get_shadow_page(struct page *page)
362{
363 if (s390_noexec && !list_empty(&page->lru))
364 return virt_to_page(page->lru.next);
365 return NULL;
366}
367
368static inline pte_t *get_shadow_pte(pte_t *ptep)
369{
370 unsigned long pteptr = (unsigned long) (ptep);
371
372 if (s390_noexec) {
373 unsigned long offset = pteptr & (PAGE_SIZE - 1);
374 void *addr = (void *) (pteptr ^ offset);
375 struct page *page = virt_to_page(addr);
376 if (!list_empty(&page->lru))
377 return (pte_t *) ((unsigned long) page->lru.next |
378 offset);
379 }
380 return NULL;
381}
382
383static inline pmd_t *get_shadow_pmd(pmd_t *pmdp)
384{
385 unsigned long pmdptr = (unsigned long) (pmdp);
386
387 if (s390_noexec) {
388 unsigned long offset = pmdptr &
389 ((PAGE_SIZE << PMD_SHADOW_SHIFT) - 1);
390 void *addr = (void *) (pmdptr ^ offset);
391 struct page *page = virt_to_page(addr);
392 if (!list_empty(&page->lru))
393 return (pmd_t *) ((unsigned long) page->lru.next |
394 offset);
395 }
396 return NULL;
397}
398
399static inline pgd_t *get_shadow_pgd(pgd_t *pgdp)
400{
401 unsigned long pgdptr = (unsigned long) (pgdp);
402
403 if (s390_noexec) {
404 unsigned long offset = pgdptr &
405 ((PAGE_SIZE << PGD_SHADOW_SHIFT) - 1);
406 void *addr = (void *) (pgdptr ^ offset);
407 struct page *page = virt_to_page(addr);
408 if (!list_empty(&page->lru))
409 return (pgd_t *) ((unsigned long) page->lru.next |
410 offset);
411 }
412 return NULL;
413}
340 414
341/* 415/*
342 * Certain architectures need to do special things when PTEs 416 * Certain architectures need to do special things when PTEs
@@ -345,7 +419,16 @@ extern char empty_zero_page[PAGE_SIZE];
345 */ 419 */
346static inline void set_pte(pte_t *pteptr, pte_t pteval) 420static inline void set_pte(pte_t *pteptr, pte_t pteval)
347{ 421{
422 pte_t *shadow_pte = get_shadow_pte(pteptr);
423
348 *pteptr = pteval; 424 *pteptr = pteval;
425 if (shadow_pte) {
426 if (!(pte_val(pteval) & _PAGE_INVALID) &&
427 (pte_val(pteval) & _PAGE_SWX))
428 pte_val(*shadow_pte) = pte_val(pteval) | _PAGE_RO;
429 else
430 pte_val(*shadow_pte) = _PAGE_TYPE_EMPTY;
431 }
349} 432}
350#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) 433#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
351 434
@@ -463,7 +546,7 @@ static inline int pte_read(pte_t pte)
463 546
464static inline void pgd_clear(pgd_t * pgdp) { } 547static inline void pgd_clear(pgd_t * pgdp) { }
465 548
466static inline void pmd_clear(pmd_t * pmdp) 549static inline void pmd_clear_kernel(pmd_t * pmdp)
467{ 550{
468 pmd_val(pmdp[0]) = _PAGE_TABLE_INV; 551 pmd_val(pmdp[0]) = _PAGE_TABLE_INV;
469 pmd_val(pmdp[1]) = _PAGE_TABLE_INV; 552 pmd_val(pmdp[1]) = _PAGE_TABLE_INV;
@@ -471,24 +554,55 @@ static inline void pmd_clear(pmd_t * pmdp)
471 pmd_val(pmdp[3]) = _PAGE_TABLE_INV; 554 pmd_val(pmdp[3]) = _PAGE_TABLE_INV;
472} 555}
473 556
557static inline void pmd_clear(pmd_t * pmdp)
558{
559 pmd_t *shadow_pmd = get_shadow_pmd(pmdp);
560
561 pmd_clear_kernel(pmdp);
562 if (shadow_pmd)
563 pmd_clear_kernel(shadow_pmd);
564}
565
474#else /* __s390x__ */ 566#else /* __s390x__ */
475 567
476static inline void pgd_clear(pgd_t * pgdp) 568static inline void pgd_clear_kernel(pgd_t * pgdp)
477{ 569{
478 pgd_val(*pgdp) = _PGD_ENTRY_INV | _PGD_ENTRY; 570 pgd_val(*pgdp) = _PGD_ENTRY_INV | _PGD_ENTRY;
479} 571}
480 572
481static inline void pmd_clear(pmd_t * pmdp) 573static inline void pgd_clear(pgd_t * pgdp)
574{
575 pgd_t *shadow_pgd = get_shadow_pgd(pgdp);
576
577 pgd_clear_kernel(pgdp);
578 if (shadow_pgd)
579 pgd_clear_kernel(shadow_pgd);
580}
581
582static inline void pmd_clear_kernel(pmd_t * pmdp)
482{ 583{
483 pmd_val(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY; 584 pmd_val(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY;
484 pmd_val1(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY; 585 pmd_val1(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY;
485} 586}
486 587
588static inline void pmd_clear(pmd_t * pmdp)
589{
590 pmd_t *shadow_pmd = get_shadow_pmd(pmdp);
591
592 pmd_clear_kernel(pmdp);
593 if (shadow_pmd)
594 pmd_clear_kernel(shadow_pmd);
595}
596
487#endif /* __s390x__ */ 597#endif /* __s390x__ */
488 598
489static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) 599static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
490{ 600{
601 pte_t *shadow_pte = get_shadow_pte(ptep);
602
491 pte_val(*ptep) = _PAGE_TYPE_EMPTY; 603 pte_val(*ptep) = _PAGE_TYPE_EMPTY;
604 if (shadow_pte)
605 pte_val(*shadow_pte) = _PAGE_TYPE_EMPTY;
492} 606}
493 607
494/* 608/*
@@ -606,8 +720,11 @@ ptep_clear_flush(struct vm_area_struct *vma,
606 unsigned long address, pte_t *ptep) 720 unsigned long address, pte_t *ptep)
607{ 721{
608 pte_t pte = *ptep; 722 pte_t pte = *ptep;
723 pte_t *shadow_pte = get_shadow_pte(ptep);
609 724
610 __ptep_ipte(address, ptep); 725 __ptep_ipte(address, ptep);
726 if (shadow_pte)
727 __ptep_ipte(address, shadow_pte);
611 return pte; 728 return pte;
612} 729}
613 730
@@ -815,11 +932,17 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
815 932
816#define kern_addr_valid(addr) (1) 933#define kern_addr_valid(addr) (1)
817 934
935extern int add_shared_memory(unsigned long start, unsigned long size);
936extern int remove_shared_memory(unsigned long start, unsigned long size);
937
818/* 938/*
819 * No page table caches to initialise 939 * No page table caches to initialise
820 */ 940 */
821#define pgtable_cache_init() do { } while (0) 941#define pgtable_cache_init() do { } while (0)
822 942
943#define __HAVE_ARCH_MEMMAP_INIT
944extern void memmap_init(unsigned long, int, unsigned long, unsigned long);
945
823#define __HAVE_ARCH_PTEP_ESTABLISH 946#define __HAVE_ARCH_PTEP_ESTABLISH
824#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS 947#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
825#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG 948#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG