diff options
-rw-r--r-- | arch/powerpc/kernel/asm-offsets.c | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/crash.c | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/entry_64.S | 39 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_64.S | 110 | ||||
-rw-r--r-- | arch/powerpc/kernel/idle_power4.S | 8 | ||||
-rw-r--r-- | arch/powerpc/kernel/irq.c | 24 | ||||
-rw-r--r-- | arch/powerpc/kernel/ppc_ksyms.c | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup_64.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/iseries/ksyms.c | 6 | ||||
-rw-r--r-- | arch/powerpc/platforms/iseries/misc.S | 35 | ||||
-rw-r--r-- | include/asm-powerpc/hw_irq.h | 31 | ||||
-rw-r--r-- | include/asm-powerpc/paca.h | 3 |
12 files changed, 160 insertions, 111 deletions
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index d06f378597bb..e96521530d21 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -118,7 +118,8 @@ int main(void) | |||
118 | DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr)); | 118 | DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr)); |
119 | DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1)); | 119 | DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1)); |
120 | DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc)); | 120 | DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc)); |
121 | DEFINE(PACAPROCENABLED, offsetof(struct paca_struct, proc_enabled)); | 121 | DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled)); |
122 | DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled)); | ||
122 | DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); | 123 | DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); |
123 | DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); | 124 | DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); |
124 | DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); | 125 | DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); |
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 1af41f7616dc..89b03c8da9d2 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c | |||
@@ -111,7 +111,7 @@ void crash_ipi_callback(struct pt_regs *regs) | |||
111 | if (!cpu_online(cpu)) | 111 | if (!cpu_online(cpu)) |
112 | return; | 112 | return; |
113 | 113 | ||
114 | local_irq_disable(); | 114 | hard_irq_disable(); |
115 | if (!cpu_isset(cpu, cpus_in_crash)) | 115 | if (!cpu_isset(cpu, cpus_in_crash)) |
116 | crash_save_this_cpu(regs, cpu); | 116 | crash_save_this_cpu(regs, cpu); |
117 | cpu_set(cpu, cpus_in_crash); | 117 | cpu_set(cpu, cpus_in_crash); |
@@ -289,7 +289,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs) | |||
289 | * an SMP system. | 289 | * an SMP system. |
290 | * The kernel is broken so disable interrupts. | 290 | * The kernel is broken so disable interrupts. |
291 | */ | 291 | */ |
292 | local_irq_disable(); | 292 | hard_irq_disable(); |
293 | 293 | ||
294 | for_each_irq(irq) { | 294 | for_each_irq(irq) { |
295 | struct irq_desc *desc = irq_desc + irq; | 295 | struct irq_desc *desc = irq_desc + irq; |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 748e74fcf541..efda48741b29 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -87,6 +87,10 @@ system_call_common: | |||
87 | addi r9,r1,STACK_FRAME_OVERHEAD | 87 | addi r9,r1,STACK_FRAME_OVERHEAD |
88 | ld r11,exception_marker@toc(r2) | 88 | ld r11,exception_marker@toc(r2) |
89 | std r11,-16(r9) /* "regshere" marker */ | 89 | std r11,-16(r9) /* "regshere" marker */ |
90 | li r10,1 | ||
91 | stb r10,PACASOFTIRQEN(r13) | ||
92 | stb r10,PACAHARDIRQEN(r13) | ||
93 | std r10,SOFTE(r1) | ||
90 | #ifdef CONFIG_PPC_ISERIES | 94 | #ifdef CONFIG_PPC_ISERIES |
91 | BEGIN_FW_FTR_SECTION | 95 | BEGIN_FW_FTR_SECTION |
92 | /* Hack for handling interrupts when soft-enabling on iSeries */ | 96 | /* Hack for handling interrupts when soft-enabling on iSeries */ |
@@ -94,8 +98,6 @@ BEGIN_FW_FTR_SECTION | |||
94 | andi. r10,r12,MSR_PR /* from kernel */ | 98 | andi. r10,r12,MSR_PR /* from kernel */ |
95 | crand 4*cr0+eq,4*cr1+eq,4*cr0+eq | 99 | crand 4*cr0+eq,4*cr1+eq,4*cr0+eq |
96 | beq hardware_interrupt_entry | 100 | beq hardware_interrupt_entry |
97 | lbz r10,PACAPROCENABLED(r13) | ||
98 | std r10,SOFTE(r1) | ||
99 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | 101 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) |
100 | #endif | 102 | #endif |
101 | mfmsr r11 | 103 | mfmsr r11 |
@@ -460,9 +462,9 @@ _GLOBAL(ret_from_except_lite) | |||
460 | #endif | 462 | #endif |
461 | 463 | ||
462 | restore: | 464 | restore: |
465 | ld r5,SOFTE(r1) | ||
463 | #ifdef CONFIG_PPC_ISERIES | 466 | #ifdef CONFIG_PPC_ISERIES |
464 | BEGIN_FW_FTR_SECTION | 467 | BEGIN_FW_FTR_SECTION |
465 | ld r5,SOFTE(r1) | ||
466 | cmpdi 0,r5,0 | 468 | cmpdi 0,r5,0 |
467 | beq 4f | 469 | beq 4f |
468 | /* Check for pending interrupts (iSeries) */ | 470 | /* Check for pending interrupts (iSeries) */ |
@@ -472,16 +474,16 @@ BEGIN_FW_FTR_SECTION | |||
472 | beq+ 4f /* skip do_IRQ if no interrupts */ | 474 | beq+ 4f /* skip do_IRQ if no interrupts */ |
473 | 475 | ||
474 | li r3,0 | 476 | li r3,0 |
475 | stb r3,PACAPROCENABLED(r13) /* ensure we are soft-disabled */ | 477 | stb r3,PACASOFTIRQEN(r13) /* ensure we are soft-disabled */ |
476 | ori r10,r10,MSR_EE | 478 | ori r10,r10,MSR_EE |
477 | mtmsrd r10 /* hard-enable again */ | 479 | mtmsrd r10 /* hard-enable again */ |
478 | addi r3,r1,STACK_FRAME_OVERHEAD | 480 | addi r3,r1,STACK_FRAME_OVERHEAD |
479 | bl .do_IRQ | 481 | bl .do_IRQ |
480 | b .ret_from_except_lite /* loop back and handle more */ | 482 | b .ret_from_except_lite /* loop back and handle more */ |
481 | 483 | 4: | |
482 | 4: stb r5,PACAPROCENABLED(r13) | ||
483 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | 484 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) |
484 | #endif | 485 | #endif |
486 | stb r5,PACASOFTIRQEN(r13) | ||
485 | 487 | ||
486 | ld r3,_MSR(r1) | 488 | ld r3,_MSR(r1) |
487 | andi. r0,r3,MSR_RI | 489 | andi. r0,r3,MSR_RI |
@@ -538,25 +540,15 @@ do_work: | |||
538 | /* Check that preempt_count() == 0 and interrupts are enabled */ | 540 | /* Check that preempt_count() == 0 and interrupts are enabled */ |
539 | lwz r8,TI_PREEMPT(r9) | 541 | lwz r8,TI_PREEMPT(r9) |
540 | cmpwi cr1,r8,0 | 542 | cmpwi cr1,r8,0 |
541 | #ifdef CONFIG_PPC_ISERIES | ||
542 | BEGIN_FW_FTR_SECTION | ||
543 | ld r0,SOFTE(r1) | 543 | ld r0,SOFTE(r1) |
544 | cmpdi r0,0 | 544 | cmpdi r0,0 |
545 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | ||
546 | #endif | ||
547 | BEGIN_FW_FTR_SECTION | ||
548 | andi. r0,r3,MSR_EE | ||
549 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) | ||
550 | crandc eq,cr1*4+eq,eq | 545 | crandc eq,cr1*4+eq,eq |
551 | bne restore | 546 | bne restore |
552 | /* here we are preempting the current task */ | 547 | /* here we are preempting the current task */ |
553 | 1: | 548 | 1: |
554 | #ifdef CONFIG_PPC_ISERIES | ||
555 | BEGIN_FW_FTR_SECTION | ||
556 | li r0,1 | 549 | li r0,1 |
557 | stb r0,PACAPROCENABLED(r13) | 550 | stb r0,PACASOFTIRQEN(r13) |
558 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | 551 | stb r0,PACAHARDIRQEN(r13) |
559 | #endif | ||
560 | ori r10,r10,MSR_EE | 552 | ori r10,r10,MSR_EE |
561 | mtmsrd r10,1 /* reenable interrupts */ | 553 | mtmsrd r10,1 /* reenable interrupts */ |
562 | bl .preempt_schedule | 554 | bl .preempt_schedule |
@@ -639,8 +631,7 @@ _GLOBAL(enter_rtas) | |||
639 | /* There is no way it is acceptable to get here with interrupts enabled, | 631 | /* There is no way it is acceptable to get here with interrupts enabled, |
640 | * check it with the asm equivalent of WARN_ON | 632 | * check it with the asm equivalent of WARN_ON |
641 | */ | 633 | */ |
642 | mfmsr r6 | 634 | lbz r0,PACASOFTIRQEN(r13) |
643 | andi. r0,r6,MSR_EE | ||
644 | 1: tdnei r0,0 | 635 | 1: tdnei r0,0 |
645 | .section __bug_table,"a" | 636 | .section __bug_table,"a" |
646 | .llong 1b,__LINE__ + 0x1000000, 1f, 2f | 637 | .llong 1b,__LINE__ + 0x1000000, 1f, 2f |
@@ -649,7 +640,13 @@ _GLOBAL(enter_rtas) | |||
649 | 1: .asciz __FILE__ | 640 | 1: .asciz __FILE__ |
650 | 2: .asciz "enter_rtas" | 641 | 2: .asciz "enter_rtas" |
651 | .previous | 642 | .previous |
652 | 643 | ||
644 | /* Hard-disable interrupts */ | ||
645 | mfmsr r6 | ||
646 | rldicl r7,r6,48,1 | ||
647 | rotldi r7,r7,16 | ||
648 | mtmsrd r7,1 | ||
649 | |||
653 | /* Unfortunately, the stack pointer and the MSR are also clobbered, | 650 | /* Unfortunately, the stack pointer and the MSR are also clobbered, |
654 | * so they are saved in the PACA which allows us to restore | 651 | * so they are saved in the PACA which allows us to restore |
655 | * our original state after RTAS returns. | 652 | * our original state after RTAS returns. |
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 645c7f10fb28..c93d9f35a121 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -35,9 +35,7 @@ | |||
35 | #include <asm/thread_info.h> | 35 | #include <asm/thread_info.h> |
36 | #include <asm/firmware.h> | 36 | #include <asm/firmware.h> |
37 | 37 | ||
38 | #ifdef CONFIG_PPC_ISERIES | ||
39 | #define DO_SOFT_DISABLE | 38 | #define DO_SOFT_DISABLE |
40 | #endif | ||
41 | 39 | ||
42 | /* | 40 | /* |
43 | * We layout physical memory as follows: | 41 | * We layout physical memory as follows: |
@@ -308,7 +306,9 @@ exception_marker: | |||
308 | std r9,_LINK(r1); \ | 306 | std r9,_LINK(r1); \ |
309 | mfctr r10; /* save CTR in stackframe */ \ | 307 | mfctr r10; /* save CTR in stackframe */ \ |
310 | std r10,_CTR(r1); \ | 308 | std r10,_CTR(r1); \ |
309 | lbz r10,PACASOFTIRQEN(r13); \ | ||
311 | mfspr r11,SPRN_XER; /* save XER in stackframe */ \ | 310 | mfspr r11,SPRN_XER; /* save XER in stackframe */ \ |
311 | std r10,SOFTE(r1); \ | ||
312 | std r11,_XER(r1); \ | 312 | std r11,_XER(r1); \ |
313 | li r9,(n)+1; \ | 313 | li r9,(n)+1; \ |
314 | std r9,_TRAP(r1); /* set trap number */ \ | 314 | std r9,_TRAP(r1); /* set trap number */ \ |
@@ -343,6 +343,34 @@ label##_pSeries: \ | |||
343 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) | 343 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) |
344 | 344 | ||
345 | 345 | ||
346 | #define MASKABLE_EXCEPTION_PSERIES(n, label) \ | ||
347 | . = n; \ | ||
348 | .globl label##_pSeries; \ | ||
349 | label##_pSeries: \ | ||
350 | HMT_MEDIUM; \ | ||
351 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
352 | mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ | ||
353 | std r9,PACA_EXGEN+EX_R9(r13); /* save r9, r10 */ \ | ||
354 | std r10,PACA_EXGEN+EX_R10(r13); \ | ||
355 | lbz r10,PACASOFTIRQEN(r13); \ | ||
356 | mfcr r9; \ | ||
357 | cmpwi r10,0; \ | ||
358 | beq masked_interrupt; \ | ||
359 | mfspr r10,SPRN_SPRG1; \ | ||
360 | std r10,PACA_EXGEN+EX_R13(r13); \ | ||
361 | std r11,PACA_EXGEN+EX_R11(r13); \ | ||
362 | std r12,PACA_EXGEN+EX_R12(r13); \ | ||
363 | clrrdi r12,r13,32; /* get high part of &label */ \ | ||
364 | mfmsr r10; \ | ||
365 | mfspr r11,SPRN_SRR0; /* save SRR0 */ \ | ||
366 | LOAD_HANDLER(r12,label##_common) \ | ||
367 | ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \ | ||
368 | mtspr SPRN_SRR0,r12; \ | ||
369 | mfspr r12,SPRN_SRR1; /* and SRR1 */ \ | ||
370 | mtspr SPRN_SRR1,r10; \ | ||
371 | rfid; \ | ||
372 | b . /* prevent speculative execution */ | ||
373 | |||
346 | #define STD_EXCEPTION_ISERIES(n, label, area) \ | 374 | #define STD_EXCEPTION_ISERIES(n, label, area) \ |
347 | .globl label##_iSeries; \ | 375 | .globl label##_iSeries; \ |
348 | label##_iSeries: \ | 376 | label##_iSeries: \ |
@@ -358,40 +386,32 @@ label##_iSeries: \ | |||
358 | HMT_MEDIUM; \ | 386 | HMT_MEDIUM; \ |
359 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | 387 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ |
360 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \ | 388 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \ |
361 | lbz r10,PACAPROCENABLED(r13); \ | 389 | lbz r10,PACASOFTIRQEN(r13); \ |
362 | cmpwi 0,r10,0; \ | 390 | cmpwi 0,r10,0; \ |
363 | beq- label##_iSeries_masked; \ | 391 | beq- label##_iSeries_masked; \ |
364 | EXCEPTION_PROLOG_ISERIES_2; \ | 392 | EXCEPTION_PROLOG_ISERIES_2; \ |
365 | b label##_common; \ | 393 | b label##_common; \ |
366 | 394 | ||
367 | #ifdef DO_SOFT_DISABLE | 395 | #ifdef CONFIG_PPC_ISERIES |
368 | #define DISABLE_INTS \ | 396 | #define DISABLE_INTS \ |
369 | BEGIN_FW_FTR_SECTION; \ | ||
370 | lbz r10,PACAPROCENABLED(r13); \ | ||
371 | li r11,0; \ | 397 | li r11,0; \ |
372 | std r10,SOFTE(r1); \ | 398 | stb r11,PACASOFTIRQEN(r13); \ |
399 | BEGIN_FW_FTR_SECTION; \ | ||
400 | stb r11,PACAHARDIRQEN(r13); \ | ||
401 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \ | ||
402 | BEGIN_FW_FTR_SECTION; \ | ||
373 | mfmsr r10; \ | 403 | mfmsr r10; \ |
374 | stb r11,PACAPROCENABLED(r13); \ | ||
375 | ori r10,r10,MSR_EE; \ | 404 | ori r10,r10,MSR_EE; \ |
376 | mtmsrd r10,1; \ | 405 | mtmsrd r10,1; \ |
377 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | 406 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) |
378 | 407 | ||
379 | #define ENABLE_INTS \ | 408 | #else |
380 | BEGIN_FW_FTR_SECTION; \ | 409 | #define DISABLE_INTS \ |
381 | lbz r10,PACAPROCENABLED(r13); \ | 410 | li r11,0; \ |
382 | mfmsr r11; \ | 411 | stb r11,PACASOFTIRQEN(r13); \ |
383 | std r10,SOFTE(r1); \ | 412 | stb r11,PACAHARDIRQEN(r13) |
384 | ori r11,r11,MSR_EE; \ | ||
385 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES); \ | ||
386 | BEGIN_FW_FTR_SECTION; \ | ||
387 | ld r12,_MSR(r1); \ | ||
388 | mfmsr r11; \ | ||
389 | rlwimi r11,r12,0,MSR_EE; \ | ||
390 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \ | ||
391 | mtmsrd r11,1 | ||
392 | 413 | ||
393 | #else /* hard enable/disable interrupts */ | 414 | #endif /* CONFIG_PPC_ISERIES */ |
394 | #define DISABLE_INTS | ||
395 | 415 | ||
396 | #define ENABLE_INTS \ | 416 | #define ENABLE_INTS \ |
397 | ld r12,_MSR(r1); \ | 417 | ld r12,_MSR(r1); \ |
@@ -399,8 +419,6 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \ | |||
399 | rlwimi r11,r12,0,MSR_EE; \ | 419 | rlwimi r11,r12,0,MSR_EE; \ |
400 | mtmsrd r11,1 | 420 | mtmsrd r11,1 |
401 | 421 | ||
402 | #endif | ||
403 | |||
404 | #define STD_EXCEPTION_COMMON(trap, label, hdlr) \ | 422 | #define STD_EXCEPTION_COMMON(trap, label, hdlr) \ |
405 | .align 7; \ | 423 | .align 7; \ |
406 | .globl label##_common; \ | 424 | .globl label##_common; \ |
@@ -541,11 +559,11 @@ instruction_access_slb_pSeries: | |||
541 | mfspr r12,SPRN_SRR1 /* and SRR1 */ | 559 | mfspr r12,SPRN_SRR1 /* and SRR1 */ |
542 | b .slb_miss_realmode /* Rel. branch works in real mode */ | 560 | b .slb_miss_realmode /* Rel. branch works in real mode */ |
543 | 561 | ||
544 | STD_EXCEPTION_PSERIES(0x500, hardware_interrupt) | 562 | MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt) |
545 | STD_EXCEPTION_PSERIES(0x600, alignment) | 563 | STD_EXCEPTION_PSERIES(0x600, alignment) |
546 | STD_EXCEPTION_PSERIES(0x700, program_check) | 564 | STD_EXCEPTION_PSERIES(0x700, program_check) |
547 | STD_EXCEPTION_PSERIES(0x800, fp_unavailable) | 565 | STD_EXCEPTION_PSERIES(0x800, fp_unavailable) |
548 | STD_EXCEPTION_PSERIES(0x900, decrementer) | 566 | MASKABLE_EXCEPTION_PSERIES(0x900, decrementer) |
549 | STD_EXCEPTION_PSERIES(0xa00, trap_0a) | 567 | STD_EXCEPTION_PSERIES(0xa00, trap_0a) |
550 | STD_EXCEPTION_PSERIES(0xb00, trap_0b) | 568 | STD_EXCEPTION_PSERIES(0xb00, trap_0b) |
551 | 569 | ||
@@ -597,7 +615,24 @@ system_call_pSeries: | |||
597 | /*** pSeries interrupt support ***/ | 615 | /*** pSeries interrupt support ***/ |
598 | 616 | ||
599 | /* moved from 0xf00 */ | 617 | /* moved from 0xf00 */ |
600 | STD_EXCEPTION_PSERIES(., performance_monitor) | 618 | MASKABLE_EXCEPTION_PSERIES(., performance_monitor) |
619 | |||
620 | /* | ||
621 | * An interrupt came in while soft-disabled; clear EE in SRR1, | ||
622 | * clear paca->hard_enabled and return. | ||
623 | */ | ||
624 | masked_interrupt: | ||
625 | stb r10,PACAHARDIRQEN(r13) | ||
626 | mtcrf 0x80,r9 | ||
627 | ld r9,PACA_EXGEN+EX_R9(r13) | ||
628 | mfspr r10,SPRN_SRR1 | ||
629 | rldicl r10,r10,48,1 /* clear MSR_EE */ | ||
630 | rotldi r10,r10,16 | ||
631 | mtspr SPRN_SRR1,r10 | ||
632 | ld r10,PACA_EXGEN+EX_R10(r13) | ||
633 | mfspr r13,SPRN_SPRG1 | ||
634 | rfid | ||
635 | b . | ||
601 | 636 | ||
602 | .align 7 | 637 | .align 7 |
603 | _GLOBAL(do_stab_bolted_pSeries) | 638 | _GLOBAL(do_stab_bolted_pSeries) |
@@ -952,7 +987,8 @@ fast_exception_return: | |||
952 | REST_8GPRS(2, r1) | 987 | REST_8GPRS(2, r1) |
953 | 988 | ||
954 | mfmsr r10 | 989 | mfmsr r10 |
955 | clrrdi r10,r10,2 /* clear RI (LE is 0 already) */ | 990 | rldicl r10,r10,48,1 /* clear EE */ |
991 | rldicr r10,r10,16,61 /* clear RI (LE is 0 already) */ | ||
956 | mtmsrd r10,1 | 992 | mtmsrd r10,1 |
957 | 993 | ||
958 | mtspr SPRN_SRR1,r12 | 994 | mtspr SPRN_SRR1,r12 |
@@ -1877,11 +1913,16 @@ _GLOBAL(__secondary_start) | |||
1877 | /* enable MMU and jump to start_secondary */ | 1913 | /* enable MMU and jump to start_secondary */ |
1878 | LOAD_REG_ADDR(r3, .start_secondary_prolog) | 1914 | LOAD_REG_ADDR(r3, .start_secondary_prolog) |
1879 | LOAD_REG_IMMEDIATE(r4, MSR_KERNEL) | 1915 | LOAD_REG_IMMEDIATE(r4, MSR_KERNEL) |
1880 | #ifdef DO_SOFT_DISABLE | 1916 | #ifdef CONFIG_PPC_ISERIES |
1881 | BEGIN_FW_FTR_SECTION | 1917 | BEGIN_FW_FTR_SECTION |
1882 | ori r4,r4,MSR_EE | 1918 | ori r4,r4,MSR_EE |
1883 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | 1919 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) |
1884 | #endif | 1920 | #endif |
1921 | BEGIN_FW_FTR_SECTION | ||
1922 | stb r7,PACASOFTIRQEN(r13) | ||
1923 | stb r7,PACAHARDIRQEN(r13) | ||
1924 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) | ||
1925 | |||
1885 | mtspr SPRN_SRR0,r3 | 1926 | mtspr SPRN_SRR0,r3 |
1886 | mtspr SPRN_SRR1,r4 | 1927 | mtspr SPRN_SRR1,r4 |
1887 | rfid | 1928 | rfid |
@@ -2019,15 +2060,18 @@ _STATIC(start_here_common) | |||
2019 | 2060 | ||
2020 | /* Load up the kernel context */ | 2061 | /* Load up the kernel context */ |
2021 | 5: | 2062 | 5: |
2022 | #ifdef DO_SOFT_DISABLE | ||
2023 | BEGIN_FW_FTR_SECTION | ||
2024 | li r5,0 | 2063 | li r5,0 |
2025 | stb r5,PACAPROCENABLED(r13) /* Soft Disabled */ | 2064 | stb r5,PACASOFTIRQEN(r13) /* Soft Disabled */ |
2065 | #ifdef CONFIG_PPC_ISERIES | ||
2066 | BEGIN_FW_FTR_SECTION | ||
2026 | mfmsr r5 | 2067 | mfmsr r5 |
2027 | ori r5,r5,MSR_EE /* Hard Enabled */ | 2068 | ori r5,r5,MSR_EE /* Hard Enabled */ |
2028 | mtmsrd r5 | 2069 | mtmsrd r5 |
2029 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | 2070 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) |
2030 | #endif | 2071 | #endif |
2072 | BEGIN_FW_FTR_SECTION | ||
2073 | stb r5,PACAHARDIRQEN(r13) | ||
2074 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) | ||
2031 | 2075 | ||
2032 | bl .start_kernel | 2076 | bl .start_kernel |
2033 | 2077 | ||
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S index 30de81da7b40..ba3195478600 100644 --- a/arch/powerpc/kernel/idle_power4.S +++ b/arch/powerpc/kernel/idle_power4.S | |||
@@ -30,6 +30,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP) | |||
30 | beqlr | 30 | beqlr |
31 | 31 | ||
32 | /* Go to NAP now */ | 32 | /* Go to NAP now */ |
33 | mfmsr r7 | ||
34 | rldicl r0,r7,48,1 | ||
35 | rotldi r0,r0,16 | ||
36 | mtmsrd r0,1 /* hard-disable interrupts */ | ||
37 | li r0,1 | ||
38 | stb r0,PACASOFTIRQEN(r13) /* we'll hard-enable shortly */ | ||
39 | stb r0,PACAHARDIRQEN(r13) | ||
33 | BEGIN_FTR_SECTION | 40 | BEGIN_FTR_SECTION |
34 | DSSALL | 41 | DSSALL |
35 | sync | 42 | sync |
@@ -38,7 +45,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
38 | ld r8,TI_LOCAL_FLAGS(r9) /* set napping bit */ | 45 | ld r8,TI_LOCAL_FLAGS(r9) /* set napping bit */ |
39 | ori r8,r8,_TLF_NAPPING /* so when we take an exception */ | 46 | ori r8,r8,_TLF_NAPPING /* so when we take an exception */ |
40 | std r8,TI_LOCAL_FLAGS(r9) /* it will return to our caller */ | 47 | std r8,TI_LOCAL_FLAGS(r9) /* it will return to our caller */ |
41 | mfmsr r7 | ||
42 | ori r7,r7,MSR_EE | 48 | ori r7,r7,MSR_EE |
43 | oris r7,r7,MSR_POW@h | 49 | oris r7,r7,MSR_POW@h |
44 | 1: sync | 50 | 1: sync |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 5e37bf14ef2d..67b21a008f6e 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -64,8 +64,9 @@ | |||
64 | #include <asm/ptrace.h> | 64 | #include <asm/ptrace.h> |
65 | #include <asm/machdep.h> | 65 | #include <asm/machdep.h> |
66 | #include <asm/udbg.h> | 66 | #include <asm/udbg.h> |
67 | #ifdef CONFIG_PPC_ISERIES | 67 | #ifdef CONFIG_PPC64 |
68 | #include <asm/paca.h> | 68 | #include <asm/paca.h> |
69 | #include <asm/firmware.h> | ||
69 | #endif | 70 | #endif |
70 | 71 | ||
71 | int __irq_offset_value; | 72 | int __irq_offset_value; |
@@ -95,6 +96,27 @@ extern atomic_t ipi_sent; | |||
95 | EXPORT_SYMBOL(irq_desc); | 96 | EXPORT_SYMBOL(irq_desc); |
96 | 97 | ||
97 | int distribute_irqs = 1; | 98 | int distribute_irqs = 1; |
99 | |||
100 | void local_irq_restore(unsigned long en) | ||
101 | { | ||
102 | get_paca()->soft_enabled = en; | ||
103 | if (!en) | ||
104 | return; | ||
105 | |||
106 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { | ||
107 | if (get_paca()->lppaca_ptr->int_dword.any_int) | ||
108 | iseries_handle_interrupts(); | ||
109 | return; | ||
110 | } | ||
111 | |||
112 | if (get_paca()->hard_enabled) | ||
113 | return; | ||
114 | /* need to hard-enable interrupts here */ | ||
115 | get_paca()->hard_enabled = en; | ||
116 | if ((int)mfspr(SPRN_DEC) < 0) | ||
117 | mtspr(SPRN_DEC, 1); | ||
118 | hard_irq_enable(); | ||
119 | } | ||
98 | #endif /* CONFIG_PPC64 */ | 120 | #endif /* CONFIG_PPC64 */ |
99 | 121 | ||
100 | int show_interrupts(struct seq_file *p, void *v) | 122 | int show_interrupts(struct seq_file *p, void *v) |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 807193a3c784..9179f0739ea2 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -49,6 +49,10 @@ | |||
49 | #include <asm/commproc.h> | 49 | #include <asm/commproc.h> |
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | #ifdef CONFIG_PPC64 | ||
53 | EXPORT_SYMBOL(local_irq_restore); | ||
54 | #endif | ||
55 | |||
52 | #ifdef CONFIG_PPC32 | 56 | #ifdef CONFIG_PPC32 |
53 | extern void transfer_to_handler(void); | 57 | extern void transfer_to_handler(void); |
54 | extern void do_IRQ(struct pt_regs *regs); | 58 | extern void do_IRQ(struct pt_regs *regs); |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 4b2e32eab9dc..b1b0cda3f748 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -223,8 +223,8 @@ void early_setup_secondary(void) | |||
223 | { | 223 | { |
224 | struct paca_struct *lpaca = get_paca(); | 224 | struct paca_struct *lpaca = get_paca(); |
225 | 225 | ||
226 | /* Mark enabled in PACA */ | 226 | /* Mark interrupts enabled in PACA */ |
227 | lpaca->proc_enabled = 0; | 227 | lpaca->soft_enabled = 0; |
228 | 228 | ||
229 | /* Initialize hash table for that CPU */ | 229 | /* Initialize hash table for that CPU */ |
230 | htab_initialize_secondary(); | 230 | htab_initialize_secondary(); |
diff --git a/arch/powerpc/platforms/iseries/ksyms.c b/arch/powerpc/platforms/iseries/ksyms.c index a2200842f4e5..2430848b98e7 100644 --- a/arch/powerpc/platforms/iseries/ksyms.c +++ b/arch/powerpc/platforms/iseries/ksyms.c | |||
@@ -19,9 +19,3 @@ EXPORT_SYMBOL(HvCall4); | |||
19 | EXPORT_SYMBOL(HvCall5); | 19 | EXPORT_SYMBOL(HvCall5); |
20 | EXPORT_SYMBOL(HvCall6); | 20 | EXPORT_SYMBOL(HvCall6); |
21 | EXPORT_SYMBOL(HvCall7); | 21 | EXPORT_SYMBOL(HvCall7); |
22 | |||
23 | #ifdef CONFIG_SMP | ||
24 | EXPORT_SYMBOL(local_get_flags); | ||
25 | EXPORT_SYMBOL(local_irq_disable); | ||
26 | EXPORT_SYMBOL(local_irq_restore); | ||
27 | #endif | ||
diff --git a/arch/powerpc/platforms/iseries/misc.S b/arch/powerpc/platforms/iseries/misc.S index 7641fc7e550a..2c6ff0fdac98 100644 --- a/arch/powerpc/platforms/iseries/misc.S +++ b/arch/powerpc/platforms/iseries/misc.S | |||
@@ -19,39 +19,8 @@ | |||
19 | 19 | ||
20 | .text | 20 | .text |
21 | 21 | ||
22 | /* unsigned long local_save_flags(void) */ | 22 | /* Handle pending interrupts in interrupt context */ |
23 | _GLOBAL(local_get_flags) | 23 | _GLOBAL(iseries_handle_interrupts) |
24 | lbz r3,PACAPROCENABLED(r13) | ||
25 | blr | ||
26 | |||
27 | /* unsigned long local_irq_disable(void) */ | ||
28 | _GLOBAL(local_irq_disable) | ||
29 | lbz r3,PACAPROCENABLED(r13) | ||
30 | li r4,0 | ||
31 | stb r4,PACAPROCENABLED(r13) | ||
32 | blr /* Done */ | ||
33 | |||
34 | /* void local_irq_restore(unsigned long flags) */ | ||
35 | _GLOBAL(local_irq_restore) | ||
36 | lbz r5,PACAPROCENABLED(r13) | ||
37 | /* Check if things are setup the way we want _already_. */ | ||
38 | cmpw 0,r3,r5 | ||
39 | beqlr | ||
40 | /* are we enabling interrupts? */ | ||
41 | cmpdi 0,r3,0 | ||
42 | stb r3,PACAPROCENABLED(r13) | ||
43 | beqlr | ||
44 | /* Check pending interrupts */ | ||
45 | /* A decrementer, IPI or PMC interrupt may have occurred | ||
46 | * while we were in the hypervisor (which enables) */ | ||
47 | ld r4,PACALPPACAPTR(r13) | ||
48 | ld r4,LPPACAANYINT(r4) | ||
49 | cmpdi r4,0 | ||
50 | beqlr | ||
51 | |||
52 | /* | ||
53 | * Handle pending interrupts in interrupt context | ||
54 | */ | ||
55 | li r0,0x5555 | 24 | li r0,0x5555 |
56 | sc | 25 | sc |
57 | blr | 26 | blr |
diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h index d40359204aba..c4a1ab608f6f 100644 --- a/include/asm-powerpc/hw_irq.h +++ b/include/asm-powerpc/hw_irq.h | |||
@@ -7,16 +7,30 @@ | |||
7 | #ifdef __KERNEL__ | 7 | #ifdef __KERNEL__ |
8 | 8 | ||
9 | #include <linux/errno.h> | 9 | #include <linux/errno.h> |
10 | #include <linux/compiler.h> | ||
10 | #include <asm/ptrace.h> | 11 | #include <asm/ptrace.h> |
11 | #include <asm/processor.h> | 12 | #include <asm/processor.h> |
12 | 13 | ||
13 | extern void timer_interrupt(struct pt_regs *); | 14 | extern void timer_interrupt(struct pt_regs *); |
14 | 15 | ||
15 | #ifdef CONFIG_PPC_ISERIES | 16 | #ifdef CONFIG_PPC64 |
17 | #include <asm/paca.h> | ||
18 | |||
19 | static inline unsigned long local_get_flags(void) | ||
20 | { | ||
21 | return get_paca()->soft_enabled; | ||
22 | } | ||
23 | |||
24 | static inline unsigned long local_irq_disable(void) | ||
25 | { | ||
26 | unsigned long flag = get_paca()->soft_enabled; | ||
27 | get_paca()->soft_enabled = 0; | ||
28 | barrier(); | ||
29 | return flag; | ||
30 | } | ||
16 | 31 | ||
17 | extern unsigned long local_get_flags(void); | ||
18 | extern unsigned long local_irq_disable(void); | ||
19 | extern void local_irq_restore(unsigned long); | 32 | extern void local_irq_restore(unsigned long); |
33 | extern void iseries_handle_interrupts(void); | ||
20 | 34 | ||
21 | #define local_irq_enable() local_irq_restore(1) | 35 | #define local_irq_enable() local_irq_restore(1) |
22 | #define local_save_flags(flags) ((flags) = local_get_flags()) | 36 | #define local_save_flags(flags) ((flags) = local_get_flags()) |
@@ -24,17 +38,14 @@ extern void local_irq_restore(unsigned long); | |||
24 | 38 | ||
25 | #define irqs_disabled() (local_get_flags() == 0) | 39 | #define irqs_disabled() (local_get_flags() == 0) |
26 | 40 | ||
41 | #define hard_irq_enable() __mtmsrd(mfmsr() | MSR_EE, 1) | ||
42 | #define hard_irq_disable() __mtmsrd(mfmsr() & ~MSR_EE, 1) | ||
43 | |||
27 | #else | 44 | #else |
28 | 45 | ||
29 | #if defined(CONFIG_BOOKE) | 46 | #if defined(CONFIG_BOOKE) |
30 | #define SET_MSR_EE(x) mtmsr(x) | 47 | #define SET_MSR_EE(x) mtmsr(x) |
31 | #define local_irq_restore(flags) __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory") | 48 | #define local_irq_restore(flags) __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory") |
32 | #elif defined(__powerpc64__) | ||
33 | #define SET_MSR_EE(x) __mtmsrd(x, 1) | ||
34 | #define local_irq_restore(flags) do { \ | ||
35 | __asm__ __volatile__("": : :"memory"); \ | ||
36 | __mtmsrd((flags), 1); \ | ||
37 | } while(0) | ||
38 | #else | 49 | #else |
39 | #define SET_MSR_EE(x) mtmsr(x) | 50 | #define SET_MSR_EE(x) mtmsr(x) |
40 | #define local_irq_restore(flags) mtmsr(flags) | 51 | #define local_irq_restore(flags) mtmsr(flags) |
@@ -81,7 +92,7 @@ static inline void local_irq_save_ptr(unsigned long *flags) | |||
81 | #define local_irq_save(flags) local_irq_save_ptr(&flags) | 92 | #define local_irq_save(flags) local_irq_save_ptr(&flags) |
82 | #define irqs_disabled() ((mfmsr() & MSR_EE) == 0) | 93 | #define irqs_disabled() ((mfmsr() & MSR_EE) == 0) |
83 | 94 | ||
84 | #endif /* CONFIG_PPC_ISERIES */ | 95 | #endif /* CONFIG_PPC64 */ |
85 | 96 | ||
86 | #define mask_irq(irq) \ | 97 | #define mask_irq(irq) \ |
87 | ({ \ | 98 | ({ \ |
diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h index 0a4e5c93e8e6..0d3adc09c847 100644 --- a/include/asm-powerpc/paca.h +++ b/include/asm-powerpc/paca.h | |||
@@ -93,7 +93,8 @@ struct paca_struct { | |||
93 | u64 stab_rr; /* stab/slb round-robin counter */ | 93 | u64 stab_rr; /* stab/slb round-robin counter */ |
94 | u64 saved_r1; /* r1 save for RTAS calls */ | 94 | u64 saved_r1; /* r1 save for RTAS calls */ |
95 | u64 saved_msr; /* MSR saved here by enter_rtas */ | 95 | u64 saved_msr; /* MSR saved here by enter_rtas */ |
96 | u8 proc_enabled; /* irq soft-enable flag */ | 96 | u8 soft_enabled; /* irq soft-enable flag */ |
97 | u8 hard_enabled; /* set if irqs are enabled in MSR */ | ||
97 | u8 io_sync; /* writel() needs spin_unlock sync */ | 98 | u8 io_sync; /* writel() needs spin_unlock sync */ |
98 | 99 | ||
99 | /* Stuff for accurate time accounting */ | 100 | /* Stuff for accurate time accounting */ |