[ 079/127] s390/pgtable: Fix check for pgste/storage key handling

From: Greg Kroah-Hartman
Date: Wed Jun 05 2013 - 17:47:14 EST


3.9-stable review patch. If anyone has any objections, please let me know.

------------------

From: Christian Borntraeger <borntraeger@xxxxxxxxxx>

commit b56433cb782d1cc7e44fc46d2ce3917fa75d2236 upstream.

pte_present might return true on PAGE_TYPE_NONE, even if
the invalid bit is on. Modify the existing check of the
pgste functions to avoid crashes.

[ Martin Schwidefsky: added ptep_modify_prot_[start|commit] bits ]

Reported-by: Martin Schwidefky <schwidefsky@xxxxxxxxxx>
Signed-off-by: Christian Borntraeger <borntraeger@xxxxxxxxxx>
Signed-off-by: Martin Schwidefsky <schwidefsky@xxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>

---
arch/s390/include/asm/pgtable.h | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)

--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -637,7 +637,7 @@ static inline pgste_t pgste_update_all(p
unsigned long address, bits;
unsigned char skey;

- if (!pte_present(*ptep))
+ if (pte_val(*ptep) & _PAGE_INVALID)
return pgste;
address = pte_val(*ptep) & PAGE_MASK;
skey = page_get_storage_key(address);
@@ -671,7 +671,7 @@ static inline pgste_t pgste_update_young
#ifdef CONFIG_PGSTE
int young;

- if (!pte_present(*ptep))
+ if (pte_val(*ptep) & _PAGE_INVALID)
return pgste;
/* Get referenced bit from storage key */
young = page_reset_referenced(pte_val(*ptep) & PAGE_MASK);
@@ -697,7 +697,7 @@ static inline void pgste_set_key(pte_t *
unsigned long address;
unsigned long okey, nkey;

- if (!pte_present(entry))
+ if (pte_val(entry) & _PAGE_INVALID)
return;
address = pte_val(entry) & PAGE_MASK;
okey = nkey = page_get_storage_key(address);
@@ -1072,6 +1072,9 @@ static inline pte_t ptep_modify_prot_sta
pte = *ptep;
if (!mm_exclusive(mm))
__ptep_ipte(address, ptep);
+
+ if (mm_has_pgste(mm))
+ pgste = pgste_update_all(&pte, pgste);
return pte;
}

@@ -1079,9 +1082,13 @@ static inline void ptep_modify_prot_comm
unsigned long address,
pte_t *ptep, pte_t pte)
{
+ pgste_t pgste;
+
if (mm_has_pgste(mm)) {
+ pgste = *(pgste_t *)(ptep + PTRS_PER_PTE);
+ pgste_set_key(ptep, pgste, pte);
pgste_set_pte(ptep, pte);
- pgste_set_unlock(ptep, *(pgste_t *)(ptep + PTRS_PER_PTE));
+ pgste_set_unlock(ptep, pgste);
} else
*ptep = pte;
}


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/