2008-04-18 17:08:44 -07:00
/*
* Access to user system call parameters and results
*
* Copyright ( C ) 2008 Red Hat , Inc . All rights reserved .
*
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
* of the GNU General Public License v .2 .
*
* See asm - generic / syscall . h for descriptions of what we must do here .
*/
# ifndef _ASM_SYSCALL_H
# define _ASM_SYSCALL_H 1
# include <linux/sched.h>
2008-09-03 13:31:42 +02:00
# include <linux/err.h>
2008-04-18 17:08:44 -07:00
static inline long syscall_get_nr ( struct task_struct * task ,
struct pt_regs * regs )
{
/*
* We always sign - extend a - 1 value being set here ,
* so this is always either - 1L or a syscall number .
*/
return regs - > orig_ax ;
}
static inline void syscall_rollback ( struct task_struct * task ,
struct pt_regs * regs )
{
regs - > ax = regs - > orig_ax ;
}
static inline long syscall_get_error ( struct task_struct * task ,
struct pt_regs * regs )
{
unsigned long error = regs - > ax ;
# ifdef CONFIG_IA32_EMULATION
/*
* TS_COMPAT is set for 32 - bit syscall entries and then
* remains set until we return to user mode .
*/
if ( task_thread_info ( task ) - > status & TS_COMPAT )
/*
* Sign - extend the value so ( int ) - EFOO becomes ( long ) - EFOO
* and will match correctly in comparisons .
*/
error = ( long ) ( int ) error ;
# endif
2008-09-03 13:31:42 +02:00
return IS_ERR_VALUE ( error ) ? error : 0 ;
2008-04-18 17:08:44 -07:00
}
static inline long syscall_get_return_value ( struct task_struct * task ,
struct pt_regs * regs )
{
return regs - > ax ;
}
static inline void syscall_set_return_value ( struct task_struct * task ,
struct pt_regs * regs ,
int error , long val )
{
regs - > ax = ( long ) error ? : val ;
}
# ifdef CONFIG_X86_32
static inline void syscall_get_arguments ( struct task_struct * task ,
struct pt_regs * regs ,
unsigned int i , unsigned int n ,
unsigned long * args )
{
BUG_ON ( i + n > 6 ) ;
memcpy ( args , & regs - > bx + i , n * sizeof ( args [ 0 ] ) ) ;
}
static inline void syscall_set_arguments ( struct task_struct * task ,
struct pt_regs * regs ,
unsigned int i , unsigned int n ,
const unsigned long * args )
{
BUG_ON ( i + n > 6 ) ;
memcpy ( & regs - > bx + i , args , n * sizeof ( args [ 0 ] ) ) ;
}
# else /* CONFIG_X86_64 */
static inline void syscall_get_arguments ( struct task_struct * task ,
struct pt_regs * regs ,
unsigned int i , unsigned int n ,
unsigned long * args )
{
# ifdef CONFIG_IA32_EMULATION
if ( task_thread_info ( task ) - > status & TS_COMPAT )
switch ( i + n ) {
case 6 :
if ( ! n - - ) break ;
* args + + = regs - > bp ;
case 5 :
if ( ! n - - ) break ;
* args + + = regs - > di ;
case 4 :
if ( ! n - - ) break ;
* args + + = regs - > si ;
case 3 :
if ( ! n - - ) break ;
* args + + = regs - > dx ;
case 2 :
if ( ! n - - ) break ;
* args + + = regs - > cx ;
case 1 :
if ( ! n - - ) break ;
* args + + = regs - > bx ;
case 0 :
if ( ! n - - ) break ;
default :
BUG ( ) ;
break ;
}
else
# endif
switch ( i + n ) {
case 6 :
if ( ! n - - ) break ;
* args + + = regs - > r9 ;
case 5 :
if ( ! n - - ) break ;
* args + + = regs - > r8 ;
case 4 :
if ( ! n - - ) break ;
* args + + = regs - > r10 ;
case 3 :
if ( ! n - - ) break ;
* args + + = regs - > dx ;
case 2 :
if ( ! n - - ) break ;
* args + + = regs - > si ;
case 1 :
if ( ! n - - ) break ;
* args + + = regs - > di ;
case 0 :
if ( ! n - - ) break ;
default :
BUG ( ) ;
break ;
}
}
static inline void syscall_set_arguments ( struct task_struct * task ,
struct pt_regs * regs ,
unsigned int i , unsigned int n ,
const unsigned long * args )
{
# ifdef CONFIG_IA32_EMULATION
if ( task_thread_info ( task ) - > status & TS_COMPAT )
switch ( i + n ) {
case 6 :
if ( ! n - - ) break ;
regs - > bp = * args + + ;
case 5 :
if ( ! n - - ) break ;
regs - > di = * args + + ;
case 4 :
if ( ! n - - ) break ;
regs - > si = * args + + ;
case 3 :
if ( ! n - - ) break ;
regs - > dx = * args + + ;
case 2 :
if ( ! n - - ) break ;
regs - > cx = * args + + ;
case 1 :
if ( ! n - - ) break ;
regs - > bx = * args + + ;
case 0 :
if ( ! n - - ) break ;
default :
BUG ( ) ;
}
else
# endif
switch ( i + n ) {
case 6 :
if ( ! n - - ) break ;
regs - > r9 = * args + + ;
case 5 :
if ( ! n - - ) break ;
regs - > r8 = * args + + ;
case 4 :
if ( ! n - - ) break ;
regs - > r10 = * args + + ;
case 3 :
if ( ! n - - ) break ;
regs - > dx = * args + + ;
case 2 :
if ( ! n - - ) break ;
regs - > si = * args + + ;
case 1 :
if ( ! n - - ) break ;
regs - > di = * args + + ;
case 0 :
if ( ! n - - ) break ;
default :
BUG ( ) ;
}
}
# endif /* CONFIG_X86_32 */
# endif /* _ASM_SYSCALL_H */