162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * System call callback functions for SPUs
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#undef DEBUG
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/kallsyms.h>
962306a36Sopenharmony_ci#include <linux/export.h>
1062306a36Sopenharmony_ci#include <linux/syscalls.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <asm/spu.h>
1362306a36Sopenharmony_ci#include <asm/syscalls.h>
1462306a36Sopenharmony_ci#include <asm/unistd.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci/*
1762306a36Sopenharmony_ci * This table defines the system calls that an SPU can call.
1862306a36Sopenharmony_ci * It is currently a subset of the 64 bit powerpc system calls,
1962306a36Sopenharmony_ci * with the exact semantics.
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci * The reasons for disabling some of the system calls are:
2262306a36Sopenharmony_ci * 1. They interact with the way SPU syscalls are handled
2362306a36Sopenharmony_ci *    and we can't let them execute ever:
2462306a36Sopenharmony_ci *	restart_syscall, exit, for, execve, ptrace, ...
2562306a36Sopenharmony_ci * 2. They are deprecated and replaced by other means:
2662306a36Sopenharmony_ci *	uselib, pciconfig_*, sysfs, ...
2762306a36Sopenharmony_ci * 3. They are somewhat interacting with the system in a way
2862306a36Sopenharmony_ci *    we don't want an SPU to:
2962306a36Sopenharmony_ci *	reboot, init_module, mount, kexec_load
3062306a36Sopenharmony_ci * 4. They are optional and we can't rely on them being
3162306a36Sopenharmony_ci *    linked into the kernel. Unfortunately, the cond_syscall
3262306a36Sopenharmony_ci *    helper does not work here as it does not add the necessary
3362306a36Sopenharmony_ci *    opd symbols:
3462306a36Sopenharmony_ci *	mbind, mq_open, ipc, ...
3562306a36Sopenharmony_ci */
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic const syscall_fn spu_syscall_table[] = {
3862306a36Sopenharmony_ci#define __SYSCALL_WITH_COMPAT(nr, entry, compat) __SYSCALL(nr, entry)
3962306a36Sopenharmony_ci#define __SYSCALL(nr, entry) [nr] = (void *) entry,
4062306a36Sopenharmony_ci#include <asm/syscall_table_spu.h>
4162306a36Sopenharmony_ci};
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cilong spu_sys_callback(struct spu_syscall_block *s)
4462306a36Sopenharmony_ci{
4562306a36Sopenharmony_ci	syscall_fn syscall;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	if (s->nr_ret >= ARRAY_SIZE(spu_syscall_table)) {
4862306a36Sopenharmony_ci		pr_debug("%s: invalid syscall #%lld", __func__, s->nr_ret);
4962306a36Sopenharmony_ci		return -ENOSYS;
5062306a36Sopenharmony_ci	}
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	syscall = spu_syscall_table[s->nr_ret];
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	pr_debug("SPU-syscall "
5562306a36Sopenharmony_ci		 "%pSR:syscall%lld(%llx, %llx, %llx, %llx, %llx, %llx)\n",
5662306a36Sopenharmony_ci		 syscall,
5762306a36Sopenharmony_ci		 s->nr_ret,
5862306a36Sopenharmony_ci		 s->parm[0], s->parm[1], s->parm[2],
5962306a36Sopenharmony_ci		 s->parm[3], s->parm[4], s->parm[5]);
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	return syscall(s->parm[0], s->parm[1], s->parm[2],
6262306a36Sopenharmony_ci		       s->parm[3], s->parm[4], s->parm[5]);
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(spu_sys_callback);
65