diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
index 9ba445de989d..f492a7779ea3 100644
--- a/arch/powerpc/include/asm/hw_irq.h
+++ b/arch/powerpc/include/asm/hw_irq.h
@@ -22,6 +22,7 @@
  * and allow a proper replay. Additionally, PACA_IRQ_HARD_DIS
  * is set whenever we manually hard disable.
  */
+#ifdef CONFIG_PPC_BOOK3E
 #define PACA_IRQ_HARD_DIS	0x01
 #define PACA_IRQ_DBELL		0x02
 #define PACA_IRQ_EE		0x04
@@ -30,14 +31,22 @@
 #define PACA_IRQ_HMI		0x20
 #define PACA_IRQ_PMI		0x40
 
+#else /* CONFIG_PPC_BOOK3E */
 /*
- * 64s uses r14 rather than paca for irq_soft_mask
+ * 64s uses r14 rather than paca for irq_soft_mask and irq_happened
  */
-#ifdef CONFIG_PPC_BOOK3S
+
+#define PACA_IRQ_HARD_DIS	(0x01 << R14_BIT_IRQ_HAPPENED_SHIFT)
+#define PACA_IRQ_DBELL		(0x02 << R14_BIT_IRQ_HAPPENED_SHIFT)
+#define PACA_IRQ_EE		(0x04 << R14_BIT_IRQ_HAPPENED_SHIFT)
+#define PACA_IRQ_DEC		(0x08 << R14_BIT_IRQ_HAPPENED_SHIFT)
+#define PACA_IRQ_HMI		(0x10 << R14_BIT_IRQ_HAPPENED_SHIFT)
+#define PACA_IRQ_PMI		(0x20 << R14_BIT_IRQ_HAPPENED_SHIFT)
+
 #define IRQ_SOFT_MASK_STD	(0x01 << R14_BIT_IRQ_SOFT_MASK_SHIFT)
 #define IRQ_SOFT_MASK_PMU	(0x02 << R14_BIT_IRQ_SOFT_MASK_SHIFT)
 #define IRQ_SOFT_MASK_ALL	(0x03 << R14_BIT_IRQ_SOFT_MASK_SHIFT)
-#endif /* CONFIG_PPC_BOOK3S */
+#endif /* CONFIG_PPC_BOOK3E */
 
 #endif /* CONFIG_PPC64 */
 
@@ -206,14 +215,14 @@ static inline bool arch_irqs_disabled(void)
 	unsigned long flags;						\
 	__hard_irq_disable();						\
 	flags = irq_soft_mask_set_return(IRQ_SOFT_MASK_ALL);		\
-	local_paca->irq_happened |= PACA_IRQ_HARD_DIS;			\
+	r14_set_bits(PACA_IRQ_HARD_DIS);				\
 	if (!arch_irqs_disabled_flags(flags))				\
 		trace_hardirqs_off();					\
 } while(0)
 
 static inline bool lazy_irq_pending(void)
 {
-	return !!(get_paca()->irq_happened & ~PACA_IRQ_HARD_DIS);
+	return !!(local_r14 & R14_BIT_IRQ_HAPPENED_MASK & ~PACA_IRQ_HARD_DIS);
 }
 
 /*
@@ -223,8 +232,8 @@ static inline bool lazy_irq_pending(void)
  */
 static inline void may_hard_irq_enable(void)
 {
-	get_paca()->irq_happened &= ~PACA_IRQ_HARD_DIS;
-	if (!(get_paca()->irq_happened & PACA_IRQ_EE))
+	r14_clear_bits(PACA_IRQ_HARD_DIS);
+	if (!(local_r14 & PACA_IRQ_EE))
 		__hard_irq_enable();
 }
 
diff --git a/arch/powerpc/include/asm/irqflags.h b/arch/powerpc/include/asm/irqflags.h
index 19a2752868f8..140e51b9f436 100644
--- a/arch/powerpc/include/asm/irqflags.h
+++ b/arch/powerpc/include/asm/irqflags.h
@@ -45,26 +45,21 @@
  *
  * NB: This may call C code, so the caller must be prepared for volatiles to
  * be clobbered.
+ * XXX: could make this single-register now
  */
