xref: /openbmc/linux/arch/powerpc/include/asm/syscall.h (revision a7657844)
1b8b572e1SStephen Rothwell /*
2b8b572e1SStephen Rothwell  * Access to user system call parameters and results
3b8b572e1SStephen Rothwell  *
4b8b572e1SStephen Rothwell  * Copyright (C) 2008 Red Hat, Inc.  All rights reserved.
5b8b572e1SStephen Rothwell  *
6b8b572e1SStephen Rothwell  * This copyrighted material is made available to anyone wishing to use,
7b8b572e1SStephen Rothwell  * modify, copy, or redistribute it subject to the terms and conditions
8b8b572e1SStephen Rothwell  * of the GNU General Public License v.2.
9b8b572e1SStephen Rothwell  *
10b8b572e1SStephen Rothwell  * See asm-generic/syscall.h for descriptions of what we must do here.
11b8b572e1SStephen Rothwell  */
12b8b572e1SStephen Rothwell 
13b8b572e1SStephen Rothwell #ifndef _ASM_SYSCALL_H
14b8b572e1SStephen Rothwell #define _ASM_SYSCALL_H	1
15b8b572e1SStephen Rothwell 
16ce5d1128SEric Paris #include <uapi/linux/audit.h>
17b8b572e1SStephen Rothwell #include <linux/sched.h>
1875dddcbdSEric Paris #include <linux/thread_info.h>
19b8b572e1SStephen Rothwell 
2002424d89SIan Munsie /* ftrace syscalls requires exporting the sys_call_table */
2102424d89SIan Munsie #ifdef CONFIG_FTRACE_SYSCALLS
221028ccf5SRomeo Cane extern const unsigned long sys_call_table[];
2302424d89SIan Munsie #endif /* CONFIG_FTRACE_SYSCALLS */
2402424d89SIan Munsie 
25b8b572e1SStephen Rothwell static inline long syscall_get_nr(struct task_struct *task,
26b8b572e1SStephen Rothwell 				  struct pt_regs *regs)
27b8b572e1SStephen Rothwell {
28b8b572e1SStephen Rothwell 	return TRAP(regs) == 0xc00 ? regs->gpr[0] : -1L;
29b8b572e1SStephen Rothwell }
30b8b572e1SStephen Rothwell 
31b8b572e1SStephen Rothwell static inline void syscall_rollback(struct task_struct *task,
32b8b572e1SStephen Rothwell 				    struct pt_regs *regs)
33b8b572e1SStephen Rothwell {
34b8b572e1SStephen Rothwell 	regs->gpr[3] = regs->orig_gpr3;
35b8b572e1SStephen Rothwell }
36b8b572e1SStephen Rothwell 
37b8b572e1SStephen Rothwell static inline long syscall_get_return_value(struct task_struct *task,
38b8b572e1SStephen Rothwell 					    struct pt_regs *regs)
39b8b572e1SStephen Rothwell {
40b8b572e1SStephen Rothwell 	return regs->gpr[3];
41b8b572e1SStephen Rothwell }
42b8b572e1SStephen Rothwell 
43b8b572e1SStephen Rothwell static inline void syscall_set_return_value(struct task_struct *task,
44b8b572e1SStephen Rothwell 					    struct pt_regs *regs,
45b8b572e1SStephen Rothwell 					    int error, long val)
46b8b572e1SStephen Rothwell {
471b1a3702SMichael Ellerman 	/*
481b1a3702SMichael Ellerman 	 * In the general case it's not obvious that we must deal with CCR
491b1a3702SMichael Ellerman 	 * here, as the syscall exit path will also do that for us. However
501b1a3702SMichael Ellerman 	 * there are some places, eg. the signal code, which check ccr to
511b1a3702SMichael Ellerman 	 * decide if the value in r3 is actually an error.
521b1a3702SMichael Ellerman 	 */
53b8b572e1SStephen Rothwell 	if (error) {
54409d241bSNathan Lynch 		regs->ccr |= 0x10000000L;
551b1a3702SMichael Ellerman 		regs->gpr[3] = error;
56b8b572e1SStephen Rothwell 	} else {
57409d241bSNathan Lynch 		regs->ccr &= ~0x10000000L;
58b8b572e1SStephen Rothwell 		regs->gpr[3] = val;
59b8b572e1SStephen Rothwell 	}
60b8b572e1SStephen Rothwell }
61b8b572e1SStephen Rothwell 
62b8b572e1SStephen Rothwell static inline void syscall_get_arguments(struct task_struct *task,
63b8b572e1SStephen Rothwell 					 struct pt_regs *regs,
64b8b572e1SStephen Rothwell 					 unsigned int i, unsigned int n,
65b8b572e1SStephen Rothwell 					 unsigned long *args)
66b8b572e1SStephen Rothwell {
67a7657844SMichael Ellerman 	unsigned long mask = -1UL;
68a7657844SMichael Ellerman 
69b8b572e1SStephen Rothwell 	BUG_ON(i + n > 6);
70a7657844SMichael Ellerman 
71a7657844SMichael Ellerman #ifdef CONFIG_COMPAT
72a7657844SMichael Ellerman 	if (test_tsk_thread_flag(task, TIF_32BIT))
73a7657844SMichael Ellerman 		mask = 0xffffffff;
74b8b572e1SStephen Rothwell #endif
75a7657844SMichael Ellerman 	while (n--)
76a7657844SMichael Ellerman 		args[n] = regs->gpr[3 + i + n] & mask;
77b8b572e1SStephen Rothwell }
78b8b572e1SStephen Rothwell 
79b8b572e1SStephen Rothwell static inline void syscall_set_arguments(struct task_struct *task,
80b8b572e1SStephen Rothwell 					 struct pt_regs *regs,
81b8b572e1SStephen Rothwell 					 unsigned int i, unsigned int n,
82b8b572e1SStephen Rothwell 					 const unsigned long *args)
83b8b572e1SStephen Rothwell {
84b8b572e1SStephen Rothwell 	BUG_ON(i + n > 6);
85b8b572e1SStephen Rothwell 	memcpy(&regs->gpr[3 + i], args, n * sizeof(args[0]));
86b8b572e1SStephen Rothwell }
87b8b572e1SStephen Rothwell 
88ce5d1128SEric Paris static inline int syscall_get_arch(void)
89ce5d1128SEric Paris {
9063f13448SRichard Guy Briggs 	int arch = is_32bit_task() ? AUDIT_ARCH_PPC : AUDIT_ARCH_PPC64;
9163f13448SRichard Guy Briggs #ifdef __LITTLE_ENDIAN__
9263f13448SRichard Guy Briggs 	arch |= __AUDIT_ARCH_LE;
9363f13448SRichard Guy Briggs #endif
9463f13448SRichard Guy Briggs 	return arch;
95ce5d1128SEric Paris }
96b8b572e1SStephen Rothwell #endif	/* _ASM_SYSCALL_H */
97