aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm/hash_utils_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/mm/hash_utils_64.c')
-rw-r--r--arch/powerpc/mm/hash_utils_64.c63
1 files changed, 39 insertions, 24 deletions
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
154static 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
155int htab_bolt_mapping(unsigned long vstart, unsigned long vend, 173int 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
520void create_section_mapping(unsigned long start, unsigned long end) 534void 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
527int remove_section_mapping(unsigned long start, unsigned long end) 541int 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);