aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/include/asm/pgtable.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/include/asm/pgtable.h')
-rw-r--r--arch/s390/include/asm/pgtable.h45
1 files changed, 43 insertions, 2 deletions
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 0bdb704ae051..1a928f84afd6 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -281,6 +281,9 @@ extern char empty_zero_page[PAGE_SIZE];
281#define RCP_GR_BIT 50 281#define RCP_GR_BIT 50
282#define RCP_GC_BIT 49 282#define RCP_GC_BIT 49
283 283
284/* User dirty bit for KVM's migration feature */
285#define KVM_UD_BIT 47
286
284#ifndef __s390x__ 287#ifndef __s390x__
285 288
286/* Bits in the segment table address-space-control-element */ 289/* Bits in the segment table address-space-control-element */
@@ -575,12 +578,16 @@ static inline void ptep_rcp_copy(pte_t *ptep)
575 unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE); 578 unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
576 579
577 skey = page_get_storage_key(page_to_phys(page)); 580 skey = page_get_storage_key(page_to_phys(page));
578 if (skey & _PAGE_CHANGED) 581 if (skey & _PAGE_CHANGED) {
579 set_bit_simple(RCP_GC_BIT, pgste); 582 set_bit_simple(RCP_GC_BIT, pgste);
583 set_bit_simple(KVM_UD_BIT, pgste);
584 }
580 if (skey & _PAGE_REFERENCED) 585 if (skey & _PAGE_REFERENCED)
581 set_bit_simple(RCP_GR_BIT, pgste); 586 set_bit_simple(RCP_GR_BIT, pgste);
582 if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) 587 if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) {
583 SetPageDirty(page); 588 SetPageDirty(page);
589 set_bit_simple(KVM_UD_BIT, pgste);
590 }
584 if (test_and_clear_bit_simple(RCP_HR_BIT, pgste)) 591 if (test_and_clear_bit_simple(RCP_HR_BIT, pgste))
585 SetPageReferenced(page); 592 SetPageReferenced(page);
586#endif 593#endif
@@ -744,6 +751,40 @@ static inline pte_t pte_mkspecial(pte_t pte)
744 return pte; 751 return pte;
745} 752}
746 753
754#ifdef CONFIG_PGSTE
755/*
756 * Get (and clear) the user dirty bit for a PTE.
757 */
758static inline int kvm_s390_test_and_clear_page_dirty(struct mm_struct *mm,
759 pte_t *ptep)
760{
761 int dirty;
762 unsigned long *pgste;
763 struct page *page;
764 unsigned int skey;
765
766 if (!mm->context.pgstes)
767 return -EINVAL;
768 rcp_lock(ptep);
769 pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
770 page = virt_to_page(pte_val(*ptep));
771 skey = page_get_storage_key(page_to_phys(page));
772 if (skey & _PAGE_CHANGED) {
773 set_bit_simple(RCP_GC_BIT, pgste);
774 set_bit_simple(KVM_UD_BIT, pgste);
775 }
776 if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) {
777 SetPageDirty(page);
778 set_bit_simple(KVM_UD_BIT, pgste);
779 }
780 dirty = test_and_clear_bit_simple(KVM_UD_BIT, pgste);
781 if (skey & _PAGE_CHANGED)
782 page_clear_dirty(page);
783 rcp_unlock(ptep);
784 return dirty;
785}
786#endif
787
747#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG 788#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
748static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, 789static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
749 unsigned long addr, pte_t *ptep) 790 unsigned long addr, pte_t *ptep)