[PATCH 2/6] powerpc: Provide syscall wrapper
Christophe Leroy
christophe.leroy at csgroup.eu
Thu Jun 2 00:33:41 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.
>
> 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.
>
Also wondering why I get duplicated syscall functions. Shouldn't the
sys_ ones go away once we implement the __powerpc_sys_ ones ?
c001e9a0 <sys_fork>:
c001e9a0: 94 21 ff b0 stwu r1,-80(r1)
c001e9a4: 7c 08 02 a6 mflr r0
c001e9a8: 38 a0 00 40 li r5,64
c001e9ac: 38 80 00 00 li r4,0
c001e9b0: 38 61 00 08 addi r3,r1,8
c001e9b4: 90 01 00 54 stw r0,84(r1)
c001e9b8: 4b ff 6d 55 bl c001570c <memset>
c001e9bc: 38 61 00 08 addi r3,r1,8
c001e9c0: 39 20 00 11 li r9,17
c001e9c4: 91 21 00 1c stw r9,28(r1)
c001e9c8: 4b ff fb 31 bl c001e4f8 <kernel_clone>
c001e9cc: 80 01 00 54 lwz r0,84(r1)
c001e9d0: 38 21 00 50 addi r1,r1,80
c001e9d4: 7c 08 03 a6 mtlr r0
c001e9d8: 4e 80 00 20 blr
c001e9dc <__powerpc_sys_fork>:
c001e9dc: 94 21 ff b0 stwu r1,-80(r1)
c001e9e0: 7c 08 02 a6 mflr r0
c001e9e4: 38 a0 00 40 li r5,64
c001e9e8: 38 80 00 00 li r4,0
c001e9ec: 38 61 00 08 addi r3,r1,8
c001e9f0: 90 01 00 54 stw r0,84(r1)
c001e9f4: 4b ff 6d 19 bl c001570c <memset>
c001e9f8: 38 61 00 08 addi r3,r1,8
c001e9fc: 39 20 00 11 li r9,17
c001ea00: 91 21 00 1c stw r9,28(r1)
c001ea04: 4b ff fa f5 bl c001e4f8 <kernel_clone>
c001ea08: 80 01 00 54 lwz r0,84(r1)
c001ea0c: 38 21 00 50 addi r1,r1,80
c001ea10: 7c 08 03 a6 mtlr r0
c001ea14: 4e 80 00 20 blr
c001ea18 <sys_vfork>:
c001ea18: 94 21 ff b0 stwu r1,-80(r1)
c001ea1c: 7c 08 02 a6 mflr r0
c001ea20: 38 a0 00 38 li r5,56
c001ea24: 38 80 00 00 li r4,0
c001ea28: 38 61 00 10 addi r3,r1,16
c001ea2c: 90 01 00 54 stw r0,84(r1)
c001ea30: 4b ff 6c dd bl c001570c <memset>
c001ea34: 38 61 00 08 addi r3,r1,8
c001ea38: 39 40 00 00 li r10,0
c001ea3c: 39 60 41 00 li r11,16640
c001ea40: 39 20 00 11 li r9,17
c001ea44: 91 41 00 08 stw r10,8(r1)
c001ea48: 91 61 00 0c stw r11,12(r1)
c001ea4c: 91 21 00 1c stw r9,28(r1)
c001ea50: 4b ff fa a9 bl c001e4f8 <kernel_clone>
c001ea54: 80 01 00 54 lwz r0,84(r1)
c001ea58: 38 21 00 50 addi r1,r1,80
c001ea5c: 7c 08 03 a6 mtlr r0
c001ea60: 4e 80 00 20 blr
c001ea64 <__powerpc_sys_vfork>:
c001ea64: 94 21 ff b0 stwu r1,-80(r1)
c001ea68: 7c 08 02 a6 mflr r0
c001ea6c: 38 a0 00 38 li r5,56
c001ea70: 38 80 00 00 li r4,0
c001ea74: 38 61 00 10 addi r3,r1,16
c001ea78: 90 01 00 54 stw r0,84(r1)
c001ea7c: 4b ff 6c 91 bl c001570c <memset>
c001ea80: 38 61 00 08 addi r3,r1,8
c001ea84: 39 40 00 00 li r10,0
c001ea88: 39 60 41 00 li r11,16640
c001ea8c: 39 20 00 11 li r9,17
c001ea90: 91 41 00 08 stw r10,8(r1)
c001ea94: 91 61 00 0c stw r11,12(r1)
c001ea98: 91 21 00 1c stw r9,28(r1)
c001ea9c: 4b ff fa 5d bl c001e4f8 <kernel_clone>
c001eaa0: 80 01 00 54 lwz r0,84(r1)
c001eaa4: 38 21 00 50 addi r1,r1,80
c001eaa8: 7c 08 03 a6 mtlr r0
c001eaac: 4e 80 00 20 blr
Christophe
> 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);
> 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);
> 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);
>
> -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 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);
> +
> /*
> * 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);
> +
> +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
> +#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);
> +
> /*
> * 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