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> 10 struct task_struct; 11 struct 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 */ 29 static inline int 30 syscall_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 */ 51 static inline void 52 syscall_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 */ 67 static inline long 68 syscall_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 */ 85 static inline long 86 syscall_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 */ 106 static inline void 107 syscall_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 126 static inline void 127 syscall_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 */ 147 static inline void 148 syscall_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 157 static inline int 158 syscall_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 */