aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm/pgtable.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/mm/pgtable.c')
-rw-r--r--arch/s390/mm/pgtable.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 71c7eff2c89f..be99357d238c 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -844,7 +844,7 @@ int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
844 844
845 down_read(&mm->mmap_sem); 845 down_read(&mm->mmap_sem);
846retry: 846retry:
847 ptep = get_locked_pte(current->mm, addr, &ptl); 847 ptep = get_locked_pte(mm, addr, &ptl);
848 if (unlikely(!ptep)) { 848 if (unlikely(!ptep)) {
849 up_read(&mm->mmap_sem); 849 up_read(&mm->mmap_sem);
850 return -EFAULT; 850 return -EFAULT;
@@ -888,6 +888,45 @@ retry:
888} 888}
889EXPORT_SYMBOL(set_guest_storage_key); 889EXPORT_SYMBOL(set_guest_storage_key);
890 890
891unsigned long get_guest_storage_key(struct mm_struct *mm, unsigned long addr)
892{
893 spinlock_t *ptl;
894 pgste_t pgste;
895 pte_t *ptep;
896 uint64_t physaddr;
897 unsigned long key = 0;
898
899 down_read(&mm->mmap_sem);
900 ptep = get_locked_pte(mm, addr, &ptl);
901 if (unlikely(!ptep)) {
902 up_read(&mm->mmap_sem);
903 return -EFAULT;
904 }
905 pgste = pgste_get_lock(ptep);
906
907 if (pte_val(*ptep) & _PAGE_INVALID) {
908 key |= (pgste_val(pgste) & PGSTE_ACC_BITS) >> 56;
909 key |= (pgste_val(pgste) & PGSTE_FP_BIT) >> 56;
910 key |= (pgste_val(pgste) & PGSTE_GR_BIT) >> 48;
911 key |= (pgste_val(pgste) & PGSTE_GC_BIT) >> 48;
912 } else {
913 physaddr = pte_val(*ptep) & PAGE_MASK;
914 key = page_get_storage_key(physaddr);
915
916 /* Reflect guest's logical view, not physical */
917 if (pgste_val(pgste) & PGSTE_GR_BIT)
918 key |= _PAGE_REFERENCED;
919 if (pgste_val(pgste) & PGSTE_GC_BIT)
920 key |= _PAGE_CHANGED;
921 }
922
923 pgste_set_unlock(ptep, pgste);
924 pte_unmap_unlock(ptep, ptl);
925 up_read(&mm->mmap_sem);
926 return key;
927}
928EXPORT_SYMBOL(get_guest_storage_key);
929
891#else /* CONFIG_PGSTE */ 930#else /* CONFIG_PGSTE */
892 931
893static inline int page_table_with_pgste(struct page *page) 932static inline int page_table_with_pgste(struct page *page)