[PATCH 2/6] powerpc: Provide syscall wrapper

Christophe Leroy christophe.leroy at csgroup.eu
Wed Jun 1 18:29:08 AEST 2022



Le 01/06/2022 à 07:48, Rohan McLure a écrit :
> [Vous ne recevez pas souvent de courriers de la part de rmclure at linux.ibm.com. Découvrez pourquoi cela peut être important à l'adresse https://aka.ms/LearnAboutSenderIdentification.]
> 
> Syscall wrapper implemented as per s390, x86, arm64, providing the
> option for gprs to be cleared on entry to the kernel, reducing caller
> influence influence on speculation within syscall routine. The wrapper
> is a macro that emits syscall handler implementations with parameters
> passed by stack pointer.

Passing parameters by stack is going to be sub-optimal. Did you make any 
measurement of the implied performance degradation ? We usually use the 
null_syscall selftest for that everytime we touch syscall entries/exits.

Why going via stack ? The main advantage of a RISC processor like 
powerpc is that, unlike x86, there are enough registers to avoid going 
through memory. RISC processors are optimised with three operands 
operations and many registers, and usually have slow memory in return.

> 
> For platforms supporting this syscall wrapper, emit symbols with usual
> in-register parameters (`sys...`) to support calls to syscall handlers
> from within the kernel.
> 
> Syscalls are wrapped on all platforms except Cell processor. SPUs require
> access syscall prototypes which are omitted with ARCH_HAS_SYSCALL_WRAPPER
> enabled.
This commit message isn't very clear, please describe in more details 
what is done, how and why.

> 
> Co-developed-by: Andrew Donnellan <ajd at linux.ibm.com>
> Signed-off-by: Andrew Donnellan <ajd at linux.ibm.com>
> Signed-off-by: Rohan McLure <rmclure at linux.ibm.com>
> ---
>   arch/powerpc/Kconfig                       |  1 +
>   arch/powerpc/include/asm/interrupt.h       |  3 +-
>   arch/powerpc/include/asm/syscall_wrapper.h | 92 ++++++++++++++++++++++
>   arch/powerpc/include/asm/syscalls.h        | 83 +++++++++++++------
>   arch/powerpc/kernel/entry_32.S             |  6 +-
>   arch/powerpc/kernel/interrupt.c            | 35 ++++----
>   arch/powerpc/kernel/interrupt_64.S         | 30 +++----
>   arch/powerpc/kernel/sys_ppc32.c            | 50 +++++++-----
>   arch/powerpc/kernel/syscalls.c             | 19 +++--
>   arch/powerpc/kernel/systbl.S               | 21 +++++
>   arch/powerpc/kernel/vdso.c                 |  2 +
>   11 files changed, 255 insertions(+), 87 deletions(-)
>   create mode 100644 arch/powerpc/include/asm/syscall_wrapper.h
> 
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 174edabb74fa..e58287a70061 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -137,6 +137,7 @@ config PPC
>          select ARCH_HAS_STRICT_KERNEL_RWX       if (PPC_BOOK3S || PPC_8xx || 40x) && !HIBERNATION
>          select ARCH_HAS_STRICT_KERNEL_RWX       if FSL_BOOKE && !HIBERNATION && !RANDOMIZE_BASE
>          select ARCH_HAS_STRICT_MODULE_RWX       if ARCH_HAS_STRICT_KERNEL_RWX
> +       select ARCH_HAS_SYSCALL_WRAPPER         if !SPU_BASE
>          select ARCH_HAS_TICK_BROADCAST          if GENERIC_CLOCKEVENTS_BROADCAST
>          select ARCH_HAS_UACCESS_FLUSHCACHE
>          select ARCH_HAS_UBSAN_SANITIZE_ALL
> diff --git a/arch/powerpc/include/asm/interrupt.h b/arch/powerpc/include/asm/interrupt.h
> index f964ef5c57d8..8e8949e4db7a 100644
> --- a/arch/powerpc/include/asm/interrupt.h
> +++ b/arch/powerpc/include/asm/interrupt.h
> @@ -636,8 +636,7 @@ static inline void interrupt_cond_local_irq_enable(struct pt_regs *regs)
>                  local_irq_enable();
>   }
> 
> -long system_call_exception(long r3, long r4, long r5, long r6, long r7, long r8,
> -                          unsigned long r0, struct pt_regs *regs);
> +long system_call_exception(unsigned long r0, struct pt_regs *regs);
>   notrace unsigned long syscall_exit_prepare(unsigned long r3, struct pt_regs *regs, long scv);
>   notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs);
>   notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs);
> diff --git a/arch/powerpc/include/asm/syscall_wrapper.h b/arch/powerpc/include/asm/syscall_wrapper.h
> new file mode 100644
> index 000000000000..23da22b081e4
> --- /dev/null
> +++ b/arch/powerpc/include/asm/syscall_wrapper.h
> @@ -0,0 +1,92 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * syscall_wrapper.h - powerpc specific wrappers to syscall definitions
> + *
> + * Based on arch/{x86,arm64}/include/asm/syscall_wrapper.h
> + */
> +
> +#ifndef __ASM_SYSCALL_WRAPPER_H
> +#define __ASM_SYSCALL_WRAPPER_H
> +
> +struct pt_regs;
> +
> +#define SC_POWERPC_REGS_TO_ARGS(x, ...)                                \
> +       __MAP(x,__SC_ARGS                                       \
> +             ,,regs->gpr[3],,regs->gpr[4],,regs->gpr[5]        \
> +             ,,regs->gpr[6],,regs->gpr[7],,regs->gpr[8])
> +
> +#ifdef CONFIG_COMPAT
> +
> +#define COMPAT_SYSCALL_DEFINEx(x, name, ...)                                           \
> +       asmlinkage long __powerpc_compat_sys##name(const struct pt_regs *regs);         \
> +       ALLOW_ERROR_INJECTION(__powerpc_compat_sys##name, ERRNO);                       \
> +       static long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__));              \
> +       static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));       \
> +       asmlinkage long __powerpc_compat_sys##name(const struct pt_regs *regs)          \
> +       {                                                                               \
> +               return __se_compat_sys##name(SC_POWERPC_REGS_TO_ARGS(x,__VA_ARGS__));   \
> +       }                                                                               \
> +       static long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))               \
> +       {                                                                               \
> +               return __do_compat_sys##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__));        \
> +       }                                                                               \
> +       static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
> +
> +#define COMPAT_SYSCALL_DEFINE0(sname)                                                  \
> +       asmlinkage long __powerpc_compat_sys_##sname(const struct pt_regs *__unused);   \
> +       ALLOW_ERROR_INJECTION(__powerpc_compat_sys_##sname, ERRNO);                     \
> +       asmlinkage long __powerpc_compat_sys_##sname(const struct pt_regs *__unused)
> +
> +#define COND_SYSCALL_COMPAT(name)                                                      \
> +       asmlinkage long __weak __powerpc_compat_sys_##name(const struct pt_regs *regs)  \
> +       {                                                                               \
> +               return sys_ni_syscall();                                                \
> +       }
> +#define COMPAT_SYS_NI(name) \
> +       SYSCALL_ALIAS(__powerpc_compat_sys_##name, sys_ni_posix_timers);
> +
> +#endif /* CONFIG_COMPAT */
> +
> +#define __SYSCALL_DEFINEx(x, name, ...)                                                \
> +       asmlinkage long __powerpc_sys##name(const struct pt_regs *regs);        \
> +       ALLOW_ERROR_INJECTION(__powerpc_sys##name, ERRNO);                      \
> +       long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));                         \
> +       static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__));             \
> +       static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));      \
> +       asmlinkage long __powerpc_sys##name(const struct pt_regs *regs)         \
> +       {                                                                       \
> +               return __se_sys##name(SC_POWERPC_REGS_TO_ARGS(x,__VA_ARGS__));  \
> +       }                                                                       \
> +       long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))                          \
> +       {                                                                       \
> +               return __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));          \
> +       }                                                                       \
> +       static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))              \
> +       {                                                                       \
> +               long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));      \
> +               __MAP(x,__SC_TEST,__VA_ARGS__);                                 \
> +               __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));               \
> +               return ret;                                                     \
> +       }                                                                       \
> +       static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
> +
> +#define SYSCALL_DEFINE0(sname)                                                 \
> +       SYSCALL_METADATA(_##sname, 0);                                          \
> +       long sys_##name(void);                                                  \
> +       asmlinkage long __powerpc_sys_##sname(const struct pt_regs *__unused);  \
> +       ALLOW_ERROR_INJECTION(__powerpc_sys_##sname, ERRNO);                    \
> +       long sys_##sname(void)                                                  \
> +       {                                                                       \
> +               return __powerpc_sys_##sname(NULL);                             \
> +       }                                                                       \
> +       asmlinkage long __powerpc_sys_##sname(const struct pt_regs *__unused)
> +
> +#define COND_SYSCALL(name)                                                     \
> +       asmlinkage long __weak __powerpc_sys_##name(const struct pt_regs *regs) \
> +       {                                                                       \
> +               return sys_ni_syscall();                                        \
> +       }
> +
> +#define SYS_NI(name) SYSCALL_ALIAS(__powerpc_sys_##name, sys_ni_posix_timers);
> +
> +#endif /* __ASM_SYSCALL_WRAPPER_H */
> diff --git a/arch/powerpc/include/asm/syscalls.h b/arch/powerpc/include/asm/syscalls.h
> index a2b13e55254f..75d8e1822caf 100644
> --- a/arch/powerpc/include/asm/syscalls.h
> +++ b/arch/powerpc/include/asm/syscalls.h
> @@ -8,14 +8,47 @@
>   #include <linux/types.h>
>   #include <linux/compat.h>
> 
> +/*
> + * For PowerPC specific syscall implementations, wrapper takes exact name and
> + * return type for a given function.
> + */
> +
> +#ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER
> +#define PPC_SYSCALL_DEFINE(x, type, name, ...)                                 \
> +       asmlinkage type __powerpc_##name(const struct pt_regs *regs);           \
> +       ALLOW_ERROR_INJECTION(__powerpc_##name, ERRNO);                         \
> +       type sys_##name(__MAP(x,__SC_DECL,__VA_ARGS__));                        \
> +       static type __se_##name(__MAP(x,__SC_LONG,__VA_ARGS__));                \
> +       static inline type __do_##name(__MAP(x,__SC_DECL,__VA_ARGS__));         \
> +       asmlinkage type __powerpc_##name(const struct pt_regs *regs)            \
> +       {                                                                       \
> +               return __se_##name(SC_POWERPC_REGS_TO_ARGS(x,__VA_ARGS__));     \
> +       }                                                                       \
> +       type sys_##name(__MAP(x,__SC_DECL,__VA_ARGS__))                         \
> +       {                                                                       \
> +               return __do_##name(__MAP(x,__SC_CAST,__VA_ARGS__));             \
> +       }                                                                       \
> +       static type __se_##name(__MAP(x,__SC_LONG,__VA_ARGS__))                 \
> +       {                                                                       \
> +               type ret = __do_##name(__MAP(x,__SC_CAST,__VA_ARGS__));         \
> +               __MAP(x,__SC_TEST,__VA_ARGS__);                                 \
> +               __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));               \
> +               return ret;                                                     \
> +       }                                                                       \
> +       static inline type __do_##name(__MAP(x,__SC_DECL,__VA_ARGS__))
> +#else
> +#define PPC_SYSCALL_DEFINE(x, type, name, ...)                                 \
> +       type name(__MAP(x,__SC_DECL,__VA_ARGS__))
> +#endif
> +
>   struct rtas_args;
> 
>   asmlinkage long sys_mmap(unsigned long addr, size_t len,
> -               unsigned long prot, unsigned long flags,
> -               unsigned long fd, off_t offset);
> +                        unsigned long prot, unsigned long flags,
> +                        unsigned long fd, off_t offset);

