Merge tag ‘efi-urgent’ into x86/urgent [Linux 3.15]

This Linux kernel change "Merge tag ‘efi-urgent’ into x86/urgent" is included in the Linux 3.15 release. This change is authored by H. Peter Anvin <hpa [at] linux.intel.com> on Thu Jun 5 13:09:44 2014 -0700. The commit for this change in Linux stable tree is 1778754 (patch). Other info about this change: Merge: 3e1a878 a3530e8

Merge tag 'efi-urgent' into x86/urgent

 * Fix earlyprintk=efi,keep support by switching to an ioremap() mapping
   of the framebuffer when early_ioremap() is no longer available and
   dropping __init from functions that may be invoked after
   free_initmem() - Dave Young

 * We shouldn't be exporting the EFI runtime map in sysfs if not using
   the new 1:1 EFI mapping code since in that case the mappings are not
   static across a kexec reboot - Dave Young

Signed-off-by: H. Peter Anvin <[email protected]>

There is no are 0 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 arch/x86/kernel/cpu/common.c | 27 +++++++-----
 arch/x86/kernel/smpboot.c    | 99 ++++++++++++++------------------------------
 2 files changed, 47 insertions(+), 79 deletions(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index a135239..a4bcbac 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1221,6 +1221,17 @@ static void dbg_restore_debug_regs(void)
 #define dbg_restore_debug_regs()
 #endif /* ! CONFIG_KGDB */

+static void wait_for_master_cpu(int cpu)
+{
+   /*
+    * wait for ACK from master CPU before continuing
+    * with AP initialization
+    */
+   WARN_ON(cpumask_test_and_set_cpu(cpu, cpu_initialized_mask));
+   while (!cpumask_test_cpu(cpu, cpu_callout_mask))
+       cpu_relax();
+}
+
 /*
  * cpu_init() initializes state that is per-CPU. Some data is already
  * initialized (naturally) in the bootstrap process, such as the GDT
@@ -1236,16 +1247,17 @@ void cpu_init(void)
    struct task_struct *me;
    struct tss_struct *t;
    unsigned long v;
-   int cpu;
+   int cpu = stack_smp_processor_id();
    int i;

+   wait_for_master_cpu(cpu);
+
    /*
     * Load microcode on this cpu if a valid microcode is available.
     * This is early microcode loading procedure.
     */
    load_ucode_ap();

-   cpu = stack_smp_processor_id();
    t = &per_cpu(init_tss, cpu);
    oist = &per_cpu(orig_ist, cpu);

@@ -1257,9 +1269,6 @@ void cpu_init(void)

    me = current;

-   if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask))
-       panic("CPU#%d already initialized!n", cpu);
-
    pr_debug("Initializing CPU#%dn", cpu);

    clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
@@ -1336,13 +1345,9 @@ void cpu_init(void)
    struct tss_struct *t = &per_cpu(init_tss, cpu);
    struct thread_struct *thread = &curr->thread;

-   show_ucode_info_early();
+   wait_for_master_cpu(cpu);

-   if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)) {
-       printk(KERN_WARNING "CPU#%d already initialized!n", cpu);
-       for (;;)
-           local_irq_enable();
-   }
+   show_ucode_info_early();

    printk(KERN_INFO "Initializing CPU#%dn", cpu);

diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index ae2fd975..bc52fac 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -111,7 +111,6 @@
 static void smp_callin(void)
 {
    int cpuid, phys_id;
-   unsigned long timeout;

    /*
     * If waken up by an INIT in an 82489DX configuration
@@ -130,37 +129,6 @@ static void smp_callin(void)
     * (This works even if the APIC is not enabled.)
     */
    phys_id = read_apic_id();
-   if (cpumask_test_cpu(cpuid, cpu_callin_mask)) {
-       panic("%s: phys CPU#%d, CPU#%d already present??n", __func__,
-                   phys_id, cpuid);
-   }
-   pr_debug("CPU#%d (phys ID: %d) waiting for CALLOUTn", cpuid, phys_id);
-
-   /*
-    * STARTUP IPIs are fragile beasts as they might sometimes
-    * trigger some glue motherboard logic. Complete APIC bus
-    * silence for 1 second, this overestimates the time the
-    * boot CPU is spending to send the up to 2 STARTUP IPIs
-    * by a factor of two. This should be enough.
-    */
-
-   /*
-    * Waiting 2s total for startup (udelay is not yet working)
-    */
-   timeout = jiffies + 2*HZ;
-   while (time_before(jiffies, timeout)) {
-       /*
-        * Has the boot CPU finished it's STARTUP sequence?
-        */
-       if (cpumask_test_cpu(cpuid, cpu_callout_mask))
-           break;
-       cpu_relax();
-   }
-
-   if (!time_before(jiffies, timeout)) {
-       panic("%s: CPU%d started up but did not get a callout!n",
-             __func__, cpuid);
-   }

    /*
     * the boot CPU has finished the init stage and is spinning
@@ -750,8 +718,8 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
    unsigned long start_ip = real_mode_header->trampoline_start;

    unsigned long boot_error = 0;
-   int timeout;
    int cpu0_nmi_registered = 0;
+   unsigned long timeout;

    /* Just in case we booted with a single CPU. */
    alternatives_enable_smp();
@@ -799,6 +767,15 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
    }

    /*
+    * AP might wait on cpu_callout_mask in cpu_init() with
+    * cpu_initialized_mask set if previous attempt to online
+    * it timed-out. Clear cpu_initialized_mask so that after
+    * INIT/SIPI it could start with a clean state.
+    */
+   cpumask_clear_cpu(cpu, cpu_initialized_mask);
+   smp_mb();
+
+   /*
     * Wake up a CPU in difference cases:
     * - Use the method in the APIC driver if it's defined
     * Otherwise,
@@ -810,55 +787,41 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
        boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid,
                             &cpu0_nmi_registered);

+
    if (!boot_error) {
        /*
-        * allow APs to start initializing.
+        * Wait 10s total for a response from AP
         */
-       pr_debug("Before Callout %dn", cpu);
-       cpumask_set_cpu(cpu, cpu_callout_mask);
-       pr_debug("After Callout %dn", cpu);
+       boot_error = -1;
+       timeout = jiffies + 10*HZ;
+       while (time_before(jiffies, timeout)) {
+           if (cpumask_test_cpu(cpu, cpu_initialized_mask)) {
+               /*
+                * Tell AP to proceed with initialization
+                */
+               cpumask_set_cpu(cpu, cpu_callout_mask);
+               boot_error = 0;
+               break;
+           }
+           udelay(100);
+           schedule();
+       }
+   }

+   if (!boot_error) {
        /*
-        * Wait 5s total for a response
+        * Wait till AP completes initial initialization
         */
-       for (timeout = 0; timeout < 50000; timeout++) {
-           if (cpumask_test_cpu(cpu, cpu_callin_mask))
-               break;  /* It has booted */
-           udelay(100);
+       while (!cpumask_test_cpu(cpu, cpu_callin_mask)) {
            /*
             * Allow other tasks to run while we wait for the
             * AP to come online. This also gives a chance
             * for the MTRR work(triggered by the AP coming online)
             * to be completed in the stop machine context.
             */
+           udelay(100);
            schedule();
        }
-
-       if (cpumask_test_cpu(cpu, cpu_callin_mask)) {
-           print_cpu_msr(&cpu_data(cpu));
-           pr_debug("CPU%d: has booted.n", cpu);
-       } else {
-           boot_error = 1;
-           if (*trampoline_status == 0xA5A5A5A5)
-               /* trampoline started but...? */
-               pr_err("CPU%d: Stuck ??n", cpu);
-           else
-               /* trampoline code not run */
-               pr_err("CPU%d: Not respondingn", cpu);
-           if (apic->inquire_remote_apic)
-               apic->inquire_remote_apic(apicid);
-       }
-   }
-
-   if (boot_error) {
-       /* Try to put things back the way they were before ... */
-       numa_remove_cpu(cpu); /* was set by numa_add_cpu */
-
-       /* was set by do_boot_cpu() */
-       cpumask_clear_cpu(cpu, cpu_callout_mask);
-
-       /* was set by cpu_init() */
-       cpumask_clear_cpu(cpu, cpu_initialized_mask);
    }

    /* mark "stuck" area as not stuck */

Leave a Reply

Your email address will not be published. Required fields are marked *