aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/asm-offsets.c3
-rw-r--r--arch/powerpc/kernel/crash.c4
-rw-r--r--arch/powerpc/kernel/entry_64.S39
-rw-r--r--arch/powerpc/kernel/head_64.S110
-rw-r--r--arch/powerpc/kernel/idle_power4.S8
-rw-r--r--arch/powerpc/kernel/irq.c24
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c4
-rw-r--r--arch/powerpc/kernel/setup_64.c4
-rw-r--r--arch/powerpc/platforms/iseries/ksyms.c6
-rw-r--r--arch/powerpc/platforms/iseries/misc.S35
-rw-r--r--include/asm-powerpc/hw_irq.h31
-rw-r--r--include/asm-powerpc/paca.h3
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
91BEGIN_FW_FTR_SECTION 95BEGIN_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)
99END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) 101END_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
462restore: 464restore:
465 ld r5,SOFTE(r1)
463#ifdef CONFIG_PPC_ISERIES 466#ifdef CONFIG_PPC_ISERIES
464BEGIN_FW_FTR_SECTION 467BEGIN_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 4834:
4824: stb r5,PACAPROCENABLED(r13)
483END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) 484END_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
542BEGIN_FW_FTR_SECTION
543 ld r0,SOFTE(r1) 543 ld r0,SOFTE(r1)
544 cmpdi r0,0 544 cmpdi r0,0
545END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
546#endif
547BEGIN_FW_FTR_SECTION
548 andi. r0,r3,MSR_EE
549END_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 */
5531: 5481:
554#ifdef CONFIG_PPC_ISERIES
555BEGIN_FW_FTR_SECTION
556 li r0,1 549 li r0,1
557 stb r0,PACAPROCENABLED(r13) 550 stb r0,PACASOFTIRQEN(r13)
558END_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
6441: tdnei r0,0 6351: 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)
6491: .asciz __FILE__ 6401: .asciz __FILE__
6502: .asciz "enter_rtas" 6412: .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; \
349label##_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; \
348label##_iSeries: \ 376label##_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 \
369BEGIN_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); \
399BEGIN_FW_FTR_SECTION; \
400 stb r11,PACAHARDIRQEN(r13); \
401END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \
402BEGIN_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; \
377END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) 406END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
378 407
379#define ENABLE_INTS \ 408#else
380BEGIN_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; \
385END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES); \
386BEGIN_FW_FTR_SECTION; \
387 ld r12,_MSR(r1); \
388 mfmsr r11; \
389 rlwimi r11,r12,0,MSR_EE; \
390END_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 */
624masked_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
1881BEGIN_FW_FTR_SECTION 1917BEGIN_FW_FTR_SECTION
1882 ori r4,r4,MSR_EE 1918 ori r4,r4,MSR_EE
1883END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) 1919END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
1884#endif 1920#endif
1921BEGIN_FW_FTR_SECTION
1922 stb r7,PACASOFTIRQEN(r13)
1923 stb r7,PACAHARDIRQEN(r13)
1924END_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 */
20215: 20625:
2022#ifdef DO_SOFT_DISABLE
2023BEGIN_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
2066BEGIN_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
2029END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) 2070END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
2030#endif 2071#endif
2072BEGIN_FW_FTR_SECTION
2073 stb r5,PACAHARDIRQEN(r13)
2074END_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)
33BEGIN_FTR_SECTION 40BEGIN_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
441: sync 501: 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
71int __irq_offset_value; 72int __irq_offset_value;
@@ -95,6 +96,27 @@ extern atomic_t ipi_sent;
95EXPORT_SYMBOL(irq_desc); 96EXPORT_SYMBOL(irq_desc);
96 97
97int distribute_irqs = 1; 98int distribute_irqs = 1;
99
100void 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
100int show_interrupts(struct seq_file *p, void *v) 122int 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
53EXPORT_SYMBOL(local_irq_restore);
54#endif
55
52#ifdef CONFIG_PPC32 56#ifdef CONFIG_PPC32
53extern void transfer_to_handler(void); 57extern void transfer_to_handler(void);
54extern void do_IRQ(struct pt_regs *regs); 58extern 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);
19EXPORT_SYMBOL(HvCall5); 19EXPORT_SYMBOL(HvCall5);
20EXPORT_SYMBOL(HvCall6); 20EXPORT_SYMBOL(HvCall6);
21EXPORT_SYMBOL(HvCall7); 21EXPORT_SYMBOL(HvCall7);
22
23#ifdef CONFIG_SMP
24EXPORT_SYMBOL(local_get_flags);
25EXPORT_SYMBOL(local_irq_disable);
26EXPORT_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
13extern void timer_interrupt(struct pt_regs *); 14extern void timer_interrupt(struct pt_regs *);
14 15
15#ifdef CONFIG_PPC_ISERIES 16#ifdef CONFIG_PPC64
17#include <asm/paca.h>
18
19static inline unsigned long local_get_flags(void)
20{
21 return get_paca()->soft_enabled;
22}
23
24static 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
17extern unsigned long local_get_flags(void);
18extern unsigned long local_irq_disable(void);
19extern void local_irq_restore(unsigned long); 32extern void local_irq_restore(unsigned long);
33extern 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 */