]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - arch/powerpc/mm/pgtable-radix.c
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma
[linux.git] / arch / powerpc / mm / pgtable-radix.c
index 8c13e4282308add562bf794be32b989ef90eb803..671a45d86c18dd7e174ffb909084cd0a37fcdaff 100644 (file)
@@ -25,6 +25,9 @@
 
 #include <trace/events/thp.h>
 
+unsigned int mmu_pid_bits;
+unsigned int mmu_base_pid;
+
 static int native_register_process_table(unsigned long base, unsigned long pg_sz,
                                         unsigned long table_size)
 {
@@ -112,10 +115,9 @@ int radix__map_kernel_page(unsigned long ea, unsigned long pa,
 }
 
 #ifdef CONFIG_STRICT_KERNEL_RWX
-void radix__mark_rodata_ro(void)
+void radix__change_memory_range(unsigned long start, unsigned long end,
+                               unsigned long clear)
 {
-       unsigned long start = (unsigned long)_stext;
-       unsigned long end = (unsigned long)__init_begin;
        unsigned long idx;
        pgd_t *pgdp;
        pud_t *pudp;
@@ -125,7 +127,8 @@ void radix__mark_rodata_ro(void)
        start = ALIGN_DOWN(start, PAGE_SIZE);
        end = PAGE_ALIGN(end); // aligns up
 
-       pr_devel("marking ro start %lx, end %lx\n", start, end);
+       pr_debug("Changing flags on range %lx-%lx removing 0x%lx\n",
+                start, end, clear);
 
        for (idx = start; idx < end; idx += PAGE_SIZE) {
                pgdp = pgd_offset_k(idx);
@@ -147,11 +150,29 @@ void radix__mark_rodata_ro(void)
                if (!ptep)
                        continue;
 update_the_pte:
-               radix__pte_update(&init_mm, idx, ptep, _PAGE_WRITE, 0, 0);
+               radix__pte_update(&init_mm, idx, ptep, clear, 0, 0);
        }
 
        radix__flush_tlb_kernel_range(start, end);
 }
+
+void radix__mark_rodata_ro(void)
+{
+       unsigned long start, end;
+
+       start = (unsigned long)_stext;
+       end = (unsigned long)__init_begin;
+
+       radix__change_memory_range(start, end, _PAGE_WRITE);
+}
+
+void radix__mark_initmem_nx(void)
+{
+       unsigned long start = (unsigned long)__init_begin;
+       unsigned long end = (unsigned long)__init_end;
+
+       radix__change_memory_range(start, end, _PAGE_EXEC);
+}
 #endif /* CONFIG_STRICT_KERNEL_RWX */
 
 static inline void __meminit print_mapping(unsigned long start,
@@ -243,11 +264,34 @@ static void __init radix_init_pgtable(void)
        for_each_memblock(memory, reg)
                WARN_ON(create_physical_mapping(reg->base,
                                                reg->base + reg->size));
+
+       /* Find out how many PID bits are supported */
+       if (cpu_has_feature(CPU_FTR_HVMODE)) {
+               if (!mmu_pid_bits)
+                       mmu_pid_bits = 20;
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+               /*
+                * When KVM is possible, we only use the top half of the
+                * PID space to avoid collisions between host and guest PIDs
+                * which can cause problems due to prefetch when exiting the
+                * guest with AIL=3
+                */
+               mmu_base_pid = 1 << (mmu_pid_bits - 1);
+#else
+               mmu_base_pid = 1;
+#endif
+       } else {
+               /* The guest uses the bottom half of the PID space */
+               if (!mmu_pid_bits)
+                       mmu_pid_bits = 19;
+               mmu_base_pid = 1;
+       }
+
        /*
         * Allocate Partition table and process table for the
         * host.
         */
-       BUILD_BUG_ON_MSG((PRTB_SIZE_SHIFT > 36), "Process table size too large.");
+       BUG_ON(PRTB_SIZE_SHIFT > 36);
        process_tb = early_alloc_pgtable(1UL << PRTB_SIZE_SHIFT);
        /*
         * Fill in the process table.
@@ -321,6 +365,12 @@ static int __init radix_dt_scan_page_sizes(unsigned long node,
        if (type == NULL || strcmp(type, "cpu") != 0)
                return 0;
 
+       /* Find MMU PID size */
+       prop = of_get_flat_dt_prop(node, "ibm,mmu-pid-bits", &size);
+       if (prop && size == 4)
+               mmu_pid_bits = be32_to_cpup(prop);
+
+       /* Grab page size encodings */
        prop = of_get_flat_dt_prop(node, "ibm,processor-radix-AP-encodings", &size);
        if (!prop)
                return 0;