diff options
Diffstat (limited to 'arch/s390/include/asm/pgtable.h')
-rw-r--r-- | arch/s390/include/asm/pgtable.h | 75 |
1 files changed, 11 insertions, 64 deletions
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 02ace3491c51..763620ec7925 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h | |||
@@ -256,8 +256,6 @@ extern unsigned long VMALLOC_START; | |||
256 | #define _PAGE_TYPE_FILE 0x601 /* bit 0x002 is used for offset !! */ | 256 | #define _PAGE_TYPE_FILE 0x601 /* bit 0x002 is used for offset !! */ |
257 | #define _PAGE_TYPE_RO 0x200 | 257 | #define _PAGE_TYPE_RO 0x200 |
258 | #define _PAGE_TYPE_RW 0x000 | 258 | #define _PAGE_TYPE_RW 0x000 |
259 | #define _PAGE_TYPE_EX_RO 0x202 | ||
260 | #define _PAGE_TYPE_EX_RW 0x002 | ||
261 | 259 | ||
262 | /* | 260 | /* |
263 | * Only four types for huge pages, using the invalid bit and protection bit | 261 | * Only four types for huge pages, using the invalid bit and protection bit |
@@ -287,8 +285,6 @@ extern unsigned long VMALLOC_START; | |||
287 | * _PAGE_TYPE_FILE 11?1 -> 11?1 | 285 | * _PAGE_TYPE_FILE 11?1 -> 11?1 |
288 | * _PAGE_TYPE_RO 0100 -> 1100 | 286 | * _PAGE_TYPE_RO 0100 -> 1100 |
289 | * _PAGE_TYPE_RW 0000 -> 1000 | 287 | * _PAGE_TYPE_RW 0000 -> 1000 |
290 | * _PAGE_TYPE_EX_RO 0110 -> 1110 | ||
291 | * _PAGE_TYPE_EX_RW 0010 -> 1010 | ||
292 | * | 288 | * |
293 | * pte_none is true for bits combinations 1000, 1010, 1100, 1110 | 289 | * pte_none is true for bits combinations 1000, 1010, 1100, 1110 |
294 | * pte_present is true for bits combinations 0000, 0010, 0100, 0110, 1001 | 290 | * pte_present is true for bits combinations 0000, 0010, 0100, 0110, 1001 |
@@ -387,55 +383,33 @@ extern unsigned long VMALLOC_START; | |||
387 | #define PAGE_NONE __pgprot(_PAGE_TYPE_NONE) | 383 | #define PAGE_NONE __pgprot(_PAGE_TYPE_NONE) |
388 | #define PAGE_RO __pgprot(_PAGE_TYPE_RO) | 384 | #define PAGE_RO __pgprot(_PAGE_TYPE_RO) |
389 | #define PAGE_RW __pgprot(_PAGE_TYPE_RW) | 385 | #define PAGE_RW __pgprot(_PAGE_TYPE_RW) |
390 | #define PAGE_EX_RO __pgprot(_PAGE_TYPE_EX_RO) | ||
391 | #define PAGE_EX_RW __pgprot(_PAGE_TYPE_EX_RW) | ||
392 | 386 | ||
393 | #define PAGE_KERNEL PAGE_RW | 387 | #define PAGE_KERNEL PAGE_RW |
394 | #define PAGE_COPY PAGE_RO | 388 | #define PAGE_COPY PAGE_RO |
395 | 389 | ||
396 | /* | 390 | /* |
397 | * Dependent on the EXEC_PROTECT option s390 can do execute protection. | 391 | * On s390 the page table entry has an invalid bit and a read-only bit. |
398 | * Write permission always implies read permission. In theory with a | 392 | * Read permission implies execute permission and write permission |
399 | * primary/secondary page table execute only can be implemented but | 393 | * implies read permission. |
400 | * it would cost an additional bit in the pte to distinguish all the | ||
401 | * different pte types. To avoid that execute permission currently | ||
402 | * implies read permission as well. | ||
403 | */ | 394 | */ |
404 | /*xwr*/ | 395 | /*xwr*/ |
405 | #define __P000 PAGE_NONE | 396 | #define __P000 PAGE_NONE |
406 | #define __P001 PAGE_RO | 397 | #define __P001 PAGE_RO |
407 | #define __P010 PAGE_RO | 398 | #define __P010 PAGE_RO |
408 | #define __P011 PAGE_RO | 399 | #define __P011 PAGE_RO |
409 | #define __P100 PAGE_EX_RO | 400 | #define __P100 PAGE_RO |
410 | #define __P101 PAGE_EX_RO | 401 | #define __P101 PAGE_RO |
411 | #define __P110 PAGE_EX_RO | 402 | #define __P110 PAGE_RO |
412 | #define __P111 PAGE_EX_RO | 403 | #define __P111 PAGE_RO |
413 | 404 | ||
414 | #define __S000 PAGE_NONE | 405 | #define __S000 PAGE_NONE |
415 | #define __S001 PAGE_RO | 406 | #define __S001 PAGE_RO |
416 | #define __S010 PAGE_RW | 407 | #define __S010 PAGE_RW |
417 | #define __S011 PAGE_RW | 408 | #define __S011 PAGE_RW |
418 | #define __S100 PAGE_EX_RO | 409 | #define __S100 PAGE_RO |
419 | #define __S101 PAGE_EX_RO | 410 | #define __S101 PAGE_RO |
420 | #define __S110 PAGE_EX_RW | 411 | #define __S110 PAGE_RW |
421 | #define __S111 PAGE_EX_RW | 412 | #define __S111 PAGE_RW |
422 | |||
423 | #ifndef __s390x__ | ||
424 | # define PxD_SHADOW_SHIFT 1 | ||
425 | #else /* __s390x__ */ | ||
426 | # define PxD_SHADOW_SHIFT 2 | ||
427 | #endif /* __s390x__ */ | ||
428 | |||
429 | static inline void *get_shadow_table(void *table) | ||
430 | { | ||
431 | unsigned long addr, offset; | ||
432 | struct page *page; | ||
433 | |||
434 | addr = (unsigned long) table; | ||
435 | offset = addr & ((PAGE_SIZE << PxD_SHADOW_SHIFT) - 1); | ||
436 | page = virt_to_page((void *)(addr ^ offset)); | ||
437 | return (void *)(addr_t)(page->index ? (page->index | offset) : 0UL); | ||
438 | } | ||
439 | 413 | ||
440 | /* | 414 | /* |
441 | * Certain architectures need to do special things when PTEs | 415 | * Certain architectures need to do special things when PTEs |
@@ -446,14 +420,6 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
446 | pte_t *ptep, pte_t entry) | 420 | pte_t *ptep, pte_t entry) |
447 | { | 421 | { |
448 | *ptep = entry; | 422 | *ptep = entry; |
449 | if (mm->context.noexec) { | ||
450 | if (!(pte_val(entry) & _PAGE_INVALID) && | ||
451 | (pte_val(entry) & _PAGE_SWX)) | ||
452 | pte_val(entry) |= _PAGE_RO; | ||
453 | else | ||
454 | pte_val(entry) = _PAGE_TYPE_EMPTY; | ||
455 | ptep[PTRS_PER_PTE] = entry; | ||
456 | } | ||
457 | } | 423 | } |
458 | 424 | ||
459 | /* | 425 | /* |
@@ -662,11 +628,7 @@ static inline void pgd_clear_kernel(pgd_t * pgd) | |||
662 | 628 | ||
663 | static inline void pgd_clear(pgd_t * pgd) | 629 | static inline void pgd_clear(pgd_t * pgd) |
664 | { | 630 | { |
665 | pgd_t *shadow = get_shadow_table(pgd); | ||
666 | |||
667 | pgd_clear_kernel(pgd); | 631 | pgd_clear_kernel(pgd); |
668 | if (shadow) | ||
669 | pgd_clear_kernel(shadow); | ||
670 | } | 632 | } |
671 | 633 | ||
672 | static inline void pud_clear_kernel(pud_t *pud) | 634 | static inline void pud_clear_kernel(pud_t *pud) |
@@ -677,13 +639,8 @@ static inline void pud_clear_kernel(pud_t *pud) | |||
677 | 639 | ||
678 | static inline void pud_clear(pud_t *pud) | 640 | static inline void pud_clear(pud_t *pud) |
679 | { | 641 | { |
680 | pud_t *shadow = get_shadow_table(pud); | ||
681 | |||
682 | pud_clear_kernel(pud); | 642 | pud_clear_kernel(pud); |
683 | if (shadow) | ||
684 | pud_clear_kernel(shadow); | ||
685 | } | 643 | } |
686 | |||
687 | #endif /* __s390x__ */ | 644 | #endif /* __s390x__ */ |
688 | 645 | ||
689 | static inline void pmd_clear_kernel(pmd_t * pmdp) | 646 | static inline void pmd_clear_kernel(pmd_t * pmdp) |
@@ -693,18 +650,12 @@ static inline void pmd_clear_kernel(pmd_t * pmdp) | |||
693 | 650 | ||
694 | static inline void pmd_clear(pmd_t *pmd) | 651 | static inline void pmd_clear(pmd_t *pmd) |
695 | { | 652 | { |
696 | pmd_t *shadow = get_shadow_table(pmd); | ||
697 | |||
698 | pmd_clear_kernel(pmd); | 653 | pmd_clear_kernel(pmd); |
699 | if (shadow) | ||
700 | pmd_clear_kernel(shadow); | ||
701 | } | 654 | } |
702 | 655 | ||
703 | static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | 656 | static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) |
704 | { | 657 | { |
705 | pte_val(*ptep) = _PAGE_TYPE_EMPTY; | 658 | pte_val(*ptep) = _PAGE_TYPE_EMPTY; |
706 | if (mm->context.noexec) | ||
707 | pte_val(ptep[PTRS_PER_PTE]) = _PAGE_TYPE_EMPTY; | ||
708 | } | 659 | } |
709 | 660 | ||
710 | /* | 661 | /* |
@@ -903,10 +854,6 @@ static inline void ptep_invalidate(struct mm_struct *mm, | |||
903 | } | 854 | } |
904 | __ptep_ipte(address, ptep); | 855 | __ptep_ipte(address, ptep); |
905 | pte_val(*ptep) = _PAGE_TYPE_EMPTY; | 856 | pte_val(*ptep) = _PAGE_TYPE_EMPTY; |
906 | if (mm->context.noexec) { | ||
907 | __ptep_ipte(address, ptep + PTRS_PER_PTE); | ||
908 | pte_val(*(ptep + PTRS_PER_PTE)) = _PAGE_TYPE_EMPTY; | ||
909 | } | ||
910 | } | 857 | } |
911 | 858 | ||
912 | /* | 859 | /* |