Merge branch 'x86-trampoline-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
Linus Torvalds [Wed, 30 May 2012 03:14:53 +0000 (20:14 -0700)]
Pull x86 trampoline rework from H. Peter Anvin:
 "This code reworks all the "trampoline"/"realmode" code (various bits
  that need to live in the first megabyte of memory, most but not all of
  which runs in real mode at some point) in the kernel into a single
  object.  The main reason for doing this is that it eliminates the last
  place in the kernel where we needed pages to be mapped RWX.  This code
  separates all that code into proper R/RW/RX pages."

Fix up conflicts in arch/x86/kernel/Makefile (mca removed next to reboot
code), and arch/x86/kernel/reboot.c (reboot code moved around in one
branch, modified in this one), and arch/x86/tools/relocs.c (mostly same
code came in earlier due to working around the ld bugs just before the
3.4 release).

Also remove stale x86-relocs entry from scripts/.gitignore as per Peter
Anvin.

* commit '61f5446169046c217a5479517edac3a890c3bee7': (36 commits)
  x86, realmode: Move end signature into header.S
  x86, relocs: When printing an error, say relative or absolute
  x86, relocs: More relocations which may end up as absolute
  x86, relocs: Workaround for binutils 2.22.52.0.1 section bug
  xen-acpi-processor: Add missing #include <xen/xen.h>
  acpi, bgrd: Add missing <linux/io.h> to drivers/acpi/bgrt.c
  x86, realmode: Change EFER to a single u64 field
  x86, realmode: Move kernel/realmode.c to realmode/init.c
  x86, realmode: Move not-common bits out of trampoline_common.S
  x86, realmode: Mask out EFER.LMA when saving trampoline EFER
  x86, realmode: Fix no cache bits test in reboot_32.S
  x86, realmode: Make sure all generated files are listed in targets
  x86, realmode: build fix: remove duplicate build
  x86, realmode: read cr4 and EFER from kernel for 64-bit trampoline
  x86, realmode: fixes compilation issue in tboot.c
  x86, realmode: move relocs from scripts/ to arch/x86/tools
  x86, realmode: header for trampoline code
  x86, realmode: flattened rm hierachy
  x86, realmode: don't copy real_mode_header
  x86, realmode: fix 64-bit wakeup sequence
  ...

1  2 
arch/x86/include/asm/processor.h
arch/x86/kernel/Makefile
arch/x86/kernel/head_32.S
arch/x86/kernel/head_64.S
arch/x86/kernel/mpparse.c
arch/x86/kernel/reboot.c
arch/x86/kernel/setup.c
arch/x86/kernel/smpboot.c
arch/x86/tools/relocs.c
drivers/acpi/sleep.c

Simple merge
@@@ -48,7 -47,7 +47,6 @@@ obj-$(CONFIG_STACKTRACE)      += stacktrace.
  obj-y                         += cpu/
  obj-y                         += acpi/
  obj-y                         += reboot.o
- obj-$(CONFIG_X86_32)          += reboot_32.o
 -obj-$(CONFIG_MCA)             += mca_32.o
  obj-$(CONFIG_X86_MSR)         += msr.o
  obj-$(CONFIG_X86_CPUID)               += cpuid.o
  obj-$(CONFIG_PCI)             += early-quirks.o
Simple merge
Simple merge
Simple merge
@@@ -156,82 -151,6 +157,62 @@@ static int __init set_bios_reboot(cons
        return 0;
  }
  
