[S390] merge page_test_dirty and page_clear_dirty

The page_clear_dirty primitive always sets the default storage key
which resets the access control bits and the fetch protection bit.
That will surprise a KVM guest that sets non-zero access control
bits or the fetch protection bit. Merge page_test_dirty and
page_clear_dirty back to a single function and only clear the
dirty bit from the storage key.

In addition move the function page_test_and_clear_dirty and
page_test_and_clear_young to page.h where they belong. This
requires to change the parameter from a struct page * to a page
frame number.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 763620e..4ca4dd2 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -373,10 +373,6 @@
 #define _ASCE_USER_BITS		(_ASCE_SPACE_SWITCH | _ASCE_PRIVATE_SPACE | \
 				 _ASCE_ALT_EVENT)
 
-/* Bits int the storage key */
-#define _PAGE_CHANGED    0x02          /* HW changed bit                   */
-#define _PAGE_REFERENCED 0x04          /* HW referenced bit                */
-
 /*
  * Page protection definitions.
  */
@@ -555,8 +551,6 @@
 #endif
 }
 
-/* forward declaration for SetPageUptodate in page-flags.h*/
-static inline void page_clear_dirty(struct page *page, int mapped);
 #include <linux/page-flags.h>
 
 static inline void ptep_rcp_copy(pte_t *ptep)
@@ -566,7 +560,7 @@
 	unsigned int skey;
 	unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
 
-	skey = page_get_storage_key(page_to_phys(page));
+	skey = page_get_storage_key(pte_val(*ptep) >> PAGE_SHIFT);
 	if (skey & _PAGE_CHANGED) {
 		set_bit_simple(RCP_GC_BIT, pgste);
 		set_bit_simple(KVM_UD_BIT, pgste);
@@ -760,6 +754,7 @@
 {
 	int dirty;
 	unsigned long *pgste;
+	unsigned long pfn;
 	struct page *page;
 	unsigned int skey;
 
@@ -767,8 +762,9 @@
 		return -EINVAL;
 	rcp_lock(ptep);
 	pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
-	page = virt_to_page(pte_val(*ptep));
-	skey = page_get_storage_key(page_to_phys(page));
+	pfn = pte_val(*ptep) >> PAGE_SHIFT;
+	page = pfn_to_page(pfn);
+	skey = page_get_storage_key(pfn);
 	if (skey & _PAGE_CHANGED) {
 		set_bit_simple(RCP_GC_BIT, pgste);
 		set_bit_simple(KVM_UD_BIT, pgste);
@@ -779,7 +775,7 @@
 	}
 	dirty = test_and_clear_bit_simple(KVM_UD_BIT, pgste);
 	if (skey & _PAGE_CHANGED)
-		page_clear_dirty(page, 1);
+		page_set_storage_key(pfn, skey & ~_PAGE_CHANGED, 1);
 	rcp_unlock(ptep);
 	return dirty;
 }
@@ -790,16 +786,16 @@
 					    unsigned long addr, pte_t *ptep)
 {
 #ifdef CONFIG_PGSTE
-	unsigned long physpage;
+	unsigned long pfn;
 	int young;
 	unsigned long *pgste;
 
 	if (!vma->vm_mm->context.has_pgste)
 		return 0;
-	physpage = pte_val(*ptep) & PAGE_MASK;
+	pfn = pte_val(*ptep) >> PAGE_SHIFT;
 	pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
 
-	young = ((page_get_storage_key(physpage) & _PAGE_REFERENCED) != 0);
+	young = ((page_get_storage_key(pfn) & _PAGE_REFERENCED) != 0);
 	rcp_lock(ptep);
 	if (young)
 		set_bit_simple(RCP_GR_BIT, pgste);
@@ -937,42 +933,6 @@
 })
 
 /*
- * Test and clear dirty bit in storage key.
- * We can't clear the changed bit atomically. This is a potential
- * race against modification of the referenced bit. This function
- * should therefore only be called if it is not mapped in any
- * address space.
- */
-#define __HAVE_ARCH_PAGE_TEST_DIRTY
-static inline int page_test_dirty(struct page *page)
-{
-	return (page_get_storage_key(page_to_phys(page)) & _PAGE_CHANGED) != 0;
-}
-
-#define __HAVE_ARCH_PAGE_CLEAR_DIRTY
-static inline void page_clear_dirty(struct page *page, int mapped)
-{
-	page_set_storage_key(page_to_phys(page), PAGE_DEFAULT_KEY, mapped);
-}
-
-/*
- * Test and clear referenced bit in storage key.
- */
-#define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG
-static inline int page_test_and_clear_young(struct page *page)
-{
-	unsigned long physpage = page_to_phys(page);
-	int ccode;
-
-	asm volatile(
-		"	rrbe	0,%1\n"
-		"	ipm	%0\n"
-		"	srl	%0,28\n"
-		: "=d" (ccode) : "a" (physpage) : "cc" );
-	return ccode & 2;
-}
-
-/*
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  */