162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2012 ARM Ltd. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci#ifndef __ASM_SYSCALL_H 662306a36Sopenharmony_ci#define __ASM_SYSCALL_H 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <uapi/linux/audit.h> 962306a36Sopenharmony_ci#include <linux/compat.h> 1062306a36Sopenharmony_ci#include <linux/err.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_citypedef long (*syscall_fn_t)(const struct pt_regs *regs); 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ciextern const syscall_fn_t sys_call_table[]; 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 1762306a36Sopenharmony_ciextern const syscall_fn_t compat_sys_call_table[]; 1862306a36Sopenharmony_ci#endif 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic inline int syscall_get_nr(struct task_struct *task, 2162306a36Sopenharmony_ci struct pt_regs *regs) 2262306a36Sopenharmony_ci{ 2362306a36Sopenharmony_ci return regs->syscallno; 2462306a36Sopenharmony_ci} 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic inline void syscall_rollback(struct task_struct *task, 2762306a36Sopenharmony_ci struct pt_regs *regs) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci regs->regs[0] = regs->orig_x0; 3062306a36Sopenharmony_ci} 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic inline long syscall_get_return_value(struct task_struct *task, 3362306a36Sopenharmony_ci struct pt_regs *regs) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci unsigned long val = regs->regs[0]; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci if (is_compat_thread(task_thread_info(task))) 3862306a36Sopenharmony_ci val = sign_extend64(val, 31); 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci return val; 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic inline long syscall_get_error(struct task_struct *task, 4462306a36Sopenharmony_ci struct pt_regs *regs) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci unsigned long error = syscall_get_return_value(task, regs); 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci return IS_ERR_VALUE(error) ? error : 0; 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic inline void syscall_set_return_value(struct task_struct *task, 5262306a36Sopenharmony_ci struct pt_regs *regs, 5362306a36Sopenharmony_ci int error, long val) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci if (error) 5662306a36Sopenharmony_ci val = error; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci if (is_compat_thread(task_thread_info(task))) 5962306a36Sopenharmony_ci val = lower_32_bits(val); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci regs->regs[0] = val; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci#define SYSCALL_MAX_ARGS 6 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic inline void syscall_get_arguments(struct task_struct *task, 6762306a36Sopenharmony_ci struct pt_regs *regs, 6862306a36Sopenharmony_ci unsigned long *args) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci args[0] = regs->orig_x0; 7162306a36Sopenharmony_ci args++; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci memcpy(args, ®s->regs[1], 5 * sizeof(args[0])); 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci/* 7762306a36Sopenharmony_ci * We don't care about endianness (__AUDIT_ARCH_LE bit) here because 7862306a36Sopenharmony_ci * AArch64 has the same system calls both on little- and big- endian. 7962306a36Sopenharmony_ci */ 8062306a36Sopenharmony_cistatic inline int syscall_get_arch(struct task_struct *task) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci if (is_compat_thread(task_thread_info(task))) 8362306a36Sopenharmony_ci return AUDIT_ARCH_ARM; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci return AUDIT_ARCH_AARCH64; 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ciint syscall_trace_enter(struct pt_regs *regs); 8962306a36Sopenharmony_civoid syscall_trace_exit(struct pt_regs *regs); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci#endif /* __ASM_SYSCALL_H */ 92