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 <linux/sched.h> 22 #include <linux/err.h> 23 24 /* The array of function pointers for syscalls. */ 25 extern void *sys_call_table[]; 26 27 /* 28 * Only the low 32 bits of orig_r0 are meaningful, so we return int. 29 * This importantly ignores the high bits on 64-bit, so comparisons 30 * sign-extend the low 32 bits. 31 */ 32 static inline int syscall_get_nr(struct task_struct *task, 33 struct pt_regs *regs) 34 { 35 return regs->a7; 36 } 37 38 static inline void syscall_set_nr(struct task_struct *task, 39 struct pt_regs *regs, 40 int sysno) 41 { 42 regs->a7 = sysno; 43 } 44 45 static inline void syscall_rollback(struct task_struct *task, 46 struct pt_regs *regs) 47 { 48 regs->a0 = regs->orig_a0; 49 } 50 51 static inline long syscall_get_error(struct task_struct *task, 52 struct pt_regs *regs) 53 { 54 unsigned long error = regs->a0; 55 56 return IS_ERR_VALUE(error) ? error : 0; 57 } 58 59 static inline long syscall_get_return_value(struct task_struct *task, 60 struct pt_regs *regs) 61 { 62 return regs->a0; 63 } 64 65 static inline void syscall_set_return_value(struct task_struct *task, 66 struct pt_regs *regs, 67 int error, long val) 68 { 69 regs->a0 = (long) error ?: val; 70 } 71 72 static inline void syscall_get_arguments(struct task_struct *task, 73 struct pt_regs *regs, 74 unsigned int i, unsigned int n, 75 unsigned long *args) 76 { 77 BUG_ON(i + n > 6); 78 if (i == 0) { 79 args[0] = regs->orig_a0; 80 args++; 81 i++; 82 n--; 83 } 84 memcpy(args, ®s->a1 + i * sizeof(regs->a1), n * sizeof(args[0])); 85 } 86 87 static inline void syscall_set_arguments(struct task_struct *task, 88 struct pt_regs *regs, 89 unsigned int i, unsigned int n, 90 const unsigned long *args) 91 { 92 BUG_ON(i + n > 6); 93 if (i == 0) { 94 regs->orig_a0 = args[0]; 95 args++; 96 i++; 97 n--; 98 } 99 memcpy(®s->a1 + i * sizeof(regs->a1), args, n * sizeof(regs->a0)); 100 } 101 102 #endif /* _ASM_RISCV_SYSCALL_H */ 103