Commit 09b53883 authored by Martin Schwidefsky's avatar Martin Schwidefsky

[S390] fix pgste update logic

The pgste_update_all / pgste_update_young and pgste_set_pte need to
check if the pte entry contains a valid page address before the storage
key can be accessed. In addition pgste_set_pte needs to set the access
key and fetch protection bit of the new pte entry, not the old entry.
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 80025297
...@@ -593,6 +593,8 @@ static inline pgste_t pgste_update_all(pte_t *ptep, pgste_t pgste) ...@@ -593,6 +593,8 @@ static inline pgste_t pgste_update_all(pte_t *ptep, pgste_t pgste)
unsigned long address, bits; unsigned long address, bits;
unsigned char skey; unsigned char skey;
if (!pte_present(*ptep))
return pgste;
address = pte_val(*ptep) & PAGE_MASK; address = pte_val(*ptep) & PAGE_MASK;
skey = page_get_storage_key(address); skey = page_get_storage_key(address);
bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED); bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED);
...@@ -625,6 +627,8 @@ static inline pgste_t pgste_update_young(pte_t *ptep, pgste_t pgste) ...@@ -625,6 +627,8 @@ static inline pgste_t pgste_update_young(pte_t *ptep, pgste_t pgste)
#ifdef CONFIG_PGSTE #ifdef CONFIG_PGSTE
int young; int young;
if (!pte_present(*ptep))
return pgste;
young = page_reset_referenced(pte_val(*ptep) & PAGE_MASK); young = page_reset_referenced(pte_val(*ptep) & PAGE_MASK);
/* Transfer page referenced bit to pte software bit (host view) */ /* Transfer page referenced bit to pte software bit (host view) */
if (young || (pgste_val(pgste) & RCP_HR_BIT)) if (young || (pgste_val(pgste) & RCP_HR_BIT))
...@@ -638,13 +642,15 @@ static inline pgste_t pgste_update_young(pte_t *ptep, pgste_t pgste) ...@@ -638,13 +642,15 @@ static inline pgste_t pgste_update_young(pte_t *ptep, pgste_t pgste)
} }
static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste) static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste, pte_t entry)
{ {
#ifdef CONFIG_PGSTE #ifdef CONFIG_PGSTE
unsigned long address; unsigned long address;
unsigned long okey, nkey; unsigned long okey, nkey;
address = pte_val(*ptep) & PAGE_MASK; if (!pte_present(entry))
return;
address = pte_val(entry) & PAGE_MASK;
okey = nkey = page_get_storage_key(address); okey = nkey = page_get_storage_key(address);
nkey &= ~(_PAGE_ACC_BITS | _PAGE_FP_BIT); nkey &= ~(_PAGE_ACC_BITS | _PAGE_FP_BIT);
/* Set page access key and fetch protection bit from pgste */ /* Set page access key and fetch protection bit from pgste */
...@@ -712,7 +718,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, ...@@ -712,7 +718,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
if (mm_has_pgste(mm)) { if (mm_has_pgste(mm)) {
pgste = pgste_get_lock(ptep); pgste = pgste_get_lock(ptep);
pgste_set_pte(ptep, pgste); pgste_set_pte(ptep, pgste, entry);
*ptep = entry; *ptep = entry;
pgste_set_unlock(ptep, pgste); pgste_set_unlock(ptep, pgste);
} else } else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment