diff options
Diffstat (limited to 'arch/powerpc/kernel')
| -rw-r--r-- | arch/powerpc/kernel/Makefile | 4 | ||||
| -rw-r--r-- | arch/powerpc/kernel/cpu_setup_power4.S | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/crash.c | 11 | ||||
| -rw-r--r-- | arch/powerpc/kernel/irq.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/kprobes.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/machine_kexec.c | 56 | ||||
| -rw-r--r-- | arch/powerpc/kernel/machine_kexec_64.c | 57 | ||||
| -rw-r--r-- | arch/powerpc/kernel/rtas.c | 21 | ||||
| -rw-r--r-- | arch/powerpc/kernel/traps.c | 18 | 
9 files changed, 109 insertions, 64 deletions
| diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 814f242aeb8c..956c2e5564b7 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 \ | |||
| 67 | pci_direct_iommu.o iomap.o | 67 | pci_direct_iommu.o iomap.o | 
| 68 | pci32-$(CONFIG_PPC32) := pci_32.o | 68 | pci32-$(CONFIG_PPC32) := pci_32.o | 
| 69 | obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) | 69 | obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) | 
| 70 | kexec-$(CONFIG_PPC64) := machine_kexec_64.o crash.o | 70 | kexec-$(CONFIG_PPC64) := machine_kexec_64.o | 
| 71 | kexec-$(CONFIG_PPC32) := machine_kexec_32.o | 71 | kexec-$(CONFIG_PPC32) := machine_kexec_32.o | 
| 72 | obj-$(CONFIG_KEXEC) += machine_kexec.o $(kexec-y) | 72 | obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o $(kexec-y) | 
| 73 | 73 | ||
| 74 | ifeq ($(CONFIG_PPC_ISERIES),y) | 74 | ifeq ($(CONFIG_PPC_ISERIES),y) | 
| 75 | $(obj)/head_64.o: $(obj)/lparmap.s | 75 | $(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 f69af2c5d7b3..76e97aa71c45 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) | |||
| 76 | mfspr r0,SPRN_HID0 | 76 | mfspr r0,SPRN_HID0 | 
| 77 | li r11,5 /* clear DOZE and SLEEP */ | 77 | li r11,5 /* clear DOZE and SLEEP */ | 
| 78 | rldimi r0,r11,52,8 /* set NAP and DPM */ | 78 | rldimi r0,r11,52,8 /* set NAP and DPM */ | 
| 79 | li r11,0 | ||
| 80 | rldimi r0,r11,32,31 /* clear EN_ATTN */ | ||
| 79 | mtspr SPRN_HID0,r0 | 81 | mtspr SPRN_HID0,r0 | 
| 80 | mfspr r0,SPRN_HID0 | 82 | mfspr r0,SPRN_HID0 | 
| 81 | mfspr r0,SPRN_HID0 | 83 | mfspr r0,SPRN_HID0 | 
| diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 358cecdc6aef..f04c18e08b8b 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | /* This keeps a track of which one is crashing cpu. */ | 44 | /* This keeps a track of which one is crashing cpu. */ | 
| 45 | int crashing_cpu = -1; | 45 | int crashing_cpu = -1; | 
| 46 | static cpumask_t cpus_in_crash = CPU_MASK_NONE; | 46 | static cpumask_t cpus_in_crash = CPU_MASK_NONE; | 
| 47 | cpumask_t cpus_in_sr = CPU_MASK_NONE; | ||
| 47 | 48 | ||
| 48 | static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data, | 49 | static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data, | 
| 49 | size_t data_len) | 50 | size_t data_len) | 
| @@ -139,7 +140,13 @@ void crash_ipi_callback(struct pt_regs *regs) | |||
| 139 | 140 | ||
| 140 | if (ppc_md.kexec_cpu_down) | 141 | if (ppc_md.kexec_cpu_down) | 
| 141 | ppc_md.kexec_cpu_down(1, 1); | 142 | ppc_md.kexec_cpu_down(1, 1); | 
| 143 | |||
| 144 | #ifdef CONFIG_PPC64 | ||
| 142 | kexec_smp_wait(); | 145 | kexec_smp_wait(); | 
| 146 | #else | ||
| 147 | for (;;); /* FIXME */ | ||
| 148 | #endif | ||
| 149 | |||
| 143 | /* NOTREACHED */ | 150 | /* NOTREACHED */ | 
| 144 | } | 151 | } | 
| 145 | 152 | ||
| @@ -255,7 +262,11 @@ static void crash_kexec_prepare_cpus(int cpu) | |||
| 255 | * | 262 | * | 
| 256 | * do this if kexec in setup.c ? | 263 | * do this if kexec in setup.c ? | 
| 257 | */ | 264 | */ | 
| 265 | #ifdef CONFIG_PPC64 | ||
| 258 | smp_release_cpus(); | 266 | smp_release_cpus(); | 
| 267 | #else | ||
| 268 | /* FIXME */ | ||
| 269 | #endif | ||
| 259 | } | 270 | } | 
| 260 | 271 | ||
| 261 | void crash_kexec_secondary(struct pt_regs *regs) | 272 | void crash_kexec_secondary(struct pt_regs *regs) | 
| diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 01bdae35cb55..7ee685433319 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, | |||
| 693 | /* If not there, try to insert it */ | 693 | /* If not there, try to insert it */ | 
| 694 | virq = irq_find_mapping(host, hwirq); | 694 | virq = irq_find_mapping(host, hwirq); | 
| 695 | if (virq != NO_IRQ) | 695 | if (virq != NO_IRQ) | 
| 696 | radix_tree_insert(tree, virq, &irq_map[virq]); | 696 | radix_tree_insert(tree, hwirq, &irq_map[virq]); | 
| 697 | bail: | 697 | bail: | 
| 698 | spin_unlock_irqrestore(&irq_big_lock, flags); | 698 | spin_unlock_irqrestore(&irq_big_lock, flags); | 
| 699 | return virq; | 699 | return virq; | 
| diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 9f0898c89759..cd65c367b8b6 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) | |||
| 61 | if (!ret) { | 61 | if (!ret) { | 
| 62 | memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); | 62 | memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); | 
| 63 | p->opcode = *p->addr; | 63 | p->opcode = *p->addr; | 
| 64 | flush_icache_range((unsigned long)p->ainsn.insn, | ||
| 65 | (unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t)); | ||
| 64 | } | 66 | } | 
| 65 | 67 | ||
| 66 | return ret; | 68 | return ret; | 
| diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c index a81ca1b841ec..e60a0c544d63 100644 --- a/arch/powerpc/kernel/machine_kexec.c +++ b/arch/powerpc/kernel/machine_kexec.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/reboot.h> | 13 | #include <linux/reboot.h> | 
| 14 | #include <linux/threads.h> | 14 | #include <linux/threads.h> | 
| 15 | #include <asm/machdep.h> | 15 | #include <asm/machdep.h> | 
| 16 | #include <asm/lmb.h> | ||
| 16 | 17 | ||
| 17 | void machine_crash_shutdown(struct pt_regs *regs) | 18 | void machine_crash_shutdown(struct pt_regs *regs) | 
| 18 | { | 19 | { | 
| @@ -59,3 +60,58 @@ NORET_TYPE void machine_kexec(struct kimage *image) | |||
| 59 | } | 60 | } | 
| 60 | for(;;); | 61 | for(;;); | 
| 61 | } | 62 | } | 
| 63 | |||
| 64 | static int __init early_parse_crashk(char *p) | ||
| 65 | { | ||
| 66 | unsigned long size; | ||
| 67 | |||
| 68 | if (!p) | ||
| 69 | return 1; | ||
| 70 | |||
| 71 | size = memparse(p, &p); | ||
| 72 | |||
| 73 | if (*p == '@') | ||
| 74 | crashk_res.start = memparse(p + 1, &p); | ||
| 75 | else | ||
| 76 | crashk_res.start = KDUMP_KERNELBASE; | ||
| 77 | |||
| 78 | crashk_res.end = crashk_res.start + size - 1; | ||
| 79 | |||
| 80 | return 0; | ||
| 81 | } | ||
| 82 | early_param("crashkernel", early_parse_crashk); | ||
| 83 | |||
| 84 | void __init reserve_crashkernel(void) | ||
| 85 | { | ||
| 86 | unsigned long size; | ||
| 87 | |||
| 88 | if (crashk_res.start == 0) | ||
| 89 | return; | ||
| 90 | |||
| 91 | /* We might have got these values via the command line or the | ||
| 92 | * device tree, either way sanitise them now. */ | ||
| 93 | |||
| 94 | size = crashk_res.end - crashk_res.start + 1; | ||
| 95 | |||
| 96 | if (crashk_res.start != KDUMP_KERNELBASE) | ||
| 97 | printk("Crash kernel location must be 0x%x\n", | ||
| 98 | KDUMP_KERNELBASE); | ||
| 99 | |||
| 100 | crashk_res.start = KDUMP_KERNELBASE; | ||
| 101 | size = PAGE_ALIGN(size); | ||
| 102 | crashk_res.end = crashk_res.start + size - 1; | ||
| 103 | |||
| 104 | /* Crash kernel trumps memory limit */ | ||
| 105 | if (memory_limit && memory_limit <= crashk_res.end) { | ||
| 106 | memory_limit = crashk_res.end + 1; | ||
| 107 | printk("Adjusted memory limit for crashkernel, now 0x%lx\n", | ||
| 108 | memory_limit); | ||
| 109 | } | ||
| 110 | |||
| 111 | lmb_reserve(crashk_res.start, size); | ||
| 112 | } | ||
| 113 | |||
| 114 | int overlaps_crashkernel(unsigned long start, unsigned long size) | ||
| 115 | { | ||
| 116 | return (start + size) > crashk_res.start && start <= crashk_res.end; | ||
| 117 | } | ||
| diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index b438d45a068c..be58985c7681 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | */ | 10 | */ | 
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | #include <linux/cpumask.h> | ||
| 14 | #include <linux/kexec.h> | 13 | #include <linux/kexec.h> | 
| 15 | #include <linux/smp.h> | 14 | #include <linux/smp.h> | 
| 16 | #include <linux/thread_info.h> | 15 | #include <linux/thread_info.h> | 
| @@ -21,7 +20,6 @@ | |||
| 21 | #include <asm/machdep.h> | 20 | #include <asm/machdep.h> | 
| 22 | #include <asm/cacheflush.h> | 21 | #include <asm/cacheflush.h> | 
| 23 | #include <asm/paca.h> | 22 | #include <asm/paca.h> | 
| 24 | #include <asm/lmb.h> | ||
| 25 | #include <asm/mmu.h> | 23 | #include <asm/mmu.h> | 
| 26 | #include <asm/sections.h> /* _end */ | 24 | #include <asm/sections.h> /* _end */ | 
| 27 | #include <asm/prom.h> | 25 | #include <asm/prom.h> | 
| @@ -385,58 +383,3 @@ static int __init kexec_setup(void) | |||
| 385 | return 0; | 383 | return 0; | 
| 386 | } | 384 | } | 
| 387 | __initcall(kexec_setup); | 385 | __initcall(kexec_setup); | 
| 388 | |||
| 389 | static int __init early_parse_crashk(char *p) | ||
| 390 | { | ||
| 391 | unsigned long size; | ||
| 392 | |||
| 393 | if (!p) | ||
| 394 | return 1; | ||
| 395 | |||
| 396 | size = memparse(p, &p); | ||
| 397 | |||
| 398 | if (*p == '@') | ||
| 399 | crashk_res.start = memparse(p + 1, &p); | ||
| 400 | else | ||
| 401 | crashk_res.start = KDUMP_KERNELBASE; | ||
| 402 | |||
| 403 | crashk_res.end = crashk_res.start + size - 1; | ||
| 404 | |||
| 405 | return 0; | ||
| 406 | } | ||
| 407 | early_param("crashkernel", early_parse_crashk); | ||
| 408 | |||
| 409 | void __init reserve_crashkernel(void) | ||
| 410 | { | ||
| 411 | unsigned long size; | ||
| 412 | |||
| 413 | if (crashk_res.start == 0) | ||
| 414 | return; | ||
| 415 | |||
| 416 | /* We might have got these values via the command line or the | ||
| 417 | * device tree, either way sanitise them now. */ | ||
| 418 | |||
| 419 | size = crashk_res.end - crashk_res.start + 1; | ||
| 420 | |||
| 421 | if (crashk_res.start != KDUMP_KERNELBASE) | ||
| 422 | printk("Crash kernel location must be 0x%x\n", | ||
| 423 | KDUMP_KERNELBASE); | ||
| 424 | |||
| 425 | crashk_res.start = KDUMP_KERNELBASE; | ||
| 426 | size = PAGE_ALIGN(size); | ||
| 427 | crashk_res.end = crashk_res.start + size - 1; | ||
| 428 | |||
| 429 | /* Crash kernel trumps memory limit */ | ||
| 430 | if (memory_limit && memory_limit <= crashk_res.end) { | ||
| 431 | memory_limit = crashk_res.end + 1; | ||
| 432 | printk("Adjusted memory limit for crashkernel, now 0x%lx\n", | ||
| 433 | memory_limit); | ||
| 434 | } | ||
| 435 | |||
| 436 | lmb_reserve(crashk_res.start, size); | ||
| 437 | } | ||
| 438 | |||
| 439 | int overlaps_crashkernel(unsigned long start, unsigned long size) | ||
| 440 | { | ||
| 441 | return (start + size) > crashk_res.start && start <= crashk_res.end; | ||
| 442 | } | ||
| diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 4a4cb5598402..77f1e06d208d 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) | |||
| 569 | } | 569 | } | 
| 570 | EXPORT_SYMBOL(rtas_set_indicator); | 570 | EXPORT_SYMBOL(rtas_set_indicator); | 
| 571 | 571 | ||
| 572 | /* | ||
| 573 | * Ignoring RTAS extended delay | ||
| 574 | */ | ||
| 575 | int rtas_set_indicator_fast(int indicator, int index, int new_value) | ||
| 576 | { | ||
| 577 | int rc; | ||
| 578 | int token = rtas_token("set-indicator"); | ||
| 579 | |||
| 580 | if (token == RTAS_UNKNOWN_SERVICE) | ||
| 581 | return -ENOENT; | ||
| 582 | |||
| 583 | rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value); | ||
| 584 | |||
| 585 | WARN_ON(rc == -2 || (rc >= 9900 && rc <= 9905)); | ||
| 586 | |||
| 587 | if (rc < 0) | ||
| 588 | return rtas_error_rc(rc); | ||
| 589 | |||
| 590 | return rc; | ||
| 591 | } | ||
| 592 | |||
| 572 | void rtas_restart(char *cmd) | 593 | void rtas_restart(char *cmd) | 
| 573 | { | 594 | { | 
| 574 | if (rtas_flash_term_hook) | 595 | if (rtas_flash_term_hook) | 
| diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 2105767fcc57..e4d1713e8aea 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
| @@ -55,9 +55,6 @@ | |||
| 55 | 55 | ||
| 56 | #ifdef CONFIG_PPC64 /* XXX */ | 56 | #ifdef CONFIG_PPC64 /* XXX */ | 
| 57 | #define _IO_BASE pci_io_base | 57 | #define _IO_BASE pci_io_base | 
| 58 | #ifdef CONFIG_KEXEC | ||
| 59 | cpumask_t cpus_in_sr = CPU_MASK_NONE; | ||
| 60 | #endif | ||
| 61 | #endif | 58 | #endif | 
| 62 | 59 | ||
| 63 | #ifdef CONFIG_DEBUGGER | 60 | #ifdef CONFIG_DEBUGGER | 
| @@ -151,7 +148,7 @@ int die(const char *str, struct pt_regs *regs, long err) | |||
| 151 | panic("Fatal exception in interrupt"); | 148 | panic("Fatal exception in interrupt"); | 
| 152 | 149 | ||
| 153 | if (panic_on_oops) | 150 | if (panic_on_oops) | 
| 154 | panic("Fatal exception: panic_on_oops"); | 151 | panic("Fatal exception"); | 
| 155 | 152 | ||
| 156 | do_exit(err); | 153 | do_exit(err); | 
| 157 | 154 | ||
| @@ -211,6 +208,19 @@ void system_reset_exception(struct pt_regs *regs) | |||
| 211 | 208 | ||
| 212 | die("System Reset", regs, SIGABRT); | 209 | die("System Reset", regs, SIGABRT); | 
| 213 | 210 | ||
| 211 | /* | ||
| 212 | * Some CPUs when released from the debugger will execute this path. | ||
| 213 | * These CPUs entered the debugger via a soft-reset. If the CPU was | ||
| 214 | * hung before entering the debugger it will return to the hung | ||
| 215 | * state when exiting this function. This causes a problem in | ||
| 216 | * kdump since the hung CPU(s) will not respond to the IPI sent | ||
| 217 | * from kdump. To prevent the problem we call crash_kexec_secondary() | ||
| 218 | * here. If a kdump had not been initiated or we exit the debugger | ||
| 219 | * with the "exit and recover" command (x) crash_kexec_secondary() | ||
| 220 | * will return after 5ms and the CPU returns to its previous state. | ||
| 221 | */ | ||
| 222 | crash_kexec_secondary(regs); | ||
| 223 | |||
| 214 | /* Must die if the interrupt is not recoverable */ | 224 | /* Must die if the interrupt is not recoverable */ | 
| 215 | if (!(regs->msr & MSR_RI)) | 225 | if (!(regs->msr & MSR_RI)) | 
| 216 | panic("Unrecoverable System Reset"); | 226 | panic("Unrecoverable System Reset"); | 
