aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm
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/mm
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/mm')
-rw-r--r--arch/s390/mm/pageattr.c38
1 files changed, 31 insertions, 7 deletions
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