]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
x86/realmode: Make the location of the trampoline configurable
authorYunhong Jiang <yunhong.jiang@linux.intel.com>
Wed, 4 Mar 2026 23:41:17 +0000 (15:41 -0800)
committerDexuan Cui <decui@microsoft.com>
Thu, 28 May 2026 20:01:25 +0000 (20:01 +0000)
x86 CPUs boot in real mode. This mode uses a 1MB address space. The
trampoline must reside below this 1MB memory boundary.

There are platforms in which the firmware boots the secondary CPUs,
switches them to long mode and transfers control to the kernel. An example
of such a mechanism is the ACPI Multiprocessor Wakeup Structure.

In this scenario there is no restriction on locating the trampoline under
1MB memory. Moreover, certain platforms (for example, Hyper-V VTL guests)
may not have memory available for allocation below 1MB.

Add a new member to struct x86_init_resources to specify the upper bound
for the location of the trampoline memory. Preserve the default upper bound
of 1MB to conserve the current behavior.

Reviewed-by: Dexuan Cui <decui@microsoft.com>
Reviewed-by: Michael Kelley <mhklinux@outlook.com>
Originally-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Yunhong Jiang <yunhong.jiang@linux.intel.com>
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Signed-off-by: Dexuan Cui <dexuan@kernel.org>
arch/x86/include/asm/x86_init.h
arch/x86/kernel/x86_init.c
arch/x86/realmode/init.c

index 6c8a6ead84f6ee2abfede3885f165b26c60d38d8..953d3199408ae5466be68fbdb9c39c55887158cc 100644 (file)
@@ -31,12 +31,15 @@ struct x86_init_mpparse {
  *                             platform
  * @memory_setup:              platform specific memory setup
  * @dmi_setup:                 platform specific DMI setup
+ * @realmode_limit:            platform specific address limit for the real mode trampoline
+ *                             (default 1M)
  */
 struct x86_init_resources {
        void (*probe_roms)(void);
        void (*reserve_resources)(void);
        char *(*memory_setup)(void);
        void (*dmi_setup)(void);
+       unsigned long realmode_limit;
 };
 
 /**
index ebefb77c37bbd067ea33f7c6d4b679d6e2e377db..252c5827d0634ffdea676cfde61d9a09123084c7 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/acpi.h>
+#include <linux/sizes.h>
 
 #include <asm/acpi.h>
 #include <asm/bios_ebda.h>
@@ -69,6 +70,8 @@ struct x86_init_ops x86_init __initdata = {
                .reserve_resources      = reserve_standard_io_resources,
                .memory_setup           = e820__memory_setup_default,
                .dmi_setup              = dmi_setup,
+               /* Has to be under 1M so we can execute real-mode AP code. */
+               .realmode_limit         = SZ_1M,
        },
 
        .mpparse = {
index 88be32026768c15449da84b8d559fab57260fdf9..694d80a5c68e143d74da0c1a65a9d9e6c433ad11 100644 (file)
@@ -46,7 +46,7 @@ void load_trampoline_pgtable(void)
 
 void __init reserve_real_mode(void)
 {
-       phys_addr_t mem;
+       phys_addr_t mem, limit = x86_init.resources.realmode_limit;
        size_t size = real_mode_size_needed();
 
        if (!size)
@@ -54,10 +54,9 @@ void __init reserve_real_mode(void)
 
        WARN_ON(slab_is_available());
 
-       /* Has to be under 1M so we can execute real-mode AP code. */
-       mem = memblock_phys_alloc_range(size, PAGE_SIZE, 0, 1<<20);
+       mem = memblock_phys_alloc_range(size, PAGE_SIZE, 0, limit);
        if (!mem)
-               pr_info("No sub-1M memory is available for the trampoline\n");
+               pr_info("No memory below %pa for the real-mode trampoline\n", &limit);
        else
                set_real_mode_mem(mem);