aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/pgalloc.h1
-rw-r--r--arch/s390/kvm/diag.c3
-rw-r--r--arch/s390/mm/pgtable.c72
3 files changed, 76 insertions, 0 deletions
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h
index e1408ddb94f8..14d43c77d6cf 100644
--- a/arch/s390/include/asm/pgalloc.h
+++ b/arch/s390/include/asm/pgalloc.h
@@ -22,6 +22,7 @@ unsigned long *page_table_alloc(struct mm_struct *, unsigned long);
22void page_table_free(struct mm_struct *, unsigned long *); 22void page_table_free(struct mm_struct *, unsigned long *);
23void page_table_free_rcu(struct mmu_gather *, unsigned long *); 23void page_table_free_rcu(struct mmu_gather *, unsigned long *);
24 24
25void page_table_reset_pgste(struct mm_struct *, unsigned long, unsigned long);
25int set_guest_storage_key(struct mm_struct *mm, unsigned long addr, 26int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
26 unsigned long key, bool nq); 27 unsigned long key, bool nq);
27 28
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c
index 8216c0e0b2e2..6f9cfa500372 100644
--- a/arch/s390/kvm/diag.c
+++ b/arch/s390/kvm/diag.c
@@ -13,6 +13,7 @@
13 13
14#include <linux/kvm.h> 14#include <linux/kvm.h>
15#include <linux/kvm_host.h> 15#include <linux/kvm_host.h>
16#include <asm/pgalloc.h>
16#include <asm/virtio-ccw.h> 17#include <asm/virtio-ccw.h>
17#include "kvm-s390.h" 18#include "kvm-s390.h"
18#include "trace.h" 19#include "trace.h"
@@ -86,9 +87,11 @@ static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
86 switch (subcode) { 87 switch (subcode) {
87 case 3: 88 case 3:
88 vcpu->run->s390_reset_flags = KVM_S390_RESET_CLEAR; 89 vcpu->run->s390_reset_flags = KVM_S390_RESET_CLEAR;
90 page_table_reset_pgste(current->mm, 0, TASK_SIZE);
89 break; 91 break;
90 case 4: 92 case 4:
91 vcpu->run->s390_reset_flags = 0; 93 vcpu->run->s390_reset_flags = 0;
94 page_table_reset_pgste(current->mm, 0, TASK_SIZE);
92 break; 95 break;
93 default: 96 default:
94 return -EOPNOTSUPP; 97 return -EOPNOTSUPP;
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 9e2b4705dea2..9c26b7aa96d9 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -879,6 +879,78 @@ static inline void page_table_free_pgste(unsigned long *table)
879 __free_page(page); 879 __free_page(page);
880} 880}
881 881
882static inline unsigned long page_table_reset_pte(struct mm_struct *mm,
883 pmd_t *pmd, unsigned long addr, unsigned long end)
884{
885 pte_t *start_pte, *pte;
886 spinlock_t *ptl;
887 pgste_t pgste;
888
889 start_pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
890 pte = start_pte;
891 do {
892 pgste = pgste_get_lock(pte);
893 pgste_val(pgste) &= ~_PGSTE_GPS_USAGE_MASK;
894 pgste_set_unlock(pte, pgste);
895 } while (pte++, addr += PAGE_SIZE, addr != end);
896 pte_unmap_unlock(start_pte, ptl);
897
898 return addr;
899}
900
901static inline unsigned long page_table_reset_pmd(struct mm_struct *mm,
902 pud_t *pud, unsigned long addr, unsigned long end)
903{
904 unsigned long next;
905 pmd_t *pmd;
906
907 pmd = pmd_offset(pud, addr);
908 do {
909 next = pmd_addr_end(addr, end);
910 if (pmd_none_or_clear_bad(pmd))
911 continue;
912 next = page_table_reset_pte(mm, pmd, addr, next);
913 } while (pmd++, addr = next, addr != end);
914
915 return addr;
916}
917
918static inline unsigned long page_table_reset_pud(struct mm_struct *mm,
919 pgd_t *pgd, unsigned long addr, unsigned long end)
920{
921 unsigned long next;
922 pud_t *pud;
923
924 pud = pud_offset(pgd, addr);
925 do {
926 next = pud_addr_end(addr, end);
927 if (pud_none_or_clear_bad(pud))
928 continue;
929 next = page_table_reset_pmd(mm, pud, addr, next);
930 } while (pud++, addr = next, addr != end);
931
932 return addr;
933}
934
935void page_table_reset_pgste(struct mm_struct *mm,
936 unsigned long start, unsigned long end)
937{
938 unsigned long addr, next;
939 pgd_t *pgd;
940
941 addr = start;
942 down_read(&mm->mmap_sem);
943 pgd = pgd_offset(mm, addr);
944 do {
945 next = pgd_addr_end(addr, end);
946 if (pgd_none_or_clear_bad(pgd))
947 continue;
948 next = page_table_reset_pud(mm, pgd, addr, next);
949 } while (pgd++, addr = next, addr != end);
950 up_read(&mm->mmap_sem);
951}
952EXPORT_SYMBOL(page_table_reset_pgste);
953
882int set_guest_storage_key(struct mm_struct *mm, unsigned long addr, 954int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
883 unsigned long key, bool nq) 955 unsigned long key, bool nq)
884{ 956{