[S390] add support for nonquiescing sske
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Mon, 25 Oct 2010 14:10:14 +0000 (16:10 +0200)
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>
Mon, 25 Oct 2010 14:10:15 +0000 (16:10 +0200)
Improve performance of the sske operation by using the nonquiescing
variant if the affected page has no mappings established. On machines
with no support for the new sske variant the mask bit will be ignored.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/page.h
arch/s390/include/asm/pgtable.h
arch/s390/kernel/early.c
arch/s390/kernel/setup.c
include/asm-generic/pgtable.h
include/linux/page-flags.h
mm/rmap.c

index af650fb472064a82c09ab508cab7ccd341412c79..a8729ea7e9ac1d12826fb4a0e76923a19af307fa 100644 (file)
@@ -108,9 +108,13 @@ typedef pte_t *pgtable_t;
 #define __pgprot(x)     ((pgprot_t) { (x) } )
 
 static inline void
-page_set_storage_key(unsigned long addr, unsigned int skey)
+page_set_storage_key(unsigned long addr, unsigned int skey, int mapped)
 {
-       asm volatile("sske %0,%1" : : "d" (skey), "a" (addr));
+       if (!mapped)
+               asm volatile(".insn rrf,0xb22b0000,%0,%1,8,0"
+                            : : "d" (skey), "a" (addr));
+       else
+               asm volatile("sske %0,%1" : : "d" (skey), "a" (addr));
 }
 
 static inline unsigned int
index 85cd4b039de6b90e998185566e8b2f0c78252ac9..f79e7bb9ae1e8a926f7ea885b44b96cedf681338 100644 (file)
@@ -590,7 +590,7 @@ static inline void rcp_unlock(pte_t *ptep)
 }
 
 /* forward declaration for SetPageUptodate in page-flags.h*/
-static inline void page_clear_dirty(struct page *page);
+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)
@@ -800,7 +800,7 @@ static inline int kvm_s390_test_and_clear_page_dirty(struct mm_struct *mm,
        }
        dirty = test_and_clear_bit_simple(KVM_UD_BIT, pgste);
        if (skey & _PAGE_CHANGED)
-               page_clear_dirty(page);
+               page_clear_dirty(page, 1);
        rcp_unlock(ptep);
        return dirty;
 }
@@ -975,9 +975,9 @@ static inline int page_test_dirty(struct page *page)
 }
 
 #define __HAVE_ARCH_PAGE_CLEAR_DIRTY
-static inline void page_clear_dirty(struct page *page)
+static inline void page_clear_dirty(struct page *page, int mapped)
 {
-       page_set_storage_key(page_to_phys(page), PAGE_DEFAULT_KEY);
+       page_set_storage_key(page_to_phys(page), PAGE_DEFAULT_KEY, mapped);
 }
 
 /*
index c00856ad4e5a15b00450322053914964122f7cf7..0badc6344eb434e2df8313d902f3c986a3d11283 100644 (file)
@@ -208,7 +208,8 @@ static noinline __init void init_kernel_storage_key(void)
        end_pfn = PFN_UP(__pa(&_end));
 
        for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++)
-               page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
+               page_set_storage_key(init_pfn << PAGE_SHIFT,
+                                    PAGE_DEFAULT_KEY, 0);
 }
 
 static __initdata struct sysinfo_3_2_2 vmms __aligned(PAGE_SIZE);
index c8e8e1354e1dd403d6bcbb56e5c0d6f8ac3a0b33..9071e984dcf145ceac8afc101c7e644c6b383139 100644 (file)
@@ -627,7 +627,8 @@ setup_memory(void)
                add_active_range(0, start_chunk, end_chunk);
                pfn = max(start_chunk, start_pfn);
                for (; pfn < end_chunk; pfn++)
-                       page_set_storage_key(PFN_PHYS(pfn), PAGE_DEFAULT_KEY);
+                       page_set_storage_key(PFN_PHYS(pfn),
+                                            PAGE_DEFAULT_KEY, 0);
        }
 
        psw_set_key(PAGE_DEFAULT_KEY);
index f4d4120e5128a8fe76580286151017ddb68c497b..6f3c6ae4fe03381755264f7d58b9b5ba57fc286f 100644 (file)
@@ -108,7 +108,7 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
 #endif
 
 #ifndef __HAVE_ARCH_PAGE_CLEAR_DIRTY
-#define page_clear_dirty(page)         do { } while (0)
+#define page_clear_dirty(page, mapped) do { } while (0)
 #endif
 
 #ifndef __HAVE_ARCH_PAGE_TEST_DIRTY
index 6fa317801e1c72be3e6977b538f49da988be49ee..5f38c460367e41c1d9c7f9dab04fb2af993f52dc 100644 (file)
@@ -310,7 +310,7 @@ static inline void SetPageUptodate(struct page *page)
 {
 #ifdef CONFIG_S390
        if (!test_and_set_bit(PG_uptodate, &page->flags))
-               page_clear_dirty(page);
+               page_clear_dirty(page, 0);
 #else
        /*
         * Memory barrier must be issued before setting the PG_uptodate bit,
index 92e6757f196ed4e3b3598c1f8b7214616a4cbe39..5f17fad1bee8bfcd6281fd955f21019480651d94 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -745,7 +745,7 @@ int page_mkclean(struct page *page)
                if (mapping) {
                        ret = page_mkclean_file(mapping, page);
                        if (page_test_dirty(page)) {
-                               page_clear_dirty(page);
+                               page_clear_dirty(page, 1);
                                ret = 1;
                        }
                }
@@ -942,7 +942,7 @@ void page_remove_rmap(struct page *page)
         * containing the swap entry, but page not yet written to swap.
         */
        if ((!PageAnon(page) || PageSwapCache(page)) && page_test_dirty(page)) {
-               page_clear_dirty(page);
+               page_clear_dirty(page, 1);
                set_page_dirty(page);
        }
        /*