Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9b81c021 authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman
Browse files

powerpc/64s: make PACA_IRQ_HARD_DIS track MSR[EE] closely



When the masked interrupt handler clears MSR[EE] for an interrupt in
the PACA_IRQ_MUST_HARD_MASK set, it does not set PACA_IRQ_HARD_DIS.
This makes them get out of synch.

With that taken into account, it's only low level irq manipulation
(and interrupt entry before reconcile) where they can be out of synch.
This makes the code less surprising.

It also allows the IRQ replay code to rely on the IRQ_HARD_DIS value
and not have to mtmsrd again in this case (e.g., for an external
interrupt that has been masked). The bigger benefit might just be
that there is not such an element of surprise in these two bits of
state.

Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 29e8131c
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -253,15 +253,17 @@ static inline bool lazy_irq_pending(void)

/*
 * This is called by asynchronous interrupts to conditionally
 * re-enable hard interrupts when soft-disabled after having
 * cleared the source of the interrupt
 * re-enable hard interrupts after having cleared the source
 * of the interrupt. They are kept disabled if there is a different
 * soft-masked interrupt pending that requires hard masking.
 */
static inline void may_hard_irq_enable(void)
{
	if (!(get_paca()->irq_happened & PACA_IRQ_MUST_HARD_MASK)) {
		get_paca()->irq_happened &= ~PACA_IRQ_HARD_DIS;
	if (!(get_paca()->irq_happened & PACA_IRQ_MUST_HARD_MASK))
		__hard_irq_enable();
	}
}

static inline bool arch_irq_disabled_regs(struct pt_regs *regs)
{
+8 −0
Original line number Diff line number Diff line
@@ -992,6 +992,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
	or	r4,r4,r3
	std	r4,_TRAP(r1)

	/*
	 * PACA_IRQ_HARD_DIS won't always be set here, so set it now
	 * to reconcile the IRQ state. Tracing is already accounted for.
	 */
	lbz	r4,PACAIRQHAPPENED(r13)
	ori	r4,r4,PACA_IRQ_HARD_DIS
	stb	r4,PACAIRQHAPPENED(r13)

	/*
	 * Then find the right handler and call it. Interrupts are
	 * still soft-disabled and we keep them that way.
+4 −0
Original line number Diff line number Diff line
@@ -949,7 +949,11 @@ kernel_dbg_exc:

.macro masked_interrupt_book3e paca_irq full_mask
	lbz	r10,PACAIRQHAPPENED(r13)
	.if \full_mask == 1
	ori	r10,r10,\paca_irq | PACA_IRQ_HARD_DIS
	.else
	ori	r10,r10,\paca_irq
	.endif
	stb	r10,PACAIRQHAPPENED(r13)

	.if \full_mask == 1
+4 −1
Original line number Diff line number Diff line
@@ -1498,7 +1498,10 @@ masked_##_H##interrupt: \
	mfspr	r10,SPRN_##_H##SRR1;			\
	xori	r10,r10,MSR_EE; /* clear MSR_EE */	\
	mtspr	SPRN_##_H##SRR1,r10;			\
2:	mtcrf	0x80,r9;				\
	ori	r11,r11,PACA_IRQ_HARD_DIS;		\
	stb	r11,PACAIRQHAPPENED(r13);		\
2:	/* done */					\
	mtcrf	0x80,r9;				\
	std	r1,PACAR1(r13);				\
	ld	r9,PACA_EXGEN+EX_R9(r13);		\
	ld	r10,PACA_EXGEN+EX_R10(r13);		\
+6 −1
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ _GLOBAL(\name)
	 */
	lbz	r3,PACAIRQHAPPENED(r13)
	cmpwi	cr0,r3,0
	bnelr
	bne	2f

	/* Now we are going to mark ourselves as soft and hard enabled in
	 * order to be able to take interrupts while asleep. We inform lockdep
@@ -72,6 +72,11 @@ _GLOBAL(\name)
	wrteei	1
	\loop

2:
	lbz	r10,PACAIRQHAPPENED(r13)
	ori	r10,r10,PACA_IRQ_HARD_DIS
	stb	r10,PACAIRQHAPPENED(r13)
	blr
.endm

.macro BOOK3E_IDLE_LOOP
Loading