[PATCH 2/6] powerpc: Provide syscall wrapper
Rohan McLure
rmclure at linux.ibm.com
Fri Jun 3 13:24:46 AEST 2022
Thanks for your comment. I comment briefly here on how files like
arch/powerpc/kernel/syscalls.c implement ppc specialisations of
various syscalls, with implementations that themselves call syscall
symbols.
>> For platforms supporting this syscall wrapper, emit symbols with usual
>> in-register parameters (`sys...`) to support calls to syscall handlers
>> from within the kernel.
The implementation of ppc_personality can be immediately reworked to
call ksys_personality, but I can’t do the same for sys_old_select for
example, which is required to implement ppc_select. As such we emit both
symbols (sys_... and __powerpc...) so that ppc implementations can
efficiently call other implementations without needing to allocate
another pt_regs onto the stack.
This does admittedly introduce some code bloat into the binary. I see
a couple ways of fixing this:
1. Remove all calls to syscall implementations via sys_... symbols from
within the kernel.
2. Restrict which syscall implementations receive a sys_... symbol to
limit the number of duplicated functions.
Do you have any suggestions on how I might fix this?
> On 2 Jun 2022, at 12:33 am, Christophe Leroy <christophe.leroy at csgroup.eu> wrote:
>
>
>
> 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