diff options
author | Christian Borntraeger <borntraeger@de.ibm.com> | 2013-06-04 09:53:59 +0200 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2013-06-05 17:36:19 +0200 |
commit | 338679f7ba4a81906b3fdfa6507824fdf704be80 (patch) | |
tree | 794df0317cf02d6b32670887f081ffc8e7e73ebc /arch/s390/include | |
parent | 4d3797d7e1861ac1af150a6189315786c5e1c820 (diff) | |
download | op-kernel-dev-338679f7ba4a81906b3fdfa6507824fdf704be80.zip op-kernel-dev-338679f7ba4a81906b3fdfa6507824fdf704be80.tar.gz |
s390/pgtable: Fix guest overindication for change bit
When doing the transition invalid->valid in the host page table for
a guest, then the guest view of C/R is in the pgste. After validation
the view is pgste OR real key. We must zero out the real key C/R to
avoid guest over-indication for change (and reference).
Touching the real key is ok also for the host: The change bit is
tracked via write protection and the reference bit is also ok
because set_pte_at was called and the page will be touched anyway
soon. Furthermore architecture defines reference as "substantially
accurate", over- and underindication are ok.
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/include')
-rw-r--r-- | arch/s390/include/asm/pgtable.h | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index ac01463..391e592 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -704,17 +704,19 @@ static inline void pgste_set_key(pte_t *ptep, pgste_t pgste, pte_t entry) { #ifdef CONFIG_PGSTE unsigned long address; - unsigned long okey, nkey; + unsigned long nkey; if (pte_val(entry) & _PAGE_INVALID) return; + VM_BUG_ON(!(pte_val(*ptep) & _PAGE_INVALID)); address = pte_val(entry) & PAGE_MASK; - okey = nkey = page_get_storage_key(address); - nkey &= ~(_PAGE_ACC_BITS | _PAGE_FP_BIT); - /* Set page access key and fetch protection bit from pgste */ - nkey |= (pgste_val(pgste) & (RCP_ACC_BITS | RCP_FP_BIT)) >> 56; - if (okey != nkey) - page_set_storage_key(address, nkey, 0); + /* + * Set page access key and fetch protection bit from pgste. + * The guest C/R information is still in the PGSTE, set real + * key C/R to 0. + */ + nkey = (pgste_val(pgste) & (RCP_ACC_BITS | RCP_FP_BIT)) >> 56; + page_set_storage_key(address, nkey, 0); #endif } |