| /* syscall parameter access functions | |
| * | |
| * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved. | |
| * Written by David Howells (dhowells@redhat.com) | |
| * | |
| * This program is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU General Public Licence | |
| * as published by the Free Software Foundation; either version | |
| * 2 of the Licence, or (at your option) any later version. | |
| */ | |
| #ifndef _ASM_SYSCALL_H | |
| #define _ASM_SYSCALL_H | |
| #include <linux/err.h> | |
| #include <asm/ptrace.h> | |
| /* | |
| * Get the system call number or -1 | |
| */ | |
| static inline long syscall_get_nr(struct task_struct *task, | |
| struct pt_regs *regs) | |
| { | |
| return regs->syscallno; | |
| } | |
| /* | |
| * Restore the clobbered GR8 register | |
| * (1st syscall arg was overwritten with syscall return or error) | |
| */ | |
| static inline void syscall_rollback(struct task_struct *task, | |
| struct pt_regs *regs) | |
| { | |
| regs->gr8 = regs->orig_gr8; | |
| } | |
| /* | |
| * See if the syscall return value is an error, returning it if it is and 0 if | |
| * not | |
| */ | |
| static inline long syscall_get_error(struct task_struct *task, | |
| struct pt_regs *regs) | |
| { | |
| return IS_ERR_VALUE(regs->gr8) ? regs->gr8 : 0; | |
| } | |
| /* | |
| * Get the syscall return value | |
| */ | |
| static inline long syscall_get_return_value(struct task_struct *task, | |
| struct pt_regs *regs) | |
| { | |
| return regs->gr8; | |
| } | |
| /* | |
| * Set the syscall return value | |
| */ | |
| static inline void syscall_set_return_value(struct task_struct *task, | |
| struct pt_regs *regs, | |
| int error, long val) | |
| { | |
| if (error) | |
| regs->gr8 = -error; | |
| else | |
| regs->gr8 = val; | |
| } | |
| /* | |
| * Retrieve the system call arguments | |
| */ | |
| static inline void syscall_get_arguments(struct task_struct *task, | |
| struct pt_regs *regs, | |
| unsigned int i, unsigned int n, | |
| unsigned long *args) | |
| { | |
| /* | |
| * Do this simply for now. If we need to start supporting | |
| * fetching arguments from arbitrary indices, this will need some | |
| * extra logic. Presently there are no in-tree users that depend | |
| * on this behaviour. | |
| */ | |
| BUG_ON(i); | |
| /* Argument pattern is: GR8, GR9, GR10, GR11, GR12, GR13 */ | |
| switch (n) { | |
| case 6: args[5] = regs->gr13; | |
| case 5: args[4] = regs->gr12; | |
| case 4: args[3] = regs->gr11; | |
| case 3: args[2] = regs->gr10; | |
| case 2: args[1] = regs->gr9; | |
| case 1: args[0] = regs->gr8; | |
| break; | |
| default: | |
| BUG(); | |
| } | |
| } | |
| /* | |
| * Alter the system call arguments | |
| */ | |
| static inline void syscall_set_arguments(struct task_struct *task, | |
| struct pt_regs *regs, | |
| unsigned int i, unsigned int n, | |
| const unsigned long *args) | |
| { | |
| /* Same note as above applies */ | |
| BUG_ON(i); | |
| switch (n) { | |
| case 6: regs->gr13 = args[5]; | |
| case 5: regs->gr12 = args[4]; | |
| case 4: regs->gr11 = args[3]; | |
| case 3: regs->gr10 = args[2]; | |
| case 2: regs->gr9 = args[1]; | |
| case 1: regs->gr8 = args[0]; | |
| break; | |
| default: | |
| BUG(); | |
| } | |
| } | |
| #endif /* _ASM_SYSCALL_H */ |