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 15579ec9e1SEric Paris #include <uapi/linux/audit.h> 169bf1226bSHeiko Carstens #include <linux/sched.h> 1720b40a79SMartin Schwidefsky #include <linux/err.h> 18753c4dd6SMartin Schwidefsky #include <asm/ptrace.h> 19753c4dd6SMartin Schwidefsky 20e7b8e675SMike Frysinger /* 21e7b8e675SMike Frysinger * The syscall table always contains 32 bit pointers since we know that the 22e7b8e675SMike Frysinger * address of the function to be called is (way) below 4GB. So the "int" 23e7b8e675SMike Frysinger * type here is what we want [need] for both 32 bit and 64 bit systems. 24e7b8e675SMike Frysinger */ 25e7b8e675SMike Frysinger extern const unsigned int sys_call_table[]; 2661649881SMartin Schwidefsky extern const unsigned int sys_call_table_emu[]; 27e7b8e675SMike Frysinger 28753c4dd6SMartin Schwidefsky static inline long syscall_get_nr(struct task_struct *task, 29753c4dd6SMartin Schwidefsky struct pt_regs *regs) 30753c4dd6SMartin Schwidefsky { 31b6ef5bb3SMartin Schwidefsky return test_tsk_thread_flag(task, TIF_SYSCALL) ? 32aa33c8cbSMartin Schwidefsky (regs->int_code & 0xffff) : -1; 33753c4dd6SMartin Schwidefsky } 34753c4dd6SMartin Schwidefsky 35753c4dd6SMartin Schwidefsky static inline void syscall_rollback(struct task_struct *task, 36753c4dd6SMartin Schwidefsky struct pt_regs *regs) 37753c4dd6SMartin Schwidefsky { 38753c4dd6SMartin Schwidefsky regs->gprs[2] = regs->orig_gpr2; 39753c4dd6SMartin Schwidefsky } 40753c4dd6SMartin Schwidefsky 41753c4dd6SMartin Schwidefsky static inline long syscall_get_error(struct task_struct *task, 42753c4dd6SMartin Schwidefsky struct pt_regs *regs) 43753c4dd6SMartin Schwidefsky { 4420b40a79SMartin Schwidefsky return IS_ERR_VALUE(regs->gprs[2]) ? regs->gprs[2] : 0; 45753c4dd6SMartin Schwidefsky } 46753c4dd6SMartin Schwidefsky 47753c4dd6SMartin Schwidefsky static inline long syscall_get_return_value(struct task_struct *task, 48753c4dd6SMartin Schwidefsky struct pt_regs *regs) 49753c4dd6SMartin Schwidefsky { 50753c4dd6SMartin Schwidefsky return regs->gprs[2]; 51753c4dd6SMartin Schwidefsky } 52753c4dd6SMartin Schwidefsky 53753c4dd6SMartin Schwidefsky static inline void syscall_set_return_value(struct task_struct *task, 54753c4dd6SMartin Schwidefsky struct pt_regs *regs, 55753c4dd6SMartin Schwidefsky int error, long val) 56753c4dd6SMartin Schwidefsky { 57753c4dd6SMartin Schwidefsky regs->gprs[2] = error ? -error : val; 58753c4dd6SMartin Schwidefsky } 59753c4dd6SMartin Schwidefsky 60753c4dd6SMartin Schwidefsky static inline void syscall_get_arguments(struct task_struct *task, 61753c4dd6SMartin Schwidefsky struct pt_regs *regs, 62753c4dd6SMartin Schwidefsky unsigned int i, unsigned int n, 63753c4dd6SMartin Schwidefsky unsigned long *args) 64753c4dd6SMartin Schwidefsky { 6559da2139SMartin Schwidefsky unsigned long mask = -1UL; 6659da2139SMartin Schwidefsky 67753c4dd6SMartin Schwidefsky BUG_ON(i + n > 6); 68753c4dd6SMartin Schwidefsky #ifdef CONFIG_COMPAT 6959da2139SMartin Schwidefsky if (test_tsk_thread_flag(task, TIF_31BIT)) 7059da2139SMartin Schwidefsky mask = 0xffffffff; 71753c4dd6SMartin Schwidefsky #endif 7259da2139SMartin Schwidefsky while (n-- > 0) 7359da2139SMartin Schwidefsky if (i + n > 0) 7459da2139SMartin Schwidefsky args[n] = regs->gprs[2 + i + n] & mask; 7559da2139SMartin Schwidefsky if (i == 0) 7659da2139SMartin Schwidefsky args[0] = regs->orig_gpr2 & mask; 77753c4dd6SMartin Schwidefsky } 78753c4dd6SMartin Schwidefsky 79753c4dd6SMartin Schwidefsky static inline void syscall_set_arguments(struct task_struct *task, 80753c4dd6SMartin Schwidefsky struct pt_regs *regs, 81753c4dd6SMartin Schwidefsky unsigned int i, unsigned int n, 82753c4dd6SMartin Schwidefsky const unsigned long *args) 83753c4dd6SMartin Schwidefsky { 84753c4dd6SMartin Schwidefsky BUG_ON(i + n > 6); 8559da2139SMartin Schwidefsky while (n-- > 0) 8659da2139SMartin Schwidefsky if (i + n > 0) 8759da2139SMartin Schwidefsky regs->gprs[2 + i + n] = args[n]; 8859da2139SMartin Schwidefsky if (i == 0) 8959da2139SMartin Schwidefsky regs->orig_gpr2 = args[0]; 90753c4dd6SMartin Schwidefsky } 91753c4dd6SMartin Schwidefsky 925e937a9aSEric Paris static inline int syscall_get_arch(void) 93c63cb468SHeiko Carstens { 94c63cb468SHeiko Carstens #ifdef CONFIG_COMPAT 955e937a9aSEric Paris if (test_tsk_thread_flag(current, TIF_31BIT)) 96c63cb468SHeiko Carstens return AUDIT_ARCH_S390; 97c63cb468SHeiko Carstens #endif 98c63cb468SHeiko Carstens return sizeof(long) == 8 ? AUDIT_ARCH_S390X : AUDIT_ARCH_S390; 99c63cb468SHeiko Carstens } 100753c4dd6SMartin Schwidefsky #endif /* _ASM_SYSCALL_H */ 101