Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 283542
b: refs/heads/master
c: 3603a25
h: refs/heads/master
v: v3
  • Loading branch information
Don Zickus authored and Ingo Molnar committed Dec 5, 2011
1 parent 0281c82 commit dfe035e
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 467e6b7a7c0eb792ebaf322ddb7363742b4ead40
refs/heads/master: 3603a2512f9e69dc87914ba922eb4a0812b21cd6
59 changes: 57 additions & 2 deletions trunk/arch/x86/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <asm/mmu_context.h>
#include <asm/proto.h>
#include <asm/apic.h>
#include <asm/nmi.h>
/*
* Some notes on x86 processor bugs affecting SMP operation:
*
Expand Down Expand Up @@ -148,6 +149,60 @@ void native_send_call_func_ipi(const struct cpumask *mask)
free_cpumask_var(allbutself);
}

static atomic_t stopping_cpu = ATOMIC_INIT(-1);

static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs)
{
/* We are registered on stopping cpu too, avoid spurious NMI */
if (raw_smp_processor_id() == atomic_read(&stopping_cpu))
return NMI_HANDLED;

stop_this_cpu(NULL);

return NMI_HANDLED;
}

static void native_nmi_stop_other_cpus(int wait)
{
unsigned long flags;
unsigned long timeout;

if (reboot_force)
return;

/*
* Use an own vector here because smp_call_function
* does lots of things not suitable in a panic situation.
*/
if (num_online_cpus() > 1) {
/* did someone beat us here? */
if (atomic_cmpxchg(&stopping_cpu, -1, safe_smp_processor_id() != -1))
return;

if (register_nmi_handler(NMI_LOCAL, smp_stop_nmi_callback,
NMI_FLAG_FIRST, "smp_stop"))
/* Note: we ignore failures here */
return;

/* sync above data before sending NMI */
wmb();

apic->send_IPI_allbutself(NMI_VECTOR);

/*
* Don't wait longer than a second if the caller
* didn't ask us to wait.
*/
timeout = USEC_PER_SEC;
while (num_online_cpus() > 1 && (wait || timeout--))
udelay(1);
}

local_irq_save(flags);
disable_local_APIC();
local_irq_restore(flags);
}

/*
* this function calls the 'stop' function on all other CPUs in the system.
*/
Expand All @@ -160,7 +215,7 @@ asmlinkage void smp_reboot_interrupt(void)
irq_exit();
}

static void native_stop_other_cpus(int wait)
static void native_irq_stop_other_cpus(int wait)
{
unsigned long flags;
unsigned long timeout;
Expand Down Expand Up @@ -230,7 +285,7 @@ struct smp_ops smp_ops = {
.smp_prepare_cpus = native_smp_prepare_cpus,
.smp_cpus_done = native_smp_cpus_done,

.stop_other_cpus = native_stop_other_cpus,
.stop_other_cpus = native_nmi_stop_other_cpus,
.smp_send_reschedule = native_smp_send_reschedule,

.cpu_up = native_cpu_up,
Expand Down

0 comments on commit dfe035e

Please sign in to comment.