-#define RECONCILE_IRQ_STATE(__rA, __rB)		\
-	lbz	__rB,PACAIRQHAPPENED(r13);	\
-	andi.	__rA,r14,IRQ_SOFT_MASK_STD;	\
-	ori	r14,r14,IRQ_SOFT_MASK_STD;	\
-	ori	__rB,__rB,PACA_IRQ_HARD_DIS;	\
-	stb	__rB,PACAIRQHAPPENED(r13);	\
-	bne	44f;				\
-	TRACE_DISABLE_INTS;			\
+#define RECONCILE_IRQ_STATE(__rA, __rB)					\
+	andi.	__rA,r14,IRQ_SOFT_MASK_STD;				\
+	ori	r14,r14,(PACA_IRQ_HARD_DIS | IRQ_SOFT_MASK_STD);	\
+	bne	44f;							\
+	TRACE_DISABLE_INTS;						\
 44:
 
 #else
 #define TRACE_ENABLE_INTS
 #define TRACE_DISABLE_INTS
 
-#define RECONCILE_IRQ_STATE(__rA, __rB)		\
-	lbz	__rA,PACAIRQHAPPENED(r13);	\
-	ori	r14,r14,IRQ_SOFT_MASK_STD;	\
-	ori	__rA,__rA,PACA_IRQ_HARD_DIS;	\
-	stb	__rA,PACAIRQHAPPENED(r13)
+#define RECONCILE_IRQ_STATE(__rA, __rB)					\
+	ori	r14,r14,(PACA_IRQ_HARD_DIS | IRQ_SOFT_MASK_STD)
 #endif
 #endif
 
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 028b7cefe089..45202e124003 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -869,10 +869,10 @@ static inline void kvmppc_fix_ee_before_entry(void)
 	 * To avoid races, the caller must have gone directly from having
 	 * interrupts fully-enabled to hard-disabled.
 	 */
-	WARN_ON(local_paca->irq_happened != PACA_IRQ_HARD_DIS);
+	WARN_ON((local_r14 & R14_BIT_IRQ_HAPPENED_MASK) != PACA_IRQ_HARD_DIS);
 
 	/* Only need to enable IRQs by hard enabling them after this */
-	local_paca->irq_happened = 0;
+	r14_clear_bits(R14_BIT_IRQ_HAPPENED_MASK);
 	__irq_soft_mask_clear(IRQ_SOFT_MASK_ALL);
 #endif
 }
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index dbf80fff2f53..4edfcdecb268 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -38,8 +38,10 @@ register struct paca_struct *local_paca asm("r13");
 
 #define R14_BIT_IRQ_SOFT_MASK_SHIFT	0
 #define R14_BIT_IRQ_SOFT_MASK		(0x3 << R14_BIT_IRQ_SOFT_MASK_SHIFT)
-#define R14_BIT_IO_SYNC			0x0004
-#define R14_BIT_IRQ_WORK_PENDING	0x0008 /* IRQ_WORK interrupt while soft-disable */
+#define R14_BIT_IRQ_HAPPENED_SHIFT	2
+#define R14_BIT_IRQ_HAPPENED_MASK	(0x3f << R14_BIT_IRQ_HAPPENED_SHIFT) /* irq happened while soft-disabled */
+#define R14_BIT_IO_SYNC			0x0100
+#define R14_BIT_IRQ_WORK_PENDING	0x0200 /* IRQ_WORK interrupt while soft-disable */
 
 /*
  * The top 32-bits of r14 is used as the per-cpu offset, shifted by PAGE_SHIFT.
@@ -224,7 +226,6 @@ struct paca_struct {
 	u64 saved_r1;			/* r1 save for RTAS calls or PM */
 	u64 saved_msr;			/* MSR saved here by enter_rtas */
 	u16 trap_save;			/* Used when bad stack is encountered */
-	u8 irq_happened;		/* irq happened while soft-disabled */
 	u8 nap_state_lost;		/* NV GPR values lost in power7_idle */
 	u64 sprg_vdso;			/* Saved user-visible sprg */
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index c5c005d354b0..2f03f778baf2 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -88,6 +88,14 @@ int main(void)
 	DEFINE(IRQ_SOFT_MASK_STD, IRQ_SOFT_MASK_STD);
 	DEFINE(IRQ_SOFT_MASK_PMU, IRQ_SOFT_MASK_PMU);
 	DEFINE(IRQ_SOFT_MASK_ALL, IRQ_SOFT_MASK_ALL);
