Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

openrisc: Add HAVE_REGS_AND_STACK_ACCESS_API support

Support for HAVE_REGS_AND_STACK_ACCESS_API needed for restartable
sequences.

The implementation has been copied from riscv and tested with the
restartable sequences self tests.

Note, pt-regs members are 'long' on openrisc which require casts for the
api, someday we should try to update these to be 'unsigned long' as
that's what they really are.

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
[stafford: Updated commit message]
Signed-off-by: Stafford Horne <shorne@gmail.com>

authored by

Michael Jeanson and committed by
Stafford Horne
7ce8716e 134502ab

+169 -1
+1
arch/openrisc/Kconfig
··· 27 27 select HAVE_PCI 28 28 select HAVE_UID16 29 29 select HAVE_PAGE_SIZE_8KB 30 + select HAVE_REGS_AND_STACK_ACCESS_API 30 31 select GENERIC_ATOMIC64 31 32 select GENERIC_CLOCKEVENTS_BROADCAST 32 33 select GENERIC_SMP_IDLE_THREAD
+72 -1
arch/openrisc/include/asm/ptrace.h
··· 17 17 18 18 #include <asm/spr_defs.h> 19 19 #include <uapi/asm/ptrace.h> 20 + #include <linux/compiler.h> 20 21 21 22 /* 22 23 * Make kernel PTrace/register structures opaque to userspace... userspace can ··· 43 42 /* Named registers */ 44 43 long sr; /* Stored in place of r0 */ 45 44 long sp; /* r1 */ 45 + long gpr2; 46 + long gpr3; 47 + long gpr4; 48 + long gpr5; 49 + long gpr6; 50 + long gpr7; 51 + long gpr8; 52 + long gpr9; 53 + long gpr10; 54 + long gpr11; 55 + long gpr12; 56 + long gpr13; 57 + long gpr14; 58 + long gpr15; 59 + long gpr16; 60 + long gpr17; 61 + long gpr18; 62 + long gpr19; 63 + long gpr20; 64 + long gpr21; 65 + long gpr22; 66 + long gpr23; 67 + long gpr24; 68 + long gpr25; 69 + long gpr26; 70 + long gpr27; 71 + long gpr28; 72 + long gpr29; 73 + long gpr30; 74 + long gpr31; 46 75 }; 47 76 struct { 48 77 /* Old style */ ··· 97 66 /* TODO: Rename this to REDZONE because that's what it is */ 98 67 #define STACK_FRAME_OVERHEAD 128 /* size of minimum stack frame */ 99 68 100 - #define instruction_pointer(regs) ((regs)->pc) 69 + #define MAX_REG_OFFSET offsetof(struct pt_regs, orig_gpr11) 70 + 71 + /* Helpers for working with the instruction pointer */ 72 + static inline unsigned long instruction_pointer(struct pt_regs *regs) 73 + { 74 + return (unsigned long)regs->pc; 75 + } 76 + static inline void instruction_pointer_set(struct pt_regs *regs, 77 + unsigned long val) 78 + { 79 + regs->pc = val; 80 + } 81 + 101 82 #define user_mode(regs) (((regs)->sr & SPR_SR_SM) == 0) 102 83 #define user_stack_pointer(regs) ((unsigned long)(regs)->sp) 103 84 #define profile_pc(regs) instruction_pointer(regs) 104 85 86 + /* Valid only for Kernel mode traps. */ 87 + static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) 88 + { 89 + return (unsigned long)regs->sp; 90 + } 91 + 105 92 static inline long regs_return_value(struct pt_regs *regs) 106 93 { 107 94 return regs->gpr[11]; 95 + } 96 + 97 + extern int regs_query_register_offset(const char *name); 98 + extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, 99 + unsigned int n); 100 + 101 + /** 102 + * regs_get_register() - get register value from its offset 103 + * @regs: pt_regs from which register value is gotten 104 + * @offset: offset of the register. 105 + * 106 + * regs_get_register returns the value of a register whose offset from @regs. 107 + * The @offset is the offset of the register in struct pt_regs. 108 + * If @offset is bigger than MAX_REG_OFFSET, this returns 0. 109 + */ 110 + static inline unsigned long regs_get_register(struct pt_regs *regs, 111 + unsigned int offset) 112 + { 113 + if (unlikely(offset > MAX_REG_OFFSET)) 114 + return 0; 115 + 116 + return *(unsigned long *)((unsigned long)regs + offset); 108 117 } 109 118 110 119 #endif /* __ASSEMBLY__ */
+96
arch/openrisc/kernel/ptrace.c
··· 160 160 * in exit.c or in signal.c. 161 161 */ 162 162 163 + struct pt_regs_offset { 164 + const char *name; 165 + int offset; 166 + }; 167 + 168 + #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)} 169 + #define REG_OFFSET_END {.name = NULL, .offset = 0} 170 + 171 + static const struct pt_regs_offset regoffset_table[] = { 172 + REG_OFFSET_NAME(sr), 173 + REG_OFFSET_NAME(sp), 174 + REG_OFFSET_NAME(gpr2), 175 + REG_OFFSET_NAME(gpr3), 176 + REG_OFFSET_NAME(gpr4), 177 + REG_OFFSET_NAME(gpr5), 178 + REG_OFFSET_NAME(gpr6), 179 + REG_OFFSET_NAME(gpr7), 180 + REG_OFFSET_NAME(gpr8), 181 + REG_OFFSET_NAME(gpr9), 182 + REG_OFFSET_NAME(gpr10), 183 + REG_OFFSET_NAME(gpr11), 184 + REG_OFFSET_NAME(gpr12), 185 + REG_OFFSET_NAME(gpr13), 186 + REG_OFFSET_NAME(gpr14), 187 + REG_OFFSET_NAME(gpr15), 188 + REG_OFFSET_NAME(gpr16), 189 + REG_OFFSET_NAME(gpr17), 190 + REG_OFFSET_NAME(gpr18), 191 + REG_OFFSET_NAME(gpr19), 192 + REG_OFFSET_NAME(gpr20), 193 + REG_OFFSET_NAME(gpr21), 194 + REG_OFFSET_NAME(gpr22), 195 + REG_OFFSET_NAME(gpr23), 196 + REG_OFFSET_NAME(gpr24), 197 + REG_OFFSET_NAME(gpr25), 198 + REG_OFFSET_NAME(gpr26), 199 + REG_OFFSET_NAME(gpr27), 200 + REG_OFFSET_NAME(gpr28), 201 + REG_OFFSET_NAME(gpr29), 202 + REG_OFFSET_NAME(gpr30), 203 + REG_OFFSET_NAME(gpr31), 204 + REG_OFFSET_NAME(pc), 205 + REG_OFFSET_NAME(orig_gpr11), 206 + REG_OFFSET_END, 207 + }; 208 + 209 + /** 210 + * regs_query_register_offset() - query register offset from its name 211 + * @name: the name of a register 212 + * 213 + * regs_query_register_offset() returns the offset of a register in struct 214 + * pt_regs from its name. If the name is invalid, this returns -EINVAL; 215 + */ 216 + int regs_query_register_offset(const char *name) 217 + { 218 + const struct pt_regs_offset *roff; 219 + 220 + for (roff = regoffset_table; roff->name != NULL; roff++) 221 + if (!strcmp(roff->name, name)) 222 + return roff->offset; 223 + return -EINVAL; 224 + } 225 + 226 + /** 227 + * regs_within_kernel_stack() - check the address in the stack 228 + * @regs: pt_regs which contains kernel stack pointer. 229 + * @addr: address which is checked. 230 + * 231 + * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). 232 + * If @addr is within the kernel stack, it returns true. If not, returns false. 233 + */ 234 + static bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) 235 + { 236 + return (addr & ~(THREAD_SIZE - 1)) == 237 + (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)); 238 + } 239 + 240 + /** 241 + * regs_get_kernel_stack_nth() - get Nth entry of the stack 242 + * @regs: pt_regs which contains kernel stack pointer. 243 + * @n: stack entry number. 244 + * 245 + * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which 246 + * is specified by @regs. If the @n th entry is NOT in the kernel stack, 247 + * this returns 0. 248 + */ 249 + unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) 250 + { 251 + unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); 252 + 253 + addr += n; 254 + if (regs_within_kernel_stack(regs, (unsigned long)addr)) 255 + return *addr; 256 + else 257 + return 0; 258 + } 163 259 164 260 /* 165 261 * Called by kernel/ptrace.c when detaching..