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 19c7a9403490..c2df53c5ceb9 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 5ce5a4dcd008..14be408dfc9b 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 4f7df85129d8..036fe2f10c77 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 | ||
