1 /* 2 * Copyright (C) 2008-2009 Red Hat, Inc. All rights reserved. 3 * Copyright 2010 Tilera Corporation. All Rights Reserved. 4 * Copyright 2015 Regents of the University of California, Berkeley 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation, version 2. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * See asm-generic/syscall.h for descriptions of what we must do here. 16 */ 17 18 #ifndef _ASM_RISCV_SYSCALL_H 19 #define _ASM_RISCV_SYSCALL_H 20 21 #include <uapi/linux/audit.h> 22 #include <linux/sched.h> 23 #include <linux/err.h> 24 25 /* The array of function pointers for syscalls. */ 26 extern void *sys_call_table[]; 27 28 /* 29 * Only the low 32 bits of orig_r0 are meaningful, so we return int. 30 * This importantly ignores the high bits on 64-bit, so comparisons 31 * sign-extend the low 32 bits. 32 */ 33 static inline int syscall_get_nr(struct task_struct *task, 34 struct pt_regs *regs) 35 { 36 return regs->a7; 37 } 38 39 static inline void syscall_set_nr(struct task_struct *task, 40 struct pt_regs *regs, 41 int sysno) 42 { 43 regs->a7 = sysno; 44 } 45 46 static inline void syscall_rollback(struct task_struct *task, 47 struct pt_regs *regs) 48 { 49 regs->a0 = regs->orig_a0; 50 } 51 52 static inline long syscall_get_error(struct task_struct *task, 53 struct pt_regs *regs) 54 { 55 unsigned long error = regs->a0; 56 57 return IS_ERR_VALUE(error) ? error : 0; 58 } 59 60 static inline long syscall_get_return_value(struct task_struct *task, 61 struct pt_regs *regs) 62 { 63 return regs->a0; 64 } 65 66 static inline void syscall_set_return_value(struct task_struct *task, 67 struct pt_regs *regs, 68 int error, long val) 69 { 70 regs->a0 = (long) error ?: val; 71 } 72 73 static inline void syscall_get_arguments(struct task_struct *task, 74 struct pt_regs *regs, 75 unsigned int i, unsigned int n, 76 unsigned long *args) 77 { 78 BUG_ON(i + n > 6); 79 if (i == 0) { 80 args[0] = regs->orig_a0; 81 args++; 82 i++; 83 n--; 84 } 85 memcpy(args, ®s->a1 + i * sizeof(regs->a1), n * sizeof(args[0])); 86 } 87 88 static inline void syscall_set_arguments(struct task_struct *task, 89 struct pt_regs *regs, 90 unsigned int i, unsigned int n, 91 const unsigned long *args) 92 { 93 BUG_ON(i + n > 6); 94 if (i == 0) { 95 regs->orig_a0 = args[0]; 96 args++; 97 i++; 98 n--; 99 } 100 memcpy(®s->a1 + i * sizeof(regs->a1), args, n * sizeof(regs->a0)); 101 } 102 103 static inline int syscall_get_arch(void) 104 { 105 #ifdef CONFIG_64BIT 106 return AUDIT_ARCH_RISCV64; 107 #else 108 return AUDIT_ARCH_RISCV32; 109 #endif 110 } 111 112 #endif /* _ASM_RISCV_SYSCALL_H */ 113