Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 196667
b: refs/heads/master
c: 1fc711f
h: refs/heads/master
i:
  196665: dea2e8c
  196663: ff3b9f1
v: v3
  • Loading branch information
Michael Neuling authored and Benjamin Herrenschmidt committed May 21, 2010
1 parent 8bcb3b9 commit de1d9ef
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 18 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: d504bed676caad29a3dba3d3727298c560628f5c
refs/heads/master: 1fc711f7ffb01089efc58042cfdbac8573d1b59a
4 changes: 4 additions & 0 deletions trunk/arch/powerpc/include/asm/kexec.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
#define KEXEC_ARCH KEXEC_ARCH_PPC
#endif

#define KEXEC_STATE_NONE 0
#define KEXEC_STATE_IRQS_OFF 1
#define KEXEC_STATE_REAL_MODE 2

#ifndef __ASSEMBLY__
#include <linux/cpumask.h>
#include <asm/reg.h>
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/powerpc/include/asm/paca.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ struct paca_struct {
s16 hw_cpu_id; /* Physical processor number */
u8 cpu_start; /* At startup, processor spins until */
/* this becomes non-zero. */
u8 kexec_state; /* set when kexec down has irqs off */
#ifdef CONFIG_PPC_STD_MMU_64
struct slb_shadow *slb_shadow_ptr;

Expand Down
1 change: 1 addition & 0 deletions trunk/arch/powerpc/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ int main(void)
#endif /* CONFIG_PPC_STD_MMU_64 */
DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp));
DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state));
DEFINE(PACA_STARTPURR, offsetof(struct paca_struct, startpurr));
DEFINE(PACA_STARTSPURR, offsetof(struct paca_struct, startspurr));
DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time));
Expand Down
48 changes: 34 additions & 14 deletions trunk/arch/powerpc/kernel/machine_kexec_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,33 +155,38 @@ void kexec_copy_flush(struct kimage *image)

#ifdef CONFIG_SMP

/* FIXME: we should schedule this function to be called on all cpus based
* on calling the interrupts, but we would like to call it off irq level
* so that the interrupt controller is clean.
*/
static int kexec_all_irq_disabled = 0;

static void kexec_smp_down(void *arg)
{
local_irq_disable();
mb(); /* make sure our irqs are disabled before we say they are */
get_paca()->kexec_state = KEXEC_STATE_IRQS_OFF;
while(kexec_all_irq_disabled == 0)
cpu_relax();
mb(); /* make sure all irqs are disabled before this */
/*
* Now every CPU has IRQs off, we can clear out any pending
* IPIs and be sure that no more will come in after this.
*/
if (ppc_md.kexec_cpu_down)
ppc_md.kexec_cpu_down(0, 1);

local_irq_disable();
kexec_smp_wait();
/* NOTREACHED */
}

static void kexec_prepare_cpus(void)
static void kexec_prepare_cpus_wait(int wait_state)
{
int my_cpu, i, notified=-1;

smp_call_function(kexec_smp_down, NULL, /* wait */0);
my_cpu = get_cpu();

/* check the others cpus are now down (via paca hw cpu id == -1) */
/* Make sure each CPU has atleast made it to the state we need */
for (i=0; i < NR_CPUS; i++) {
if (i == my_cpu)
continue;

while (paca[i].hw_cpu_id != -1) {
while (paca[i].kexec_state < wait_state) {
barrier();
if (!cpu_possible(i)) {
printk("kexec: cpu %d hw_cpu_id %d is not"
Expand All @@ -201,20 +206,35 @@ static void kexec_prepare_cpus(void)
}
if (i != notified) {
printk( "kexec: waiting for cpu %d (physical"
" %d) to go down\n",
i, paca[i].hw_cpu_id);
" %d) to enter %i state\n",
i, paca[i].hw_cpu_id, wait_state);
notified = i;
}
}
}
mb();
}

static void kexec_prepare_cpus(void)
{

smp_call_function(kexec_smp_down, NULL, /* wait */0);
local_irq_disable();
mb(); /* make sure IRQs are disabled before we say they are */
get_paca()->kexec_state = KEXEC_STATE_IRQS_OFF;

kexec_prepare_cpus_wait(KEXEC_STATE_IRQS_OFF);
/* we are sure every CPU has IRQs off at this point */
kexec_all_irq_disabled = 1;

/* after we tell the others to go down */
if (ppc_md.kexec_cpu_down)
ppc_md.kexec_cpu_down(0, 0);

put_cpu();
/* Before removing MMU mapings make sure all CPUs have entered real mode */
kexec_prepare_cpus_wait(KEXEC_STATE_REAL_MODE);

local_irq_disable();
put_cpu();
}

#else /* ! SMP */
Expand Down
8 changes: 5 additions & 3 deletions trunk/arch/powerpc/kernel/misc_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <asm/asm-offsets.h>
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/kexec.h>

.text

Expand Down Expand Up @@ -471,6 +472,10 @@ _GLOBAL(kexec_wait)
1: mflr r5
addi r5,r5,kexec_flag-1b

li r4,KEXEC_STATE_REAL_MODE
stb r4,PACAKEXECSTATE(r13)
SYNC

99: HMT_LOW
#ifdef CONFIG_KEXEC /* use no memory without kexec */
lwz r4,0(r5)
Expand All @@ -494,14 +499,11 @@ kexec_flag:
* note: this is a terminal routine, it does not save lr
*
* get phys id from paca
* set paca id to -1 to say we got here
* switch to real mode
* join other cpus in kexec_wait(phys_id)
*/
_GLOBAL(kexec_smp_wait)
lhz r3,PACAHWCPUID(r13)
li r4,-1
sth r4,PACAHWCPUID(r13) /* let others know we left */
bl real_mode
b .kexec_wait

Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/powerpc/kernel/paca.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <asm/pgtable.h>
#include <asm/iseries/lpar_map.h>
#include <asm/iseries/hv_types.h>
#include <asm/kexec.h>

/* This symbol is provided by the linker - let it fill in the paca
* field correctly */
Expand Down Expand Up @@ -97,6 +98,7 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu)
new_paca->kernelbase = (unsigned long) _stext;
new_paca->kernel_msr = MSR_KERNEL;
new_paca->hw_cpu_id = 0xffff;
new_paca->kexec_state = KEXEC_STATE_NONE;
new_paca->__current = &init_task;
#ifdef CONFIG_PPC_STD_MMU_64
new_paca->slb_shadow_ptr = &slb_shadow[cpu];
Expand Down

0 comments on commit de1d9ef

Please sign in to comment.