aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2012-10-08 03:18:26 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-11-23 05:14:24 -0500
commit18da236908793abccebc6f365fbe6e95a5b41db0 (patch)
tree34899d0c737b625660a44f2b47436e5e82a17511 /arch/s390/mm
parent26d29d06ea020411559f75ec908db235ca1838d9 (diff)
s390/mm,vmem: use 2GB frames for identity mapping
Use 2GB frames for indentity mapping if EDAT2 is available to reduce TLB pressure. 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/dump_pagetables.c7
-rw-r--r--arch/s390/mm/pageattr.c2
-rw-r--r--arch/s390/mm/vmem.c20
3 files changed, 23 insertions, 6 deletions
diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c
index cbc6668acb85..04e4892247d2 100644
--- a/arch/s390/mm/dump_pagetables.c
+++ b/arch/s390/mm/dump_pagetables.c
@@ -150,6 +150,7 @@ static void walk_pmd_level(struct seq_file *m, struct pg_state *st,
150static void walk_pud_level(struct seq_file *m, struct pg_state *st, 150static void walk_pud_level(struct seq_file *m, struct pg_state *st,
151 pgd_t *pgd, unsigned long addr) 151 pgd_t *pgd, unsigned long addr)
152{ 152{
153 unsigned int prot;
153 pud_t *pud; 154 pud_t *pud;
154 int i; 155 int i;
155 156
@@ -157,7 +158,11 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st,
157 st->current_address = addr; 158 st->current_address = addr;
158 pud = pud_offset(pgd, addr); 159 pud = pud_offset(pgd, addr);
159 if (!pud_none(*pud)) 160 if (!pud_none(*pud))
160 walk_pmd_level(m, st, pud, addr); 161 if (pud_large(*pud)) {
162 prot = pud_val(*pud) & _PAGE_RO;
163 note_page(m, st, prot, 2);
164 } else
165 walk_pmd_level(m, st, pud, addr);
161 else 166 else
162 note_page(m, st, _PAGE_INVALID, 2); 167 note_page(m, st, _PAGE_INVALID, 2);
163 addr += PUD_SIZE; 168 addr += PUD_SIZE;
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
index 00be01c4b4f3..c7ec7c2e46b0 100644
--- a/arch/s390/mm/pageattr.c
+++ b/arch/s390/mm/pageattr.c
@@ -19,7 +19,7 @@ static pte_t *walk_page_table(unsigned long addr)
19 if (pgd_none(*pgdp)) 19 if (pgd_none(*pgdp))
20 return NULL; 20 return NULL;
21 pudp = pud_offset(pgdp, addr); 21 pudp = pud_offset(pgdp, addr);
22 if (pud_none(*pudp)) 22 if (pud_none(*pudp) || pud_large(*pudp))
23 return NULL; 23 return NULL;
24 pmdp = pmd_offset(pudp, addr); 24 pmdp = pmd_offset(pudp, addr);
25 if (pmd_none(*pmdp) || pmd_large(*pmdp)) 25 if (pmd_none(*pmdp) || pmd_large(*pmdp))
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 387c7c60b5b8..bf37a094a46b 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -89,6 +89,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
89 int ret = -ENOMEM; 89 int ret = -ENOMEM;
90 90
91 while (address < end) { 91 while (address < end) {
92 pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0));
92 pg_dir = pgd_offset_k(address); 93 pg_dir = pgd_offset_k(address);
93 if (pgd_none(*pg_dir)) { 94 if (pgd_none(*pg_dir)) {
94 pu_dir = vmem_pud_alloc(); 95 pu_dir = vmem_pud_alloc();
@@ -96,18 +97,24 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
96 goto out; 97 goto out;
97 pgd_populate(&init_mm, pg_dir, pu_dir); 98 pgd_populate(&init_mm, pg_dir, pu_dir);
98 } 99 }
99
100 pu_dir = pud_offset(pg_dir, address); 100 pu_dir = pud_offset(pg_dir, address);
101#if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC)
102 if (MACHINE_HAS_EDAT2 && pud_none(*pu_dir) && address &&
103 !(address & ~PUD_MASK) && (address + PUD_SIZE <= end)) {
104 pte_val(pte) |= _REGION3_ENTRY_LARGE;
105 pte_val(pte) |= _REGION_ENTRY_TYPE_R3;
106 pud_val(*pu_dir) = pte_val(pte);
107 address += PUD_SIZE;
108 continue;
109 }
110#endif
101 if (pud_none(*pu_dir)) { 111 if (pud_none(*pu_dir)) {
102 pm_dir = vmem_pmd_alloc(); 112 pm_dir = vmem_pmd_alloc();
103 if (!pm_dir) 113 if (!pm_dir)
104 goto out; 114 goto out;
105 pud_populate(&init_mm, pu_dir, pm_dir); 115 pud_populate(&init_mm, pu_dir, pm_dir);
106 } 116 }
107
108 pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0));
109 pm_dir = pmd_offset(pu_dir, address); 117 pm_dir = pmd_offset(pu_dir, address);
110
111#if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC) 118#if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC)
112 if (MACHINE_HAS_EDAT1 && pmd_none(*pm_dir) && address && 119 if (MACHINE_HAS_EDAT1 && pmd_none(*pm_dir) && address &&
113 !(address & ~PMD_MASK) && (address + PMD_SIZE <= end)) { 120 !(address & ~PMD_MASK) && (address + PMD_SIZE <= end)) {
@@ -160,6 +167,11 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
160 address += PUD_SIZE; 167 address += PUD_SIZE;
161 continue; 168 continue;
162 } 169 }
170 if (pud_large(*pu_dir)) {
171 pud_clear(pu_dir);
172 address += PUD_SIZE;
173 continue;
174 }
163 pm_dir = pmd_offset(pu_dir, address); 175 pm_dir = pmd_offset(pu_dir, address);
164 if (pmd_none(*pm_dir)) { 176 if (pmd_none(*pm_dir)) {
165 address += PMD_SIZE; 177 address += PMD_SIZE;