1/* SPDX-License-Identifier: GPL-2.0 */ 2// Copyright (C) 2008-2009 Red Hat, Inc. All rights reserved. 3// Copyright (C) 2005-2017 Andes Technology Corporation 4 5#ifndef _ASM_NDS32_SYSCALL_H 6#define _ASM_NDS32_SYSCALL_H 1 7 8#include <uapi/linux/audit.h> 9#include <linux/err.h> 10struct task_struct; 11struct pt_regs; 12 13/** 14 * syscall_get_nr - find what system call a task is executing 15 * @task: task of interest, must be blocked 16 * @regs: task_pt_regs() of @task 17 * 18 * If @task is executing a system call or is at system call 19 * tracing about to attempt one, returns the system call number. 20 * If @task is not executing a system call, i.e. it's blocked 21 * inside the kernel for a fault or signal, returns -1. 22 * 23 * Note this returns int even on 64-bit machines. Only 32 bits of 24 * system call number can be meaningful. If the actual arch value 25 * is 64 bits, this truncates to 32 bits so 0xffffffff means -1. 26 * 27 * It's only valid to call this when @task is known to be blocked. 28 */ 29static inline int 30syscall_get_nr(struct task_struct *task, struct pt_regs *regs) 31{ 32 return regs->syscallno; 33} 34 35/** 36 * syscall_rollback - roll back registers after an aborted system call 37 * @task: task of interest, must be in system call exit tracing 38 * @regs: task_pt_regs() of @task 39 * 40 * It's only valid to call this when @task is stopped for system 41 * call exit tracing (due to TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT), 42 * after tracehook_report_syscall_entry() returned nonzero to prevent 43 * the system call from taking place. 44 * 45 * This rolls back the register state in @regs so it's as if the 46 * system call instruction was a no-op. The registers containing 47 * the system call number and arguments are as they were before the 48 * system call instruction. This may not be the same as what the 49 * register state looked like at system call entry tracing. 50 */ 51static inline void 52syscall_rollback(struct task_struct *task, struct pt_regs *regs) 53{ 54 regs->uregs[0] = regs->orig_r0; 55} 56 57/** 58 * syscall_get_error - check result of traced system call 59 * @task: task of interest, must be blocked 60 * @regs: task_pt_regs() of @task 61 * 62 * Returns 0 if the system call succeeded, or -ERRORCODE if it failed. 63 * 64 * It's only valid to call this when @task is stopped for tracing on exit 65 * from a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT. 66 */ 67static inline long 68syscall_get_error(struct task_struct *task, struct pt_regs *regs) 69{ 70 unsigned long error = regs->uregs[0]; 71 return IS_ERR_VALUE(error) ? error : 0; 72} 73 74/** 75 * syscall_get_return_value - get the return value of a traced system call 76 * @task: task of interest, must be blocked 77 * @regs: task_pt_regs() of @task 78 * 79 * Returns the return value of the successful system call. 80 * This value is meaningless if syscall_get_error() returned nonzero. 81 * 82 * It's only valid to call this when @task is stopped for tracing on exit 83 * from a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT. 84 */ 85static inline long 86syscall_get_return_value(struct task_struct *task, struct pt_regs *regs) 87{ 88 return regs->uregs[0]; 89} 90 91/** 92 * syscall_set_return_value - change the return value of a traced system call 93 * @task: task of interest, must be blocked 94 * @regs: task_pt_regs() of @task 95 * @error: negative error code, or zero to indicate success 96 * @val: user return value if @error is zero 97 * 98 * This changes the results of the system call that user mode will see. 99 * If @error is zero, the user sees a successful system call with a 100 * return value of @val. If @error is nonzero, it's a negated errno 101 * code; the user sees a failed system call with this errno code. 102 * 103 * It's only valid to call this when @task is stopped for tracing on exit 104 * from a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT. 105 */ 106static inline void 107syscall_set_return_value(struct task_struct *task, struct pt_regs *regs, 108 int error, long val) 109{ 110 regs->uregs[0] = (long)error ? error : val; 111} 112 113/** 114 * syscall_get_arguments - extract system call parameter values 115 * @task: task of interest, must be blocked 116 * @regs: task_pt_regs() of @task 117 * @args: array filled with argument values 118 * 119 * Fetches 6 arguments to the system call (from 0 through 5). The first 120 * argument is stored in @args[0], and so on. 121 * 122 * It's only valid to call this when @task is stopped for tracing on 123 * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT. 124 */ 125#define SYSCALL_MAX_ARGS 6 126static inline void 127syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, 128 unsigned long *args) 129{ 130 args[0] = regs->orig_r0; 131 args++; 132 memcpy(args, ®s->uregs[0] + 1, 5 * sizeof(args[0])); 133} 134 135/** 136 * syscall_set_arguments - change system call parameter value 137 * @task: task of interest, must be in system call entry tracing 138 * @regs: task_pt_regs() of @task 139 * @args: array of argument values to store 140 * 141 * Changes 6 arguments to the system call. The first argument gets value 142 * @args[0], and so on. 143 * 144 * It's only valid to call this when @task is stopped for tracing on 145 * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT. 146 */ 147static inline void 148syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, 149 const unsigned long *args) 150{ 151 regs->orig_r0 = args[0]; 152 args++; 153 154 memcpy(®s->uregs[0] + 1, args, 5 * sizeof(args[0])); 155} 156 157static inline int 158syscall_get_arch(struct task_struct *task) 159{ 160 return IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) 161 ? AUDIT_ARCH_NDS32BE : AUDIT_ARCH_NDS32; 162} 163 164#endif /* _ASM_NDS32_SYSCALL_H */ 165