aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/head_64.S35
-rw-r--r--arch/powerpc/kernel/legacy_serial.c13
-rw-r--r--arch/powerpc/kernel/misc_64.S2
-rw-r--r--arch/powerpc/kernel/prom_init.c36
-rw-r--r--arch/powerpc/kernel/smp.c24
-rw-r--r--arch/powerpc/kernel/sysfs.c4
-rw-r--r--arch/powerpc/kernel/traps.c10
-rw-r--r--arch/powerpc/kernel/udbg_16550.c6
-rw-r--r--arch/powerpc/kernel/vdso32/Makefile3
-rw-r--r--arch/powerpc/kernel/vdso32/vdso32.lds.S1
-rw-r--r--arch/powerpc/kernel/vdso64/Makefile3
-rw-r--r--arch/powerpc/kernel/vdso64/vdso64.lds.S1
12 files changed, 111 insertions, 27 deletions
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index e16eb2a33173..6ff3cf506088 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -191,6 +191,37 @@ exception_marker:
191 ori reg,reg,(label)@l; /* virt addr of handler ... */ 191 ori reg,reg,(label)@l; /* virt addr of handler ... */
192#endif 192#endif
193 193
194/*
195 * Equal to EXCEPTION_PROLOG_PSERIES, except that it forces 64bit mode.
196 * The firmware calls the registered system_reset_fwnmi and
197 * machine_check_fwnmi handlers in 32bit mode if the cpu happens to run
198 * a 32bit application at the time of the event.
199 * This firmware bug is present on POWER4 and JS20.
200 */
201#define EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(area, label) \
202 mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \
203 std r9,area+EX_R9(r13); /* save r9 - r12 */ \
204 std r10,area+EX_R10(r13); \
205 std r11,area+EX_R11(r13); \
206 std r12,area+EX_R12(r13); \
207 mfspr r9,SPRN_SPRG1; \
208 std r9,area+EX_R13(r13); \
209 mfcr r9; \
210 clrrdi r12,r13,32; /* get high part of &label */ \
211 mfmsr r10; \
212 /* force 64bit mode */ \
213 li r11,5; /* MSR_SF_LG|MSR_ISF_LG */ \
214 rldimi r10,r11,61,0; /* insert into top 3 bits */ \
215 /* done 64bit mode */ \
216 mfspr r11,SPRN_SRR0; /* save SRR0 */ \
217 LOAD_HANDLER(r12,label) \
218 ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \
219 mtspr SPRN_SRR0,r12; \
220 mfspr r12,SPRN_SRR1; /* and SRR1 */ \
221 mtspr SPRN_SRR1,r10; \
222 rfid; \
223 b . /* prevent speculative execution */
224
194#define EXCEPTION_PROLOG_PSERIES(area, label) \ 225#define EXCEPTION_PROLOG_PSERIES(area, label) \
195 mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ 226 mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \
196 std r9,area+EX_R9(r13); /* save r9 - r12 */ \ 227 std r9,area+EX_R9(r13); /* save r9 - r12 */ \
@@ -604,14 +635,14 @@ slb_miss_user_pseries:
604system_reset_fwnmi: 635system_reset_fwnmi:
605 HMT_MEDIUM 636 HMT_MEDIUM
606 mtspr SPRN_SPRG1,r13 /* save r13 */ 637 mtspr SPRN_SPRG1,r13 /* save r13 */
607 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common) 638 EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXGEN, system_reset_common)
608 639
609 .globl machine_check_fwnmi 640 .globl machine_check_fwnmi
610 .align 7 641 .align 7
611machine_check_fwnmi: 642machine_check_fwnmi:
612 HMT_MEDIUM 643 HMT_MEDIUM
613 mtspr SPRN_SPRG1,r13 /* save r13 */ 644 mtspr SPRN_SPRG1,r13 /* save r13 */
614 EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) 645 EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXMC, machine_check_common)
615 646
616#ifdef CONFIG_PPC_ISERIES 647#ifdef CONFIG_PPC_ISERIES
617/*** ISeries-LPAR interrupt handlers ***/ 648/*** ISeries-LPAR interrupt handlers ***/
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index 7e98e778b52f..359ab89748e0 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -112,7 +112,7 @@ static int __init add_legacy_port(struct device_node *np, int want_index,
112static int __init add_legacy_soc_port(struct device_node *np, 112static int __init add_legacy_soc_port(struct device_node *np,
113 struct device_node *soc_dev) 113 struct device_node *soc_dev)
114{ 114{
115 phys_addr_t addr; 115 u64 addr;
116 u32 *addrp; 116 u32 *addrp;
117 upf_t flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ; 117 upf_t flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
118 118
@@ -143,7 +143,7 @@ static int __init add_legacy_isa_port(struct device_node *np,
143 u32 *reg; 143 u32 *reg;
144 char *typep; 144 char *typep;
145 int index = -1; 145 int index = -1;
146 phys_addr_t taddr; 146 u64 taddr;
147 147
148 DBG(" -> add_legacy_isa_port(%s)\n", np->full_name); 148 DBG(" -> add_legacy_isa_port(%s)\n", np->full_name);
149 149
@@ -165,10 +165,13 @@ static int __init add_legacy_isa_port(struct device_node *np,
165 if (typep && *typep == 'S') 165 if (typep && *typep == 'S')
166 index = simple_strtol(typep+1, NULL, 0) - 1; 166 index = simple_strtol(typep+1, NULL, 0) - 1;
167 167
168 /* Translate ISA address */ 168 /* Translate ISA address. If it fails, we still register the port
169 * with no translated address so that it can be picked up as an IO
170 * port later by the serial driver
171 */
169 taddr = of_translate_address(np, reg); 172 taddr = of_translate_address(np, reg);
170 if (taddr == OF_BAD_ADDR) 173 if (taddr == OF_BAD_ADDR)
171 return -1; 174 taddr = 0;
172 175
173 /* Add port, irq will be dealt with later */ 176 /* Add port, irq will be dealt with later */
174 return add_legacy_port(np, index, UPIO_PORT, reg[1], taddr, 177 return add_legacy_port(np, index, UPIO_PORT, reg[1], taddr,
@@ -180,7 +183,7 @@ static int __init add_legacy_isa_port(struct device_node *np,
180static int __init add_legacy_pci_port(struct device_node *np, 183static int __init add_legacy_pci_port(struct device_node *np,
181 struct device_node *pci_dev) 184 struct device_node *pci_dev)
182{ 185{
183 phys_addr_t addr, base; 186 u64 addr, base;
184 u32 *addrp; 187 u32 *addrp;
185 unsigned int flags; 188 unsigned int flags;
186 int iotype, index = -1, lindex = 0; 189 int iotype, index = -1, lindex = 0;
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index bfb407fc1aa1..e3ed21cd3d94 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -687,7 +687,7 @@ _GLOBAL(kexec_sequence)
687 /* clear out hardware hash page table and tlb */ 687 /* clear out hardware hash page table and tlb */
688 ld r5,0(r27) /* deref function descriptor */ 688 ld r5,0(r27) /* deref function descriptor */
689 mtctr r5 689 mtctr r5
690 bctrl /* ppc_md.hash_clear_all(void); */ 690 bctrl /* ppc_md.hpte_clear_all(void); */
691 691
692/* 692/*
693 * kexec image calling is: 693 * kexec image calling is:
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index ebd501a59abd..462bced40c12 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -557,7 +557,9 @@ unsigned long prom_memparse(const char *ptr, const char **retptr)
557static void __init early_cmdline_parse(void) 557static void __init early_cmdline_parse(void)
558{ 558{
559 struct prom_t *_prom = &RELOC(prom); 559 struct prom_t *_prom = &RELOC(prom);
560#ifdef CONFIG_PPC64
560 const char *opt; 561 const char *opt;
562#endif
561 char *p; 563 char *p;
562 int l = 0; 564 int l = 0;
563 565
@@ -2030,6 +2032,39 @@ static void __init fixup_device_tree_maple(void)
2030#define fixup_device_tree_maple() 2032#define fixup_device_tree_maple()
2031#endif 2033#endif
2032 2034
2035#ifdef CONFIG_PPC_CHRP
2036/* Pegasos lacks the "ranges" property in the isa node */
2037static void __init fixup_device_tree_chrp(void)
2038{
2039 phandle isa;
2040 u32 isa_ranges[6];
2041 char *name;
2042 int rc;
2043
2044 name = "/pci@80000000/isa@c";
2045 isa = call_prom("finddevice", 1, 1, ADDR(name));
2046 if (!PHANDLE_VALID(isa))
2047 return;
2048
2049 rc = prom_getproplen(isa, "ranges");
2050 if (rc != 0 && rc != PROM_ERROR)
2051 return;
2052
2053 prom_printf("Fixing up missing ISA range on Pegasos...\n");
2054
2055 isa_ranges[0] = 0x1;
2056 isa_ranges[1] = 0x0;
2057 isa_ranges[2] = 0x01006000;
2058 isa_ranges[3] = 0x0;
2059 isa_ranges[4] = 0x0;
2060 isa_ranges[5] = 0x00010000;
2061 prom_setprop(isa, name, "ranges",
2062 isa_ranges, sizeof(isa_ranges));
2063}
2064#else
2065#define fixup_device_tree_chrp()
2066#endif
2067
2033#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC) 2068#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
2034static void __init fixup_device_tree_pmac(void) 2069static void __init fixup_device_tree_pmac(void)
2035{ 2070{
@@ -2077,6 +2112,7 @@ static void __init fixup_device_tree_pmac(void)
2077static void __init fixup_device_tree(void) 2112static void __init fixup_device_tree(void)
2078{ 2113{
2079 fixup_device_tree_maple(); 2114 fixup_device_tree_maple();
2115 fixup_device_tree_chrp();
2080 fixup_device_tree_pmac(); 2116 fixup_device_tree_pmac();
2081} 2117}
2082 2118
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 46c56cfd1b2f..6a9bc9ce54e0 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -144,13 +144,15 @@ void smp_message_recv(int msg, struct pt_regs *regs)
144 144
145void smp_send_reschedule(int cpu) 145void smp_send_reschedule(int cpu)
146{ 146{
147 smp_ops->message_pass(cpu, PPC_MSG_RESCHEDULE); 147 if (likely(smp_ops))
148 smp_ops->message_pass(cpu, PPC_MSG_RESCHEDULE);
148} 149}
149 150
150#ifdef CONFIG_DEBUGGER 151#ifdef CONFIG_DEBUGGER
151void smp_send_debugger_break(int cpu) 152void smp_send_debugger_break(int cpu)
152{ 153{
153 smp_ops->message_pass(cpu, PPC_MSG_DEBUGGER_BREAK); 154 if (likely(smp_ops))
155 smp_ops->message_pass(cpu, PPC_MSG_DEBUGGER_BREAK);
154} 156}
155#endif 157#endif
156 158
@@ -158,7 +160,7 @@ void smp_send_debugger_break(int cpu)
158void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *)) 160void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *))
159{ 161{
160 crash_ipi_function_ptr = crash_ipi_callback; 162 crash_ipi_function_ptr = crash_ipi_callback;
161 if (crash_ipi_callback) { 163 if (crash_ipi_callback && smp_ops) {
162 mb(); 164 mb();
163 smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_DEBUGGER_BREAK); 165 smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_DEBUGGER_BREAK);
164 } 166 }
@@ -220,6 +222,9 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
220 /* Can deadlock when called with interrupts disabled */ 222 /* Can deadlock when called with interrupts disabled */
221 WARN_ON(irqs_disabled()); 223 WARN_ON(irqs_disabled());
222 224
225 if (unlikely(smp_ops == NULL))
226 return -1;
227
223 data.func = func; 228 data.func = func;
224 data.info = info; 229 data.info = info;
225 atomic_set(&data.started, 0); 230 atomic_set(&data.started, 0);
@@ -357,7 +362,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
357 smp_store_cpu_info(boot_cpuid); 362 smp_store_cpu_info(boot_cpuid);
358 cpu_callin_map[boot_cpuid] = 1; 363 cpu_callin_map[boot_cpuid] = 1;
359 364
360 max_cpus = smp_ops->probe(); 365 if (smp_ops)
366 max_cpus = smp_ops->probe();
367 else
368 max_cpus = 1;
361 369
362 smp_space_timers(max_cpus); 370 smp_space_timers(max_cpus);
363 371
@@ -453,7 +461,7 @@ void generic_mach_cpu_die(void)
453 461
454static int __devinit cpu_enable(unsigned int cpu) 462static int __devinit cpu_enable(unsigned int cpu)
455{ 463{
456 if (smp_ops->cpu_enable) 464 if (smp_ops && smp_ops->cpu_enable)
457 return smp_ops->cpu_enable(cpu); 465 return smp_ops->cpu_enable(cpu);
458 466
459 return -ENOSYS; 467 return -ENOSYS;
@@ -467,7 +475,8 @@ int __devinit __cpu_up(unsigned int cpu)
467 if (!cpu_enable(cpu)) 475 if (!cpu_enable(cpu))
468 return 0; 476 return 0;
469 477
470 if (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)) 478 if (smp_ops == NULL ||
479 (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)))
471 return -EINVAL; 480 return -EINVAL;
472 481
473 /* Make sure callin-map entry is 0 (can be leftover a CPU 482 /* Make sure callin-map entry is 0 (can be leftover a CPU
@@ -568,7 +577,8 @@ void __init smp_cpus_done(unsigned int max_cpus)
568 old_mask = current->cpus_allowed; 577 old_mask = current->cpus_allowed;
569 set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid)); 578 set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid));
570 579
571 smp_ops->setup_cpu(boot_cpuid); 580 if (smp_ops)
581 smp_ops->setup_cpu(boot_cpuid);
572 582
573 set_cpus_allowed(current, old_mask); 583 set_cpus_allowed(current, old_mask);
574 584
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 010435095550..fec228cd0163 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -278,7 +278,7 @@ static void unregister_cpu_online(unsigned int cpu)
278} 278}
279#endif /* CONFIG_HOTPLUG_CPU */ 279#endif /* CONFIG_HOTPLUG_CPU */
280 280
281static int __devinit sysfs_cpu_notify(struct notifier_block *self, 281static int __cpuinit sysfs_cpu_notify(struct notifier_block *self,
282 unsigned long action, void *hcpu) 282 unsigned long action, void *hcpu)
283{ 283{
284 unsigned int cpu = (unsigned int)(long)hcpu; 284 unsigned int cpu = (unsigned int)(long)hcpu;
@@ -296,7 +296,7 @@ static int __devinit sysfs_cpu_notify(struct notifier_block *self,
296 return NOTIFY_OK; 296 return NOTIFY_OK;
297} 297}
298 298
299static struct notifier_block __devinitdata sysfs_cpu_nb = { 299static struct notifier_block __cpuinitdata sysfs_cpu_nb = {
300 .notifier_call = sysfs_cpu_notify, 300 .notifier_call = sysfs_cpu_notify,
301}; 301};
302 302
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 3c668078e524..2105767fcc57 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -150,13 +150,9 @@ int die(const char *str, struct pt_regs *regs, long err)
150 if (in_interrupt()) 150 if (in_interrupt())
151 panic("Fatal exception in interrupt"); 151 panic("Fatal exception in interrupt");
152 152
153 if (panic_on_oops) { 153 if (panic_on_oops)
154#ifdef CONFIG_PPC64 154 panic("Fatal exception: panic_on_oops");
155 printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n"); 155
156 ssleep(5);
157#endif
158 panic("Fatal exception");
159 }
160 do_exit(err); 156 do_exit(err);
161 157
162 return 0; 158 return 0;
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c
index 0835b4841dea..2d17f2b8eda7 100644
--- a/arch/powerpc/kernel/udbg_16550.c
+++ b/arch/powerpc/kernel/udbg_16550.c
@@ -81,10 +81,14 @@ static int udbg_550_getc(void)
81void udbg_init_uart(void __iomem *comport, unsigned int speed, 81void udbg_init_uart(void __iomem *comport, unsigned int speed,
82 unsigned int clock) 82 unsigned int clock)
83{ 83{
84 unsigned int dll, base_bauds = clock / 16; 84 unsigned int dll, base_bauds;
85 85
86 if (clock == 0)
87 clock = 1843200;
86 if (speed == 0) 88 if (speed == 0)
87 speed = 9600; 89 speed = 9600;
90
91 base_bauds = clock / 16;
88 dll = base_bauds / speed; 92 dll = base_bauds / speed;
89 93
90 if (comport) { 94 if (comport) {
diff --git a/arch/powerpc/kernel/vdso32/Makefile b/arch/powerpc/kernel/vdso32/Makefile
index 8a3bed5f143a..3726358faae8 100644
--- a/arch/powerpc/kernel/vdso32/Makefile
+++ b/arch/powerpc/kernel/vdso32/Makefile
@@ -14,7 +14,8 @@ obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32))
14 14
15 15
16EXTRA_CFLAGS := -shared -s -fno-common -fno-builtin 16EXTRA_CFLAGS := -shared -s -fno-common -fno-builtin
17EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso32.so.1 17EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso32.so.1 \
18 $(call ld-option, -Wl$(comma)--hash-style=sysv)
18EXTRA_AFLAGS := -D__VDSO32__ -s 19EXTRA_AFLAGS := -D__VDSO32__ -s
19 20
20obj-y += vdso32_wrapper.o 21obj-y += vdso32_wrapper.o
diff --git a/arch/powerpc/kernel/vdso32/vdso32.lds.S b/arch/powerpc/kernel/vdso32/vdso32.lds.S
index f4bad720cb0a..6187af2d54c3 100644
--- a/arch/powerpc/kernel/vdso32/vdso32.lds.S
+++ b/arch/powerpc/kernel/vdso32/vdso32.lds.S
@@ -14,6 +14,7 @@ SECTIONS
14{ 14{
15 . = VDSO32_LBASE + SIZEOF_HEADERS; 15 . = VDSO32_LBASE + SIZEOF_HEADERS;
16 .hash : { *(.hash) } :text 16 .hash : { *(.hash) } :text
17 .gnu.hash : { *(.gnu.hash) }
17 .dynsym : { *(.dynsym) } 18 .dynsym : { *(.dynsym) }
18 .dynstr : { *(.dynstr) } 19 .dynstr : { *(.dynstr) }
19 .gnu.version : { *(.gnu.version) } 20 .gnu.version : { *(.gnu.version) }
diff --git a/arch/powerpc/kernel/vdso64/Makefile b/arch/powerpc/kernel/vdso64/Makefile
index ab39988452cc..43af9b2a6f3b 100644
--- a/arch/powerpc/kernel/vdso64/Makefile
+++ b/arch/powerpc/kernel/vdso64/Makefile
@@ -8,7 +8,8 @@ targets := $(obj-vdso64) vdso64.so
8obj-vdso64 := $(addprefix $(obj)/, $(obj-vdso64)) 8obj-vdso64 := $(addprefix $(obj)/, $(obj-vdso64))
9 9
10EXTRA_CFLAGS := -shared -s -fno-common -fno-builtin 10EXTRA_CFLAGS := -shared -s -fno-common -fno-builtin
11EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso64.so.1 11EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso64.so.1 \
12 $(call ld-option, -Wl$(comma)--hash-style=sysv)
12EXTRA_AFLAGS := -D__VDSO64__ -s 13EXTRA_AFLAGS := -D__VDSO64__ -s
13 14
14obj-y += vdso64_wrapper.o 15obj-y += vdso64_wrapper.o
diff --git a/arch/powerpc/kernel/vdso64/vdso64.lds.S b/arch/powerpc/kernel/vdso64/vdso64.lds.S
index 4bdf224464ab..4a2b6dc0960c 100644
--- a/arch/powerpc/kernel/vdso64/vdso64.lds.S
+++ b/arch/powerpc/kernel/vdso64/vdso64.lds.S
@@ -12,6 +12,7 @@ SECTIONS
12{ 12{
13 . = VDSO64_LBASE + SIZEOF_HEADERS; 13 . = VDSO64_LBASE + SIZEOF_HEADERS;
14 .hash : { *(.hash) } :text 14 .hash : { *(.hash) } :text
15 .gnu.hash : { *(.gnu.hash) }
15 .dynsym : { *(.dynsym) } 16 .dynsym : { *(.dynsym) }
16 .dynstr : { *(.dynstr) } 17 .dynstr : { *(.dynstr) }
17 .gnu.version : { *(.gnu.version) } 18 .gnu.version : { *(.gnu.version) }