This is a cleanup that is not part of the change. Please move in a 
preparatory patch.


>   asmlinkage long sys_mmap2(unsigned long addr, size_t len,
> -               unsigned long prot, unsigned long flags,
> -               unsigned long fd, unsigned long pgoff);
> +                         unsigned long prot, unsigned long flags,
> +                         unsigned long fd, unsigned long pgoff);

Same.

>   asmlinkage long ppc64_personality(unsigned long personality);
>   asmlinkage long sys_rtas(struct rtas_args __user *uargs);
>   int ppc_select(int n, fd_set __user *inp, fd_set __user *outp,
> @@ -24,32 +57,38 @@ long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low,
>                        u32 len_high, u32 len_low);
> 
>   #ifdef CONFIG_COMPAT
> -unsigned long compat_sys_mmap2(unsigned long addr, size_t len,
> -                              unsigned long prot, unsigned long flags,
> -                              unsigned long fd, unsigned long pgoff);
> +asmlinkage unsigned long compat_sys_mmap2(unsigned long addr, size_t len,
> +                                         unsigned long prot, unsigned long flags,
> +                                         unsigned long fd, unsigned long pgoff);

There was some discussion in the past that asmlinkage is useless. Is 
that change and the ones below really necessary ?

If really needed, is that directly linked to this patch or should it be 
in a preparation patch ?

