1753c4dd6SMartin Schwidefsky /* 2753c4dd6SMartin Schwidefsky * Access to user system call parameters and results 3753c4dd6SMartin Schwidefsky * 4753c4dd6SMartin Schwidefsky * Copyright IBM Corp. 2008 5753c4dd6SMartin Schwidefsky * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) 6753c4dd6SMartin Schwidefsky * 7753c4dd6SMartin Schwidefsky * This program is free software; you can redistribute it and/or modify 8753c4dd6SMartin Schwidefsky * it under the terms of the GNU General Public License (version 2 only) 9753c4dd6SMartin Schwidefsky * as published by the Free Software Foundation. 10753c4dd6SMartin Schwidefsky */ 11753c4dd6SMartin Schwidefsky 12753c4dd6SMartin Schwidefsky #ifndef _ASM_SYSCALL_H 13753c4dd6SMartin Schwidefsky #define _ASM_SYSCALL_H 1 14753c4dd6SMartin Schwidefsky 159bf1226bSHeiko Carstens #include <linux/sched.h> 1620b40a79SMartin Schwidefsky #include <linux/err.h> 17753c4dd6SMartin Schwidefsky #include <asm/ptrace.h> 18753c4dd6SMartin Schwidefsky 19e7b8e675SMike Frysinger /* 20e7b8e675SMike Frysinger * The syscall table always contains 32 bit pointers since we know that the 21e7b8e675SMike Frysinger * address of the function to be called is (way) below 4GB. So the "int" 22e7b8e675SMike Frysinger * type here is what we want [need] for both 32 bit and 64 bit systems. 23e7b8e675SMike Frysinger */ 24e7b8e675SMike Frysinger extern const unsigned int sys_call_table[]; 25e7b8e675SMike Frysinger 26753c4dd6SMartin Schwidefsky static inline long syscall_get_nr(struct task_struct *task, 27753c4dd6SMartin Schwidefsky struct pt_regs *regs) 28753c4dd6SMartin Schwidefsky { 29b6ef5bb3SMartin Schwidefsky return test_tsk_thread_flag(task, TIF_SYSCALL) ? 30b6ef5bb3SMartin Schwidefsky (regs->svc_code & 0xffff) : -1; 31753c4dd6SMartin Schwidefsky } 32753c4dd6SMartin Schwidefsky 33753c4dd6SMartin Schwidefsky static inline void syscall_rollback(struct task_struct *task, 34753c4dd6SMartin Schwidefsky struct pt_regs *regs) 35753c4dd6SMartin Schwidefsky { 36753c4dd6SMartin Schwidefsky regs->gprs[2] = regs->orig_gpr2; 37753c4dd6SMartin Schwidefsky } 38753c4dd6SMartin Schwidefsky 39753c4dd6SMartin Schwidefsky static inline long syscall_get_error(struct task_struct *task, 40753c4dd6SMartin Schwidefsky struct pt_regs *regs) 41753c4dd6SMartin Schwidefsky { 4220b40a79SMartin Schwidefsky return IS_ERR_VALUE(regs->gprs[2]) ? regs->gprs[2] : 0; 43753c4dd6SMartin Schwidefsky } 44753c4dd6SMartin Schwidefsky 45753c4dd6SMartin Schwidefsky static inline long syscall_get_return_value(struct task_struct *task, 46753c4dd6SMartin Schwidefsky struct pt_regs *regs) 47753c4dd6SMartin Schwidefsky { 48753c4dd6SMartin Schwidefsky return regs->gprs[2]; 49753c4dd6SMartin Schwidefsky } 50753c4dd6SMartin Schwidefsky 51753c4dd6SMartin Schwidefsky static inline void syscall_set_return_value(struct task_struct *task, 52753c4dd6SMartin Schwidefsky struct pt_regs *regs, 53753c4dd6SMartin Schwidefsky int error, long val) 54753c4dd6SMartin Schwidefsky { 55753c4dd6SMartin Schwidefsky regs->gprs[2] = error ? -error : val; 56753c4dd6SMartin Schwidefsky } 57753c4dd6SMartin Schwidefsky 58753c4dd6SMartin Schwidefsky static inline void syscall_get_arguments(struct task_struct *task, 59753c4dd6SMartin Schwidefsky struct pt_regs *regs, 60753c4dd6SMartin Schwidefsky unsigned int i, unsigned int n, 61753c4dd6SMartin Schwidefsky unsigned long *args) 62753c4dd6SMartin Schwidefsky { 6359da2139SMartin Schwidefsky unsigned long mask = -1UL; 6459da2139SMartin Schwidefsky 65753c4dd6SMartin Schwidefsky BUG_ON(i + n > 6); 66753c4dd6SMartin Schwidefsky #ifdef CONFIG_COMPAT 6759da2139SMartin Schwidefsky if (test_tsk_thread_flag(task, TIF_31BIT)) 6859da2139SMartin Schwidefsky mask = 0xffffffff; 69753c4dd6SMartin Schwidefsky #endif 7059da2139SMartin Schwidefsky while (n-- > 0) 7159da2139SMartin Schwidefsky if (i + n > 0) 7259da2139SMartin Schwidefsky args[n] = regs->gprs[2 + i + n] & mask; 7359da2139SMartin Schwidefsky if (i == 0) 7459da2139SMartin Schwidefsky args[0] = regs->orig_gpr2 & mask; 75753c4dd6SMartin Schwidefsky } 76753c4dd6SMartin Schwidefsky 77753c4dd6SMartin Schwidefsky static inline void syscall_set_arguments(struct task_struct *task, 78753c4dd6SMartin Schwidefsky struct pt_regs *regs, 79753c4dd6SMartin Schwidefsky unsigned int i, unsigned int n, 80753c4dd6SMartin Schwidefsky const unsigned long *args) 81753c4dd6SMartin Schwidefsky { 82753c4dd6SMartin Schwidefsky BUG_ON(i + n > 6); 8359da2139SMartin Schwidefsky while (n-- > 0) 8459da2139SMartin Schwidefsky if (i + n > 0) 8559da2139SMartin Schwidefsky regs->gprs[2 + i + n] = args[n]; 8659da2139SMartin Schwidefsky if (i == 0) 8759da2139SMartin Schwidefsky regs->orig_gpr2 = args[0]; 88753c4dd6SMartin Schwidefsky } 89753c4dd6SMartin Schwidefsky 90753c4dd6SMartin Schwidefsky #endif /* _ASM_SYSCALL_H */ 91