Re: [RFC PATCH 27/27] powerpc/64s: system call support for scv/rfscv instructions
From: Michal Suchánek <hidden>
Date: 2019-10-02 08:26:41
On Sun, Sep 15, 2019 at 11:28:13AM +1000, Nicholas Piggin wrote:
Add support for the scv instruction on POWER9 and later CPUs. For now this implements the zeroth scv vector 'scv 0', as identical to 'sc' system calls, with the exception that lr is not preserved, and it is 64-bit only. There may yet be changes made to this ABI, so it's for testing only. This also doesn't yet properly handle PR KVM, or the case where a guest is denied AIL=3 mode. I haven't added real mode entry points, so scv must not be used when AIL=0, but I haven't cleared the FSCR in this case. This also implements a strange hack to handle the non-implemented vectors, scheduling a decrementer and expecting it to interrupt and replay pending soft masked interrupts. This is unlikely to be a good idea, and needs to actually do a proper handler and replay in case an interrupt is pending. It may also require some errata handling before it can be safely used on all POWER9 CPUs, I have to look that up. rfscv is implemented to return from scv type system calls. It can not be used to return from sc system calls because those are defined to preserve lr. In a comparison of getpid syscall, the test program had scv taking about 3 more cycles in user mode (92 vs 89 for sc), due to lr handling. Total cycles taken for a getpid system call on POWER9 are improved from 436 to 345 (26.3% faster), mostly due to reducing mtmsr and mtspr.
...
quoted hunk ↗ jump to hunk
diff --git a/arch/powerpc/kernel/syscall_64.c b/arch/powerpc/kernel/syscall_64.c index 034b52d3d78c..3e8aa5ae8ec8 100644 --- a/arch/powerpc/kernel/syscall_64.c +++ b/arch/powerpc/kernel/syscall_64.c@@ -15,6 +15,77 @@ extern void __noreturn tabort_syscall(void); typedef long (*syscall_fn)(long, long, long, long, long, long); +#ifdef CONFIG_PPC_BOOK3S +long system_call_vectored_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_RI)); + BUG_ON(!(regs->msr & MSR_PR)); + BUG_ON(!FULL_REGS(regs)); + BUG_ON(regs->softe != IRQS_ENABLED); + + 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))
This adds another instance of the lack of endian conversion issue.
+ accumulate_stolen_time(); + } +#endif
Thanks Michal