aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2016-05-10 03:50:21 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2016-06-10 06:07:31 -0400
commita7e19ab55ffdd82f1a8d12694b9a0c0beeef534c (patch)
tree77c52e6a73a3a871caaba0a0e7b7eda3789fa53a /arch/s390/mm
parent11ddcd41bce5c2394b0390584236afdd13656998 (diff)
KVM: s390: handle missing storage-key facility
Without the storage-key facility, SIE won't interpret SSKE, ISKE and RRBE for us. So let's add proper interception handlers that will be called if lazy sske cannot be enabled. Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch/s390/mm')
-rw-r--r--arch/s390/mm/pgtable.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index e791e8b27fd2..fa286d0c0f2d 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -572,6 +572,43 @@ int cond_set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
572} 572}
573EXPORT_SYMBOL(cond_set_guest_storage_key); 573EXPORT_SYMBOL(cond_set_guest_storage_key);
574 574
575/**
576 * Reset a guest reference bit (rrbe), returning the reference and changed bit.
577 *
578 * Returns < 0 in case of error, otherwise the cc to be reported to the guest.
579 */
580int reset_guest_reference_bit(struct mm_struct *mm, unsigned long addr)
581{
582 spinlock_t *ptl;
583 pgste_t old, new;
584 pte_t *ptep;
585 int cc = 0;
586
587 ptep = get_locked_pte(mm, addr, &ptl);
588 if (unlikely(!ptep))
589 return -EFAULT;
590
591 new = old = pgste_get_lock(ptep);
592 /* Reset guest reference bit only */
593 pgste_val(new) &= ~PGSTE_GR_BIT;
594
595 if (!(pte_val(*ptep) & _PAGE_INVALID)) {
596 cc = page_reset_referenced(pte_val(*ptep) & PAGE_MASK);
597 /* Merge real referenced bit into host-set */
598 pgste_val(new) |= ((unsigned long) cc << 53) & PGSTE_HR_BIT;
599 }
600 /* Reflect guest's logical view, not physical */
601 cc |= (pgste_val(old) & (PGSTE_GR_BIT | PGSTE_GC_BIT)) >> 49;
602 /* Changing the guest storage key is considered a change of the page */
603 if ((pgste_val(new) ^ pgste_val(old)) & PGSTE_GR_BIT)
604 pgste_val(new) |= PGSTE_UC_BIT;
605
606 pgste_set_unlock(ptep, new);
607 pte_unmap_unlock(ptep, ptl);
608 return 0;
609}
610EXPORT_SYMBOL(reset_guest_reference_bit);
611
575int get_guest_storage_key(struct mm_struct *mm, unsigned long addr, 612int get_guest_storage_key(struct mm_struct *mm, unsigned long addr,
576 unsigned char *key) 613 unsigned char *key)
577{ 614{