diff options
Diffstat (limited to 'arch/s390/mm/pgtable.c')
-rw-r--r-- | arch/s390/mm/pgtable.c | 41 |
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); |
846 | retry: | 846 | retry: |
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 | } |
889 | EXPORT_SYMBOL(set_guest_storage_key); | 889 | EXPORT_SYMBOL(set_guest_storage_key); |
890 | 890 | ||
891 | unsigned 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 | } | ||
928 | EXPORT_SYMBOL(get_guest_storage_key); | ||
929 | |||
891 | #else /* CONFIG_PGSTE */ | 930 | #else /* CONFIG_PGSTE */ |
892 | 931 | ||
893 | static inline int page_table_with_pgste(struct page *page) | 932 | static inline int page_table_with_pgste(struct page *page) |