aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2014-09-23 15:29:20 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2014-09-30 04:19:29 -0400
commitcfb0b24143b4f587ff3e3bd829f9f471285d097b (patch)
tree217a325aaba02fa8b6a0c91d8dd2abe7b96fcb66 /arch/s390
parent242a112af62ea73ce507cbe76c2c944c23b6a1e3 (diff)
s390/mm: make use of ipte range facility
Invalidate several pte entries at once if the ipte range facility is available. Currently this works only for DEBUG_PAGE_ALLOC where several up to 2 ^ MAX_ORDER may be invalidated at once. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/include/asm/pgtable.h16
-rw-r--r--arch/s390/mm/pageattr.c38
2 files changed, 47 insertions, 7 deletions
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 7c4af56f2b73..2de229c1b467 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -1053,6 +1053,22 @@ static inline void __ptep_ipte_local(unsigned long address, pte_t *ptep)
1053 : "=m" (*ptep) : "m" (*ptep), "a" (pto), "a" (address)); 1053 : "=m" (*ptep) : "m" (*ptep), "a" (pto), "a" (address));
1054} 1054}
1055 1055
1056static inline void __ptep_ipte_range(unsigned long address, int nr, pte_t *ptep)
1057{
1058 unsigned long pto = (unsigned long) ptep;
1059
1060#ifndef CONFIG_64BIT
1061 /* pto in ESA mode must point to the start of the segment table */
1062 pto &= 0x7ffffc00;
1063#endif
1064 /* Invalidate a range of ptes + global TLB flush of the ptes */
1065 do {
1066 asm volatile(
1067 " .insn rrf,0xb2210000,%2,%0,%1,0"
1068 : "+a" (address), "+a" (nr) : "a" (pto) : "memory");
1069 } while (nr != 255);
1070}
1071
1056static inline void ptep_flush_direct(struct mm_struct *mm, 1072static inline void ptep_flush_direct(struct mm_struct *mm,
1057 unsigned long address, pte_t *ptep) 1073 unsigned long address, pte_t *ptep)
1058{ 1074{
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
index 8400f494623f..3fef3b299665 100644
--- a/arch/s390/mm/pageattr.c
+++ b/arch/s390/mm/pageattr.c
@@ -6,6 +6,7 @@
6#include <linux/module.h> 6#include <linux/module.h>
7#include <linux/mm.h> 7#include <linux/mm.h>
8#include <asm/cacheflush.h> 8#include <asm/cacheflush.h>
9#include <asm/facility.h>
9#include <asm/pgtable.h> 10#include <asm/pgtable.h>
10#include <asm/page.h> 11#include <asm/page.h>
11 12
@@ -103,27 +104,50 @@ int set_memory_x(unsigned long addr, int numpages)
103} 104}
104 105
105#ifdef CONFIG_DEBUG_PAGEALLOC 106#ifdef CONFIG_DEBUG_PAGEALLOC
107
108static void ipte_range(pte_t *pte, unsigned long address, int nr)
109{
110 int i;
111
112 if (test_facility(13) && IS_ENABLED(CONFIG_64BIT)) {
113 __ptep_ipte_range(address, nr - 1, pte);
114 return;
115 }
116 for (i = 0; i < nr; i++) {
117 __ptep_ipte(address, pte);
118 address += PAGE_SIZE;
119 pte++;
120 }
121}
122
106void kernel_map_pages(struct page *page, int numpages, int enable) 123void kernel_map_pages(struct page *page, int numpages, int enable)
107{ 124{
108 unsigned long address; 125 unsigned long address;
126 int nr, i, j;
109 pgd_t *pgd; 127 pgd_t *pgd;
110 pud_t *pud; 128 pud_t *pud;
111 pmd_t *pmd; 129 pmd_t *pmd;
112 pte_t *pte; 130 pte_t *pte;
113 int i;
114 131
115 for (i = 0; i < numpages; i++) { 132 for (i = 0; i < numpages;) {
116 address = page_to_phys(page + i); 133 address = page_to_phys(page + i);
117 pgd = pgd_offset_k(address); 134 pgd = pgd_offset_k(address);
118 pud = pud_offset(pgd, address); 135 pud = pud_offset(pgd, address);
119 pmd = pmd_offset(pud, address); 136 pmd = pmd_offset(pud, address);
120 pte = pte_offset_kernel(pmd, address); 137 pte = pte_offset_kernel(pmd, address);
121 if (!enable) { 138 nr = (unsigned long)pte >> ilog2(sizeof(long));
122 __ptep_ipte(address, pte); 139 nr = PTRS_PER_PTE - (nr & (PTRS_PER_PTE - 1));
123 pte_val(*pte) = _PAGE_INVALID; 140 nr = min(numpages - i, nr);
124 continue; 141 if (enable) {
142 for (j = 0; j < nr; j++) {
143 pte_val(*pte) = __pa(address);
144 address += PAGE_SIZE;
145 pte++;
146 }
147 } else {
148 ipte_range(pte, address, nr);
125 } 149 }
126 pte_val(*pte) = __pa(address); 150 i += nr;
127 } 151 }
128} 152}
129 153