+	DEFINE(R14_BIT_IRQ_HAPPENED_SHIFT, R14_BIT_IRQ_HAPPENED_SHIFT);
+	DEFINE(R14_BIT_IRQ_HAPPENED_MASK, R14_BIT_IRQ_HAPPENED_MASK);
+	DEFINE(PACA_IRQ_HARD_DIS, PACA_IRQ_HARD_DIS);
+	DEFINE(PACA_IRQ_EE, PACA_IRQ_EE);
+	DEFINE(PACA_IRQ_DBELL, PACA_IRQ_DBELL);
+	DEFINE(PACA_IRQ_DEC, PACA_IRQ_DEC);
+	DEFINE(PACA_IRQ_HMI, PACA_IRQ_HMI);
+	DEFINE(PACA_IRQ_PMI, PACA_IRQ_PMI);
 
 	OFFSET(TASKTHREADPPR, task_struct, thread.ppr);
 #else
@@ -184,7 +192,6 @@ int main(void)
 	OFFSET(PACATOC, paca_struct, kernel_toc);
 	OFFSET(PACAKBASE, paca_struct, kernelbase);
 	OFFSET(PACAKMSR, paca_struct, kernel_msr);
-	OFFSET(PACAIRQHAPPENED, paca_struct, irq_happened);
 #ifdef CONFIG_PPC_BOOK3S
 	OFFSET(PACACONTEXTID, paca_struct, mm_ctx_id);
 #ifdef CONFIG_PPC_MM_SLICES
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index dd06f8f874f3..33e596d587fb 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -805,8 +805,7 @@ restore:
 	 * at this point). We check if there's anything that needs to
 	 * be replayed first.
 	 */
-	lbz	r0,PACAIRQHAPPENED(r13)
-	cmpwi	cr0,r0,0
+	andi.	r0,r14,R14_BIT_IRQ_HAPPENED_MASK
 	bne-	.Lrestore_check_irq_replay
 
 	/*
@@ -919,16 +918,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
 	 */
 .Lrestore_irq_off:
 	ld	r3,_MSR(r1)
-	lbz	r7,PACAIRQHAPPENED(r13)
+	ori	r14,r14,IRQ_SOFT_MASK_STD
 	andi.	r0,r3,MSR_EE
 	beq	1f
-	rlwinm	r7,r7,0,~PACA_IRQ_HARD_DIS
-	stb	r7,PACAIRQHAPPENED(r13)
+	li	r0,PACA_IRQ_HARD_DIS
+	andc	r14,r14,r0
 1:
 #if defined(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG) && defined(CONFIG_BUG)
 	/* The interrupt should not have soft enabled. */
-	lbz	r7,PACAIRQSOFTMASK(r13)
-	tdeqi	r7,IRQ_SOFT_MASK_NONE
+	andi.	r7,r14,R14_BIT_IRQ_SOFT_MASK
+1:	tdeqi	r7,0
 	EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,BUGFLAG_WARNING
 #endif
 	b	.Ldo_restore
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index ca962bf85b8a..4da2b586e29e 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1404,9 +1404,7 @@ EXC_COMMON_BEGIN(soft_nmi_common)
  */
 #define MASKED_INTERRUPT(_H)				\
 masked_##_H##interrupt:					\
-	lbz	r11,PACAIRQHAPPENED(r13);		\
-	or	r11,r11,r10;				\
-	stb	r11,PACAIRQHAPPENED(r13);		\
+	or	r14,r14,r10;				\
 	cmpwi	r10,PACA_IRQ_DEC;			\
 	bne	1f;					\
 	lis	r10,0x7fff;				\
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index cdb710f43681..60de1aa6ef85 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -767,10 +767,7 @@ _GLOBAL(pmac_secondary_start)
 	/* Mark interrupts soft and hard disabled (they might be enabled
 	 * in the PACA when doing hotplug)
 	 */
-	li	r0,IRQ_SOFT_MASK_STD
-	stb	r0,PACAIRQSOFTMASK(r13)
-	li	r0,PACA_IRQ_HARD_DIS
-	stb	r0,PACAIRQHAPPENED(r13)
+	ori	r14,r14,(IRQ_SOFT_MASK_STD | PACA_IRQ_HARD_DIS)
 
 	/* Create a temp kernel stack for use before relocation is on.	*/
 	ld	r1,PACAEMERGSP(r13)
@@ -824,10 +821,7 @@ __secondary_start:
 	/* Mark interrupts soft and hard disabled (they might be enabled
 	 * in the PACA when doing hotplug)
 	 */
-	li	r7,IRQ_SOFT_MASK_STD
-	stb	r7,PACAIRQSOFTMASK(r13)
-	li	r0,PACA_IRQ_HARD_DIS
-	stb	r0,PACAIRQHAPPENED(r13)
+	ori	r14,r14,(IRQ_SOFT_MASK_STD | PACA_IRQ_HARD_DIS)
 
 	/* enable MMU and jump to start_secondary */
 	LOAD_REG_ADDR(r3, start_secondary_prolog)
