2020#include <asm/setup.h>
2121
2222/*
23- * We organize the E820 table into two main data structures:
23+ * We organize the E820 table into three main data structures:
2424 *
2525 * - 'e820_table_firmware': the original firmware version passed to us by the
26- * bootloader - not modified by the kernel. We use this to:
26+ * bootloader - not modified by the kernel. It is composed of two parts:
27+ * the first 128 E820 memory entries in boot_params.e820_table and the remaining
28+ * (if any) entries of the SETUP_E820_EXT nodes. We use this to:
2729 *
2830 * - inform the user about the firmware's notion of memory layout
2931 * via /sys/firmware/memmap
3032 *
3133 * - the hibernation code uses it to generate a kernel-independent MD5
3234 * fingerprint of the physical memory layout of a system.
3335 *
36+ * - 'e820_table_kexec': a slightly modified (by the kernel) firmware version
37+ * passed to us by the bootloader - the major difference between
38+ * e820_table_firmware[] and this one is that, the latter marks the setup_data
39+ * list created by the EFI boot stub as reserved, so that kexec can reuse the
40+ * setup_data information in the second kernel. Besides, e820_table_kexec[]
41+ * might also be modified by the kexec itself to fake a mptable.
42+ * We use this to:
43+ *
3444 * - kexec, which is a bootloader in disguise, uses the original E820
3545 * layout to pass to the kexec-ed kernel. This way the original kernel
3646 * can have a restricted E820 map while the kexec()-ed kexec-kernel
4656 * specific memory layout data during early bootup.
4757 */
4858static struct e820_table e820_table_init __initdata ;
59+ static struct e820_table e820_table_kexec_init __initdata ;
4960static struct e820_table e820_table_firmware_init __initdata ;
5061
5162struct e820_table * e820_table __refdata = & e820_table_init ;
63+ struct e820_table * e820_table_kexec __refdata = & e820_table_kexec_init ;
5264struct e820_table * e820_table_firmware __refdata = & e820_table_firmware_init ;
5365
5466/* For PCI or other memory-mapped resources */
@@ -470,9 +482,9 @@ u64 __init e820__range_update(u64 start, u64 size, enum e820_type old_type, enum
470482 return __e820__range_update (e820_table , start , size , old_type , new_type );
471483}
472484
473- static u64 __init e820__range_update_firmware (u64 start , u64 size , enum e820_type old_type , enum e820_type new_type )
485+ static u64 __init e820__range_update_kexec (u64 start , u64 size , enum e820_type old_type , enum e820_type new_type )
474486{
475- return __e820__range_update (e820_table_firmware , start , size , old_type , new_type );
487+ return __e820__range_update (e820_table_kexec , start , size , old_type , new_type );
476488}
477489
478490/* Remove a range of memory from the E820 table: */
@@ -546,9 +558,9 @@ void __init e820__update_table_print(void)
546558 e820__print_table ("modified" );
547559}
548560
549- static void __init e820__update_table_firmware (void )
561+ static void __init e820__update_table_kexec (void )
550562{
551- e820__update_table (e820_table_firmware );
563+ e820__update_table (e820_table_kexec );
552564}
553565
554566#define MAX_GAP_END 0x100000000ull
@@ -623,7 +635,7 @@ __init void e820__setup_pci_gap(void)
623635/*
624636 * Called late during init, in free_initmem().
625637 *
626- * Initial e820_table and e820_table_firmware are largish __initdata arrays.
638+ * Initial e820_table and e820_table_kexec are largish __initdata arrays.
627639 *
628640 * Copy them to a (usually much smaller) dynamically allocated area that is
629641 * sized precisely after the number of e820 entries.
@@ -643,6 +655,12 @@ __init void e820__reallocate_tables(void)
643655 memcpy (n , e820_table , size );
644656 e820_table = n ;
645657
658+ size = offsetof(struct e820_table , entries ) + sizeof (struct e820_entry )* e820_table_kexec -> nr_entries ;
659+ n = kmalloc (size , GFP_KERNEL );
660+ BUG_ON (!n );
661+ memcpy (n , e820_table_kexec , size );
662+ e820_table_kexec = n ;
663+
646664 size = offsetof(struct e820_table , entries ) + sizeof (struct e820_entry )* e820_table_firmware -> nr_entries ;
647665 n = kmalloc (size , GFP_KERNEL );
648666 BUG_ON (!n );
@@ -669,6 +687,9 @@ void __init e820__memory_setup_extended(u64 phys_addr, u32 data_len)
669687 __append_e820_table (extmap , entries );
670688 e820__update_table (e820_table );
671689
690+ memcpy (e820_table_kexec , e820_table , sizeof (* e820_table_kexec ));
691+ memcpy (e820_table_firmware , e820_table , sizeof (* e820_table_firmware ));
692+
672693 early_memunmap (sdata , data_len );
673694 pr_info ("e820: extended physical RAM map:\n" );
674695 e820__print_table ("extended" );
@@ -727,7 +748,7 @@ core_initcall(e820__register_nvs_regions);
727748/*
728749 * Allocate the requested number of bytes with the requsted alignment
729750 * and return (the physical address) to the caller. Also register this
730- * range in the 'firmware ' E820 table as a reserved range.
751+ * range in the 'kexec ' E820 table as a reserved range.
731752 *
732753 * This allows kexec to fake a new mptable, as if it came from the real
733754 * system.
@@ -738,9 +759,9 @@ u64 __init e820__memblock_alloc_reserved(u64 size, u64 align)
738759
739760 addr = __memblock_alloc_base (size , align , MEMBLOCK_ALLOC_ACCESSIBLE );
740761 if (addr ) {
741- e820__range_update_firmware (addr , size , E820_TYPE_RAM , E820_TYPE_RESERVED );
742- pr_info ("e820: update e820_table_firmware for e820__memblock_alloc_reserved()\n" );
743- e820__update_table_firmware ();
762+ e820__range_update_kexec (addr , size , E820_TYPE_RAM , E820_TYPE_RESERVED );
763+ pr_info ("e820: update e820_table_kexec for e820__memblock_alloc_reserved()\n" );
764+ e820__update_table_kexec ();
744765 }
745766
746767 return addr ;
@@ -923,13 +944,13 @@ void __init e820__reserve_setup_data(void)
923944 while (pa_data ) {
924945 data = early_memremap (pa_data , sizeof (* data ));
925946 e820__range_update (pa_data , sizeof (* data )+ data -> len , E820_TYPE_RAM , E820_TYPE_RESERVED_KERN );
947+ e820__range_update_kexec (pa_data , sizeof (* data )+ data -> len , E820_TYPE_RAM , E820_TYPE_RESERVED_KERN );
926948 pa_data = data -> next ;
927949 early_memunmap (data , sizeof (* data ));
928950 }
929951
930952 e820__update_table (e820_table );
931-
932- memcpy (e820_table_firmware , e820_table , sizeof (* e820_table_firmware ));
953+ e820__update_table (e820_table_kexec );
933954
934955 pr_info ("extended physical RAM map:\n" );
935956 e820__print_table ("reserve setup_data" );
@@ -1062,6 +1083,7 @@ void __init e820__reserve_resources(void)
10621083 res ++ ;
10631084 }
10641085
1086+ /* Expose the bootloader-provided memory layout to the sysfs. */
10651087 for (i = 0 ; i < e820_table_firmware -> nr_entries ; i ++ ) {
10661088 struct e820_entry * entry = e820_table_firmware -> entries + i ;
10671089
@@ -1175,6 +1197,7 @@ void __init e820__memory_setup(void)
11751197
11761198 who = x86_init .resources .memory_setup ();
11771199
1200+ memcpy (e820_table_kexec , e820_table , sizeof (* e820_table_kexec ));
11781201 memcpy (e820_table_firmware , e820_table , sizeof (* e820_table_firmware ));
11791202
11801203 pr_info ("e820: BIOS-provided physical RAM map:\n" );
0 commit comments