]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - arch/x86/boot/compressed/pagetable.c
x86/KASLR: Fix detection 32/64 bit bootloaders for 5-level paging
[mirror_ubuntu-bionic-kernel.git] / arch / x86 / boot / compressed / pagetable.c
index 8e69df96492e84218dd7a6675ee11e7a5ebafb86..28029be47fbb839f248826b517a9e295f4389395 100644 (file)
@@ -63,7 +63,7 @@ static void *alloc_pgt_page(void *context)
 static struct alloc_pgt_data pgt_data;
 
 /* The top level page table entry pointer. */
-static unsigned long level4p;
+static unsigned long top_level_pgt;
 
 /*
  * Mapping information structure passed to kernel_ident_mapping_init().
@@ -91,9 +91,15 @@ void initialize_identity_maps(void)
         * If we came here via startup_32(), cr3 will be _pgtable already
         * and we must append to the existing area instead of entirely
         * overwriting it.
+        *
+        * With 5-level paging, we use '_pgtable' to allocate the p4d page table,
+        * the top-level page table is allocated separately.
+        *
+        * p4d_offset(top_level_pgt, 0) would cover both the 4- and 5-level
+        * cases. On 4-level paging it's equal to 'top_level_pgt'.
         */
-       level4p = read_cr3_pa();
-       if (level4p == (unsigned long)_pgtable) {
+       top_level_pgt = read_cr3_pa();
+       if (p4d_offset((pgd_t *)top_level_pgt, 0) == (p4d_t *)_pgtable) {
                debug_putstr("booted via startup_32()\n");
                pgt_data.pgt_buf = _pgtable + BOOT_INIT_PGT_SIZE;
                pgt_data.pgt_buf_size = BOOT_PGT_SIZE - BOOT_INIT_PGT_SIZE;
@@ -103,7 +109,7 @@ void initialize_identity_maps(void)
                pgt_data.pgt_buf = _pgtable;
                pgt_data.pgt_buf_size = BOOT_PGT_SIZE;
                memset(pgt_data.pgt_buf, 0, pgt_data.pgt_buf_size);
-               level4p = (unsigned long)alloc_pgt_page(&pgt_data);
+               top_level_pgt = (unsigned long)alloc_pgt_page(&pgt_data);
        }
 }
 
@@ -123,7 +129,7 @@ void add_identity_map(unsigned long start, unsigned long size)
                return;
 
        /* Build the mapping. */
-       kernel_ident_mapping_init(&mapping_info, (pgd_t *)level4p,
+       kernel_ident_mapping_init(&mapping_info, (pgd_t *)top_level_pgt,
                                  start, end);
 }
 
@@ -134,5 +140,5 @@ void add_identity_map(unsigned long start, unsigned long size)
  */
 void finalize_identity_maps(void)
 {
-       write_cr3(level4p);
+       write_cr3(top_level_pgt);
 }