diff options
-rw-r--r-- | arch/powerpc/include/asm/mmu-hash64.h | 2 | ||||
-rw-r--r-- | arch/powerpc/mm/hash_utils_64.c | 63 | ||||
-rw-r--r-- | arch/powerpc/mm/init_64.c | 9 |
3 files changed, 43 insertions, 31 deletions
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h index 19c7a940349..c2df53c5ceb 100644 --- a/arch/powerpc/include/asm/mmu-hash64.h +++ b/arch/powerpc/include/asm/mmu-hash64.h | |||
@@ -278,7 +278,7 @@ extern int hash_huge_page(struct mm_struct *mm, unsigned long access, | |||
278 | unsigned long trap); | 278 | unsigned long trap); |
279 | 279 | ||
280 | extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend, | 280 | extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend, |
281 | unsigned long pstart, unsigned long mode, | 281 | unsigned long pstart, unsigned long prot, |
282 | int psize, int ssize); | 282 | int psize, int ssize); |
283 | extern void set_huge_psize(int psize); | 283 | extern void set_huge_psize(int psize); |
284 | extern void add_gpage(unsigned long addr, unsigned long page_size, | 284 | extern void add_gpage(unsigned long addr, unsigned long page_size, |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 5ce5a4dcd00..14be408dfc9 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -151,39 +151,53 @@ static struct mmu_psize_def mmu_psize_defaults_gp[] = { | |||
151 | }, | 151 | }, |
152 | }; | 152 | }; |
153 | 153 | ||
154 | static unsigned long htab_convert_pte_flags(unsigned long pteflags) | ||
155 | { | ||
156 | unsigned long rflags = pteflags & 0x1fa; | ||
157 | |||
158 | /* _PAGE_EXEC -> NOEXEC */ | ||
159 | if ((pteflags & _PAGE_EXEC) == 0) | ||
160 | rflags |= HPTE_R_N; | ||
161 | |||
162 | /* PP bits. PAGE_USER is already PP bit 0x2, so we only | ||
163 | * need to add in 0x1 if it's a read-only user page | ||
164 | */ | ||
165 | if ((pteflags & _PAGE_USER) && !((pteflags & _PAGE_RW) && | ||
166 | (pteflags & _PAGE_DIRTY))) | ||
167 | rflags |= 1; | ||
168 | |||
169 | /* Always add C */ | ||
170 | return rflags | HPTE_R_C; | ||
171 | } | ||
154 | 172 | ||
155 | int htab_bolt_mapping(unsigned long vstart, unsigned long vend, | 173 | int htab_bolt_mapping(unsigned long vstart, unsigned long vend, |
156 | unsigned long pstart, unsigned long mode, | 174 | unsigned long pstart, unsigned long prot, |
157 | int psize, int ssize) | 175 | int psize, int ssize) |
158 | { | 176 | { |
159 | unsigned long vaddr, paddr; | 177 | unsigned long vaddr, paddr; |
160 | unsigned int step, shift; | 178 | unsigned int step, shift; |
161 | unsigned long tmp_mode; | ||
162 | int ret = 0; | 179 | int ret = 0; |
163 | 180 | ||
164 | shift = mmu_psize_defs[psize].shift; | 181 | shift = mmu_psize_defs[psize].shift; |
165 | step = 1 << shift; | 182 | step = 1 << shift; |
166 | 183 | ||
184 | prot = htab_convert_pte_flags(prot); | ||
185 | |||
186 | DBG("htab_bolt_mapping(%lx..%lx -> %lx (%lx,%d,%d)\n", | ||
187 | vstart, vend, pstart, prot, psize, ssize); | ||
188 | |||
167 | for (vaddr = vstart, paddr = pstart; vaddr < vend; | 189 | for (vaddr = vstart, paddr = pstart; vaddr < vend; |
168 | vaddr += step, paddr += step) { | 190 | vaddr += step, paddr += step) { |
169 | unsigned long hash, hpteg; | 191 | unsigned long hash, hpteg; |
170 | unsigned long vsid = get_kernel_vsid(vaddr, ssize); | 192 | unsigned long vsid = get_kernel_vsid(vaddr, ssize); |
171 | unsigned long va = hpt_va(vaddr, vsid, ssize); | 193 | unsigned long va = hpt_va(vaddr, vsid, ssize); |
172 | 194 | ||
173 | tmp_mode = mode; | ||
174 | |||
175 | /* Make non-kernel text non-executable */ | ||
176 | if (!in_kernel_text(vaddr)) | ||
177 | tmp_mode = mode | HPTE_R_N; | ||
178 | |||
179 | hash = hpt_hash(va, shift, ssize); | 195 | hash = hpt_hash(va, shift, ssize); |
180 | hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); | 196 | hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); |
181 | 197 | ||
182 | DBG("htab_bolt_mapping: calling %p\n", ppc_md.hpte_insert); | ||
183 | |||
184 | BUG_ON(!ppc_md.hpte_insert); | 198 | BUG_ON(!ppc_md.hpte_insert); |
185 | ret = ppc_md.hpte_insert(hpteg, va, paddr, | 199 | ret = ppc_md.hpte_insert(hpteg, va, paddr, prot, |
186 | tmp_mode, HPTE_V_BOLTED, psize, ssize); | 200 | HPTE_V_BOLTED, psize, ssize); |
187 | 201 | ||
188 | if (ret < 0) | 202 | if (ret < 0) |
189 | break; | 203 | break; |
@@ -519,9 +533,9 @@ static unsigned long __init htab_get_table_size(void) | |||
519 | #ifdef CONFIG_MEMORY_HOTPLUG | 533 | #ifdef CONFIG_MEMORY_HOTPLUG |
520 | void create_section_mapping(unsigned long start, unsigned long end) | 534 | void create_section_mapping(unsigned long start, unsigned long end) |
521 | { | 535 | { |
522 | BUG_ON(htab_bolt_mapping(start, end, __pa(start), | 536 | BUG_ON(htab_bolt_mapping(start, end, __pa(start), |
523 | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX, | 537 | PAGE_KERNEL, mmu_linear_psize, |
524 | mmu_linear_psize, mmu_kernel_ssize)); | 538 | mmu_kernel_ssize)); |
525 | } | 539 | } |
526 | 540 | ||
527 | int remove_section_mapping(unsigned long start, unsigned long end) | 541 | int remove_section_mapping(unsigned long start, unsigned long end) |
@@ -570,7 +584,7 @@ void __init htab_initialize(void) | |||
570 | { | 584 | { |
571 | unsigned long table; | 585 | unsigned long table; |
572 | unsigned long pteg_count; | 586 | unsigned long pteg_count; |
573 | unsigned long mode_rw; | 587 | unsigned long prot, tprot; |
574 | unsigned long base = 0, size = 0, limit; | 588 | unsigned long base = 0, size = 0, limit; |
575 | int i; | 589 | int i; |
576 | 590 | ||
@@ -628,7 +642,7 @@ void __init htab_initialize(void) | |||
628 | mtspr(SPRN_SDR1, _SDR1); | 642 | mtspr(SPRN_SDR1, _SDR1); |
629 | } | 643 | } |
630 | 644 | ||
631 | mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX; | 645 | prot = PAGE_KERNEL; |
632 | 646 | ||
633 | #ifdef CONFIG_DEBUG_PAGEALLOC | 647 | #ifdef CONFIG_DEBUG_PAGEALLOC |
634 | linear_map_hash_count = lmb_end_of_DRAM() >> PAGE_SHIFT; | 648 | linear_map_hash_count = lmb_end_of_DRAM() >> PAGE_SHIFT; |
@@ -646,8 +660,10 @@ void __init htab_initialize(void) | |||
646 | for (i=0; i < lmb.memory.cnt; i++) { | 660 | for (i=0; i < lmb.memory.cnt; i++) { |
647 | base = (unsigned long)__va(lmb.memory.region[i].base); | 661 | base = (unsigned long)__va(lmb.memory.region[i].base); |
648 | size = lmb.memory.region[i].size; | 662 | size = lmb.memory.region[i].size; |
663 | tprot = prot | (in_kernel_text(base) ? _PAGE_EXEC : 0); | ||
649 | 664 | ||
650 | DBG("creating mapping for region: %lx : %lx\n", base, size); | 665 | DBG("creating mapping for region: %lx..%lx (prot: %x)\n", |
666 | base, size, tprot); | ||
651 | 667 | ||
652 | #ifdef CONFIG_U3_DART | 668 | #ifdef CONFIG_U3_DART |
653 | /* Do not map the DART space. Fortunately, it will be aligned | 669 | /* Do not map the DART space. Fortunately, it will be aligned |
@@ -664,21 +680,21 @@ void __init htab_initialize(void) | |||
664 | unsigned long dart_table_end = dart_tablebase + 16 * MB; | 680 | unsigned long dart_table_end = dart_tablebase + 16 * MB; |
665 | if (base != dart_tablebase) | 681 | if (base != dart_tablebase) |
666 | BUG_ON(htab_bolt_mapping(base, dart_tablebase, | 682 | BUG_ON(htab_bolt_mapping(base, dart_tablebase, |
667 | __pa(base), mode_rw, | 683 | __pa(base), tprot, |
668 | mmu_linear_psize, | 684 | mmu_linear_psize, |
669 | mmu_kernel_ssize)); | 685 | mmu_kernel_ssize)); |
670 | if ((base + size) > dart_table_end) | 686 | if ((base + size) > dart_table_end) |
671 | BUG_ON(htab_bolt_mapping(dart_tablebase+16*MB, | 687 | BUG_ON(htab_bolt_mapping(dart_tablebase+16*MB, |
672 | base + size, | 688 | base + size, |
673 | __pa(dart_table_end), | 689 | __pa(dart_table_end), |
674 | mode_rw, | 690 | tprot, |
675 | mmu_linear_psize, | 691 | mmu_linear_psize, |
676 | mmu_kernel_ssize)); | 692 | mmu_kernel_ssize)); |
677 | continue; | 693 | continue; |
678 | } | 694 | } |
679 | #endif /* CONFIG_U3_DART */ | 695 | #endif /* CONFIG_U3_DART */ |
680 | BUG_ON(htab_bolt_mapping(base, base + size, __pa(base), | 696 | BUG_ON(htab_bolt_mapping(base, base + size, __pa(base), |
681 | mode_rw, mmu_linear_psize, mmu_kernel_ssize)); | 697 | tprot, mmu_linear_psize, mmu_kernel_ssize)); |
682 | } | 698 | } |
683 | 699 | ||
684 | /* | 700 | /* |
@@ -696,7 +712,7 @@ void __init htab_initialize(void) | |||
696 | tce_alloc_start = base + size + 1; | 712 | tce_alloc_start = base + size + 1; |
697 | 713 | ||
698 | BUG_ON(htab_bolt_mapping(tce_alloc_start, tce_alloc_end, | 714 | BUG_ON(htab_bolt_mapping(tce_alloc_start, tce_alloc_end, |
699 | __pa(tce_alloc_start), mode_rw, | 715 | __pa(tce_alloc_start), prot, |
700 | mmu_linear_psize, mmu_kernel_ssize)); | 716 | mmu_linear_psize, mmu_kernel_ssize)); |
701 | } | 717 | } |
702 | 718 | ||
@@ -1117,8 +1133,7 @@ static void kernel_map_linear_page(unsigned long vaddr, unsigned long lmi) | |||
1117 | unsigned long hash, hpteg; | 1133 | unsigned long hash, hpteg; |
1118 | unsigned long vsid = get_kernel_vsid(vaddr, mmu_kernel_ssize); | 1134 | unsigned long vsid = get_kernel_vsid(vaddr, mmu_kernel_ssize); |
1119 | unsigned long va = hpt_va(vaddr, vsid, mmu_kernel_ssize); | 1135 | unsigned long va = hpt_va(vaddr, vsid, mmu_kernel_ssize); |
1120 | unsigned long mode = _PAGE_ACCESSED | _PAGE_DIRTY | | 1136 | unsigned long mode = htab_convert_pte_flags(PAGE_KERNEL); |
1121 | _PAGE_COHERENT | PP_RWXX | HPTE_R_N; | ||
1122 | int ret; | 1137 | int ret; |
1123 | 1138 | ||
1124 | hash = hpt_hash(va, PAGE_SHIFT, mmu_kernel_ssize); | 1139 | hash = hpt_hash(va, PAGE_SHIFT, mmu_kernel_ssize); |
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 4f7df85129d..036fe2f10c7 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
@@ -206,13 +206,10 @@ static int __meminit vmemmap_populated(unsigned long start, int page_size) | |||
206 | int __meminit vmemmap_populate(struct page *start_page, | 206 | int __meminit vmemmap_populate(struct page *start_page, |
207 | unsigned long nr_pages, int node) | 207 | unsigned long nr_pages, int node) |
208 | { | 208 | { |
209 | unsigned long mode_rw; | ||
210 | unsigned long start = (unsigned long)start_page; | 209 | unsigned long start = (unsigned long)start_page; |
211 | unsigned long end = (unsigned long)(start_page + nr_pages); | 210 | unsigned long end = (unsigned long)(start_page + nr_pages); |
212 | unsigned long page_size = 1 << mmu_psize_defs[mmu_vmemmap_psize].shift; | 211 | unsigned long page_size = 1 << mmu_psize_defs[mmu_vmemmap_psize].shift; |
213 | 212 | ||
214 | mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX; | ||
215 | |||
216 | /* Align to the page size of the linear mapping. */ | 213 | /* Align to the page size of the linear mapping. */ |
217 | start = _ALIGN_DOWN(start, page_size); | 214 | start = _ALIGN_DOWN(start, page_size); |
218 | 215 | ||
@@ -230,9 +227,9 @@ int __meminit vmemmap_populate(struct page *start_page, | |||
230 | pr_debug("vmemmap %08lx allocated at %p, physical %08lx.\n", | 227 | pr_debug("vmemmap %08lx allocated at %p, physical %08lx.\n", |
231 | start, p, __pa(p)); | 228 | start, p, __pa(p)); |
232 | 229 | ||
233 | mapped = htab_bolt_mapping(start, start + page_size, | 230 | mapped = htab_bolt_mapping(start, start + page_size, __pa(p), |
234 | __pa(p), mode_rw, mmu_vmemmap_psize, | 231 | PAGE_KERNEL, mmu_vmemmap_psize, |
235 | mmu_kernel_ssize); | 232 | mmu_kernel_ssize); |
236 | BUG_ON(mapped < 0); | 233 | BUG_ON(mapped < 0); |
237 | } | 234 | } |
238 | 235 | ||