Merge branch 'ras-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / arch / x86 / mm / kaslr.c
index d669c5e797e06e27a891f099739deb21e165673b..dc3f058bdf9be8bad920148a8a5737387b16b939 100644 (file)
@@ -125,10 +125,7 @@ void __init kernel_randomize_memory(void)
                 */
                entropy = remain_entropy / (ARRAY_SIZE(kaslr_regions) - i);
                prandom_bytes_state(&rand_state, &rand, sizeof(rand));
-               if (pgtable_l5_enabled())
-                       entropy = (rand % (entropy + 1)) & P4D_MASK;
-               else
-                       entropy = (rand % (entropy + 1)) & PUD_MASK;
+               entropy = (rand % (entropy + 1)) & PUD_MASK;
                vaddr += entropy;
                *kaslr_regions[i].base = vaddr;
 
@@ -137,84 +134,71 @@ void __init kernel_randomize_memory(void)
                 * randomization alignment.
                 */
                vaddr += get_padding(&kaslr_regions[i]);
-               if (pgtable_l5_enabled())
-                       vaddr = round_up(vaddr + 1, P4D_SIZE);
-               else
-                       vaddr = round_up(vaddr + 1, PUD_SIZE);
+               vaddr = round_up(vaddr + 1, PUD_SIZE);
                remain_entropy -= entropy;
        }
 }
 
 static void __meminit init_trampoline_pud(void)
 {
-       unsigned long paddr, paddr_next;
+       pud_t *pud_page_tramp, *pud, *pud_tramp;
+       p4d_t *p4d_page_tramp, *p4d, *p4d_tramp;
+       unsigned long paddr, vaddr;
        pgd_t *pgd;
-       pud_t *pud_page, *pud_page_tramp;
-       int i;
 
        pud_page_tramp = alloc_low_page();
 
+       /*
+        * There are two mappings for the low 1MB area, the direct mapping
+        * and the 1:1 mapping for the real mode trampoline:
+        *
+        * Direct mapping: virt_addr = phys_addr + PAGE_OFFSET
+        * 1:1 mapping:    virt_addr = phys_addr
+        */
        paddr = 0;
-       pgd = pgd_offset_k((unsigned long)__va(paddr));
-       pud_page = (pud_t *) pgd_page_vaddr(*pgd);
-
-       for (i = pud_index(paddr); i < PTRS_PER_PUD; i++, paddr = paddr_next) {
-               pud_t *pud, *pud_tramp;
-               unsigned long vaddr = (unsigned long)__va(paddr);
+       vaddr = (unsigned long)__va(paddr);
+       pgd = pgd_offset_k(vaddr);
 
-               pud_tramp = pud_page_tramp + pud_index(paddr);
-               pud = pud_page + pud_index(vaddr);
-               paddr_next = (paddr & PUD_MASK) + PUD_SIZE;
-
-               *pud_tramp = *pud;
-       }
+       p4d = p4d_offset(pgd, vaddr);
+       pud = pud_offset(p4d, vaddr);
 
-       set_pgd(&trampoline_pgd_entry,
-               __pgd(_KERNPG_TABLE | __pa(pud_page_tramp)));
-}
-
-static void __meminit init_trampoline_p4d(void)
-{
-       unsigned long paddr, paddr_next;
-       pgd_t *pgd;
-       p4d_t *p4d_page, *p4d_page_tramp;
-       int i;
+       pud_tramp = pud_page_tramp + pud_index(paddr);
+       *pud_tramp = *pud;
 
-       p4d_page_tramp = alloc_low_page();
-
-       paddr = 0;
-       pgd = pgd_offset_k((unsigned long)__va(paddr));
-       p4d_page = (p4d_t *) pgd_page_vaddr(*pgd);
-
-       for (i = p4d_index(paddr); i < PTRS_PER_P4D; i++, paddr = paddr_next) {
-               p4d_t *p4d, *p4d_tramp;
-               unsigned long vaddr = (unsigned long)__va(paddr);
+       if (pgtable_l5_enabled()) {
+               p4d_page_tramp = alloc_low_page();
 
                p4d_tramp = p4d_page_tramp + p4d_index(paddr);
-               p4d = p4d_page + p4d_index(vaddr);
-               paddr_next = (paddr & P4D_MASK) + P4D_SIZE;
 
-               *p4d_tramp = *p4d;
-       }
+               set_p4d(p4d_tramp,
+                       __p4d(_KERNPG_TABLE | __pa(pud_page_tramp)));
 
-       set_pgd(&trampoline_pgd_entry,
-               __pgd(_KERNPG_TABLE | __pa(p4d_page_tramp)));
+               set_pgd(&trampoline_pgd_entry,
+                       __pgd(_KERNPG_TABLE | __pa(p4d_page_tramp)));
+       } else {
+               set_pgd(&trampoline_pgd_entry,
+                       __pgd(_KERNPG_TABLE | __pa(pud_page_tramp)));
+       }
 }
 
 /*
- * Create PGD aligned trampoline table to allow real mode initialization
- * of additional CPUs. Consume only 1 low memory page.
+ * The real mode trampoline, which is required for bootstrapping CPUs
+ * occupies only a small area under the low 1MB.  See reserve_real_mode()
+ * for details.
+ *
+ * If KASLR is disabled the first PGD entry of the direct mapping is copied
+ * to map the real mode trampoline.
+ *
+ * If KASLR is enabled, copy only the PUD which covers the low 1MB
+ * area. This limits the randomization granularity to 1GB for both 4-level
+ * and 5-level paging.
  */
 void __meminit init_trampoline(void)
 {
-
        if (!kaslr_memory_enabled()) {
                init_trampoline_default();
                return;
        }
 
-       if (pgtable_l5_enabled())
-               init_trampoline_p4d();
-       else
-               init_trampoline_pud();
+       init_trampoline_pud();
 }