> 
> -compat_ssize_t compat_sys_pread64(unsigned int fd, char __user *ubuf, compat_size_t count,
> -                                 u32 reg6, u32 pos1, u32 pos2);
> +asmlinkage compat_ssize_t compat_sys_pread64(unsigned int fd, char __user *ubuf,
> +                                            compat_size_t count,
> +                                            u32 reg6, u32 pos1, u32 pos2);
> 
> -compat_ssize_t compat_sys_pwrite64(unsigned int fd, const char __user *ubuf, compat_size_t count,
> -                                  u32 reg6, u32 pos1, u32 pos2);
> +asmlinkage compat_ssize_t compat_sys_pwrite64(unsigned int fd, const char __user *ubuf,
> +                                             compat_size_t count,
> +                                             u32 reg6, u32 pos1, u32 pos2);
> 
> -compat_ssize_t compat_sys_readahead(int fd, u32 r4, u32 offset1, u32 offset2, u32 count);
> +asmlinkage compat_ssize_t compat_sys_readahead(int fd, u32 r4, u32 offset1,
> +                                              u32 offset2, u32 count);
> 
> -int compat_sys_truncate64(const char __user *path, u32 reg4,
> -                         unsigned long len1, unsigned long len2);
> +asmlinkage int compat_sys_truncate64(const char __user *path, u32 reg4,
> +                                    unsigned long len1, unsigned long len2);
> 
> -long compat_sys_fallocate(int fd, int mode, u32 offset1, u32 offset2, u32 len1, u32 len2);
> +asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offset1,
> +                                    u32 offset2, u32 len1, u32 len2);
> 
> -int compat_sys_ftruncate64(unsigned int fd, u32 reg4, unsigned long len1,
> -                          unsigned long len2);
> +asmlinkage int compat_sys_ftruncate64(unsigned int fd, u32 reg4,
> +                                     unsigned long len1, unsigned long len2);
> 
> -long ppc32_fadvise64(int fd, u32 unused, u32 offset1, u32 offset2,
> -                    size_t len, int advice);
> +asmlinkage long ppc32_fadvise64(int fd, u32 unused, u32 offset1, u32 offset2,
> +                               size_t len, int advice);
> 
> -long compat_sys_sync_file_range2(int fd, unsigned int flags,
> -                                unsigned int offset1, unsigned int offset2,
> -                                unsigned int nbytes1, unsigned int nbytes2);
> +asmlinkage long compat_sys_sync_file_range2(int fd, unsigned int flags,
> +                                           unsigned int offset1,
> +                                           unsigned int offset2,
> +                                           unsigned int nbytes1,
> +                                           unsigned int nbytes2);
>   #endif
> 
>   #endif /* __KERNEL__ */
> diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
> index 7748c278d13c..2343c577b971 100644
> --- a/arch/powerpc/kernel/entry_32.S
> +++ b/arch/powerpc/kernel/entry_32.S
> @@ -121,9 +121,9 @@ transfer_to_syscall:
>          SAVE_NVGPRS(r1)
>          kuep_lock
> 
> -       /* Calling convention has r9 = orig r0, r10 = regs */
> -       addi    r10,r1,STACK_FRAME_OVERHEAD
> -       mr      r9,r0
> +       /* Calling convention has r3 = orig r0, r4 = regs */
> +       addi    r4,r1,STACK_FRAME_OVERHEAD
> +       mr      r3,r0
>          bl      system_call_exception
> 
>   ret_from_syscall:
> diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c
> index 784ea3289c84..a38329ede1a1 100644
> --- a/arch/powerpc/kernel/interrupt.c
> +++ b/arch/powerpc/kernel/interrupt.c
> @@ -24,7 +24,11 @@
>   unsigned long global_dbcr0[NR_CPUS];
>   #endif
> 
> +#ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER
> +typedef long (*syscall_fn)(struct pt_regs *);
> +#else
>   typedef long (*syscall_fn)(long, long, long, long, long, long);
> +#endif
> 
>   #ifdef CONFIG_PPC_BOOK3S_64
>   DEFINE_STATIC_KEY_FALSE(interrupt_exit_not_reentrant);
> @@ -74,15 +78,13 @@ static notrace __always_inline bool prep_irq_for_enabled_exit(bool restartable)
>   }
> 
>   /* 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,
> -                                  unsigned long r0, struct pt_regs *regs)
> +notrace long system_call_exception(unsigned long r0, struct pt_regs *regs)
>   {
>          syscall_fn f;
> 
>          kuap_lock();
> 
> -       regs->orig_gpr3 = r3;
> +       regs->orig_gpr3 = regs->gpr[3];
> 
>          if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
>                  BUG_ON(irq_soft_mask_return() != IRQS_ALL_DISABLED);
> @@ -196,12 +198,6 @@ notrace long system_call_exception(long r3, long r4, long r5,
>                  r0 = do_syscall_trace_enter(regs);
>                  if (unlikely(r0 >= NR_syscalls))
>                          return regs->gpr[3];
> -               r3 = regs->gpr[3];
> -               r4 = regs->gpr[4];
> -               r5 = regs->gpr[5];
> -               r6 = regs->gpr[6];
> -               r7 = regs->gpr[7];
> -               r8 = regs->gpr[8];
> 
>          } else if (unlikely(r0 >= NR_syscalls)) {
>                  if (unlikely(trap_is_unsupported_scv(regs))) {
> @@ -218,18 +214,23 @@ notrace long system_call_exception(long r3, long r4, long r5,
>          if (unlikely(is_compat_task())) {
>                  f = (void *)compat_sys_call_table[r0];
> 
> -               r3 &= 0x00000000ffffffffULL;
> -               r4 &= 0x00000000ffffffffULL;
> -               r5 &= 0x00000000ffffffffULL;
> -               r6 &= 0x00000000ffffffffULL;
> -               r7 &= 0x00000000ffffffffULL;
> -               r8 &= 0x00000000ffffffffULL;
> +               regs->gpr[3] &= 0x00000000ffffffffULL;
> +               regs->gpr[4] &= 0x00000000ffffffffULL;
> +               regs->gpr[5] &= 0x00000000ffffffffULL;
> +               regs->gpr[6] &= 0x00000000ffffffffULL;
> +               regs->gpr[7] &= 0x00000000ffffffffULL;
> +               regs->gpr[8] &= 0x00000000ffffffffULL;
> 
>          } else {
>                  f = (void *)sys_call_table[r0];
>          }
> 
> -       return f(r3, r4, r5, r6, r7, r8);
> +       #ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER
> +       return f(regs);
> +       #else
> +       return f(regs->gpr[3], regs->gpr[4], regs->gpr[5],
> +                regs->gpr[6], regs->gpr[7], regs->gpr[8]);
> +       #endif
>   }
> 
>   static notrace void booke_load_dbcr0(void)
> diff --git a/arch/powerpc/kernel/interrupt_64.S b/arch/powerpc/kernel/interrupt_64.S
> index 7bab2d7de372..b11c2bd84827 100644
> --- a/arch/powerpc/kernel/interrupt_64.S
> +++ b/arch/powerpc/kernel/interrupt_64.S
> @@ -91,9 +91,9 @@ _ASM_NOKPROBE_SYMBOL(system_call_vectored_\name)
>          li      r11,\trapnr
>          std     r11,_TRAP(r1)
>          std     r12,_CCR(r1)
> -       addi    r10,r1,STACK_FRAME_OVERHEAD
> +       addi    r4,r1,STACK_FRAME_OVERHEAD
>          ld      r11,exception_marker at toc(r2)
> -       std     r11,-16(r10)            /* "regshere" marker */
> +       std     r11,-16(r4)             /* "regshere" marker */
> 
>   BEGIN_FTR_SECTION
>          HMT_MEDIUM
> @@ -108,8 +108,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
>           * but this is the best we can do.
>           */
> 
> -       /* Calling convention has r9 = orig r0, r10 = regs */
> -       mr      r9,r0
> +       /* Calling convention has r3 = orig r0, r4 = regs */
> +       mr      r3,r0
>          bl      system_call_exception
> 
>   .Lsyscall_vectored_\name\()_exit:
> @@ -285,9 +285,9 @@ END_BTB_FLUSH_SECTION
>          std     r10,_LINK(r1)
>          std     r11,_TRAP(r1)
>          std     r12,_CCR(r1)
> -       addi    r10,r1,STACK_FRAME_OVERHEAD
> +       addi    r4,r1,STACK_FRAME_OVERHEAD
>          ld      r11,exception_marker at toc(r2)
> -       std     r11,-16(r10)            /* "regshere" marker */
> +       std     r11,-16(r4)             /* "regshere" marker */
> 
>   #ifdef CONFIG_PPC_BOOK3S
>          li      r11,1
> @@ -308,8 +308,8 @@ END_BTB_FLUSH_SECTION
>          wrteei  1
>   #endif
> 
> -       /* Calling convention has r9 = orig r0, r10 = regs */
> -       mr      r9,r0
> +       /* Calling convention has r3 = orig r0, r4 = regs */
> +       mr      r3,r0
>          bl      system_call_exception
> 
>   .Lsyscall_exit:
> @@ -353,16 +353,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
>          cmpdi   r3,0
>          bne     .Lsyscall_restore_regs
>          /* Zero volatile regs that may contain sensitive kernel data */
> -       li      r0,0
> -       li      r4,0
> -       li      r5,0
> -       li      r6,0
> -       li      r7,0
> -       li      r8,0
> -       li      r9,0
> -       li      r10,0
> -       li      r11,0
> -       li      r12,0
> +       ZERO_GPR(0)
> +       ZERO_GPRS(4, 12)
>          mtctr   r0
>          mtspr   SPRN_XER,r0
>   .Lsyscall_restore_regs_cont:
> @@ -388,7 +380,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
>          REST_NVGPRS(r1)
>          mtctr   r3
>          mtspr   SPRN_XER,r4
> -       ld      r0,GPR0(r1)
> +       REST_GPR(0, r1)
>          REST_GPRS(4, 12, r1)
>          b       .Lsyscall_restore_regs_cont
>   .Lsyscall_rst_end:
> diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
> index 16ff0399a257..aa7869dbef36 100644
> --- a/arch/powerpc/kernel/sys_ppc32.c
> +++ b/arch/powerpc/kernel/sys_ppc32.c
> @@ -48,9 +48,10 @@
>   #include <asm/syscalls.h>
>   #include <asm/switch_to.h>
> 
> -unsigned long compat_sys_mmap2(unsigned long addr, size_t len,
> -                         unsigned long prot, unsigned long flags,
> -                         unsigned long fd, unsigned long pgoff)
> +PPC_SYSCALL_DEFINE(6, unsigned long, compat_sys_mmap2,
> +                  unsigned long, addr, size_t, len,
> +                  unsigned long, prot, unsigned long, flags,
> +                  unsigned long, fd, unsigned long, pgoff)

