[PATCH v2 0/4] powerpc/64: syscalls in C

Nicholas Piggin npiggin at gmail.com
Thu Aug 29 19:38:01 AEST 2019


Christophe Leroy's on August 28, 2019 7:55 pm:
> 
> 
> Le 28/08/2019 à 11:49, Nicholas Piggin a écrit :
>> Christophe Leroy's on August 28, 2019 7:06 pm:
>>>
>>>
>>> Le 27/08/2019 à 15:55, Nicholas Piggin a écrit :
>>>> Accounted for some feedback.
>>>>
>>>> Nicholas Piggin (4):
>>>>     powerpc: convert to copy_thread_tls
>>>>     powerpc/64: remove support for kernel-mode syscalls
>>>>     powerpc/64: system call remove non-volatile GPR save optimisation
>>>>     powerpc/64: system call implement the bulk of the logic in C
>>>
>>> Would it be possible to split in the following parts:
>>>
>>> 1/ Implement in C whatever can be implemented without removing
>>> non-volatile GPR save optimisation
>>> 2/ Remove non-volatile GPR save optimisation
>>> 3/ Implement in C everything else
>> 
>> Hmm. I'll have a look but I would rather not go back and add the
>> intermediate state I was hoping to avoid. I'll think about it and
>> if it's not too difficult I will try to add something. I have an
>> idea.
>> 
>> With your nvregs performance test on ppc32, are you doing the
>> nvgpr restore? The fast path should be able to avoid that.
> 
> I only added the SAVE_NVGPRS call in the syscall entry macro just after 
> the saving of volatile regs, and changed the trap from \trapno+1 to \trapno

So... this actually seems to work. Haven't booted it, but the compiler
seems to do what we want.

This may be the way to go for ppc32 I think. I had a look at various 
ways you could save nvgprs with some early tests and returning early 
from the C call if it hits trouble without all registers saved. Most of 
it becomes quite ugly.

Thanks,
Nick

diff --git a/arch/powerpc/kernel/syscall_64.c b/arch/powerpc/kernel/syscall_64.c
index d42519b86ddd..b11346447882 100644
--- a/arch/powerpc/kernel/syscall_64.c
+++ b/arch/powerpc/kernel/syscall_64.c
@@ -14,6 +14,52 @@ extern void __noreturn tabort_syscall(void);
 
 typedef long (*syscall_fn)(long, long, long, long, long, long);
 
+register unsigned long r31 asm("r31");
+register unsigned long r30 asm("r30");
+register unsigned long r29 asm("r29");
+register unsigned long r28 asm("r28");
+register unsigned long r27 asm("r27");
+register unsigned long r26 asm("r26");
+register unsigned long r25 asm("r25");
+register unsigned long r24 asm("r24");
+register unsigned long r23 asm("r23");
+register unsigned long r22 asm("r22");
+register unsigned long r21 asm("r21");
+register unsigned long r20 asm("r20");
+register unsigned long r19 asm("r19");
+register unsigned long r18 asm("r18");
+register unsigned long r17 asm("r17");
+register unsigned long r16 asm("r16");
+register unsigned long r15 asm("r15");
+register unsigned long r14 asm("r14");
+
+static inline void save_nvgprs(struct pt_regs *regs)
+{
+	if (!(regs->trap & 1))
+		return;
+
+	regs->gpr[14] = r14;
+	regs->gpr[15] = r15;
+	regs->gpr[16] = r16;
+	regs->gpr[17] = r17;
+	regs->gpr[18] = r18;
+	regs->gpr[19] = r19;
+	regs->gpr[20] = r20;
+	regs->gpr[21] = r21;
+	regs->gpr[22] = r22;
+	regs->gpr[23] = r23;
+	regs->gpr[24] = r24;
+	regs->gpr[25] = r25;
+	regs->gpr[26] = r26;
+	regs->gpr[27] = r27;
+	regs->gpr[28] = r28;
+	regs->gpr[29] = r29;
+	regs->gpr[30] = r30;
+	regs->gpr[31] = r31;
+
+	regs->trap &= 0x1;
+}
+
 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;
@@ -66,6 +112,7 @@ long system_call_exception(long r3, long r4, long r5, long r6, long r7, long r8,
 		 * do_syscall_trace_enter() returns an invalid syscall number
 		 * and the test below against NR_syscalls will fail.
 		 */
+		save_nvgprs(regs);
 		r0 = do_syscall_trace_enter(regs);
 	}
 
@@ -132,6 +179,7 @@ unsigned long syscall_exit_prepare(unsigned long r3, struct pt_regs *regs)
 		if (ti_flags & _TIF_NEED_RESCHED) {
 			schedule();
 		} else {
+			save_nvgprs(regs);
 			/*
 			 * SIGPENDING must restore signal handler function
 			 * argument GPRs, and some non-volatiles (e.g., r1).


More information about the Linuxppc-dev mailing list