aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2016-05-10 03:43:11 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2016-06-10 06:07:30 -0400
commit1824c723ac90f9870ebafae4b3b3e5f4b82ffeef (patch)
tree3168e13812bb9110be073849089f8936df750cd1 /arch/s390/mm
parent2c26d1d23abd9a67d056c95a0823132a71edc477 (diff)
KVM: s390: pfmf: support conditional-sske facility
We already indicate that facility but don't implement it in our pfmf interception handler. Let's add a new storage key handling function for conditionally setting the guest storage key. As we will reuse this function later on, let's directly implement returning the old key via parameter and indicating if any change happened via rc. 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.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 3e35298758d6..e791e8b27fd2 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -539,6 +539,39 @@ int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
539} 539}
540EXPORT_SYMBOL(set_guest_storage_key); 540EXPORT_SYMBOL(set_guest_storage_key);
541 541
542/**
543 * Conditionally set a guest storage key (handling csske).
544 * oldkey will be updated when either mr or mc is set and a pointer is given.
545 *
546 * Returns 0 if a guests storage key update wasn't necessary, 1 if the guest
547 * storage key was updated and -EFAULT on access errors.
548 */
549int cond_set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
550 unsigned char key, unsigned char *oldkey,
551 bool nq, bool mr, bool mc)
552{
553 unsigned char tmp, mask = _PAGE_ACC_BITS | _PAGE_FP_BIT;
554 int rc;
555
556 /* we can drop the pgste lock between getting and setting the key */
557 if (mr | mc) {
558 rc = get_guest_storage_key(current->mm, addr, &tmp);
559 if (rc)
560 return rc;
561 if (oldkey)
562 *oldkey = tmp;
563 if (!mr)
564 mask |= _PAGE_REFERENCED;
565 if (!mc)
566 mask |= _PAGE_CHANGED;
567 if (!((tmp ^ key) & mask))
568 return 0;
569 }
570 rc = set_guest_storage_key(current->mm, addr, key, nq);
571 return rc < 0 ? rc : 1;
572}
573EXPORT_SYMBOL(cond_set_guest_storage_key);
574
542int get_guest_storage_key(struct mm_struct *mm, unsigned long addr, 575int get_guest_storage_key(struct mm_struct *mm, unsigned long addr,
543 unsigned char *key) 576 unsigned char *key)
544{ 577{