diff options
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/asm-offsets.c | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/entry_32.S | 5 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_64.S | 11 | ||||
-rw-r--r-- | arch/powerpc/kernel/irq.c | 10 | ||||
-rw-r--r-- | arch/powerpc/kernel/misc_32.S | 25 | ||||
-rw-r--r-- | arch/powerpc/kernel/process.c | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/rio.c | 52 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup_32.c | 21 |
9 files changed, 71 insertions, 57 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 9177b21b1a95..d14cebf62bb0 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -73,7 +73,6 @@ pci64-$(CONFIG_PPC64) += pci_dn.o isa-bridge.o | |||
73 | obj-$(CONFIG_PCI) += pci_$(CONFIG_WORD_SIZE).o $(pci64-y) \ | 73 | obj-$(CONFIG_PCI) += pci_$(CONFIG_WORD_SIZE).o $(pci64-y) \ |
74 | pci-common.o | 74 | pci-common.o |
75 | obj-$(CONFIG_PCI_MSI) += msi.o | 75 | obj-$(CONFIG_PCI_MSI) += msi.o |
76 | obj-$(CONFIG_RAPIDIO) += rio.o | ||
77 | obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o \ | 76 | obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o \ |
78 | machine_kexec_$(CONFIG_WORD_SIZE).o | 77 | machine_kexec_$(CONFIG_WORD_SIZE).o |
79 | obj-$(CONFIG_AUDIT) += audit.o | 78 | obj-$(CONFIG_AUDIT) += audit.o |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 59044e7ed6f4..ec9228d687b0 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -63,6 +63,7 @@ int main(void) | |||
63 | #endif /* CONFIG_PPC64 */ | 63 | #endif /* CONFIG_PPC64 */ |
64 | 64 | ||
65 | DEFINE(KSP, offsetof(struct thread_struct, ksp)); | 65 | DEFINE(KSP, offsetof(struct thread_struct, ksp)); |
66 | DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit)); | ||
66 | DEFINE(PT_REGS, offsetof(struct thread_struct, regs)); | 67 | DEFINE(PT_REGS, offsetof(struct thread_struct, regs)); |
67 | DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode)); | 68 | DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode)); |
68 | DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); | 69 | DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); |
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 84c868633068..0c8614d9875c 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
@@ -137,11 +137,12 @@ transfer_to_handler: | |||
137 | 2: /* if from kernel, check interrupted DOZE/NAP mode and | 137 | 2: /* if from kernel, check interrupted DOZE/NAP mode and |
138 | * check for stack overflow | 138 | * check for stack overflow |
139 | */ | 139 | */ |
140 | lwz r9,THREAD_INFO-THREAD(r12) | 140 | lwz r9,KSP_LIMIT(r12) |
141 | cmplw r1,r9 /* if r1 <= current->thread_info */ | 141 | cmplw r1,r9 /* if r1 <= ksp_limit */ |
142 | ble- stack_ovf /* then the kernel stack overflowed */ | 142 | ble- stack_ovf /* then the kernel stack overflowed */ |
143 | 5: | 143 | 5: |
144 | #ifdef CONFIG_6xx | 144 | #ifdef CONFIG_6xx |
145 | rlwinm r9,r1,0,0,31-THREAD_SHIFT | ||
145 | tophys(r9,r9) /* check local flags */ | 146 | tophys(r9,r9) /* check local flags */ |
146 | lwz r12,TI_LOCAL_FLAGS(r9) | 147 | lwz r12,TI_LOCAL_FLAGS(r9) |
147 | mtcrf 0x01,r12 | 148 | mtcrf 0x01,r12 |
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 215973a2c8d5..024805e1747d 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -239,6 +239,10 @@ instruction_access_slb_pSeries: | |||
239 | .globl system_call_pSeries | 239 | .globl system_call_pSeries |
240 | system_call_pSeries: | 240 | system_call_pSeries: |
241 | HMT_MEDIUM | 241 | HMT_MEDIUM |
242 | BEGIN_FTR_SECTION | ||
243 | cmpdi r0,0x1ebe | ||
244 | beq- 1f | ||
245 | END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) | ||
242 | mr r9,r13 | 246 | mr r9,r13 |
243 | mfmsr r10 | 247 | mfmsr r10 |
244 | mfspr r13,SPRN_SPRG3 | 248 | mfspr r13,SPRN_SPRG3 |
@@ -253,6 +257,13 @@ system_call_pSeries: | |||
253 | rfid | 257 | rfid |
254 | b . /* prevent speculative execution */ | 258 | b . /* prevent speculative execution */ |
255 | 259 | ||
260 | /* Fast LE/BE switch system call */ | ||
261 | 1: mfspr r12,SPRN_SRR1 | ||
262 | xori r12,r12,MSR_LE | ||
263 | mtspr SPRN_SRR1,r12 | ||
264 | rfid /* return to userspace */ | ||
265 | b . | ||
266 | |||
256 | STD_EXCEPTION_PSERIES(0xd00, single_step) | 267 | STD_EXCEPTION_PSERIES(0xd00, single_step) |
257 | STD_EXCEPTION_PSERIES(0xe00, trap_0e) | 268 | STD_EXCEPTION_PSERIES(0xe00, trap_0e) |
258 | 269 | ||
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 425616f92d18..2f73f705d564 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -307,6 +307,7 @@ void do_IRQ(struct pt_regs *regs) | |||
307 | if (curtp != irqtp) { | 307 | if (curtp != irqtp) { |
308 | struct irq_desc *desc = irq_desc + irq; | 308 | struct irq_desc *desc = irq_desc + irq; |
309 | void *handler = desc->handle_irq; | 309 | void *handler = desc->handle_irq; |
310 | unsigned long saved_sp_limit = current->thread.ksp_limit; | ||
310 | if (handler == NULL) | 311 | if (handler == NULL) |
311 | handler = &__do_IRQ; | 312 | handler = &__do_IRQ; |
312 | irqtp->task = curtp->task; | 313 | irqtp->task = curtp->task; |
@@ -319,7 +320,10 @@ void do_IRQ(struct pt_regs *regs) | |||
319 | (irqtp->preempt_count & ~SOFTIRQ_MASK) | | 320 | (irqtp->preempt_count & ~SOFTIRQ_MASK) | |
320 | (curtp->preempt_count & SOFTIRQ_MASK); | 321 | (curtp->preempt_count & SOFTIRQ_MASK); |
321 | 322 | ||
323 | current->thread.ksp_limit = (unsigned long)irqtp + | ||
324 | _ALIGN_UP(sizeof(struct thread_info), 16); | ||
322 | call_handle_irq(irq, desc, irqtp, handler); | 325 | call_handle_irq(irq, desc, irqtp, handler); |
326 | current->thread.ksp_limit = saved_sp_limit; | ||
323 | irqtp->task = NULL; | 327 | irqtp->task = NULL; |
324 | 328 | ||
325 | 329 | ||
@@ -352,9 +356,7 @@ void __init init_IRQ(void) | |||
352 | { | 356 | { |
353 | if (ppc_md.init_IRQ) | 357 | if (ppc_md.init_IRQ) |
354 | ppc_md.init_IRQ(); | 358 | ppc_md.init_IRQ(); |
355 | #ifdef CONFIG_PPC64 | ||
356 | irq_ctx_init(); | 359 | irq_ctx_init(); |
357 | #endif | ||
358 | } | 360 | } |
359 | 361 | ||
360 | 362 | ||
@@ -383,11 +385,15 @@ void irq_ctx_init(void) | |||
383 | static inline void do_softirq_onstack(void) | 385 | static inline void do_softirq_onstack(void) |
384 | { | 386 | { |
385 | struct thread_info *curtp, *irqtp; | 387 | struct thread_info *curtp, *irqtp; |
388 | unsigned long saved_sp_limit = current->thread.ksp_limit; | ||
386 | 389 | ||
387 | curtp = current_thread_info(); | 390 | curtp = current_thread_info(); |
388 | irqtp = softirq_ctx[smp_processor_id()]; | 391 | irqtp = softirq_ctx[smp_processor_id()]; |
389 | irqtp->task = curtp->task; | 392 | irqtp->task = curtp->task; |
393 | current->thread.ksp_limit = (unsigned long)irqtp + | ||
394 | _ALIGN_UP(sizeof(struct thread_info), 16); | ||
390 | call_do_softirq(irqtp); | 395 | call_do_softirq(irqtp); |
396 | current->thread.ksp_limit = saved_sp_limit; | ||
391 | irqtp->task = NULL; | 397 | irqtp->task = NULL; |
392 | } | 398 | } |
393 | 399 | ||
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 92ccc6fcc5b0..89aaaa6f3561 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
@@ -32,6 +32,31 @@ | |||
32 | 32 | ||
33 | .text | 33 | .text |
34 | 34 | ||
35 | #ifdef CONFIG_IRQSTACKS | ||
36 | _GLOBAL(call_do_softirq) | ||
37 | mflr r0 | ||
38 | stw r0,4(r1) | ||
39 | stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3) | ||
40 | mr r1,r3 | ||
41 | bl __do_softirq | ||
42 | lwz r1,0(r1) | ||
43 | lwz r0,4(r1) | ||
44 | mtlr r0 | ||
45 | blr | ||
46 | |||
47 | _GLOBAL(call_handle_irq) | ||
48 | mflr r0 | ||
49 | stw r0,4(r1) | ||
50 | mtctr r6 | ||
51 | stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r5) | ||
52 | mr r1,r5 | ||
53 | bctrl | ||
54 | lwz r1,0(r1) | ||
55 | lwz r0,4(r1) | ||
56 | mtlr r0 | ||
57 | blr | ||
58 | #endif /* CONFIG_IRQSTACKS */ | ||
59 | |||
35 | /* | 60 | /* |
36 | * This returns the high 64 bits of the product of two 64-bit numbers. | 61 | * This returns the high 64 bits of the product of two 64-bit numbers. |
37 | */ | 62 | */ |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 6caad17ea72e..7de41c3948ec 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -589,6 +589,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, | |||
589 | kregs = (struct pt_regs *) sp; | 589 | kregs = (struct pt_regs *) sp; |
590 | sp -= STACK_FRAME_OVERHEAD; | 590 | sp -= STACK_FRAME_OVERHEAD; |
591 | p->thread.ksp = sp; | 591 | p->thread.ksp = sp; |
592 | p->thread.ksp_limit = (unsigned long)task_stack_page(p) + | ||
593 | _ALIGN_UP(sizeof(struct thread_info), 16); | ||
592 | 594 | ||
593 | #ifdef CONFIG_PPC64 | 595 | #ifdef CONFIG_PPC64 |
594 | if (cpu_has_feature(CPU_FTR_SLB)) { | 596 | if (cpu_has_feature(CPU_FTR_SLB)) { |
diff --git a/arch/powerpc/kernel/rio.c b/arch/powerpc/kernel/rio.c deleted file mode 100644 index 29487fedfc76..000000000000 --- a/arch/powerpc/kernel/rio.c +++ /dev/null | |||
@@ -1,52 +0,0 @@ | |||
1 | /* | ||
2 | * RapidIO PPC32 support | ||
3 | * | ||
4 | * Copyright 2005 MontaVista Software, Inc. | ||
5 | * Matt Porter <mporter@kernel.crashing.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/rio.h> | ||
16 | |||
17 | #include <asm/rio.h> | ||
18 | |||
19 | /** | ||
20 | * platform_rio_init - Do platform specific RIO init | ||
21 | * | ||
22 | * Any platform specific initialization of RapdIO | ||
23 | * hardware is done here as well as registration | ||
24 | * of any active master ports in the system. | ||
25 | */ | ||
26 | void __attribute__ ((weak)) | ||
27 | platform_rio_init(void) | ||
28 | { | ||
29 | printk(KERN_WARNING "RIO: No platform_rio_init() present\n"); | ||
30 | } | ||
31 | |||
32 | /** | ||
33 | * ppc_rio_init - Do PPC32 RIO init | ||
34 | * | ||
35 | * Calls platform-specific RIO init code and then calls | ||
36 | * rio_init_mports() to initialize any master ports that | ||
37 | * have been registered with the RIO subsystem. | ||
38 | */ | ||
39 | static int __init ppc_rio_init(void) | ||
40 | { | ||
41 | printk(KERN_INFO "RIO: RapidIO init\n"); | ||
42 | |||
43 | /* Platform specific initialization */ | ||
44 | platform_rio_init(); | ||
45 | |||
46 | /* Enumerate all registered ports */ | ||
47 | rio_init_mports(); | ||
48 | |||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | subsys_initcall(ppc_rio_init); | ||
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 36f6779c88d4..5112a4aa801d 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/root_dev.h> | 16 | #include <linux/root_dev.h> |
17 | #include <linux/cpu.h> | 17 | #include <linux/cpu.h> |
18 | #include <linux/console.h> | 18 | #include <linux/console.h> |
19 | #include <linux/lmb.h> | ||
19 | 20 | ||
20 | #include <asm/io.h> | 21 | #include <asm/io.h> |
21 | #include <asm/prom.h> | 22 | #include <asm/prom.h> |
@@ -229,6 +230,24 @@ int __init ppc_init(void) | |||
229 | 230 | ||
230 | arch_initcall(ppc_init); | 231 | arch_initcall(ppc_init); |
231 | 232 | ||
233 | #ifdef CONFIG_IRQSTACKS | ||
234 | static void __init irqstack_early_init(void) | ||
235 | { | ||
236 | unsigned int i; | ||
237 | |||
238 | /* interrupt stacks must be in lowmem, we get that for free on ppc32 | ||
239 | * as the lmb is limited to lowmem by LMB_REAL_LIMIT */ | ||
240 | for_each_possible_cpu(i) { | ||
241 | softirq_ctx[i] = (struct thread_info *) | ||
242 | __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE)); | ||
243 | hardirq_ctx[i] = (struct thread_info *) | ||
244 | __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE)); | ||
245 | } | ||
246 | } | ||
247 | #else | ||
248 | #define irqstack_early_init() | ||
249 | #endif | ||
250 | |||
232 | /* Warning, IO base is not yet inited */ | 251 | /* Warning, IO base is not yet inited */ |
233 | void __init setup_arch(char **cmdline_p) | 252 | void __init setup_arch(char **cmdline_p) |
234 | { | 253 | { |
@@ -286,6 +305,8 @@ void __init setup_arch(char **cmdline_p) | |||
286 | init_mm.end_data = (unsigned long) _edata; | 305 | init_mm.end_data = (unsigned long) _edata; |
287 | init_mm.brk = klimit; | 306 | init_mm.brk = klimit; |
288 | 307 | ||
308 | irqstack_early_init(); | ||
309 | |||
289 | /* set up the bootmem stuff with available memory */ | 310 | /* set up the bootmem stuff with available memory */ |
290 | do_init_bootmem(); | 311 | do_init_bootmem(); |
291 | if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab); | 312 | if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab); |