@@ -991,10 +985,7 @@ start_here_common:
 	/* Mark interrupts soft and hard disabled (they might be enabled
 	 * in the PACA when doing hotplug)
 	 */
-	li	r0,IRQ_SOFT_MASK_STD
-	stb	r0,PACAIRQSOFTMASK(r13)
-	li	r0,PACA_IRQ_HARD_DIS
-	stb	r0,PACAIRQHAPPENED(r13)
+	ori	r14,r14,(IRQ_SOFT_MASK_STD | PACA_IRQ_HARD_DIS)
 
 	/* Generic kernel entry */
 	bl	start_kernel
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 2341029653e4..ebaf210a7406 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -99,12 +99,7 @@ int distribute_irqs = 1;
 
 static inline notrace unsigned long get_irq_happened(void)
 {
-	unsigned long happened;
-
-	__asm__ __volatile__("lbz %0,%1(13)"
-	: "=r" (happened) : "i" (offsetof(struct paca_struct, irq_happened)));
-
-	return happened;
+	return local_r14 & R14_BIT_IRQ_HAPPENED_MASK;
 }
 
 static inline notrace int decrementer_check_overflow(void)
@@ -131,13 +126,6 @@ static inline notrace int decrementer_check_overflow(void)
  */
 notrace unsigned int __check_irq_replay(void)
 {
-	/*
-	 * We use local_paca rather than get_paca() to avoid all
-	 * the debug_smp_processor_id() business in this low level
-	 * function
-	 */
-	unsigned char happened = local_paca->irq_happened;
-
 	/*
 	 * We are responding to the next interrupt, so interrupt-off
 	 * latencies should be reset here.
@@ -145,20 +133,17 @@ notrace unsigned int __check_irq_replay(void)
 	trace_hardirqs_on();
 	trace_hardirqs_off();
 
-	if (happened & PACA_IRQ_HARD_DIS) {
+	if (local_r14 & PACA_IRQ_HARD_DIS) {
 		/* Clear bit 0 which we wouldn't clear otherwise */
-		local_paca->irq_happened &= ~PACA_IRQ_HARD_DIS;
-
+		r14_clear_bits(PACA_IRQ_HARD_DIS);
 		/*
 		 * We may have missed a decrementer interrupt if hard disabled.
 		 * Check the decrementer register in case we had a rollover
 		 * while hard disabled.
 		 */
-		if (!(happened & PACA_IRQ_DEC)) {
-			if (decrementer_check_overflow()) {
-				local_paca->irq_happened |= PACA_IRQ_DEC;
-				happened |= PACA_IRQ_DEC;
-			}
+		if (!(local_r14 & PACA_IRQ_DEC)) {
+			if (decrementer_check_overflow())
+				r14_set_bits(PACA_IRQ_DEC);
 		}
 	}
 
@@ -176,23 +161,24 @@ notrace unsigned int __check_irq_replay(void)
 	 * This is a higher priority interrupt than the others, so
 	 * replay it first.
 	 */
-	if (happened & PACA_IRQ_HMI) {
-		local_paca->irq_happened &= ~PACA_IRQ_HMI;
+	if (local_r14 & PACA_IRQ_HMI) {
+		r14_clear_bits(PACA_IRQ_HMI);
 		return 0xe60;
 	}
 
-	if (happened & PACA_IRQ_DEC) {
-		local_paca->irq_happened &= ~PACA_IRQ_DEC;
+	if (local_r14 & PACA_IRQ_DEC) {
+		r14_clear_bits(PACA_IRQ_DEC);
 		return 0x900;
 	}
 
-	if (happened & PACA_IRQ_PMI) {
-		local_paca->irq_happened &= ~PACA_IRQ_PMI;
+	if (local_r14 & PACA_IRQ_PMI) {
+		r14_clear_bits(PACA_IRQ_PMI);
 		return 0xf00;
 	}
 
-	if (happened & PACA_IRQ_EE) {
-		local_paca->irq_happened &= ~PACA_IRQ_EE;
+	/* Finally check if an external interrupt happened */
+	if (local_r14 & PACA_IRQ_EE) {
+		r14_clear_bits(PACA_IRQ_EE);
 		return 0x500;
 	}
 
@@ -212,14 +198,14 @@ notrace unsigned int __check_irq_replay(void)
 		return 0x280;
 	}
 #else
-	if (happened & PACA_IRQ_DBELL) {
-		local_paca->irq_happened &= ~PACA_IRQ_DBELL;
+	if (local_r14 & PACA_IRQ_DBELL) {
+		r14_clear_bits(PACA_IRQ_DBELL);
 		return 0xa00;
 	}
 #endif /* CONFIG_PPC_BOOK3E */
 
 	/* There should be nothing left ! */
-	BUG_ON(local_paca->irq_happened != 0);
+	BUG_ON((local_r14 & R14_BIT_IRQ_HAPPENED_MASK) != 0);
 
 	return 0;
 }
@@ -321,7 +307,7 @@ EXPORT_SYMBOL(arch_local_irq_restore);
 void notrace restore_interrupts(void)
 {
 	if (irqs_disabled()) {
-		local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
+		r14_set_bits(PACA_IRQ_HARD_DIS);
 		local_irq_enable();
 	} else
 		__hard_irq_enable();
@@ -349,7 +335,7 @@ bool prep_irq_for_idle(void)
 	 * occurs before we effectively enter the low power state
 	 */
 	__hard_irq_disable();
-	local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
+	r14_set_bits(PACA_IRQ_HARD_DIS);
 
 	/*
 	 * If anything happened while we were soft-disabled,
@@ -367,7 +353,7 @@ bool prep_irq_for_idle(void)
 	 * are about to hard enable as well as a side effect
 	 * of entering the low power state.
 	 */
-	local_paca->irq_happened &= ~PACA_IRQ_HARD_DIS;
+	r14_clear_bits(PACA_IRQ_HARD_DIS);
 	__irq_soft_mask_clear(IRQ_SOFT_MASK_ALL);
 
 	/* Tell the caller to enter the low power state */
@@ -390,7 +376,7 @@ bool prep_irq_for_idle_irqsoff(void)
 	 * occurs before we effectively enter the low power state
 	 */
 	__hard_irq_disable();
-	local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
+	r14_set_bits(PACA_IRQ_HARD_DIS);
 
 	/*
 	 * If anything happened while we were soft-disabled,
@@ -465,7 +451,7 @@ void irq_set_pending_from_srr1(unsigned long srr1)
 	 * If a future CPU was to designate this as an interrupt reason,
 	 * then a new index for no interrupt must be assigned.
 	 */
-	local_paca->irq_happened |= reason;
+	r14_set_bits(reason);
 }
 #endif /* CONFIG_PPC_BOOK3S */
 
@@ -481,7 +467,7 @@ void force_external_irq_replay(void)
 	WARN_ON(!arch_irqs_disabled());
 
 	/* Indicate in the PACA that we have an interrupt to replay */
-	local_paca->irq_happened |= PACA_IRQ_EE;
+	r14_set_bits(PACA_IRQ_EE);
 }
 
 #endif /* CONFIG_PPC64 */
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 2d46037ce936..870dd835c8b6 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -2614,13 +2614,13 @@ static void set_irq_happened(int trap)
 {
 	switch (trap) {
 	case BOOK3S_INTERRUPT_EXTERNAL:
-		local_paca->irq_happened |= PACA_IRQ_EE;
+		r14_set_bits(PACA_IRQ_EE);
 		break;
 	case BOOK3S_INTERRUPT_H_DOORBELL:
-		local_paca->irq_happened |= PACA_IRQ_DBELL;
+		r14_set_bits(PACA_IRQ_DBELL);
 		break;
 	case BOOK3S_INTERRUPT_HMI:
-		local_paca->irq_happened |= PACA_IRQ_HMI;
+		r14_set_bits(PACA_IRQ_HMI);
 		break;
 	case BOOK3S_INTERRUPT_SYSTEM_RESET:
 		replay_system_reset();
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index d7d3885035f2..df73f8a1f030 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -1622,8 +1622,7 @@ static void excprint(struct pt_regs *fp)
 
 	printf("  current = 0x%lx\n", current);
 #ifdef CONFIG_PPC64
-	printf("  paca    = 0x%lx\t r14: 0x%lx\t irq_happened: 0x%02x\n",
-	       local_paca, local_r14, local_paca->irq_happened);
+	printf("  paca    = 0x%lx\t r14: %lx\n", local_paca, local_r14);
 #endif
 	if (current) {
 		printf("    pid   = %ld, comm = %s\n",
@@ -2391,7 +2390,6 @@ static void dump_one_paca(int cpu)
 	DUMP(p, stab_rr, "lx");
 	DUMP(p, saved_r1, "lx");
 	DUMP(p, trap_save, "x");
-	DUMP(p, irq_happened, "x");
 	DUMP(p, nap_state_lost, "x");
 	DUMP(p, sprg_vdso, "llx");
 
