diff options
author | Christian Borntraeger <borntraeger@de.ibm.com> | 2013-06-04 03:53:59 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2013-06-05 11:36:19 -0400 |
commit | 338679f7ba4a81906b3fdfa6507824fdf704be80 (patch) | |
tree | 794df0317cf02d6b32670887f081ffc8e7e73ebc /arch/s390 | |
parent | 4d3797d7e1861ac1af150a6189315786c5e1c820 (diff) |
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')
-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 ac01463038f1..391e592356d0 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) | |||
704 | { | 704 | { |
705 | #ifdef CONFIG_PGSTE | 705 | #ifdef CONFIG_PGSTE |
706 | unsigned long address; | 706 | unsigned long address; |
707 | unsigned long okey, nkey; | 707 | unsigned long nkey; |
708 | 708 | ||
709 | if (pte_val(entry) & _PAGE_INVALID) | 709 | if (pte_val(entry) & _PAGE_INVALID) |
710 | return; | 710 | return; |
711 | VM_BUG_ON(!(pte_val(*ptep) & _PAGE_INVALID)); | ||
711 | address = pte_val(entry) & PAGE_MASK; | 712 | address = pte_val(entry) & PAGE_MASK; |
712 | okey = nkey = page_get_storage_key(address); | 713 | /* |
713 | nkey &= ~(_PAGE_ACC_BITS | _PAGE_FP_BIT); | 714 | * Set page access key and fetch protection bit from pgste. |
714 | /* Set page access key and fetch protection bit from pgste */ | 715 | * The guest C/R information is still in the PGSTE, set real |
715 | nkey |= (pgste_val(pgste) & (RCP_ACC_BITS | RCP_FP_BIT)) >> 56; | 716 | * key C/R to 0. |
716 | if (okey != nkey) | 717 | */ |
717 | page_set_storage_key(address, nkey, 0); | 718 | nkey = (pgste_val(pgste) & (RCP_ACC_BITS | RCP_FP_BIT)) >> 56; |
719 | page_set_storage_key(address, nkey, 0); | ||
718 | #endif | 720 | #endif |
719 | } | 721 | } |
720 | 722 | ||