aboutsummaryrefslogtreecommitdiff
path: root/arch/ppc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc/kernel')
-rw-r--r--arch/ppc/kernel/Makefile3
-rw-r--r--arch/ppc/kernel/cpu_setup_6xx.S3
-rw-r--r--arch/ppc/kernel/cpu_setup_power4.S3
-rw-r--r--arch/ppc/kernel/dma-mapping.c2
-rw-r--r--arch/ppc/kernel/entry.S2
-rw-r--r--arch/ppc/kernel/fpu.S2
-rw-r--r--arch/ppc/kernel/head.S30
-rw-r--r--arch/ppc/kernel/head_44x.S2
-rw-r--r--arch/ppc/kernel/head_4xx.S2
-rw-r--r--arch/ppc/kernel/head_8xx.S2
-rw-r--r--arch/ppc/kernel/head_fsl_booke.S2
-rw-r--r--arch/ppc/kernel/idle.c6
-rw-r--r--arch/ppc/kernel/idle_6xx.S2
-rw-r--r--arch/ppc/kernel/idle_power4.S2
-rw-r--r--arch/ppc/kernel/misc.S2
-rw-r--r--arch/ppc/kernel/smp.c44
-rw-r--r--arch/ppc/kernel/swsusp.S2
-rw-r--r--arch/ppc/kernel/traps.c24
18 files changed, 88 insertions, 47 deletions
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index b1457a8a9c0..1fb92f16acd 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -15,8 +15,9 @@ extra-y += vmlinux.lds
obj-y := entry.o traps.o irq.o idle.o time.o misc.o \
process.o signal.o ptrace.o align.o \
semaphore.o syscalls.o setup.o \
- cputable.o ppc_htab.o perfmon.o
+ cputable.o ppc_htab.o
obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o
+obj-$(CONFIG_E500) += perfmon.o
obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
obj-$(CONFIG_POWER4) += cpu_setup_power4.o
obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o
diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S
index bd037caa405..ba396438ede 100644
--- a/arch/ppc/kernel/cpu_setup_6xx.S
+++ b/arch/ppc/kernel/cpu_setup_6xx.S
@@ -12,10 +12,9 @@
#include <linux/config.h>
#include <asm/processor.h>
#include <asm/page.h>
-#include <asm/ppc_asm.h>
#include <asm/cputable.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/cache.h>
_GLOBAL(__setup_cpu_601)
diff --git a/arch/ppc/kernel/cpu_setup_power4.S b/arch/ppc/kernel/cpu_setup_power4.S
index f2ea1a990f1..7e4fbb65372 100644
--- a/arch/ppc/kernel/cpu_setup_power4.S
+++ b/arch/ppc/kernel/cpu_setup_power4.S
@@ -14,8 +14,7 @@
#include <asm/page.h>
#include <asm/ppc_asm.h>
#include <asm/cputable.h>
-#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/cache.h>
_GLOBAL(__970_cpu_preinit)
diff --git a/arch/ppc/kernel/dma-mapping.c b/arch/ppc/kernel/dma-mapping.c
index e0c631cf96b..b566d982806 100644
--- a/arch/ppc/kernel/dma-mapping.c
+++ b/arch/ppc/kernel/dma-mapping.c
@@ -393,7 +393,7 @@ EXPORT_SYMBOL(__dma_sync);
* __dma_sync_page() implementation for systems using highmem.
* In this case, each page of a buffer must be kmapped/kunmapped
* in order to have a virtual address for __dma_sync(). This must
- * not sleep so kmap_atmomic()/kunmap_atomic() are used.
+ * not sleep so kmap_atomic()/kunmap_atomic() are used.
*
* Note: yes, it is possible and correct to have a buffer extend
* beyond the first page.
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index cb83045e2ed..03d4886869f 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -29,7 +29,7 @@
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include <asm/unistd.h>
#undef SHOW_SYSCALLS
diff --git a/arch/ppc/kernel/fpu.S b/arch/ppc/kernel/fpu.S
index 6189b26f640..665d7d34304 100644
--- a/arch/ppc/kernel/fpu.S
+++ b/arch/ppc/kernel/fpu.S
@@ -18,7 +18,7 @@
#include <asm/cache.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
/*
* This task wants to use the FPU now.
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index a931d773715..1960fb8c259 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -31,7 +31,7 @@
#include <asm/cache.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#ifdef CONFIG_APUS
#include <asm/amigappc.h>
@@ -1023,23 +1023,21 @@ __secondary_start_gemini:
andc r4,r4,r3
mtspr SPRN_HID0,r4
sync
- bl gemini_prom_init
b __secondary_start
#endif /* CONFIG_GEMINI */
- .globl __secondary_start_psurge
-__secondary_start_psurge:
- li r24,1 /* cpu # */
- b __secondary_start_psurge99
- .globl __secondary_start_psurge2
-__secondary_start_psurge2:
- li r24,2 /* cpu # */
- b __secondary_start_psurge99
- .globl __secondary_start_psurge3
-__secondary_start_psurge3:
- li r24,3 /* cpu # */
- b __secondary_start_psurge99
-__secondary_start_psurge99:
- /* we come in here with IR=0 and DR=1, and DBAT 0
+
+ .globl __secondary_start_pmac_0
+__secondary_start_pmac_0:
+ /* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */
+ li r24,0
+ b 1f
+ li r24,1
+ b 1f
+ li r24,2
+ b 1f
+ li r24,3
+1:
+ /* on powersurge, we come in here with IR=0 and DR=1, and DBAT 0
set to map the 0xf0000000 - 0xffffffff region */
mfmsr r0
rlwinm r0,r0,0,28,26 /* clear DR (0x10) */
diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S
index 9e68e32edb6..599245b0407 100644
--- a/arch/ppc/kernel/head_44x.S
+++ b/arch/ppc/kernel/head_44x.S
@@ -40,7 +40,7 @@
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include "head_booke.h"
diff --git a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S
index ca9518b96c6..8562b807b37 100644
--- a/arch/ppc/kernel/head_4xx.S
+++ b/arch/ppc/kernel/head_4xx.S
@@ -40,7 +40,7 @@
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
/* As with the other PowerPC ports, it is expected that when code
* execution begins here, the following registers contain valid, yet
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index eb18cadb375..cb1a3a54a02 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -30,7 +30,7 @@
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
/* Macro to make the code more readable. */
#ifdef CONFIG_8xx_CPU6
diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S
index 4028f4c7d97..8e52e840831 100644
--- a/arch/ppc/kernel/head_fsl_booke.S
+++ b/arch/ppc/kernel/head_fsl_booke.S
@@ -41,7 +41,7 @@
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#include "head_booke.h"
/* As with the other PowerPC ports, it is expected that when code
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
index 53547b6de45..fba29c876b6 100644
--- a/arch/ppc/kernel/idle.c
+++ b/arch/ppc/kernel/idle.c
@@ -22,6 +22,7 @@
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/sysctl.h>
+#include <linux/cpu.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
@@ -35,6 +36,7 @@
void default_idle(void)
{
void (*powersave)(void);
+ int cpu = smp_processor_id();
powersave = ppc_md.power_save;
@@ -44,7 +46,7 @@ void default_idle(void)
#ifdef CONFIG_SMP
else {
set_thread_flag(TIF_POLLING_NRFLAG);
- while (!need_resched())
+ while (!need_resched() && !cpu_is_offline(cpu))
barrier();
clear_thread_flag(TIF_POLLING_NRFLAG);
}
@@ -52,6 +54,8 @@ void default_idle(void)
}
if (need_resched())
schedule();
+ if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
+ cpu_die();
}
/*
diff --git a/arch/ppc/kernel/idle_6xx.S b/arch/ppc/kernel/idle_6xx.S
index 25d009c75f7..1a2194cf682 100644
--- a/arch/ppc/kernel/idle_6xx.S
+++ b/arch/ppc/kernel/idle_6xx.S
@@ -20,7 +20,7 @@
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#undef DEBUG
diff --git a/arch/ppc/kernel/idle_power4.S b/arch/ppc/kernel/idle_power4.S
index 73a58ff0390..cc0d535365c 100644
--- a/arch/ppc/kernel/idle_power4.S
+++ b/arch/ppc/kernel/idle_power4.S
@@ -20,7 +20,7 @@
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
#undef DEBUG
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index ce71b4a0158..90d917d2e85 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -23,7 +23,7 @@
#include <asm/mmu.h>
#include <asm/ppc_asm.h>
#include <asm/thread_info.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
.text
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index e70b587b9e5..726fe7ce174 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -45,6 +45,7 @@ cpumask_t cpu_online_map;
cpumask_t cpu_possible_map;
int smp_hw_index[NR_CPUS];
struct thread_info *secondary_ti;
+static struct task_struct *idle_tasks[NR_CPUS];
EXPORT_SYMBOL(cpu_online_map);
EXPORT_SYMBOL(cpu_possible_map);
@@ -286,7 +287,8 @@ static void __devinit smp_store_cpu_info(int id)
void __init smp_prepare_cpus(unsigned int max_cpus)
{
- int num_cpus, i;
+ int num_cpus, i, cpu;
+ struct task_struct *p;
/* Fixup boot cpu */
smp_store_cpu_info(smp_processor_id());
@@ -308,6 +310,17 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
if (smp_ops->space_timers)
smp_ops->space_timers(num_cpus);
+
+ for_each_cpu(cpu) {
+ if (cpu == smp_processor_id())
+ continue;
+ /* create a process for the processor */
+ p = fork_idle(cpu);
+ if (IS_ERR(p))
+ panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
+ p->thread_info->cpu = cpu;
+ idle_tasks[cpu] = p;
+ }
}
void __devinit smp_prepare_boot_cpu(void)
@@ -334,12 +347,17 @@ int __devinit start_secondary(void *unused)
set_dec(tb_ticks_per_jiffy);
cpu_callin_map[cpu] = 1;
- printk("CPU %i done callin...\n", cpu);
+ printk("CPU %d done callin...\n", cpu);
smp_ops->setup_cpu(cpu);
- printk("CPU %i done setup...\n", cpu);
- local_irq_enable();
+ printk("CPU %d done setup...\n", cpu);
smp_ops->take_timebase();
- printk("CPU %i done timebase take...\n", cpu);
+ printk("CPU %d done timebase take...\n", cpu);
+
+ spin_lock(&call_lock);
+ cpu_set(cpu, cpu_online_map);
+ spin_unlock(&call_lock);
+
+ local_irq_enable();
cpu_idle();
return 0;
@@ -347,17 +365,11 @@ int __devinit start_secondary(void *unused)
int __cpu_up(unsigned int cpu)
{
- struct task_struct *p;
char buf[32];
int c;
- /* create a process for the processor */
- /* only regs.msr is actually used, and 0 is OK for it */
- p = fork_idle(cpu);
- if (IS_ERR(p))
- panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
- secondary_ti = p->thread_info;
- p->thread_info->cpu = cpu;
+ secondary_ti = idle_tasks[cpu]->thread_info;
+ mb();
/*
* There was a cache flush loop here to flush the cache
@@ -389,7 +401,11 @@ int __cpu_up(unsigned int cpu)
printk("Processor %d found.\n", cpu);
smp_ops->give_timebase();
- cpu_set(cpu, cpu_online_map);
+
+ /* Wait until cpu puts itself in the online map */
+ while (!cpu_online(cpu))
+ cpu_relax();
+
return 0;
}
diff --git a/arch/ppc/kernel/swsusp.S b/arch/ppc/kernel/swsusp.S
index 55148bb88d3..69773cc1a85 100644
--- a/arch/ppc/kernel/swsusp.S
+++ b/arch/ppc/kernel/swsusp.S
@@ -5,7 +5,7 @@
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
/*
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index d87423d1003..961ede87be7 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -118,6 +118,28 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
info.si_code = code;
info.si_addr = (void __user *) addr;
force_sig_info(signr, &info, current);
+
+ /*
+ * Init gets no signals that it doesn't have a handler for.
+ * That's all very well, but if it has caused a synchronous
+ * exception and we ignore the resulting signal, it will just
+ * generate the same exception over and over again and we get
+ * nowhere. Better to kill it and let the kernel panic.
+ */
+ if (current->pid == 1) {
+ __sighandler_t handler;
+
+ spin_lock_irq(&current->sighand->siglock);
+ handler = current->sighand->action[signr-1].sa.sa_handler;
+ spin_unlock_irq(&current->sighand->siglock);
+ if (handler == SIG_DFL) {
+ /* init has generated a synchronous exception
+ and it doesn't have a handler for the signal */
+ printk(KERN_CRIT "init has generated signal %d "
+ "but has no handler for it\n", signr);
+ do_exit(signr);
+ }
+ }
}
/*
@@ -849,10 +871,12 @@ void AltivecAssistException(struct pt_regs *regs)
}
#endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_E500
void PerformanceMonitorException(struct pt_regs *regs)
{
perf_irq(regs);
}
+#endif
#ifdef CONFIG_FSL_BOOKE
void CacheLockingException(struct pt_regs *regs, unsigned long address,