On Sun, Sep 15, 2019 at 11:28:09AM +1000, Nicholas Piggin wrote: > System call entry and particularly exit code is beyond the limit of what > is reasonable to implement in asm. > > This conversion moves all conditional branches out of the asm code, > except for the case that all GPRs should be restored at exit. > > Null syscall test is about 5% faster after this patch, because the exit > work is handled under local_irq_disable, and the hard mask and pending > interrupt replay is handled after that, which avoids games with MSR. > > Signed-off-by: Nicholas Piggin <npig...@gmail.com> > > v3: > - Fix !KUAP build [mpe] > - Fix BookE build/boot [mpe] > - Don't trace irqs with MSR[RI]=0 > - Don't allow syscall_exit_prepare to be ftraced, because function > graph tracing which traces exits barfs after the IRQ state is > prepared for kernel exit. > - Fix BE syscall table to use normal function descriptors now that they > are called from C. > - Comment syscall_exit_prepare. ... > -#if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE) && defined(CONFIG_PPC_SPLPAR) > -BEGIN_FW_FTR_SECTION > - /* see if there are any DTL entries to process */ > - ld r10,PACALPPACAPTR(r13) /* get ptr to VPA */ > - ld r11,PACA_DTL_RIDX(r13) /* get log read index */ > - addi r10,r10,LPPACA_DTLIDX > - LDX_BE r10,0,r10 /* get log write index */ > - cmpd r11,r10 > - beq+ 33f > - bl accumulate_stolen_time > - REST_GPR(0,r1) > - REST_4GPRS(3,r1) > - REST_2GPRS(7,r1) > - addi r9,r1,STACK_FRAME_OVERHEAD > -33: > -END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) > -#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE && CONFIG_PPC_SPLPAR */ ... > diff --git a/arch/powerpc/kernel/syscall_64.c > b/arch/powerpc/kernel/syscall_64.c > new file mode 100644 > index 000000000000..1d2529824588 > --- /dev/null > +++ b/arch/powerpc/kernel/syscall_64.c > @@ -0,0 +1,195 @@ > +#include <linux/err.h> > +#include <asm/book3s/64/kup-radix.h> > +#include <asm/cputime.h> > +#include <asm/hw_irq.h> > +#include <asm/kprobes.h> > +#include <asm/paca.h> > +#include <asm/ptrace.h> > +#include <asm/reg.h> > +#include <asm/signal.h> > +#include <asm/switch_to.h> > +#include <asm/syscall.h> > +#include <asm/time.h> > + > +extern void __noreturn tabort_syscall(void); > + > +typedef long (*syscall_fn)(long, long, long, long, long, long); > + > +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 ti_flags; > + syscall_fn f; > + > + BUG_ON(!(regs->msr & MSR_PR)); > + > + if (IS_ENABLED(CONFIG_PPC_TRANSACTIONAL_MEM) && > + unlikely(regs->msr & MSR_TS_T)) > + tabort_syscall(); > + > + account_cpu_user_entry(); > + > +#ifdef CONFIG_PPC_SPLPAR > + if (IS_ENABLED(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE) && > + firmware_has_feature(FW_FEATURE_SPLPAR)) { > + struct lppaca *lp = get_lppaca(); > + > + if (unlikely(local_paca->dtl_ridx != lp->dtl_idx))
sparse complains about this, and in time.c this it converted like this: if (unlikely(local_paca->dtl_ridx != be64_to_cpu(lp->dtl_idx))) The removed code has a LDX_BE there so there should be some conversion involved, right? Thanks Michal