File Index
Files and directories
Sign in
FILE

syscall.h

File preview with syntax highlighting.

linux-6.19.14/arch/arm64/include/asm/syscall.h C
  1/* SPDX-License-Identifier: GPL-2.0-only */
  2/*
  3 * Copyright (C) 2012 ARM Ltd.
  4 */
  5#ifndef __ASM_SYSCALL_H
  6#define __ASM_SYSCALL_H
  7
  8#include <uapi/linux/audit.h>
  9#include <linux/compat.h>
 10#include <linux/err.h>
 11
 12typedef long (*syscall_fn_t)(const struct pt_regs *regs);
 13
 14extern const syscall_fn_t sys_call_table[];
 15
 16#ifdef CONFIG_COMPAT
 17extern const syscall_fn_t compat_sys_call_table[];
 18#endif
 19
 20static inline int syscall_get_nr(struct task_struct *task,
 21				 struct pt_regs *regs)
 22{
 23	return regs->syscallno;
 24}
 25
 26static inline void syscall_rollback(struct task_struct *task,
 27				    struct pt_regs *regs)
 28{
 29	regs->regs[0] = regs->orig_x0;
 30}
 31
 32static inline long syscall_get_return_value(struct task_struct *task,
 33					    struct pt_regs *regs)
 34{
 35	unsigned long val = regs->regs[0];
 36
 37	if (is_compat_thread(task_thread_info(task)))
 38		val = sign_extend64(val, 31);
 39
 40	return val;
 41}
 42
 43static inline long syscall_get_error(struct task_struct *task,
 44				     struct pt_regs *regs)
 45{
 46	unsigned long error = syscall_get_return_value(task, regs);
 47
 48	return IS_ERR_VALUE(error) ? error : 0;
 49}
 50
 51static inline void syscall_set_return_value(struct task_struct *task,
 52					    struct pt_regs *regs,
 53					    int error, long val)
 54{
 55	if (error)
 56		val = error;
 57
 58	if (is_compat_thread(task_thread_info(task)))
 59		val = lower_32_bits(val);
 60
 61	regs->regs[0] = val;
 62}
 63
 64static inline void syscall_set_nr(struct task_struct *task,
 65				  struct pt_regs *regs,
 66				  int nr)
 67{
 68	regs->syscallno = nr;
 69	if (nr == -1) {
 70		/*
 71		 * When the syscall number is set to -1, the syscall will be
 72		 * skipped.  In this case the syscall return value has to be
 73		 * set explicitly, otherwise the first syscall argument is
 74		 * returned as the syscall return value.
 75		 */
 76		syscall_set_return_value(task, regs, -ENOSYS, 0);
 77	}
 78}
 79
 80#define SYSCALL_MAX_ARGS 6
 81
 82static inline void syscall_get_arguments(struct task_struct *task,
 83					 struct pt_regs *regs,
 84					 unsigned long *args)
 85{
 86	args[0] = regs->orig_x0;
 87	args++;
 88
 89	memcpy(args, &regs->regs[1], 5 * sizeof(args[0]));
 90}
 91
 92static inline void syscall_set_arguments(struct task_struct *task,
 93					 struct pt_regs *regs,
 94					 const unsigned long *args)
 95{
 96	memcpy(&regs->regs[0], args, 6 * sizeof(args[0]));
 97	/*
 98	 * Also copy the first argument into orig_x0
 99	 * so that syscall_get_arguments() would return it
100	 * instead of the previous value.
101	 */
102	regs->orig_x0 = regs->regs[0];
103}
104
105/*
106 * We don't care about endianness (__AUDIT_ARCH_LE bit) here because
107 * AArch64 has the same system calls both on little- and big- endian.
108 */
109static inline int syscall_get_arch(struct task_struct *task)
110{
111	if (is_compat_thread(task_thread_info(task)))
112		return AUDIT_ARCH_ARM;
113
114	return AUDIT_ARCH_AARCH64;
115}
116
117int syscall_trace_enter(struct pt_regs *regs);
118void syscall_trace_exit(struct pt_regs *regs);
119
120#endif	/* __ASM_SYSCALL_H */
~/ Read-only file preview.