diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2012-10-08 03:18:26 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2012-11-23 05:14:24 -0500 |
commit | 18da236908793abccebc6f365fbe6e95a5b41db0 (patch) | |
tree | 34899d0c737b625660a44f2b47436e5e82a17511 /arch/s390/mm | |
parent | 26d29d06ea020411559f75ec908db235ca1838d9 (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.c | 7 | ||||
-rw-r--r-- | arch/s390/mm/pageattr.c | 2 | ||||
-rw-r--r-- | arch/s390/mm/vmem.c | 20 |
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, | |||
150 | static void walk_pud_level(struct seq_file *m, struct pg_state *st, | 150 | static 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; |