[PATCH 4/4] powerpc/64: system call implement the bulk of the logic in C
Nicholas Piggin
npiggin at gmail.com
Tue Aug 27 20:30:15 AEST 2019
Christophe Leroy's on August 27, 2019 4:46 pm:
>
>
> Le 27/08/2019 à 05:30, Nicholas Piggin a écrit :
>> 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 a relatively simple test to see whether all GPRs should be
>> restored at exit time.
>>
>> 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.
>
> Interesting optimisation.
>
>>
>> The asm instruction scheduling has not really been analysed and
>> optimised yet, as there are higher level features and improvements to
>> add first.
>>
>> Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
>> ---
>> arch/powerpc/include/asm/asm-prototypes.h | 11 -
>> arch/powerpc/include/asm/ptrace.h | 3 +
>> arch/powerpc/include/asm/signal.h | 2 +
>> arch/powerpc/include/asm/switch_to.h | 4 +
>> arch/powerpc/include/asm/time.h | 3 +
>> arch/powerpc/kernel/Makefile | 3 +-
>> arch/powerpc/kernel/entry_64.S | 343 ++++------------------
>> arch/powerpc/kernel/process.c | 6 +-
>> arch/powerpc/kernel/signal.h | 2 -
>> arch/powerpc/kernel/syscall_64.c | 202 +++++++++++++
>> 10 files changed, 271 insertions(+), 308 deletions(-)
>> create mode 100644 arch/powerpc/kernel/syscall_64.c
>>
>
> [...]
>
>> diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
>> index 24621e7e5033..f444525da9ce 100644
>> --- a/arch/powerpc/kernel/process.c
>> +++ b/arch/powerpc/kernel/process.c
>> @@ -1609,7 +1609,6 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long usp,
>> extern void ret_from_kernel_thread(void);
>> void (*f)(void);
>> unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
>> - struct thread_info *ti = task_thread_info(p);
>>
>> klp_init_thread_info(p);
>>
>> @@ -1617,6 +1616,8 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long usp,
>> sp -= sizeof(struct pt_regs);
>> childregs = (struct pt_regs *) sp;
>> if (unlikely(p->flags & PF_KTHREAD)) {
>> + struct thread_info *ti = task_thread_info(p);
>> +
>> /* kernel thread */
>> memset(childregs, 0, sizeof(struct pt_regs));
>> childregs->gpr[1] = sp + sizeof(struct pt_regs);
>> @@ -1634,12 +1635,13 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long usp,
>> } else {
>> /* user thread */
>> struct pt_regs *regs = current_pt_regs();
>> +
>> CHECK_FULL_REGS(regs);
>> *childregs = *regs;
>> if (usp)
>> childregs->gpr[1] = usp;
>> p->thread.regs = childregs;
>> - childregs->gpr[3] = 0; /* Result from fork() */
>> + /* ret_from_fork sets fork() result to 0 */
>
> Does PPC32 ret_from_fork() do it as well ?
AFAICT it does, but I guess it should be a patch by itself
with powerpc: prefix. I will split it out.
>> +#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
>> +static inline void account_cpu_user_entry(void)
>> +{
>> + unsigned long tb = mftb();
>> +
>> + local_paca->accounting.utime += (tb - local_paca->accounting.starttime_user);
>> + local_paca->accounting.starttime = tb;
>> +}
>> +static inline void account_cpu_user_exit(void)
>> +{
>> + unsigned long tb = mftb();
>> +
>> + local_paca->accounting.stime += (tb - local_paca->accounting.starttime);
>> + local_paca->accounting.starttime_user = tb;
>> +}
>> +#else
>> +static inline void account_cpu_user_entry(void)
>> +{
>> +}
>> +static inline void account_cpu_user_exit(void)
>> +{
>> +}
>> +#endif
>
> I think this block should go in arch/powerpc/include/asm/cputime.h, we
> should limit #ifdefs as much as possible in C files.
>
> And use get_accounting() instead of local_paca->accounting in order to
> be usable on PPC32 as well
Sure thing. I need to move them for other interrupt return in C as
well.
>> +
>> +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));
>> +
>> +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
>> + if (unlikely(regs->msr & MSR_TS_T))
>> + tabort_syscall();
>> +#endif
>
> MSR_TS_T and tabort_syscall() are declared regardless of
> CONFIG_PPC_TRANSACTIONAL_MEM so IS_ENABLED(CONFIG_PPC_TRANSACTIONAL_MEM)
> should be used instead of #ifdef
Will do.
>> +#if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE) && defined(CONFIG_PPC_SPLPAR)
>> + if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
>> + struct lppaca *lp = get_lppaca();
>> +
>> + if (unlikely(local_paca->dtl_ridx != lp->dtl_idx))
>> + accumulate_stolen_time();
>> + }
>> +#endif
>
> Same here, I think everything is available so IS_ENABLED() should be
> used instead of #if
Will do.
>> +
>> +#ifdef CONFIG_PPC_KUAP_DEBUG
>> + if (mmu_has_feature(MMU_FTR_RADIX_KUAP))
>> + WARN_ON_ONCE(mfspr(SPRN_AMR) != AMR_KUAP_BLOCKED);
>> +#endif
>
> This should go in a helper in one of the kup/kuap header files.
Will do.
>> +
>> + /*
>> + * 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 defined(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)
>> + WARN_ON(irq_soft_mask_return() != IRQS_ENABLED);
>> + WARN_ON(local_paca->irq_happened);
>> +#endif
>
> Can we use IS_ENABLED() here as well ?
I think so.
>> +#ifdef CONFIG_ALTIVEC
>> + if ((regs->msr & (MSR_FP|MSR_VEC)) != (MSR_FP|MSR_VEC))
>> +#else
>> + if ((regs->msr & MSR_FP) != MSR_FP)
>> +#endif
>
> Use 'if (IS_ENABLED(CONFIG_ALTIVEC)) / else' instead of an
> #ifdef/#else/#endif
Yeah that'll be nicer.
>> +#ifdef CONFIG_PPC_KUAP_DEBUG
>> + if (mmu_has_feature(MMU_FTR_RADIX_KUAP))
>> + WARN_ON_ONCE(mfspr(SPRN_AMR) != AMR_KUAP_BLOCKED);
>> +#endif
>
> Same, define a helper in the kuap header files to avoid the #ifdefs and
> platform specif stuff here.
Will do. Thanks for the quick review.
Thanks,
Nick
More information about the Linuxppc-dev
mailing list