forked from Minki/linux
powerpc/64: Refactor interrupt exit irq disabling sequence
The same complicated sequence for juggling EE, RI, soft mask, and irq tracing is repeated 3 times, tidy these up into one function. This differs qiute a bit between sub architectures, so this makes the ppc32 port cleaner as well. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20200429062421.1675400-1-npiggin@gmail.com
This commit is contained in:
parent
18594f9b8c
commit
0bdad33d6b
@ -101,6 +101,31 @@ notrace long system_call_exception(long r3, long r4, long r5,
|
||||
return f(r3, r4, r5, r6, r7, r8);
|
||||
}
|
||||
|
||||
/*
|
||||
* local irqs must be disabled. Returns false if the caller must re-enable
|
||||
* them, check for new work, and try again.
|
||||
*/
|
||||
static notrace inline bool prep_irq_for_enabled_exit(void)
|
||||
{
|
||||
/* This must be done with RI=1 because tracing may touch vmaps */
|
||||
trace_hardirqs_on();
|
||||
|
||||
/* This pattern matches prep_irq_for_idle */
|
||||
__hard_EE_RI_disable();
|
||||
if (unlikely(lazy_irq_pending_nocheck())) {
|
||||
/* Took an interrupt, may have more exit work to do. */
|
||||
__hard_RI_enable();
|
||||
trace_hardirqs_off();
|
||||
local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
|
||||
|
||||
return false;
|
||||
}
|
||||
local_paca->irq_happened = 0;
|
||||
irq_soft_mask_set(IRQS_ENABLED);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This should be called after a syscall returns, with r3 the return value
|
||||
* from the syscall. If this function returns non-zero, the system call
|
||||
@ -186,21 +211,10 @@ again:
|
||||
}
|
||||
}
|
||||
|
||||
/* This must be done with RI=1 because tracing may touch vmaps */
|
||||
trace_hardirqs_on();
|
||||
|
||||
/* This pattern matches prep_irq_for_idle */
|
||||
__hard_EE_RI_disable();
|
||||
if (unlikely(lazy_irq_pending_nocheck())) {
|
||||
__hard_RI_enable();
|
||||
trace_hardirqs_off();
|
||||
local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
|
||||
if (unlikely(!prep_irq_for_enabled_exit())) {
|
||||
local_irq_enable();
|
||||
/* Took an interrupt, may have more exit work to do. */
|
||||
goto again;
|
||||
}
|
||||
local_paca->irq_happened = 0;
|
||||
irq_soft_mask_set(IRQS_ENABLED);
|
||||
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
local_paca->tm_scratch = regs->msr;
|
||||
@ -264,19 +278,11 @@ again:
|
||||
}
|
||||
}
|
||||
|
||||
trace_hardirqs_on();
|
||||
__hard_EE_RI_disable();
|
||||
if (unlikely(lazy_irq_pending_nocheck())) {
|
||||
__hard_RI_enable();
|
||||
trace_hardirqs_off();
|
||||
local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
|
||||
if (unlikely(!prep_irq_for_enabled_exit())) {
|
||||
local_irq_enable();
|
||||
local_irq_disable();
|
||||
/* Took an interrupt, may have more exit work to do. */
|
||||
goto again;
|
||||
}
|
||||
local_paca->irq_happened = 0;
|
||||
irq_soft_mask_set(IRQS_ENABLED);
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
if (unlikely(ts->debug.dbcr0 & DBCR0_IDM)) {
|
||||
@ -334,13 +340,7 @@ again:
|
||||
}
|
||||
}
|
||||
|
||||
trace_hardirqs_on();
|
||||
__hard_EE_RI_disable();
|
||||
if (unlikely(lazy_irq_pending_nocheck())) {
|
||||
__hard_RI_enable();
|
||||
irq_soft_mask_set(IRQS_ALL_DISABLED);
|
||||
trace_hardirqs_off();
|
||||
local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
|
||||
if (unlikely(!prep_irq_for_enabled_exit())) {
|
||||
/*
|
||||
* Can't local_irq_restore to replay if we were in
|
||||
* interrupt context. Must replay directly.
|
||||
@ -354,8 +354,6 @@ again:
|
||||
/* Took an interrupt, may have more exit work to do. */
|
||||
goto again;
|
||||
}
|
||||
local_paca->irq_happened = 0;
|
||||
irq_soft_mask_set(IRQS_ENABLED);
|
||||
} else {
|
||||
/* Returning to a kernel context with local irqs disabled. */
|
||||
__hard_EE_RI_disable();
|
||||
|
Loading…
Reference in New Issue
Block a user