| 
									
										
										
										
											2012-07-13 23:38:17 +02:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-08-17 08:22:04 +02:00
										 |  |  |  * Access to user system call parameters and results | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2012-07-13 23:38:17 +02:00
										 |  |  |  * This file is subject to the terms and conditions of the GNU General Public | 
					
						
							|  |  |  |  * License.  See the file "COPYING" in the main directory of this archive | 
					
						
							|  |  |  |  * for more details. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2012-08-17 08:22:04 +02:00
										 |  |  |  * See asm-generic/syscall.h for descriptions of what we must do here. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2012-07-13 23:38:17 +02:00
										 |  |  |  * Copyright (C) 2012 Ralf Baechle <ralf@linux-mips.org> | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef __ASM_MIPS_SYSCALL_H
 | 
					
						
							|  |  |  | #define __ASM_MIPS_SYSCALL_H
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-10 18:00:17 +01:00
										 |  |  | #include <linux/compiler.h>
 | 
					
						
							| 
									
										
										
										
											2014-03-11 12:55:42 -04:00
										 |  |  | #include <uapi/linux/audit.h>
 | 
					
						
							| 
									
										
										
										
											2012-09-26 20:16:47 +02:00
										 |  |  | #include <linux/elf-em.h>
 | 
					
						
							| 
									
										
										
										
											2012-08-17 08:22:04 +02:00
										 |  |  | #include <linux/kernel.h>
 | 
					
						
							|  |  |  | #include <linux/sched.h>
 | 
					
						
							|  |  |  | #include <linux/uaccess.h>
 | 
					
						
							|  |  |  | #include <asm/ptrace.h>
 | 
					
						
							| 
									
										
										
										
											2014-01-22 14:40:03 +00:00
										 |  |  | #include <asm/unistd.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef __NR_syscall /* Only defined if _MIPS_SIM == _MIPS_SIM_ABI32 */
 | 
					
						
							|  |  |  | #define __NR_syscall 4000
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-08-17 08:22:04 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static inline long syscall_get_nr(struct task_struct *task, | 
					
						
							|  |  |  | 				  struct pt_regs *regs) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-01-22 14:40:03 +00:00
										 |  |  | 	/* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */ | 
					
						
							|  |  |  | 	if ((config_enabled(CONFIG_32BIT) || | 
					
						
							|  |  |  | 	    test_tsk_thread_flag(task, TIF_32BIT_REGS)) && | 
					
						
							|  |  |  | 	    (regs->regs[2] == __NR_syscall)) | 
					
						
							|  |  |  | 		return regs->regs[4]; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return regs->regs[2]; | 
					
						
							| 
									
										
										
										
											2012-08-17 08:22:04 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline unsigned long mips_get_syscall_arg(unsigned long *arg, | 
					
						
							|  |  |  | 	struct task_struct *task, struct pt_regs *regs, unsigned int n) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-11-25 15:21:00 -08:00
										 |  |  | 	unsigned long usp __maybe_unused = regs->regs[29]; | 
					
						
							| 
									
										
										
										
											2012-08-17 08:22:04 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	switch (n) { | 
					
						
							|  |  |  | 	case 0: case 1: case 2: case 3: | 
					
						
							|  |  |  | 		*arg = regs->regs[4 + n]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_32BIT
 | 
					
						
							|  |  |  | 	case 4: case 5: case 6: case 7: | 
					
						
							| 
									
										
										
										
											2014-03-17 12:14:13 +01:00
										 |  |  | 		return get_user(*arg, (int *)usp + n); | 
					
						
							| 
									
										
										
										
											2012-08-17 08:22:04 +02:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_64BIT
 | 
					
						
							|  |  |  | 	case 4: case 5: case 6: case 7: | 
					
						
							|  |  |  | #ifdef CONFIG_MIPS32_O32
 | 
					
						
							|  |  |  | 		if (test_thread_flag(TIF_32BIT_REGS)) | 
					
						
							| 
									
										
										
										
											2014-03-17 12:14:13 +01:00
										 |  |  | 			return get_user(*arg, (int *)usp + n); | 
					
						
							| 
									
										
										
										
											2012-08-17 08:22:04 +02:00
										 |  |  | 		else | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 			*arg = regs->regs[4 + n]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		BUG(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-10 18:00:17 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	unreachable(); | 
					
						
							| 
									
										
										
										
											2012-08-17 08:22:04 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:24:48 +02:00
										 |  |  | static inline long syscall_get_return_value(struct task_struct *task, | 
					
						
							|  |  |  | 					    struct pt_regs *regs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return regs->regs[2]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-22 14:39:58 +00:00
										 |  |  | static inline void syscall_rollback(struct task_struct *task, | 
					
						
							|  |  |  | 				    struct pt_regs *regs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* Do nothing */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:24:48 +02:00
										 |  |  | static inline void syscall_set_return_value(struct task_struct *task, | 
					
						
							|  |  |  | 					    struct pt_regs *regs, | 
					
						
							|  |  |  | 					    int error, long val) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (error) { | 
					
						
							|  |  |  | 		regs->regs[2] = -error; | 
					
						
							|  |  |  | 		regs->regs[7] = -1; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		regs->regs[2] = val; | 
					
						
							|  |  |  | 		regs->regs[7] = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-17 08:22:04 +02:00
										 |  |  | static inline void syscall_get_arguments(struct task_struct *task, | 
					
						
							|  |  |  | 					 struct pt_regs *regs, | 
					
						
							|  |  |  | 					 unsigned int i, unsigned int n, | 
					
						
							|  |  |  | 					 unsigned long *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int ret; | 
					
						
							| 
									
										
										
										
											2014-01-22 14:40:03 +00:00
										 |  |  | 	/* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */ | 
					
						
							|  |  |  | 	if ((config_enabled(CONFIG_32BIT) || | 
					
						
							|  |  |  | 	    test_tsk_thread_flag(task, TIF_32BIT_REGS)) && | 
					
						
							|  |  |  | 	    (regs->regs[2] == __NR_syscall)) { | 
					
						
							|  |  |  | 		i++; | 
					
						
							|  |  |  | 		n++; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-08-17 08:22:04 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	while (n--) | 
					
						
							| 
									
										
										
										
											2014-01-22 14:39:57 +00:00
										 |  |  | 		ret |= mips_get_syscall_arg(args++, task, regs, i++); | 
					
						
							| 
									
										
										
										
											2012-08-17 08:22:04 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * No way to communicate an error because this is a void function. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-13 23:38:17 +02:00
										 |  |  | extern const unsigned long sys_call_table[]; | 
					
						
							|  |  |  | extern const unsigned long sys32_call_table[]; | 
					
						
							|  |  |  | extern const unsigned long sysn32_call_table[]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-11 12:48:43 -04:00
										 |  |  | static inline int syscall_get_arch(void) | 
					
						
							| 
									
										
										
										
											2012-09-26 20:16:47 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 	int arch = EM_MIPS; | 
					
						
							|  |  |  | #ifdef CONFIG_64BIT
 | 
					
						
							| 
									
										
										
										
											2014-07-24 12:10:01 +01:00
										 |  |  | 	if (!test_thread_flag(TIF_32BIT_REGS)) { | 
					
						
							| 
									
										
										
										
											2014-01-22 14:39:59 +00:00
										 |  |  | 		arch |= __AUDIT_ARCH_64BIT; | 
					
						
							| 
									
										
										
										
											2014-07-24 12:10:01 +01:00
										 |  |  | 		/* N32 sets only TIF_32BIT_ADDR */ | 
					
						
							|  |  |  | 		if (test_thread_flag(TIF_32BIT_ADDR)) | 
					
						
							|  |  |  | 			arch |= __AUDIT_ARCH_CONVENTION_MIPS64_N32; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-09-26 20:16:47 +02:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #if defined(__LITTLE_ENDIAN)
 | 
					
						
							|  |  |  | 	arch |=  __AUDIT_ARCH_LE; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	return arch; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-13 23:38:17 +02:00
										 |  |  | #endif	/* __ASM_MIPS_SYSCALL_H */
 |