aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/Makefile4
-rw-r--r--arch/powerpc/kernel/cpu_setup_power4.S2
-rw-r--r--arch/powerpc/kernel/crash.c11
-rw-r--r--arch/powerpc/kernel/irq.c2
-rw-r--r--arch/powerpc/kernel/kprobes.c2
-rw-r--r--arch/powerpc/kernel/machine_kexec.c56
-rw-r--r--arch/powerpc/kernel/machine_kexec_64.c57
-rw-r--r--arch/powerpc/kernel/rtas.c21
-rw-r--r--arch/powerpc/kernel/traps.c16
9 files changed, 108 insertions, 63 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 814f242aeb8..956c2e5564b 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -67,9 +67,9 @@ pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \
pci_direct_iommu.o iomap.o
pci32-$(CONFIG_PPC32) := pci_32.o
obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y)
-kexec-$(CONFIG_PPC64) := machine_kexec_64.o crash.o
+kexec-$(CONFIG_PPC64) := machine_kexec_64.o
kexec-$(CONFIG_PPC32) := machine_kexec_32.o
-obj-$(CONFIG_KEXEC) += machine_kexec.o $(kexec-y)
+obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o $(kexec-y)
ifeq ($(CONFIG_PPC_ISERIES),y)
$(obj)/head_64.o: $(obj)/lparmap.s
diff --git a/arch/powerpc/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S
index f69af2c5d7b..76e97aa71c4 100644
--- a/arch/powerpc/kernel/cpu_setup_power4.S
+++ b/arch/powerpc/kernel/cpu_setup_power4.S
@@ -76,6 +76,8 @@ _GLOBAL(__setup_cpu_ppc970)
mfspr r0,SPRN_HID0
li r11,5 /* clear DOZE and SLEEP */
rldimi r0,r11,52,8 /* set NAP and DPM */
+ li r11,0
+ rldimi r0,r11,32,31 /* clear EN_ATTN */
mtspr SPRN_HID0,r0
mfspr r0,SPRN_HID0
mfspr r0,SPRN_HID0
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index 358cecdc6ae..f04c18e08b8 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -44,6 +44,7 @@
/* This keeps a track of which one is crashing cpu. */
int crashing_cpu = -1;
static cpumask_t cpus_in_crash = CPU_MASK_NONE;
+cpumask_t cpus_in_sr = CPU_MASK_NONE;
static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
size_t data_len)
@@ -139,7 +140,13 @@ void crash_ipi_callback(struct pt_regs *regs)
if (ppc_md.kexec_cpu_down)
ppc_md.kexec_cpu_down(1, 1);
+
+#ifdef CONFIG_PPC64
kexec_smp_wait();
+#else
+ for (;;); /* FIXME */
+#endif
+
/* NOTREACHED */
}
@@ -255,7 +262,11 @@ static void crash_kexec_prepare_cpus(int cpu)
*
* do this if kexec in setup.c ?
*/
+#ifdef CONFIG_PPC64
smp_release_cpus();
+#else
+ /* FIXME */
+#endif
}
void crash_kexec_secondary(struct pt_regs *regs)
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 01bdae35cb5..7ee68543331 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -693,7 +693,7 @@ unsigned int irq_radix_revmap(struct irq_host *host,
/* If not there, try to insert it */
virq = irq_find_mapping(host, hwirq);
if (virq != NO_IRQ)
- radix_tree_insert(tree, virq, &irq_map[virq]);
+ radix_tree_insert(tree, hwirq, &irq_map[virq]);
bail:
spin_unlock_irqrestore(&irq_big_lock, flags);
return virq;
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 9f0898c8975..cd65c367b8b 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -61,6 +61,8 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
if (!ret) {
memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
p->opcode = *p->addr;
+ flush_icache_range((unsigned long)p->ainsn.insn,
+ (unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
}
return ret;
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
index a81ca1b841e..e60a0c544d6 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -13,6 +13,7 @@
#include <linux/reboot.h>
#include <linux/threads.h>
#include <asm/machdep.h>
+#include <asm/lmb.h>
void machine_crash_shutdown(struct pt_regs *regs)
{
@@ -59,3 +60,58 @@ NORET_TYPE void machine_kexec(struct kimage *image)
}
for(;;);
}
+
+static int __init early_parse_crashk(char *p)
+{
+ unsigned long size;
+
+ if (!p)
+ return 1;
+
+ size = memparse(p, &p);
+
+ if (*p == '@')
+ crashk_res.start = memparse(p + 1, &p);
+ else
+ crashk_res.start = KDUMP_KERNELBASE;
+
+ crashk_res.end = crashk_res.start + size - 1;
+
+ return 0;
+}
+early_param("crashkernel", early_parse_crashk);
+
+void __init reserve_crashkernel(void)
+{
+ unsigned long size;
+
+ if (crashk_res.start == 0)
+ return;
+
+ /* We might have got these values via the command line or the
+ * device tree, either way sanitise them now. */
+
+ size = crashk_res.end - crashk_res.start + 1;
+
+ if (crashk_res.start != KDUMP_KERNELBASE)
+ printk("Crash kernel location must be 0x%x\n",
+ KDUMP_KERNELBASE);
+
+ crashk_res.start = KDUMP_KERNELBASE;
+ size = PAGE_ALIGN(size);
+ crashk_res.end = crashk_res.start + size - 1;
+
+ /* Crash kernel trumps memory limit */
+ if (memory_limit && memory_limit <= crashk_res.end) {
+ memory_limit = crashk_res.end + 1;
+ printk("Adjusted memory limit for crashkernel, now 0x%lx\n",
+ memory_limit);
+ }
+
+ lmb_reserve(crashk_res.start, size);
+}
+
+int overlaps_crashkernel(unsigned long start, unsigned long size)
+{
+ return (start + size) > crashk_res.start && start <= crashk_res.end;
+}
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c
index b438d45a068..be58985c768 100644
--- a/arch/powerpc/kernel/machine_kexec_64.c
+++ b/arch/powerpc/kernel/machine_kexec_64.c
@@ -10,7 +10,6 @@
*/
-#include <linux/cpumask.h>
#include <linux/kexec.h>
#include <linux/smp.h>
#include <linux/thread_info.h>
@@ -21,7 +20,6 @@
#include <asm/machdep.h>
#include <asm/cacheflush.h>
#include <asm/paca.h>
-#include <asm/lmb.h>
#include <asm/mmu.h>
#include <asm/sections.h> /* _end */
#include <asm/prom.h>
@@ -385,58 +383,3 @@ static int __init kexec_setup(void)
return 0;
}
__initcall(kexec_setup);
-
-static int __init early_parse_crashk(char *p)
-{
- unsigned long size;
-
- if (!p)
- return 1;
-
- size = memparse(p, &p);
-
- if (*p == '@')
- crashk_res.start = memparse(p + 1, &p);
- else
- crashk_res.start = KDUMP_KERNELBASE;
-
- crashk_res.end = crashk_res.start + size - 1;
-
- return 0;
-}
-early_param("crashkernel", early_parse_crashk);
-
-void __init reserve_crashkernel(void)
-{
- unsigned long size;
-
- if (crashk_res.start == 0)
- return;
-
- /* We might have got these values via the command line or the
- * device tree, either way sanitise them now. */
-
- size = crashk_res.end - crashk_res.start + 1;
-
- if (crashk_res.start != KDUMP_KERNELBASE)
- printk("Crash kernel location must be 0x%x\n",
- KDUMP_KERNELBASE);
-
- crashk_res.start = KDUMP_KERNELBASE;
- size = PAGE_ALIGN(size);
- crashk_res.end = crashk_res.start + size - 1;
-
- /* Crash kernel trumps memory limit */
- if (memory_limit && memory_limit <= crashk_res.end) {
- memory_limit = crashk_res.end + 1;
- printk("Adjusted memory limit for crashkernel, now 0x%lx\n",
- memory_limit);
- }
-
- lmb_reserve(crashk_res.start, size);
-}
-
-int overlaps_crashkernel(unsigned long start, unsigned long size)
-{
- return (start + size) > crashk_res.start && start <= crashk_res.end;
-}
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 4a4cb559840..77f1e06d208 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -569,6 +569,27 @@ int rtas_set_indicator(int indicator, int index, int new_value)
}
EXPORT_SYMBOL(rtas_set_indicator);
+/*
+ * Ignoring RTAS extended delay
+ */
+int rtas_set_indicator_fast(int indicator, int index, int new_value)
+{
+ int rc;
+ int token = rtas_token("set-indicator");
+
+ if (token == RTAS_UNKNOWN_SERVICE)
+ return -ENOENT;
+
+ rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value);
+
+ WARN_ON(rc == -2 || (rc >= 9900 && rc <= 9905));
+
+ if (rc < 0)
+ return rtas_error_rc(rc);
+
+ return rc;
+}
+
void rtas_restart(char *cmd)
{
if (rtas_flash_term_hook)
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 05682a24b21..e4d1713e8ae 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -55,9 +55,6 @@
#ifdef CONFIG_PPC64 /* XXX */
#define _IO_BASE pci_io_base
-#ifdef CONFIG_KEXEC
-cpumask_t cpus_in_sr = CPU_MASK_NONE;
-#endif
#endif
#ifdef CONFIG_DEBUGGER
@@ -211,6 +208,19 @@ void system_reset_exception(struct pt_regs *regs)
die("System Reset", regs, SIGABRT);
+ /*
+ * Some CPUs when released from the debugger will execute this path.
+ * These CPUs entered the debugger via a soft-reset. If the CPU was
+ * hung before entering the debugger it will return to the hung
+ * state when exiting this function. This causes a problem in
+ * kdump since the hung CPU(s) will not respond to the IPI sent
+ * from kdump. To prevent the problem we call crash_kexec_secondary()
+ * here. If a kdump had not been initiated or we exit the debugger
+ * with the "exit and recover" command (x) crash_kexec_secondary()
+ * will return after 5ms and the CPU returns to its previous state.
+ */
+ crash_kexec_secondary(regs);
+
/* Must die if the interrupt is not recoverable */
if (!(regs->msr & MSR_RI))
panic("Unrecoverable System Reset");