Commit 5f0b6ac3 authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman

powerpc/64/syscall: Reconcile interrupts

This reconciles interrupts in the system call case like all other
interrupts. This allows system_call_common to be shared with the scv
system call implementation in a subsequent patch.
Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200225173541.1549955-31-npiggin@gmail.com
parent 702f0980
...@@ -119,6 +119,17 @@ END_BTB_FLUSH_SECTION ...@@ -119,6 +119,17 @@ END_BTB_FLUSH_SECTION
ld r11,exception_marker@toc(r2) ld r11,exception_marker@toc(r2)
std r11,-16(r10) /* "regshere" marker */ std r11,-16(r10) /* "regshere" marker */
/*
* RECONCILE_IRQ_STATE without calling trace_hardirqs_off(), which
* would clobber syscall parameters. Also we always enter with IRQs
* enabled and nothing pending. system_call_exception() will call
* trace_hardirqs_off().
*/
li r11,IRQS_ALL_DISABLED
li r12,PACA_IRQ_HARD_DIS
stb r11,PACAIRQSOFTMASK(r13)
stb r12,PACAIRQHAPPENED(r13)
/* Calling convention has r9 = orig r0, r10 = regs */ /* Calling convention has r9 = orig r0, r10 = regs */
mr r9,r0 mr r9,r0
bl system_call_exception bl system_call_exception
......
...@@ -17,13 +17,19 @@ ...@@ -17,13 +17,19 @@
typedef long (*syscall_fn)(long, long, long, long, long, long); typedef long (*syscall_fn)(long, long, long, long, long, long);
/* Has to run notrace because it is entered "unreconciled" */ /* Has to run notrace because it is entered not completely "reconciled" */
notrace long system_call_exception(long r3, long r4, long r5, long r6, long r7, long r8, notrace long system_call_exception(long r3, long r4, long r5,
long r6, long r7, long r8,
unsigned long r0, struct pt_regs *regs) unsigned long r0, struct pt_regs *regs)
{ {
unsigned long ti_flags; unsigned long ti_flags;
syscall_fn f; syscall_fn f;
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
BUG_ON(irq_soft_mask_return() != IRQS_ALL_DISABLED);
trace_hardirqs_off(); /* finish reconciling */
if (IS_ENABLED(CONFIG_PPC_BOOK3S)) if (IS_ENABLED(CONFIG_PPC_BOOK3S))
BUG_ON(!(regs->msr & MSR_RI)); BUG_ON(!(regs->msr & MSR_RI));
BUG_ON(!(regs->msr & MSR_PR)); BUG_ON(!(regs->msr & MSR_PR));
...@@ -44,16 +50,6 @@ notrace long system_call_exception(long r3, long r4, long r5, long r6, long r7, ...@@ -44,16 +50,6 @@ notrace long system_call_exception(long r3, long r4, long r5, long r6, long r7,
kuap_check_amr(); kuap_check_amr();
/*
* A syscall should always be called with interrupts enabled
* so we just unconditionally hard-enable here. When some kind
* of irq tracing is used, we additionally check that condition
* is correct
*/
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) {
WARN_ON(irq_soft_mask_return() != IRQS_ENABLED);
WARN_ON(local_paca->irq_happened);
}
/* /*
* This is not required for the syscall exit path, but makes the * This is not required for the syscall exit path, but makes the
* stack frame look nicer. If this was initialised in the first stack * stack frame look nicer. If this was initialised in the first stack
...@@ -62,7 +58,7 @@ notrace long system_call_exception(long r3, long r4, long r5, long r6, long r7, ...@@ -62,7 +58,7 @@ notrace long system_call_exception(long r3, long r4, long r5, long r6, long r7,
*/ */
regs->softe = IRQS_ENABLED; regs->softe = IRQS_ENABLED;
__hard_irq_enable(); local_irq_enable();
ti_flags = current_thread_info()->flags; ti_flags = current_thread_info()->flags;
if (unlikely(ti_flags & _TIF_SYSCALL_DOTRACE)) { if (unlikely(ti_flags & _TIF_SYSCALL_DOTRACE)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment