xref: /openbmc/linux/arch/powerpc/include/asm/syscall.h (revision 63f13448)
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_error(struct task_struct *task,
38b8b572e1SStephen Rothwell 				     struct pt_regs *regs)
39b8b572e1SStephen Rothwell {
40409d241bSNathan Lynch 	return (regs->ccr & 0x10000000) ? -regs->gpr[3] : 0;
41b8b572e1SStephen Rothwell }
42b8b572e1SStephen Rothwell 
43b8b572e1SStephen Rothwell static inline long syscall_get_return_value(struct task_struct *task,
44b8b572e1SStephen Rothwell 					    struct pt_regs *regs)
45b8b572e1SStephen Rothwell {
46b8b572e1SStephen Rothwell 	return regs->gpr[3];
47b8b572e1SStephen Rothwell }
48b8b572e1SStephen Rothwell 
49b8b572e1SStephen Rothwell static inline void syscall_set_return_value(struct task_struct *task,
50b8b572e1SStephen Rothwell 					    struct pt_regs *regs,
51b8b572e1SStephen Rothwell 					    int error, long val)
52b8b572e1SStephen Rothwell {
53b8b572e1SStephen Rothwell 	if (error) {
54409d241bSNathan Lynch 		regs->ccr |= 0x10000000L;
55b8b572e1SStephen Rothwell 		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 {
67b8b572e1SStephen Rothwell 	BUG_ON(i + n > 6);
68b8b572e1SStephen Rothwell #ifdef CONFIG_PPC64
69b8b572e1SStephen Rothwell 	if (test_tsk_thread_flag(task, TIF_32BIT)) {
70b8b572e1SStephen Rothwell 		/*
71b8b572e1SStephen Rothwell 		 * Zero-extend 32-bit argument values.  The high bits are
72b8b572e1SStephen Rothwell 		 * garbage ignored by the actual syscall dispatch.
73b8b572e1SStephen Rothwell 		 */
74b8b572e1SStephen Rothwell 		while (n-- > 0)
75b8b572e1SStephen Rothwell 			args[n] = (u32) regs->gpr[3 + i + n];
76b8b572e1SStephen Rothwell 		return;
77b8b572e1SStephen Rothwell 	}
78b8b572e1SStephen Rothwell #endif
79b8b572e1SStephen Rothwell 	memcpy(args, &regs->gpr[3 + i], n * sizeof(args[0]));
80b8b572e1SStephen Rothwell }
81b8b572e1SStephen Rothwell 
82b8b572e1SStephen Rothwell static inline void syscall_set_arguments(struct task_struct *task,
83b8b572e1SStephen Rothwell 					 struct pt_regs *regs,
84b8b572e1SStephen Rothwell 					 unsigned int i, unsigned int n,
85b8b572e1SStephen Rothwell 					 const unsigned long *args)
86b8b572e1SStephen Rothwell {
87b8b572e1SStephen Rothwell 	BUG_ON(i + n > 6);
88b8b572e1SStephen Rothwell 	memcpy(&regs->gpr[3 + i], args, n * sizeof(args[0]));
89b8b572e1SStephen Rothwell }
90b8b572e1SStephen Rothwell 
91ce5d1128SEric Paris static inline int syscall_get_arch(void)
92ce5d1128SEric Paris {
9363f13448SRichard Guy Briggs 	int arch = is_32bit_task() ? AUDIT_ARCH_PPC : AUDIT_ARCH_PPC64;
9463f13448SRichard Guy Briggs #ifdef __LITTLE_ENDIAN__
9563f13448SRichard Guy Briggs 	arch |= __AUDIT_ARCH_LE;
9663f13448SRichard Guy Briggs #endif
9763f13448SRichard Guy Briggs 	return arch;
98ce5d1128SEric Paris }
99b8b572e1SStephen Rothwell #endif	/* _ASM_SYSCALL_H */
100