x86, realmode: header for trampoline code
authorJarkko Sakkinen <jarkko.sakkinen@intel.com>
Tue, 8 May 2012 18:22:43 +0000 (21:22 +0300)
committerH. Peter Anvin <hpa@linux.intel.com>
Tue, 8 May 2012 18:48:45 +0000 (11:48 -0700)
Added header for trampoline code that can be used to supply
input data to it. This makes interface between real mode code
and kernel cleaner and simpler. Replaced two confusing pointers
to level4 pgt in trampoline_64.S with a single pointer to the
beginning of the page table.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@intel.com>
Link: http://lkml.kernel.org/r/1336501366-28617-21-git-send-email-jarkko.sakkinen@intel.com
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
arch/x86/include/asm/realmode.h
arch/x86/kernel/realmode.c
arch/x86/kernel/smpboot.c
arch/x86/realmode/rm/header.S
arch/x86/realmode/rm/trampoline_32.S
arch/x86/realmode/rm/trampoline_64.S
arch/x86/realmode/rm/trampoline_common.S [new file with mode: 0644]
arch/x86/realmode/rm/wakeup_asm.S

index d3ae49f4c3ef82a2aebe1c228cec208f340d22c0..1421eed1c8e8586eff49fec7fd9aab7001cb6be8 100644 (file)
@@ -8,24 +8,32 @@
 struct real_mode_header {
        u32     text_start;
        u32     ro_end;
-       /* reboot */
-#ifdef CONFIG_X86_32
-       u32     machine_real_restart_asm;
-#endif
        /* SMP trampoline */
-       u32     trampoline_data;
+       u32     trampoline_start;
        u32     trampoline_status;
-#ifdef CONFIG_X86_32
-       u32     startup_32_smp;
-       u32     boot_gdt;
-#else
-       u32     startup_64_smp;
-       u32     level3_ident_pgt;
-       u32     level3_kernel_pgt;
+       u32     trampoline_header;
+#ifdef CONFIG_X86_64
+       u32     trampoline_pgd;
 #endif
+       /* ACPI S3 wakeup */
 #ifdef CONFIG_ACPI_SLEEP
        u32     wakeup_start;
        u32     wakeup_header;
+#endif
+       /* APM/BIOS reboot */
+#ifdef CONFIG_X86_32
+       u32     machine_real_restart_asm;
+#endif
+} __attribute__((__packed__));
+
+/* This must match data at trampoline_32/64.S */
+struct trampoline_header {
+#ifdef CONFIG_X86_32
+       u32 start;
+       u16 gdt_limit;
+       u32 gdt_base;
+#else
+       u64 start;
 #endif
 } __attribute__((__packed__));
 
index 632c810ec8eaf4f3bbd2aeca4ff8700d92f5f447..712fba8fd7743c026458bed4662a41f1cdb21d9e 100644 (file)
@@ -17,8 +17,11 @@ void __init setup_real_mode(void)
        u16 *seg;
        int i;
        unsigned char *base;
-
+       struct trampoline_header *trampoline_header;
        size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob);
+#ifdef CONFIG_X86_64
+       u64 *trampoline_pgd;
+#endif
 
        /* Has to be in very low memory so we can execute real-mode AP code. */
        mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE);
@@ -28,7 +31,6 @@ void __init setup_real_mode(void)
        base = __va(mem);
        memblock_reserve(mem, size);
        real_mode_header = (struct real_mode_header *) base;
-
        printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n",
               base, (unsigned long long)mem, size);
 
@@ -53,18 +55,19 @@ void __init setup_real_mode(void)
                *ptr += __pa(base);
        }
 
+       /* Must be perfomed *after* relocation. */
+       trampoline_header = (struct trampoline_header *)
+               __va(real_mode_header->trampoline_header);
+
 #ifdef CONFIG_X86_32
-       *((u32 *)__va(real_mode_header->startup_32_smp)) = __pa(startup_32_smp);
-       *((u32 *)__va(real_mode_header->boot_gdt)) = __pa(boot_gdt);
+       trampoline_header->start = __pa(startup_32_smp);
+       trampoline_header->gdt_limit = __BOOT_DS + 7;
+       trampoline_header->gdt_base = __pa(boot_gdt);
 #else
