diff options
author | David Howells <dhowells@redhat.com> | 2009-06-11 08:05:24 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-11 12:01:26 -0400 |
commit | 4a3b98932270f5d69f2c081924e356325ed704d9 (patch) | |
tree | e2a8e37a37ed7e3be32c12ea233ea18c389549d0 /arch/frv/include | |
parent | 24ceb7e8a6c5dd6e32ac3d43a2424542c97989f5 (diff) |
FRV: Implement new-style ptrace
Implement the new-style ptrace for FRV, including adding appropriate
tracehooks.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/frv/include')
-rw-r--r-- | arch/frv/include/asm/elf.h | 1 | ||||
-rw-r--r-- | arch/frv/include/asm/ptrace.h | 11 | ||||
-rw-r--r-- | arch/frv/include/asm/syscall.h | 123 |
3 files changed, 134 insertions, 1 deletions
diff --git a/arch/frv/include/asm/elf.h b/arch/frv/include/asm/elf.h index 7279ec07d62e..7bbf6e47f8c8 100644 --- a/arch/frv/include/asm/elf.h +++ b/arch/frv/include/asm/elf.h | |||
@@ -116,6 +116,7 @@ do { \ | |||
116 | } while(0) | 116 | } while(0) |
117 | 117 | ||
118 | #define USE_ELF_CORE_DUMP | 118 | #define USE_ELF_CORE_DUMP |
119 | #define CORE_DUMP_USE_REGSET | ||
119 | #define ELF_FDPIC_CORE_EFLAGS EF_FRV_FDPIC | 120 | #define ELF_FDPIC_CORE_EFLAGS EF_FRV_FDPIC |
120 | #define ELF_EXEC_PAGESIZE 16384 | 121 | #define ELF_EXEC_PAGESIZE 16384 |
121 | 122 | ||
diff --git a/arch/frv/include/asm/ptrace.h b/arch/frv/include/asm/ptrace.h index cf6934012b64..a54b535c9e49 100644 --- a/arch/frv/include/asm/ptrace.h +++ b/arch/frv/include/asm/ptrace.h | |||
@@ -65,6 +65,8 @@ | |||
65 | #ifdef __KERNEL__ | 65 | #ifdef __KERNEL__ |
66 | #ifndef __ASSEMBLY__ | 66 | #ifndef __ASSEMBLY__ |
67 | 67 | ||
68 | struct task_struct; | ||
69 | |||
68 | /* | 70 | /* |
69 | * we dedicate GR28 to keeping a pointer to the current exception frame | 71 | * we dedicate GR28 to keeping a pointer to the current exception frame |
70 | * - gr28 is destroyed on entry to the kernel from userspace | 72 | * - gr28 is destroyed on entry to the kernel from userspace |
@@ -73,11 +75,18 @@ register struct pt_regs *__frame asm("gr28"); | |||
73 | 75 | ||
74 | #define user_mode(regs) (!((regs)->psr & PSR_S)) | 76 | #define user_mode(regs) (!((regs)->psr & PSR_S)) |
75 | #define instruction_pointer(regs) ((regs)->pc) | 77 | #define instruction_pointer(regs) ((regs)->pc) |
78 | #define user_stack_pointer(regs) ((regs)->sp) | ||
76 | 79 | ||
77 | extern unsigned long user_stack(const struct pt_regs *); | 80 | extern unsigned long user_stack(const struct pt_regs *); |
78 | extern void show_regs(struct pt_regs *); | 81 | extern void show_regs(struct pt_regs *); |
79 | #define profile_pc(regs) ((regs)->pc) | 82 | #define profile_pc(regs) ((regs)->pc) |
80 | #endif | 83 | |
84 | #define task_pt_regs(task) ((task)->thread.frame0) | ||
85 | |||
86 | #define arch_has_single_step() (1) | ||
87 | extern void user_enable_single_step(struct task_struct *); | ||
88 | extern void user_disable_single_step(struct task_struct *); | ||
81 | 89 | ||
82 | #endif /* !__ASSEMBLY__ */ | 90 | #endif /* !__ASSEMBLY__ */ |
91 | #endif /* __KERNEL__ */ | ||
83 | #endif /* _ASM_PTRACE_H */ | 92 | #endif /* _ASM_PTRACE_H */ |
diff --git a/arch/frv/include/asm/syscall.h b/arch/frv/include/asm/syscall.h new file mode 100644 index 000000000000..70689eb29b98 --- /dev/null +++ b/arch/frv/include/asm/syscall.h | |||
@@ -0,0 +1,123 @@ | |||
1 | /* syscall parameter access functions | ||
2 | * | ||
3 | * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _ASM_SYSCALL_H | ||
13 | #define _ASM_SYSCALL_H | ||
14 | |||
15 | #include <linux/err.h> | ||
16 | #include <asm/ptrace.h> | ||
17 | |||
18 | /* | ||
19 | * Get the system call number or -1 | ||
20 | */ | ||
21 | static inline long syscall_get_nr(struct task_struct *task, | ||
22 | struct pt_regs *regs) | ||
23 | { | ||
24 | return regs->syscallno; | ||
25 | } | ||
26 | |||
27 | /* | ||
28 | * Restore the clobbered GR8 register | ||
29 | * (1st syscall arg was overwritten with syscall return or error) | ||
30 | */ | ||
31 | static inline void syscall_rollback(struct task_struct *task, | ||
32 | struct pt_regs *regs) | ||
33 | { | ||
34 | regs->gr8 = regs->orig_gr8; | ||
35 | } | ||
36 | |||
37 | /* | ||
38 | * See if the syscall return value is an error, returning it if it is and 0 if | ||
39 | * not | ||
40 | */ | ||
41 | static inline long syscall_get_error(struct task_struct *task, | ||
42 | struct pt_regs *regs) | ||
43 | { | ||
44 | return IS_ERR_VALUE(regs->gr8) ? regs->gr8 : 0; | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | * Get the syscall return value | ||
49 | */ | ||
50 | static inline long syscall_get_return_value(struct task_struct *task, | ||
51 | struct pt_regs *regs) | ||
52 | { | ||
53 | return regs->gr8; | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * Set the syscall return value | ||
58 | */ | ||
59 | static inline void syscall_set_return_value(struct task_struct *task, | ||
60 | struct pt_regs *regs, | ||
61 | int error, long val) | ||
62 | { | ||
63 | if (error) | ||
64 | regs->gr8 = -error; | ||
65 | else | ||
66 | regs->gr8 = val; | ||
67 | } | ||
68 | |||
69 | /* | ||
70 | * Retrieve the system call arguments | ||
71 | */ | ||
72 | static inline void syscall_get_arguments(struct task_struct *task, | ||
73 | struct pt_regs *regs, | ||
74 | unsigned int i, unsigned int n, | ||
75 | unsigned long *args) | ||
76 | { | ||
77 | /* | ||
78 | * Do this simply for now. If we need to start supporting | ||
79 | * fetching arguments from arbitrary indices, this will need some | ||
80 | * extra logic. Presently there are no in-tree users that depend | ||
81 | * on this behaviour. | ||
82 | */ | ||
83 | BUG_ON(i); | ||
84 | |||
85 | /* Argument pattern is: GR8, GR9, GR10, GR11, GR12, GR13 */ | ||
86 | switch (n) { | ||
87 | case 6: args[5] = regs->gr13; | ||
88 | case 5: args[4] = regs->gr12; | ||
89 | case 4: args[3] = regs->gr11; | ||
90 | case 3: args[2] = regs->gr10; | ||
91 | case 2: args[1] = regs->gr9; | ||
92 | case 1: args[0] = regs->gr8; | ||
93 | break; | ||
94 | default: | ||
95 | BUG(); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * Alter the system call arguments | ||
101 | */ | ||
102 | static inline void syscall_set_arguments(struct task_struct *task, | ||
103 | struct pt_regs *regs, | ||
104 | unsigned int i, unsigned int n, | ||
105 | const unsigned long *args) | ||
106 | { | ||
107 | /* Same note as above applies */ | ||
108 | BUG_ON(i); | ||
109 | |||
110 | switch (n) { | ||
111 | case 6: regs->gr13 = args[5]; | ||
112 | case 5: regs->gr12 = args[4]; | ||
113 | case 4: regs->gr11 = args[3]; | ||
114 | case 3: regs->gr10 = args[2]; | ||
115 | case 2: regs->gr9 = args[1]; | ||
116 | case 1: regs->gr8 = args[0]; | ||
117 | break; | ||
118 | default: | ||
119 | BUG(); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | #endif /* _ASM_SYSCALL_H */ | ||