diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2013-01-18 04:42:18 -0500 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2013-02-11 09:30:38 -0500 |
commit | 4adeefe161a74369e44cc8e663f240ece0470dc3 (patch) | |
tree | e5b243c62c0f0d5f8c21b9d856ef350282bfec25 /arch/arc | |
parent | 054419ed8405da7aa93f88f698d696980efd3e37 (diff) |
ARC: Syscall support (no-legacy-syscall ABI)
This includes support for generic clone/for/vfork/execve
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/arc')
-rw-r--r-- | arch/arc/Kconfig | 1 | ||||
-rw-r--r-- | arch/arc/include/asm/ptrace.h | 5 | ||||
-rw-r--r-- | arch/arc/include/asm/syscall.h | 72 | ||||
-rw-r--r-- | arch/arc/include/asm/syscalls.h | 29 | ||||
-rw-r--r-- | arch/arc/include/asm/unistd.h | 34 | ||||
-rw-r--r-- | arch/arc/kernel/entry.S | 27 | ||||
-rw-r--r-- | arch/arc/kernel/process.c | 42 | ||||
-rw-r--r-- | arch/arc/kernel/sys.c | 18 |
8 files changed, 228 insertions, 0 deletions
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index b0b09aea98ff..8789de1c7c8f 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig | |||
@@ -9,6 +9,7 @@ | |||
9 | config ARC | 9 | config ARC |
10 | def_bool y | 10 | def_bool y |
11 | select ARCH_NO_VIRT_TO_BUS | 11 | select ARCH_NO_VIRT_TO_BUS |
12 | select CLONE_BACKWARDS | ||
12 | # ARC Busybox based initramfs absolutely relies on DEVTMPFS for /dev | 13 | # ARC Busybox based initramfs absolutely relies on DEVTMPFS for /dev |
13 | select DEVTMPFS if !INITRAMFS_SOURCE="" | 14 | select DEVTMPFS if !INITRAMFS_SOURCE="" |
14 | select GENERIC_ATOMIC64 | 15 | select GENERIC_ATOMIC64 |
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h index 446e55eee7be..4c9359477ded 100644 --- a/arch/arc/include/asm/ptrace.h +++ b/arch/arc/include/asm/ptrace.h | |||
@@ -86,6 +86,11 @@ struct callee_regs { | |||
86 | sp = -1; \ | 86 | sp = -1; \ |
87 | sp; \ | 87 | sp; \ |
88 | }) | 88 | }) |
89 | |||
90 | /* return 1 if in syscall, 0 if Intr or Exception */ | ||
91 | #define in_syscall(regs) (((regs->orig_r8) >= 0 && \ | ||
92 | (regs->orig_r8 <= NR_syscalls)) ? 1 : 0) | ||
93 | |||
89 | #endif /* !__ASSEMBLY__ */ | 94 | #endif /* !__ASSEMBLY__ */ |
90 | 95 | ||
91 | #endif /* __KERNEL__ */ | 96 | #endif /* __KERNEL__ */ |
diff --git a/arch/arc/include/asm/syscall.h b/arch/arc/include/asm/syscall.h new file mode 100644 index 000000000000..33ab3048e9b2 --- /dev/null +++ b/arch/arc/include/asm/syscall.h | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef _ASM_ARC_SYSCALL_H | ||
10 | #define _ASM_ARC_SYSCALL_H 1 | ||
11 | |||
12 | #include <linux/err.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <asm/unistd.h> | ||
15 | #include <asm/ptrace.h> /* in_syscall() */ | ||
16 | |||
17 | static inline long | ||
18 | syscall_get_nr(struct task_struct *task, struct pt_regs *regs) | ||
19 | { | ||
20 | if (user_mode(regs) && in_syscall(regs)) | ||
21 | return regs->orig_r8; | ||
22 | else | ||
23 | return -1; | ||
24 | } | ||
25 | |||
26 | static inline void | ||
27 | syscall_rollback(struct task_struct *task, struct pt_regs *regs) | ||
28 | { | ||
29 | /* XXX: I can't fathom how pt_regs->r8 will be clobbered ? */ | ||
30 | regs->r8 = regs->orig_r8; | ||
31 | } | ||
32 | |||
33 | static inline long | ||
34 | syscall_get_error(struct task_struct *task, struct pt_regs *regs) | ||
35 | { | ||
36 | /* 0 if syscall succeeded, otherwise -Errorcode */ | ||
37 | return IS_ERR_VALUE(regs->r0) ? regs->r0 : 0; | ||
38 | } | ||
39 | |||
40 | static inline long | ||
41 | syscall_get_return_value(struct task_struct *task, struct pt_regs *regs) | ||
42 | { | ||
43 | return regs->r0; | ||
44 | } | ||
45 | |||
46 | static inline void | ||
47 | syscall_set_return_value(struct task_struct *task, struct pt_regs *regs, | ||
48 | int error, long val) | ||
49 | { | ||
50 | regs->r0 = (long) error ?: val; | ||
51 | } | ||
52 | |||
53 | /* | ||
54 | * @i: argument index [0,5] | ||
55 | * @n: number of arguments; n+i must be [1,6]. | ||
56 | */ | ||
57 | static inline void | ||
58 | syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, | ||
59 | unsigned int i, unsigned int n, unsigned long *args) | ||
60 | { | ||
61 | unsigned long *inside_ptregs = &(regs->r0); | ||
62 | inside_ptregs -= i; | ||
63 | |||
64 | BUG_ON((i + n) > 6); | ||
65 | |||
66 | while (n--) { | ||
67 | args[i++] = (*inside_ptregs); | ||
68 | inside_ptregs--; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | #endif | ||
diff --git a/arch/arc/include/asm/syscalls.h b/arch/arc/include/asm/syscalls.h new file mode 100644 index 000000000000..e53a5340ba4f --- /dev/null +++ b/arch/arc/include/asm/syscalls.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef _ASM_ARC_SYSCALLS_H | ||
10 | #define _ASM_ARC_SYSCALLS_H 1 | ||
11 | |||
12 | #ifdef __KERNEL__ | ||
13 | |||
14 | #include <linux/compiler.h> | ||
15 | #include <linux/linkage.h> | ||
16 | #include <linux/types.h> | ||
17 | |||
18 | int sys_clone_wrapper(int, int, int, int, int); | ||
19 | int sys_fork_wrapper(void); | ||
20 | int sys_vfork_wrapper(void); | ||
21 | int sys_cacheflush(uint32_t, uint32_t uint32_t); | ||
22 | int sys_arc_settls(void *); | ||
23 | int sys_arc_gettls(void); | ||
24 | |||
25 | #include <asm-generic/syscalls.h> | ||
26 | |||
27 | #endif /* __KERNEL__ */ | ||
28 | |||
29 | #endif | ||
diff --git a/arch/arc/include/asm/unistd.h b/arch/arc/include/asm/unistd.h new file mode 100644 index 000000000000..6f30484f34b7 --- /dev/null +++ b/arch/arc/include/asm/unistd.h | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | /******** no-legacy-syscalls-ABI *******/ | ||
10 | |||
11 | #define __ARCH_WANT_SYS_EXECVE | ||
12 | #define __ARCH_WANT_SYS_CLONE | ||
13 | #define __ARCH_WANT_SYS_VFORK | ||
14 | #define __ARCH_WANT_SYS_FORK | ||
15 | |||
16 | #define sys_mmap2 sys_mmap_pgoff | ||
17 | |||
18 | #include <asm-generic/unistd.h> | ||
19 | |||
20 | #define NR_syscalls __NR_syscalls | ||
21 | |||
22 | /* ARC specific syscall */ | ||
23 | #define __NR_cacheflush (__NR_arch_specific_syscall + 0) | ||
24 | #define __NR_arc_settls (__NR_arch_specific_syscall + 1) | ||
25 | #define __NR_arc_gettls (__NR_arch_specific_syscall + 2) | ||
26 | |||
27 | __SYSCALL(__NR_cacheflush, sys_cacheflush) | ||
28 | __SYSCALL(__NR_arc_settls, sys_arc_settls) | ||
29 | __SYSCALL(__NR_arc_gettls, sys_arc_gettls) | ||
30 | |||
31 | |||
32 | /* Generic syscall (fs/filesystems.c - lost in asm-generic/unistd.h */ | ||
33 | #define __NR_sysfs (__NR_arch_specific_syscall + 3) | ||
34 | __SYSCALL(__NR_sysfs, sys_sysfs) | ||
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index a4acc9ee1311..0b0a190547a9 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S | |||
@@ -569,3 +569,30 @@ ARC_ENTRY ret_from_fork | |||
569 | bl @schedule_tail | 569 | bl @schedule_tail |
570 | b @ret_from_exception | 570 | b @ret_from_exception |
571 | ARC_EXIT ret_from_fork | 571 | ARC_EXIT ret_from_fork |
572 | |||
573 | ;################### Special Sys Call Wrappers ########################## | ||
574 | |||
575 | ; TBD: call do_fork directly from here | ||
576 | ARC_ENTRY sys_fork_wrapper | ||
577 | SAVE_CALLEE_SAVED_USER | ||
578 | bl @sys_fork | ||
579 | DISCARD_CALLEE_SAVED_USER | ||
580 | |||
581 | b ret_from_system_call | ||
582 | ARC_EXIT sys_fork_wrapper | ||
583 | |||
584 | ARC_ENTRY sys_vfork_wrapper | ||
585 | SAVE_CALLEE_SAVED_USER | ||
586 | bl @sys_vfork | ||
587 | DISCARD_CALLEE_SAVED_USER | ||
588 | |||
589 | b ret_from_system_call | ||
590 | ARC_EXIT sys_vfork_wrapper | ||
591 | |||
592 | ARC_ENTRY sys_clone_wrapper | ||
593 | SAVE_CALLEE_SAVED_USER | ||
594 | bl @sys_clone | ||
595 | DISCARD_CALLEE_SAVED_USER | ||
596 | |||
597 | b ret_from_system_call | ||
598 | ARC_EXIT sys_clone_wrapper | ||
diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c new file mode 100644 index 000000000000..4d14e5638c8c --- /dev/null +++ b/arch/arc/kernel/process.c | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * Amit Bhor, Kanika Nema: Codito Technologies 2004 | ||
9 | */ | ||
10 | |||
11 | #include <linux/errno.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/mm.h> | ||
15 | #include <linux/fs.h> | ||
16 | #include <linux/unistd.h> | ||
17 | #include <linux/ptrace.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/syscalls.h> | ||
20 | #include <linux/elf.h> | ||
21 | #include <linux/tick.h> | ||
22 | |||
23 | SYSCALL_DEFINE1(arc_settls, void *, user_tls_data_ptr) | ||
24 | { | ||
25 | task_thread_info(current)->thr_ptr = (unsigned int)user_tls_data_ptr; | ||
26 | return 0; | ||
27 | } | ||
28 | |||
29 | /* | ||
30 | * We return the user space TLS data ptr as sys-call return code | ||
31 | * Ideally it should be copy to user. | ||
32 | * However we can cheat by the fact that some sys-calls do return | ||
33 | * absurdly high values | ||
34 | * Since the tls dat aptr is not going to be in range of 0xFFFF_xxxx | ||
35 | * it won't be considered a sys-call error | ||
36 | * and it will be loads better than copy-to-user, which is a definite | ||
37 | * D-TLB Miss | ||
38 | */ | ||
39 | SYSCALL_DEFINE0(arc_gettls) | ||
40 | { | ||
41 | return task_thread_info(current)->thr_ptr; | ||
42 | } | ||
diff --git a/arch/arc/kernel/sys.c b/arch/arc/kernel/sys.c new file mode 100644 index 000000000000..f6bdd07583f3 --- /dev/null +++ b/arch/arc/kernel/sys.c | |||
@@ -0,0 +1,18 @@ | |||
1 | |||
2 | #include <linux/syscalls.h> | ||
3 | #include <linux/signal.h> | ||
4 | #include <linux/unistd.h> | ||
5 | |||
6 | #include <asm/syscalls.h> | ||
7 | |||
8 | #define sys_clone sys_clone_wrapper | ||
9 | #define sys_fork sys_fork_wrapper | ||
10 | #define sys_vfork sys_vfork_wrapper | ||
11 | |||
12 | #undef __SYSCALL | ||
13 | #define __SYSCALL(nr, call) [nr] = (call), | ||
14 | |||
15 | void *sys_call_table[NR_syscalls] = { | ||
16 | [0 ... NR_syscalls-1] = sys_ni_syscall, | ||
17 | #include <asm/unistd.h> | ||
18 | }; | ||