-       *((u64 *) __va(real_mode_header->startup_64_smp)) =
-               (u64)secondary_startup_64;
-
-       *((u64 *) __va(real_mode_header->level3_ident_pgt)) =
-               __pa(level3_ident_pgt) + _KERNPG_TABLE;
-
-       *((u64 *) __va(real_mode_header->level3_kernel_pgt)) =
-               __pa(level3_kernel_pgt) + _KERNPG_TABLE;
+       trampoline_header->start = (u64) secondary_startup_64;
+       trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);
+       trampoline_pgd[0] = __pa(level3_ident_pgt) + _KERNPG_TABLE;
+       trampoline_pgd[511] = __pa(level3_kernel_pgt) + _KERNPG_TABLE;
 #endif
 }
 
index b8c0661e234142102fb9a6d882aeccf97bad8f08..757c4b1d0a02456ca68b3dd5f52faf3fc0d20173 100644 (file)
@@ -667,7 +667,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)
        volatile u32 *trampoline_status =
                (volatile u32 *) __va(real_mode_header->trampoline_status);
        /* start_ip had better be page-aligned! */
-       unsigned long start_ip = real_mode_header->trampoline_data;
+       unsigned long start_ip = real_mode_header->trampoline_start;
 
        unsigned long boot_error = 0;
        int timeout;
index c83005c4d455aab7671d31f20bd20b1a899d4a00..b4c32632bf1684c05d4c9046593731f38024c487 100644 (file)
@@ -7,28 +7,25 @@
 #include <linux/linkage.h>
 #include <asm/page_types.h>
 
-               .section ".header", "a"
+       .section ".header", "a"
 
 GLOBAL(real_mode_header)
-               .long   pa_text_start
-               .long   pa_ro_end
-#ifdef CONFIG_X86_32
-               .long   pa_machine_real_restart_asm
-#endif
-               /* SMP trampoline */
-               .long   pa_trampoline_data
-               .long   pa_trampoline_status
-#ifdef CONFIG_X86_32
-               .long   pa_startup_32_smp
-               .long   pa_boot_gdt
-#else
-               .long   pa_startup_64_smp
-               .long   pa_level3_ident_pgt
-               .long   pa_level3_kernel_pgt
+       .long   pa_text_start
+       .long   pa_ro_end
+       /* SMP trampoline */
+       .long   pa_trampoline_start
+       .long   pa_trampoline_status
+       .long   pa_trampoline_header
+#ifdef CONFIG_X86_64
+       .long   pa_trampoline_pgd;
 #endif
-               /* ACPI sleep */
+       /* ACPI S3 wakeup */
 #ifdef CONFIG_ACPI_SLEEP
-               .long   pa_wakeup_start
-               .long   pa_wakeup_header
+       .long   pa_wakeup_start
+       .long   pa_wakeup_header
+#endif
+       /* APM/BIOS reboot */
+#ifdef CONFIG_X86_32
+       .long   pa_machine_real_restart_asm
 #endif
 END(real_mode_header)
index 1ecdbb59191b06b8c1ae856b42aba8475f0aee9b..6fc064b4d2b972aaeded04f5132669ebc216598c 100644 (file)
  *
  *     We jump into arch/x86/kernel/head_32.S.
  *
- *     On entry to trampoline_data, the processor is in real mode
+ *     On entry to trampoline_start, the processor is in real mode
  *     with 16-bit addressing and 16-bit data.  CS has some value
  *     and IP is zero.  Thus, we load CS to the physical segment
  *     of the real mode code before doing anything further.
- *
- *     The structure real_mode_header includes entries that need
- *     to be set up before executing this code:
- *
- *     startup_32_smp
- *     boot_gdt
  */
 
 #include <linux/linkage.h>
@@ -35,7 +29,7 @@
        .code16
 
        .balign PAGE_SIZE
-ENTRY(trampoline_data)
+ENTRY(trampoline_start)
        wbinvd                  # Needed for NUMA-Q should be harmless for others
 
        LJMPW_RM(1f)
@@ -45,7 +39,7 @@ ENTRY(trampoline_data)
 
        cli                     # We should be safe anyway
 
-       movl    startup_32_smp, %eax    # where we need to go
+       movl    tr_start, %eax  # where we need to go
 
        movl    $0xA5A5A5A5, trampoline_status
                                # write marker for master knows we're running
@@ -56,8 +50,8 @@ ENTRY(trampoline_data)
         * operand size is 16bit. Use lgdtl instead to force operand size
         * to 32 bit.
         */
