summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2010-10-25 16:10:14 +0200
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2010-10-25 16:10:15 +0200
commite2b8d7af0e3a9234de06606f9151f28cf847a8d6 (patch)
tree64bc03271383a43c2097b84b6f0e25c34ed13553
parent92f842eac7ee321c8a0749aba2513541b4ac226f (diff)
[S390] add support for nonquiescing sske
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>
-rw-r--r--arch/s390/include/asm/page.h8
-rw-r--r--arch/s390/include/asm/pgtable.h8
-rw-r--r--arch/s390/kernel/early.c3
-rw-r--r--arch/s390/kernel/setup.c3
-rw-r--r--include/asm-generic/pgtable.h2
-rw-r--r--include/linux/page-flags.h2
-rw-r--r--mm/rmap.c4
7 files changed, 18 insertions, 12 deletions
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h
index af650fb47206..a8729ea7e9ac 100644
--- a/arch/s390/include/asm/page.h
+++ b/arch/s390/include/asm/page.h
@@ -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
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 85cd4b039de6..f79e7bb9ae1e 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -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);
}
/*
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index c00856ad4e5a..0badc6344eb4 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -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);
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index c8e8e1354e1d..9071e984dcf1 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -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);
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index f4d4120e5128..6f3c6ae4fe03 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -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
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 6fa317801e1c..5f38c460367e 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -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,
diff --git a/mm/rmap.c b/mm/rmap.c
index 92e6757f196e..5f17fad1bee8 100644
--- 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);
}
/*