diff options
| -rw-r--r-- | arch/s390/include/asm/pgtable.h | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 0f0de30e3e3f..ac01463038f1 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h | |||
| @@ -646,7 +646,7 @@ static inline pgste_t pgste_update_all(pte_t *ptep, pgste_t pgste) | |||
| 646 | unsigned long address, bits; | 646 | unsigned long address, bits; |
| 647 | unsigned char skey; | 647 | unsigned char skey; |
| 648 | 648 | ||
| 649 | if (!pte_present(*ptep)) | 649 | if (pte_val(*ptep) & _PAGE_INVALID) |
| 650 | return pgste; | 650 | return pgste; |
| 651 | address = pte_val(*ptep) & PAGE_MASK; | 651 | address = pte_val(*ptep) & PAGE_MASK; |
| 652 | skey = page_get_storage_key(address); | 652 | skey = page_get_storage_key(address); |
| @@ -680,7 +680,7 @@ static inline pgste_t pgste_update_young(pte_t *ptep, pgste_t pgste) | |||
| 680 | #ifdef CONFIG_PGSTE | 680 | #ifdef CONFIG_PGSTE |
| 681 | int young; | 681 | int young; |
| 682 | 682 | ||
| 683 | if (!pte_present(*ptep)) | 683 | if (pte_val(*ptep) & _PAGE_INVALID) |
| 684 | return pgste; | 684 | return pgste; |
| 685 | /* Get referenced bit from storage key */ | 685 | /* Get referenced bit from storage key */ |
| 686 | young = page_reset_referenced(pte_val(*ptep) & PAGE_MASK); | 686 | young = page_reset_referenced(pte_val(*ptep) & PAGE_MASK); |
| @@ -706,7 +706,7 @@ static inline void pgste_set_key(pte_t *ptep, pgste_t pgste, pte_t entry) | |||
| 706 | unsigned long address; | 706 | unsigned long address; |
| 707 | unsigned long okey, nkey; | 707 | unsigned long okey, nkey; |
| 708 | 708 | ||
| 709 | if (!pte_present(entry)) | 709 | if (pte_val(entry) & _PAGE_INVALID) |
| 710 | return; | 710 | return; |
| 711 | address = pte_val(entry) & PAGE_MASK; | 711 | address = pte_val(entry) & PAGE_MASK; |
| 712 | okey = nkey = page_get_storage_key(address); | 712 | okey = nkey = page_get_storage_key(address); |
| @@ -1098,6 +1098,9 @@ static inline pte_t ptep_modify_prot_start(struct mm_struct *mm, | |||
| 1098 | pte = *ptep; | 1098 | pte = *ptep; |
| 1099 | if (!mm_exclusive(mm)) | 1099 | if (!mm_exclusive(mm)) |
| 1100 | __ptep_ipte(address, ptep); | 1100 | __ptep_ipte(address, ptep); |
| 1101 | |||
| 1102 | if (mm_has_pgste(mm)) | ||
| 1103 | pgste = pgste_update_all(&pte, pgste); | ||
| 1101 | return pte; | 1104 | return pte; |
| 1102 | } | 1105 | } |
| 1103 | 1106 | ||
| @@ -1105,9 +1108,13 @@ static inline void ptep_modify_prot_commit(struct mm_struct *mm, | |||
| 1105 | unsigned long address, | 1108 | unsigned long address, |
| 1106 | pte_t *ptep, pte_t pte) | 1109 | pte_t *ptep, pte_t pte) |
| 1107 | { | 1110 | { |
| 1111 | pgste_t pgste; | ||
| 1112 | |||
| 1108 | if (mm_has_pgste(mm)) { | 1113 | if (mm_has_pgste(mm)) { |
| 1114 | pgste = *(pgste_t *)(ptep + PTRS_PER_PTE); | ||
| 1115 | pgste_set_key(ptep, pgste, pte); | ||
| 1109 | pgste_set_pte(ptep, pte); | 1116 | pgste_set_pte(ptep, pte); |
| 1110 | pgste_set_unlock(ptep, *(pgste_t *)(ptep + PTRS_PER_PTE)); | 1117 | pgste_set_unlock(ptep, pgste); |
| 1111 | } else | 1118 | } else |
| 1112 | *ptep = pte; | 1119 | *ptep = pte; |
| 1113 | } | 1120 | } |