-       lidtl   boot_idt_descr          # load idt with 0, 0
-       lgdtl   boot_gdt_descr          # load gdt with whatever is appropriate
+       lidtl   tr_idt                  # load idt with 0, 0
+       lgdtl   tr_gdt                  # load gdt with whatever is appropriate
 
        movw    $1, %dx                 # protected mode (PE) bit
        lmsw    %dx                     # into protected mode
@@ -69,22 +63,4 @@ ENTRY(trampoline_data)
 ENTRY(startup_32)                      # note: also used from wakeup_asm.S
        jmp     *%eax
 
-       .section ".rodata","a"
-
-       .balign 4
-boot_idt_descr:
-       .word   0                               # idt limit = 0
-       .long   0                               # idt base = 0L
-
-       .data
-
-boot_gdt_descr:
-       .word   __BOOT_DS + 7                   # gdt limit
-GLOBAL(boot_gdt)
-       .long   0                               # gdt base
-
-       .bss
-
-       .balign 4
-GLOBAL(trampoline_status)      .space  4
-GLOBAL(startup_32_smp)         .space  4
+#include "trampoline_common.S"
index f71ea0800d3dc508dc9988c99cef630c03f49180..3f7293239365acc549d7ffd6594cd13ccf7c6a5e 100644 (file)
@@ -10,7 +10,7 @@
  *     trampoline page to make our stack and everything else
  *     is a mystery.
  *
- *     On entry to trampoline_data, the processor is in real mode
+ *     On entry to trampoline_start, the processor is in real mode
  *     with 16-bit addressing and 16-bit data.  CS has some value
  *     and IP is zero.  Thus, data addresses need to be absolute
  *     (no relocation) and are taken with regard to r_base.
@@ -37,7 +37,7 @@
        .balign PAGE_SIZE
        .code16
 
-ENTRY(trampoline_data)
+ENTRY(trampoline_start)
        cli                     # We should be safe anyway
        wbinvd
 
@@ -97,7 +97,7 @@ ENTRY(startup_32)
        movl    %eax, %cr4              # Enable PAE mode
 
        # Setup trampoline 4 level pagetables
-       movl    $pa_level3_ident_pgt, %eax
+       movl    $pa_trampoline_pgd, %eax
        movl    %eax, %cr3
 
        movl    $MSR_EFER, %ecx
@@ -122,7 +122,7 @@ ENTRY(startup_32)
        .balign 4
 ENTRY(startup_64)
        # Now jump into the kernel using virtual addresses
-       jmpq    *startup_64_smp(%rip)
+       jmpq    *tr_start(%rip)
 
        .section ".rodata","a"
        .balign 16
@@ -143,12 +143,4 @@ tgdt:
        .quad   0x00cf93000000ffff      # __KERNEL_DS
 tgdt_end:
 
-       .bss
-
-       .balign PAGE_SIZE
-GLOBAL(level3_ident_pgt)       .space  511*8
-GLOBAL(level3_kernel_pgt)      .space  8
-
-       .balign 8
-GLOBAL(startup_64_smp)         .space  8
-GLOBAL(trampoline_status)      .space  4
+#include "trampoline_common.S"
diff --git a/arch/x86/realmode/rm/trampoline_common.S b/arch/x86/realmode/rm/trampoline_common.S
new file mode 100644 (file)
index 0000000..c3f951c
--- /dev/null
@@ -0,0 +1,23 @@
+       .section ".rodata","a"
+
+       .balign 4
+tr_idt: .fill 1, 6, 0
+
+       .bss
+
+       .balign 4
+GLOBAL(trampoline_status)      .space  4
+
+GLOBAL(trampoline_header)
+#ifdef CONFIG_X86_32
+       tr_start:               .space  4
+       tr_gdt:                 .space  6
+#else
+       tr_start:               .space  8
+#endif
+END(trampoline_header)
+
+#ifdef CONFIG_X86_64
+       .balign PAGE_SIZE
+GLOBAL(trampoline_pgd)         .space  PAGE_SIZE
+#endif
index 8a57c5a05fbca7a484d02d42b1740804cdd78f6a..46108f05e04e07c355942893b36045fccc40a066 100644 (file)
@@ -132,7 +132,7 @@ ENTRY(wakeup_start)
        ljmpl   $__KERNEL_CS, $pa_startup_32
        /* -> jmp *%eax in trampoline_32.S */
 #else
-       jmp     trampoline_data
+       jmp     trampoline_start
 #endif
 
 bogus_real_magic: