@@ -114,6 +114,105 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
114114 return & riscv_user_native_view ;
115115}
116116
117+ struct pt_regs_offset {
118+ const char * name ;
119+ int offset ;
120+ };
121+
122+ #define REG_OFFSET_NAME (r ) {.name = #r, .offset = offsetof(struct pt_regs, r)}
123+ #define REG_OFFSET_END {.name = NULL, .offset = 0}
124+
125+ static const struct pt_regs_offset regoffset_table [] = {
126+ REG_OFFSET_NAME (epc ),
127+ REG_OFFSET_NAME (ra ),
128+ REG_OFFSET_NAME (sp ),
129+ REG_OFFSET_NAME (gp ),
130+ REG_OFFSET_NAME (tp ),
131+ REG_OFFSET_NAME (t0 ),
132+ REG_OFFSET_NAME (t1 ),
133+ REG_OFFSET_NAME (t2 ),
134+ REG_OFFSET_NAME (s0 ),
135+ REG_OFFSET_NAME (s1 ),
136+ REG_OFFSET_NAME (a0 ),
137+ REG_OFFSET_NAME (a1 ),
138+ REG_OFFSET_NAME (a2 ),
139+ REG_OFFSET_NAME (a3 ),
140+ REG_OFFSET_NAME (a4 ),
141+ REG_OFFSET_NAME (a5 ),
142+ REG_OFFSET_NAME (a6 ),
143+ REG_OFFSET_NAME (a7 ),
144+ REG_OFFSET_NAME (s2 ),
145+ REG_OFFSET_NAME (s3 ),
146+ REG_OFFSET_NAME (s4 ),
147+ REG_OFFSET_NAME (s5 ),
148+ REG_OFFSET_NAME (s6 ),
149+ REG_OFFSET_NAME (s7 ),
150+ REG_OFFSET_NAME (s8 ),
151+ REG_OFFSET_NAME (s9 ),
152+ REG_OFFSET_NAME (s10 ),
153+ REG_OFFSET_NAME (s11 ),
154+ REG_OFFSET_NAME (t3 ),
155+ REG_OFFSET_NAME (t4 ),
156+ REG_OFFSET_NAME (t5 ),
157+ REG_OFFSET_NAME (t6 ),
158+ REG_OFFSET_NAME (status ),
159+ REG_OFFSET_NAME (badaddr ),
160+ REG_OFFSET_NAME (cause ),
161+ REG_OFFSET_NAME (orig_a0 ),
162+ REG_OFFSET_END ,
163+ };
164+
165+ /**
166+ * regs_query_register_offset() - query register offset from its name
167+ * @name: the name of a register
168+ *
169+ * regs_query_register_offset() returns the offset of a register in struct
170+ * pt_regs from its name. If the name is invalid, this returns -EINVAL;
171+ */
172+ int regs_query_register_offset (const char * name )
173+ {
174+ const struct pt_regs_offset * roff ;
175+
176+ for (roff = regoffset_table ; roff -> name != NULL ; roff ++ )
177+ if (!strcmp (roff -> name , name ))
178+ return roff -> offset ;
179+ return - EINVAL ;
180+ }
181+
182+ /**
183+ * regs_within_kernel_stack() - check the address in the stack
184+ * @regs: pt_regs which contains kernel stack pointer.
185+ * @addr: address which is checked.
186+ *
187+ * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
188+ * If @addr is within the kernel stack, it returns true. If not, returns false.
189+ */
190+ static bool regs_within_kernel_stack (struct pt_regs * regs , unsigned long addr )
191+ {
192+ return (addr & ~(THREAD_SIZE - 1 )) ==
193+ (kernel_stack_pointer (regs ) & ~(THREAD_SIZE - 1 ));
194+ }
195+
196+ /**
197+ * regs_get_kernel_stack_nth() - get Nth entry of the stack
198+ * @regs: pt_regs which contains kernel stack pointer.
199+ * @n: stack entry number.
200+ *
201+ * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
202+ * is specified by @regs. If the @n th entry is NOT in the kernel stack,
203+ * this returns 0.
204+ */
205+ unsigned long regs_get_kernel_stack_nth (struct pt_regs * regs , unsigned int n )
206+ {
207+ unsigned long * addr = (unsigned long * )kernel_stack_pointer (regs );
208+
209+ addr += n ;
210+ if (regs_within_kernel_stack (regs , (unsigned long )addr ))
211+ return * addr ;
212+ else
213+ return 0 ;
214+ }
215+
117216void ptrace_disable (struct task_struct * child )
118217{
119218 clear_tsk_thread_flag (child , TIF_SYSCALL_TRACE );
0 commit comments