This could be done in a separate patch, as it also addresses other 
topics like the syscall ftracing. Same for all syscalls in this file.

>   {
>          /* This should remain 12 even if PAGE_SIZE changes */
>          return sys_mmap(addr, len, prot, flags, fd, pgoff << 12);
> @@ -68,52 +69,63 @@ unsigned long compat_sys_mmap2(unsigned long addr, size_t len,
>   #define merge_64(high, low) ((u64)high << 32) | low
>   #endif
> 
> -compat_ssize_t compat_sys_pread64(unsigned int fd, char __user *ubuf, compat_size_t count,
> -                            u32 reg6, u32 pos1, u32 pos2)
> +PPC_SYSCALL_DEFINE(6, compat_ssize_t, compat_sys_pread64,
> +                  unsigned int, fd,
> +                  char __user *, ubuf, compat_size_t, count,
> +                  u32, reg6, u32, pos1, u32, pos2)
>   {
>          return ksys_pread64(fd, ubuf, count, merge_64(pos1, pos2));
>   }
> 
> -compat_ssize_t compat_sys_pwrite64(unsigned int fd, const char __user *ubuf, compat_size_t count,
> -                             u32 reg6, u32 pos1, u32 pos2)
> +PPC_SYSCALL_DEFINE(6, compat_ssize_t, compat_sys_pwrite64,
> +                  unsigned int, fd,
> +                  const char __user *, ubuf, compat_size_t, count,
> +                  u32, reg6, u32, pos1, u32, pos2)
>   {
>          return ksys_pwrite64(fd, ubuf, count, merge_64(pos1, pos2));
>   }
> 
> -compat_ssize_t compat_sys_readahead(int fd, u32 r4, u32 offset1, u32 offset2, u32 count)
> +PPC_SYSCALL_DEFINE(5, compat_ssize_t, compat_sys_readahead,
> +                  int, fd, u32, r4,
> +                  u32, offset1, u32, offset2, u32, count)
>   {
>          return ksys_readahead(fd, merge_64(offset1, offset2), count);
>   }
> 
> -asmlinkage int compat_sys_truncate64(const char __user * path, u32 reg4,
> -                               unsigned long len1, unsigned long len2)
> +PPC_SYSCALL_DEFINE(4, int, compat_sys_truncate64,
> +                  const char __user *, path, u32, reg4,
> +                  unsigned long, len1, unsigned long, len2)
>   {
>          return ksys_truncate(path, merge_64(len1, len2));
>   }
> 
> -asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offset1, u32 offset2,
> -                                    u32 len1, u32 len2)
> +PPC_SYSCALL_DEFINE(6, long, compat_sys_fallocate,
> +                  int, fd, int, mode, u32, offset1, u32, offset2,
> +                  u32, len1, u32, len2)
>   {
>          return ksys_fallocate(fd, mode, ((loff_t)offset1 << 32) | offset2,
>                               merge_64(len1, len2));
>   }
> 
> -asmlinkage int compat_sys_ftruncate64(unsigned int fd, u32 reg4, unsigned long len1,
> -                                unsigned long len2)
> +PPC_SYSCALL_DEFINE(4, int, compat_sys_ftruncate64,
> +                  unsigned int, fd, u32, reg4, unsigned long, len1,
> +                  unsigned long, len2)
>   {
>          return ksys_ftruncate(fd, merge_64(len1, len2));
>   }
> 
> -long ppc32_fadvise64(int fd, u32 unused, u32 offset1, u32 offset2,
> -                    size_t len, int advice)
> +PPC_SYSCALL_DEFINE(6, long, ppc32_fadvise64,
> +                  int, fd, u32, unused, u32, offset1, u32, offset2,
> +                  size_t, len, int, advice)
>   {
>          return ksys_fadvise64_64(fd, merge_64(offset1, offset2), len,
>                                   advice);
>   }
> 
> -asmlinkage long compat_sys_sync_file_range2(int fd, unsigned int flags,
> -                                  unsigned offset1, unsigned offset2,
> -                                  unsigned nbytes1, unsigned nbytes2)
> +PPC_SYSCALL_DEFINE(6, long, compat_sys_sync_file_range2, int, fd,
> +                  unsigned int, flags,
> +                  unsigned int, offset1, unsigned int, offset2,
> +                  unsigned int, nbytes1, unsigned int, nbytes2)
>   {
>          loff_t offset = merge_64(offset1, offset2);
>          loff_t nbytes = merge_64(nbytes1, nbytes2);
> diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c
> index c4f5b4ce926f..c64cdb5c4435 100644
> --- a/arch/powerpc/kernel/syscalls.c
> +++ b/arch/powerpc/kernel/syscalls.c
> @@ -64,14 +64,20 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, size_t, len,
>   }
> 
>   #ifdef CONFIG_PPC32
> +asmlinkage long sys_old_select(struct sel_arg_struct __user *arg);
> +asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
> +                          fd_set __user *exp,
> +                          struct __kernel_old_timeval __user *tvp);
> +