- extern const unsigned char machine_real_restart_asm[];
- extern const u64 machine_real_restart_gdt[3];
 +void machine_real_restart(unsigned int type)
 +{
-       void *restart_va;
-       unsigned long restart_pa;
-       void (*restart_lowmem)(unsigned int);
-       u64 *lowmem_gdt;
++      void (*restart_lowmem)(unsigned int) = (void (*)(unsigned int))
++              real_mode_header->machine_real_restart_asm;
 +
 +      local_irq_disable();
 +
 +      /*
 +       * Write zero to CMOS register number 0x0f, which the BIOS POST
 +       * routine will recognize as telling it to do a proper reboot.  (Well
 +       * that's what this book in front of me says -- it may only apply to
 +       * the Phoenix BIOS though, it's not clear).  At the same time,
 +       * disable NMIs by setting the top bit in the CMOS address register,
 +       * as we're about to do peculiar things to the CPU.  I'm not sure if
 +       * `outb_p' is needed instead of just `outb'.  Use it to be on the
 +       * safe side.  (Yes, CMOS_WRITE does outb_p's. -  Paul G.)
 +       */
 +      spin_lock(&rtc_lock);
 +      CMOS_WRITE(0x00, 0x8f);
 +      spin_unlock(&rtc_lock);
 +
 +      /*
 +       * Switch back to the initial page table.
 +       */
 +      load_cr3(initial_page_table);
 +
 +      /*
 +       * Write 0x1234 to absolute memory location 0x472.  The BIOS reads
 +       * this on booting to tell it to "Bypass memory test (also warm
 +       * boot)".  This seems like a fairly standard thing that gets set by
 +       * REBOOT.COM programs, and the previous reset routine did this
 +       * too. */
 +      *((unsigned short *)0x472) = reboot_mode;
 +
-       /* Patch the GDT in the low memory trampoline */
-       lowmem_gdt = TRAMPOLINE_SYM(machine_real_restart_gdt);
-       restart_va = TRAMPOLINE_SYM(machine_real_restart_asm);
-       restart_pa = virt_to_phys(restart_va);
-       restart_lowmem = (void (*)(unsigned int))restart_pa;
-       /* GDT[0]: GDT self-pointer */
-       lowmem_gdt[0] =
-               (u64)(sizeof(machine_real_restart_gdt) - 1) +
-               ((u64)virt_to_phys(lowmem_gdt) << 16);
-       /* GDT[1]: 64K real mode code segment */
-       lowmem_gdt[1] =
-               GDT_ENTRY(0x009b, restart_pa, 0xffff);
 +      /* Jump to the identity-mapped low memory code */
 +      restart_lowmem(type);
 +}
 +#ifdef CONFIG_APM_MODULE
 +EXPORT_SYMBOL(machine_real_restart);
 +#endif
 +
 +#endif /* CONFIG_X86_32 */
 +
 +/*
 + * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot
 + */
 +static int __init set_pci_reboot(const struct dmi_system_id *d)
 +{
 +      if (reboot_type != BOOT_CF9) {
 +              reboot_type = BOOT_CF9;
 +              printk(KERN_INFO "%s series board detected. "
 +                     "Selecting PCI-method for reboots.\n", d->ident);
 +      }
 +      return 0;
 +}
 +
  static int __init set_kbd_reboot(const struct dmi_system_id *d)
  {
        if (reboot_type != BOOT_KBD) {
@@@ -906,10 -914,10 +906,10 @@@ void __init setup_arch(char **cmdline_p
        setup_bios_corruption_check();
  #endif
  
 -      printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n",
 -                      max_pfn_mapped<<PAGE_SHIFT);
 +      printk(KERN_DEBUG "initial memory mapped: [mem 0x00000000-%#010lx]\n",
 +                      (max_pfn_mapped<<PAGE_SHIFT) - 1);
  
-       setup_trampolines();
+       setup_real_mode();
  
        init_gbpages();
  
@@@ -658,11 -662,21 +660,15 @@@ static void __cpuinit announce_cpu(int 
   * Returns zero if CPU booted OK, else error code from
   * ->wakeup_secondary_cpu.
   */
 -static int __cpuinit do_boot_cpu(int apicid, int cpu)
 +static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
  {
+       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_start;
        unsigned long boot_error = 0;
-       unsigned long start_ip;
        int timeout;
 -      struct create_idle c_idle = {
 -              .cpu    = cpu,
 -              .done   = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
 -      };
 -
 -      INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle);
  
        alternatives_smp_switch(1);
  
  #endif
        early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
        initial_code = (unsigned long)start_secondary;
 -      stack_start  = c_idle.idle->thread.sp;
 +      stack_start  = idle->thread.sp;
  
-       /* start_ip had better be page-aligned! */
-       start_ip = trampoline_address();
        /* So we see what's up */
        announce_cpu(cpu, apicid);
  
Simple merge
Simple merge