1/* 2 * Copyright (C) 2008-2009 Red Hat, Inc. All rights reserved. 3 * Copyright 2010 Tilera Corporation. All Rights Reserved. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License 7 * as published by the Free Software Foundation, version 2. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 12 * NON INFRINGEMENT. See the GNU General Public License for 13 * more details. 14 * 15 * See asm-generic/syscall.h for descriptions of what we must do here. 16 */ 17 18#ifndef _ASM_TILE_SYSCALL_H 19#define _ASM_TILE_SYSCALL_H 20 21#include <linux/sched.h> 22#include <linux/err.h> 23#include <linux/audit.h> 24#include <linux/compat.h> 25#include <arch/abi.h> 26 27/* The array of function pointers for syscalls. */ 28extern void *sys_call_table[]; 29#ifdef CONFIG_COMPAT 30extern void *compat_sys_call_table[]; 31#endif 32 33/* 34 * Only the low 32 bits of orig_r0 are meaningful, so we return int. 35 * This importantly ignores the high bits on 64-bit, so comparisons 36 * sign-extend the low 32 bits. 37 */ 38static inline int syscall_get_nr(struct task_struct *t, struct pt_regs *regs) 39{ 40 return regs->regs[TREG_SYSCALL_NR]; 41} 42 43static inline void syscall_rollback(struct task_struct *task, 44 struct pt_regs *regs) 45{ 46 regs->regs[0] = regs->orig_r0; 47} 48 49static inline long syscall_get_error(struct task_struct *task, 50 struct pt_regs *regs) 51{ 52 unsigned long error = regs->regs[0]; 53 return IS_ERR_VALUE(error) ? error : 0; 54} 55 56static inline long syscall_get_return_value(struct task_struct *task, 57 struct pt_regs *regs) 58{ 59 return regs->regs[0]; 60} 61 62static inline void syscall_set_return_value(struct task_struct *task, 63 struct pt_regs *regs, 64 int error, long val) 65{ 66 if (error) { 67 /* R0 is the passed-in negative error, R1 is positive. */ 68 regs->regs[0] = error; 69 regs->regs[1] = -error; 70 } else { 71 /* R1 set to zero to indicate no error. */ 72 regs->regs[0] = val; 73 regs->regs[1] = 0; 74 } 75} 76 77static inline void syscall_get_arguments(struct task_struct *task, 78 struct pt_regs *regs, 79 unsigned int i, unsigned int n, 80 unsigned long *args) 81{ 82 BUG_ON(i + n > 6); 83 memcpy(args, ®s[i], n * sizeof(args[0])); 84} 85 86static inline void syscall_set_arguments(struct task_struct *task, 87 struct pt_regs *regs, 88 unsigned int i, unsigned int n, 89 const unsigned long *args) 90{ 91 BUG_ON(i + n > 6); 92 memcpy(®s[i], args, n * sizeof(args[0])); 93} 94 95/* 96 * We don't care about endianness (__AUDIT_ARCH_LE bit) here because 97 * tile has the same system calls both on little- and big- endian. 98 */ 99static inline int syscall_get_arch(void) 100{ 101 if (is_compat_task()) 102 return AUDIT_ARCH_TILEGX32; 103 104#ifdef CONFIG_TILEGX 105 return AUDIT_ARCH_TILEGX; 106#else 107 return AUDIT_ARCH_TILEPRO; 108#endif 109} 110 111#endif /* _ASM_TILE_SYSCALL_H */ 112