Those prototypes should go in a header file. I see you do it in a later 
patch. Should be done here directly.

>   /*
>    * Due to some executables calling the wrong select we sometimes
>    * get wrong args.  This determines how the args are being passed
>    * (a single ptr to them all args passed) then calls
>    * sys_select() with the appropriate args. -- Cort
>    */
> -int
> -ppc_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct __kernel_old_timeval __user *tvp)
> +PPC_SYSCALL_DEFINE(5, long, ppc_select,
> +                  int, n, fd_set __user *, inp, fd_set __user *, outp,
> +                  fd_set __user *, exp, struct __kernel_old_timeval __user *, tvp)
>   {
>          if ( (unsigned long)n >= 4096 )
>                  return sys_old_select((void __user *)n);
> @@ -81,7 +87,9 @@ ppc_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s
>   #endif
> 
>   #ifdef CONFIG_PPC64
> -long ppc64_personality(unsigned long personality)
> +asmlinkage long sys_personality(unsigned int personality);

Same.

> +
> +PPC_SYSCALL_DEFINE(1, long, ppc64_personality, unsigned long, personality)
>   {
>          long ret;
> 
> @@ -95,8 +103,9 @@ long ppc64_personality(unsigned long personality)
>   }
>   #endif
> 
> -long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low,
> -                     u32 len_high, u32 len_low)
> +PPC_SYSCALL_DEFINE(6, long, ppc_fadvise64_64,
> +                  int, fd, int, advice, u32, offset_high, u32, offset_low,
> +                  u32, len_high, u32, len_low)
>   {
>          return ksys_fadvise64_64(fd, (u64)offset_high << 32 | offset_low,
>                                   (u64)len_high << 32 | len_low, advice);
> diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
> index cb3358886203..70cc7120fce2 100644
> --- a/arch/powerpc/kernel/systbl.S
> +++ b/arch/powerpc/kernel/systbl.S
> @@ -16,11 +16,32 @@
> 
>   #ifdef CONFIG_PPC64
>          .p2align        3
> +#endif
> +
> +/* Where the syscall wrapper macro is used, handler functions expect parameters
> +   to reside on the stack. We still emit symbols with register-mapped
> +   parameters, which are distinguished by a prefix. */
> +
> +#ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER
> +
> +#define __powerpc_sys_ni_syscall sys_ni_syscall
> +
> +#ifdef CONFIG_PPC64
> +#define __SYSCALL(nr, entry)   .8byte __powerpc_##entry

Isn't .8bytes the same as .long on PPC64 ?

> +#else
> +#define __SYSCALL(nr, entry)   .long __powerpc_##entry
> +#endif
> +
> +#else
> +
> +#ifdef CONFIG_PPC64
>   #define __SYSCALL(nr, entry)   .8byte entry
>   #else
>   #define __SYSCALL(nr, entry)   .long entry
>   #endif
> 
> +#endif /* CONFIG_ARCH_HAS_SYSCALL_WRAPPER */
> +
>   #define __SYSCALL_WITH_COMPAT(nr, native, compat)      __SYSCALL(nr, native)
>   .globl sys_call_table
>   sys_call_table:
> diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
> index 717f2c9a7573..dcf57c07dbad 100644
> --- a/arch/powerpc/kernel/vdso.c
> +++ b/arch/powerpc/kernel/vdso.c
> @@ -40,6 +40,8 @@
>   extern char vdso32_start, vdso32_end;
>   extern char vdso64_start, vdso64_end;
> 
> +asmlinkage long sys_ni_syscall(void);
> +

Prototypes should go in a header file.

>   /*
>    * The vdso data page (aka. systemcfg for old ppc64 fans) is here.
>    * Once the early boot kernel code no longer needs to muck around
> --
> 2.34.1
> 


More information about the Linuxppc-dev mailing list