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 */ 29int syscall_get_nr(struct task_struct *task, struct pt_regs *regs) 30{ 31 return regs->syscallno; 32} 33 34/** 35 * syscall_rollback - roll back registers after an aborted system call 36 * @task: task of interest, must be in system call exit tracing 37 * @regs: task_pt_regs() of @task 38 * 39 * It's only valid to call this when @task is stopped for system 40 * call exit tracing (due to TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT), 41 * after tracehook_report_syscall_entry() returned nonzero to prevent 42 * the system call from taking place. 43 * 44 * This rolls back the register state in @regs so it's as if the 45 * system call instruction was a no-op. The registers containing 46 * the system call number and arguments are as they were before the 47 * system call instruction. This may not be the same as what the 48 * register state looked like at system call entry tracing. 49 */ 50void syscall_rollback(struct task_struct *task, struct pt_regs *regs) 51{ 52 regs->uregs[0] = regs->orig_r0; 53} 54 55/** 56 * syscall_get_error - check result of traced system call 57 * @task: task of interest, must be blocked 58 * @regs: task_pt_regs() of @task 59 * 60 * Returns 0 if the system call succeeded, or -ERRORCODE if it failed. 61 * 62 * It's only valid to call this when @task is stopped for tracing on exit 63 * from a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT. 64 */ 65long syscall_get_error(struct task_struct *task, struct pt_regs *regs) 66{ 67 unsigned long error = regs->uregs[0]; 68 return IS_ERR_VALUE(error) ? error : 0; 69} 70 71/** 72 * syscall_get_return_value - get the return value of a traced system call 73 * @task: task of interest, must be blocked 74 * @regs: task_pt_regs() of @task 75 * 76 * Returns the return value of the successful system call. 77 * This value is meaningless if syscall_get_error() returned nonzero. 78 * 79 * It's only valid to call this when @task is stopped for tracing on exit 80 * from a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT. 81 */ 82long syscall_get_return_value(struct task_struct *task, struct pt_regs *regs) 83{ 84 return regs->uregs[0]; 85} 86 87/** 88 * syscall_set_return_value - change the return value of a traced system call 89 * @task: task of interest, must be blocked 90 * @regs: task_pt_regs() of @task 91 * @error: negative error code, or zero to indicate success 92 * @val: user return value if @error is zero 93 * 94 * This changes the results of the system call that user mode will see. 95 * If @error is zero, the user sees a successful system call with a 96 * return value of @val. If @error is nonzero, it's a negated errno 97 * code; the user sees a failed system call with this errno code. 98 * 99 * It's only valid to call this when @task is stopped for tracing on exit 100 * from a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT. 101 */ 102void syscall_set_return_value(struct task_struct *task, struct pt_regs *regs, 103 int error, long val) 104{ 105 regs->uregs[0] = (long)error ? error : val; 106} 107 108/** 109 * syscall_get_arguments - extract system call parameter values 110 * @task: task of interest, must be blocked 111 * @regs: task_pt_regs() of @task 112 * @args: array filled with argument values 113 * 114 * Fetches 6 arguments to the system call (from 0 through 5). The first 115 * argument is stored in @args[0], and so on. 116 * 117 * It's only valid to call this when @task is stopped for tracing on 118 * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT. 119 */ 120#define SYSCALL_MAX_ARGS 6 121void syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, 122 unsigned long *args) 123{ 124 args[0] = regs->orig_r0; 125 args++; 126 memcpy(args, ®s->uregs[0] + 1, 5 * sizeof(args[0])); 127} 128 129/** 130 * syscall_set_arguments - change system call parameter value 131 * @task: task of interest, must be in system call entry tracing 132 * @regs: task_pt_regs() of @task 133 * @args: array of argument values to store 134 * 135 * Changes 6 arguments to the system call. The first argument gets value 136 * @args[0], and so on. 137 * 138 * It's only valid to call this when @task is stopped for tracing on 139 * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT. 140 */ 141void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, 142 const unsigned long *args) 143{ 144 regs->orig_r0 = args[0]; 145 args++; 146 147 memcpy(®s->uregs[0] + 1, args, 5 * sizeof(args[0])); 148} 149 150static inline int 151syscall_get_arch(struct task_struct *task) 152{ 153 return IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) 154 ? AUDIT_ARCH_NDS32BE : AUDIT_ARCH_NDS32; 155} 156 157#endif /* _ASM_NDS32_SYSCALL_H */ 158