Skip to content

Commit

Permalink
powerpc: Use common syscall handler type
Browse files Browse the repository at this point in the history
Cause syscall handlers to be typed as follows when called indirectly
throughout the kernel. This is to allow for better type checking.

typedef long (*syscall_fn)(unsigned long, unsigned long, unsigned long,
                           unsigned long, unsigned long, unsigned long);

Since both 32 and 64-bit abis allow for at least the first six
machine-word length parameters to a function to be passed by registers,
even handlers which admit fewer than six parameters may be viewed as
having the above type.

Coercing syscalls to syscall_fn requires a cast to void* to avoid
-Wcast-function-type.

Fixup comparisons in VDSO to avoid pointer-integer comparison. Introduce
explicit cast on systems with SPUs.

Signed-off-by: Rohan McLure <rmclure@linux.ibm.com>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20220921065605.1051927-19-rmclure@linux.ibm.com
  • Loading branch information
Rohan McLure authored and Michael Ellerman committed Sep 28, 2022
1 parent 39859ae commit 8640de0
Show file tree
Hide file tree
Showing 6 changed files with 19 additions and 12 deletions.
7 changes: 5 additions & 2 deletions arch/powerpc/include/asm/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@
#include <linux/sched.h>
#include <linux/thread_info.h>

typedef long (*syscall_fn)(unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long, unsigned long);

/* ftrace syscalls requires exporting the sys_call_table */
extern const unsigned long sys_call_table[];
extern const unsigned long compat_sys_call_table[];
extern const syscall_fn sys_call_table[];
extern const syscall_fn compat_sys_call_table[];

static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
{
Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/include/asm/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <linux/types.h>
#include <linux/compat.h>

#include <asm/syscall.h>
#ifdef CONFIG_PPC64
#include <asm/syscalls_32.h>
#endif
Expand Down
2 changes: 0 additions & 2 deletions arch/powerpc/kernel/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
#include <asm/unistd.h>


typedef long (*syscall_fn)(long, long, long, long, long, long);

/* 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,
Expand Down
11 changes: 8 additions & 3 deletions arch/powerpc/kernel/systbl.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,14 @@
#include <asm/syscalls.h>

#define __SYSCALL_WITH_COMPAT(nr, entry, compat) __SYSCALL(nr, entry)
#define __SYSCALL(nr, entry) [nr] = (unsigned long) &entry,

const unsigned long sys_call_table[] = {
/*
* Coerce syscall handlers with arbitrary parameters to common type
* requires cast to void* to avoid -Wcast-function-type.
*/
#define __SYSCALL(nr, entry) [nr] = (void *) entry,

const syscall_fn sys_call_table[] = {
#ifdef CONFIG_PPC64
#include <asm/syscall_table_64.h>
#else
Expand All @@ -29,7 +34,7 @@ const unsigned long sys_call_table[] = {
#ifdef CONFIG_COMPAT
#undef __SYSCALL_WITH_COMPAT
#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, compat)
const unsigned long compat_sys_call_table[] = {
const syscall_fn compat_sys_call_table[] = {
#include <asm/syscall_table_32.h>
};
#endif /* CONFIG_COMPAT */
4 changes: 2 additions & 2 deletions arch/powerpc/kernel/vdso.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,10 +304,10 @@ static void __init vdso_setup_syscall_map(void)
unsigned int i;

for (i = 0; i < NR_syscalls; i++) {
if (sys_call_table[i] != (unsigned long)&sys_ni_syscall)
if (sys_call_table[i] != (void *)&sys_ni_syscall)
vdso_data->syscall_map[i >> 5] |= 0x80000000UL >> (i & 0x1f);
if (IS_ENABLED(CONFIG_COMPAT) &&
compat_sys_call_table[i] != (unsigned long)&sys_ni_syscall)
compat_sys_call_table[i] != (void *)&sys_ni_syscall)
vdso_data->compat_syscall_map[i >> 5] |= 0x80000000UL >> (i & 0x1f);
}
}
Expand Down
6 changes: 3 additions & 3 deletions arch/powerpc/platforms/cell/spu_callbacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@
* mbind, mq_open, ipc, ...
*/

static void *spu_syscall_table[] = {
static const syscall_fn spu_syscall_table[] = {
#define __SYSCALL_WITH_COMPAT(nr, entry, compat) __SYSCALL(nr, entry)
#define __SYSCALL(nr, entry) [nr] = entry,
#define __SYSCALL(nr, entry) [nr] = (void *) entry,
#include <asm/syscall_table_spu.h>
};

long spu_sys_callback(struct spu_syscall_block *s)
{
long (*syscall)(u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6);
syscall_fn syscall;

if (s->nr_ret >= ARRAY_SIZE(spu_syscall_table)) {
pr_debug("%s: invalid syscall #%lld", __func__, s->nr_ret);
Expand Down

0 comments on commit 8640de0

Please sign in to comment.