| .. | .. |
|---|
| 37 | 37 | unsigned short __esh; |
|---|
| 38 | 38 | unsigned short fs; |
|---|
| 39 | 39 | unsigned short __fsh; |
|---|
| 40 | + /* On interrupt, gs and __gsh store the vector number. */ |
|---|
| 40 | 41 | unsigned short gs; |
|---|
| 41 | 42 | unsigned short __gsh; |
|---|
| 43 | + /* On interrupt, this is the error code. */ |
|---|
| 42 | 44 | unsigned long orig_ax; |
|---|
| 43 | 45 | unsigned long ip; |
|---|
| 44 | 46 | unsigned short cs; |
|---|
| .. | .. |
|---|
| 92 | 94 | #include <asm/paravirt_types.h> |
|---|
| 93 | 95 | #endif |
|---|
| 94 | 96 | |
|---|
| 97 | +#include <asm/proto.h> |
|---|
| 98 | + |
|---|
| 95 | 99 | struct cpuinfo_x86; |
|---|
| 96 | 100 | struct task_struct; |
|---|
| 97 | 101 | |
|---|
| 98 | 102 | extern unsigned long profile_pc(struct pt_regs *regs); |
|---|
| 99 | | -#define profile_pc profile_pc |
|---|
| 100 | 103 | |
|---|
| 101 | 104 | extern unsigned long |
|---|
| 102 | 105 | convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs); |
|---|
| 103 | | -extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, |
|---|
| 104 | | - int error_code, int si_code); |
|---|
| 106 | +extern void send_sigtrap(struct pt_regs *regs, int error_code, int si_code); |
|---|
| 105 | 107 | |
|---|
| 106 | 108 | |
|---|
| 107 | 109 | static inline unsigned long regs_return_value(struct pt_regs *regs) |
|---|
| .. | .. |
|---|
| 123 | 125 | * On x86_64, vm86 mode is mercifully nonexistent, and we don't need |
|---|
| 124 | 126 | * the extra check. |
|---|
| 125 | 127 | */ |
|---|
| 126 | | -static inline int user_mode(struct pt_regs *regs) |
|---|
| 128 | +static __always_inline int user_mode(struct pt_regs *regs) |
|---|
| 127 | 129 | { |
|---|
| 128 | 130 | #ifdef CONFIG_X86_32 |
|---|
| 129 | 131 | return ((regs->cs & SEGMENT_RPL_MASK) | (regs->flags & X86_VM_MASK)) >= USER_RPL; |
|---|
| .. | .. |
|---|
| 144 | 146 | static inline bool user_64bit_mode(struct pt_regs *regs) |
|---|
| 145 | 147 | { |
|---|
| 146 | 148 | #ifdef CONFIG_X86_64 |
|---|
| 147 | | -#ifndef CONFIG_PARAVIRT |
|---|
| 149 | +#ifndef CONFIG_PARAVIRT_XXL |
|---|
| 148 | 150 | /* |
|---|
| 149 | 151 | * On non-paravirt systems, this is the only long mode CPL 3 |
|---|
| 150 | 152 | * selector. We do not allow long mode selectors in the LDT. |
|---|
| .. | .. |
|---|
| 159 | 161 | #endif |
|---|
| 160 | 162 | } |
|---|
| 161 | 163 | |
|---|
| 164 | +/* |
|---|
| 165 | + * Determine whether the register set came from any context that is running in |
|---|
| 166 | + * 64-bit mode. |
|---|
| 167 | + */ |
|---|
| 168 | +static inline bool any_64bit_mode(struct pt_regs *regs) |
|---|
| 169 | +{ |
|---|
| 170 | +#ifdef CONFIG_X86_64 |
|---|
| 171 | + return !user_mode(regs) || user_64bit_mode(regs); |
|---|
| 172 | +#else |
|---|
| 173 | + return false; |
|---|
| 174 | +#endif |
|---|
| 175 | +} |
|---|
| 176 | + |
|---|
| 162 | 177 | #ifdef CONFIG_X86_64 |
|---|
| 163 | 178 | #define current_user_stack_pointer() current_pt_regs()->sp |
|---|
| 164 | 179 | #define compat_user_stack_pointer() current_pt_regs()->sp |
|---|
| 180 | + |
|---|
| 181 | +static inline bool ip_within_syscall_gap(struct pt_regs *regs) |
|---|
| 182 | +{ |
|---|
| 183 | + bool ret = (regs->ip >= (unsigned long)entry_SYSCALL_64 && |
|---|
| 184 | + regs->ip < (unsigned long)entry_SYSCALL_64_safe_stack); |
|---|
| 185 | + |
|---|
| 186 | +#ifdef CONFIG_IA32_EMULATION |
|---|
| 187 | + ret = ret || (regs->ip >= (unsigned long)entry_SYSCALL_compat && |
|---|
| 188 | + regs->ip < (unsigned long)entry_SYSCALL_compat_safe_stack); |
|---|
| 165 | 189 | #endif |
|---|
| 166 | 190 | |
|---|
| 167 | | -#ifdef CONFIG_X86_32 |
|---|
| 168 | | -extern unsigned long kernel_stack_pointer(struct pt_regs *regs); |
|---|
| 169 | | -#else |
|---|
| 191 | + return ret; |
|---|
| 192 | +} |
|---|
| 193 | +#endif |
|---|
| 194 | + |
|---|
| 170 | 195 | static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) |
|---|
| 171 | 196 | { |
|---|
| 172 | 197 | return regs->sp; |
|---|
| 173 | 198 | } |
|---|
| 174 | | -#endif |
|---|
| 175 | 199 | |
|---|
| 176 | | -#define GET_IP(regs) ((regs)->ip) |
|---|
| 177 | | -#define GET_FP(regs) ((regs)->bp) |
|---|
| 178 | | -#define GET_USP(regs) ((regs)->sp) |
|---|
| 200 | +static inline unsigned long instruction_pointer(struct pt_regs *regs) |
|---|
| 201 | +{ |
|---|
| 202 | + return regs->ip; |
|---|
| 203 | +} |
|---|
| 179 | 204 | |
|---|
| 180 | | -#include <asm-generic/ptrace.h> |
|---|
| 205 | +static inline void instruction_pointer_set(struct pt_regs *regs, |
|---|
| 206 | + unsigned long val) |
|---|
| 207 | +{ |
|---|
| 208 | + regs->ip = val; |
|---|
| 209 | +} |
|---|
| 210 | + |
|---|
| 211 | +static inline unsigned long frame_pointer(struct pt_regs *regs) |
|---|
| 212 | +{ |
|---|
| 213 | + return regs->bp; |
|---|
| 214 | +} |
|---|
| 215 | + |
|---|
| 216 | +static inline unsigned long user_stack_pointer(struct pt_regs *regs) |
|---|
| 217 | +{ |
|---|
| 218 | + return regs->sp; |
|---|
| 219 | +} |
|---|
| 220 | + |
|---|
| 221 | +static inline void user_stack_pointer_set(struct pt_regs *regs, |
|---|
| 222 | + unsigned long val) |
|---|
| 223 | +{ |
|---|
| 224 | + regs->sp = val; |
|---|
| 225 | +} |
|---|
| 226 | + |
|---|
| 227 | +static __always_inline bool regs_irqs_disabled(struct pt_regs *regs) |
|---|
| 228 | +{ |
|---|
| 229 | + return !(regs->flags & X86_EFLAGS_IF); |
|---|
| 230 | +} |
|---|
| 181 | 231 | |
|---|
| 182 | 232 | /* Query offset/name of register from its name/offset */ |
|---|
| 183 | 233 | extern int regs_query_register_offset(const char *name); |
|---|
| .. | .. |
|---|
| 199 | 249 | if (unlikely(offset > MAX_REG_OFFSET)) |
|---|
| 200 | 250 | return 0; |
|---|
| 201 | 251 | #ifdef CONFIG_X86_32 |
|---|
| 202 | | - /* |
|---|
| 203 | | - * Traps from the kernel do not save sp and ss. |
|---|
| 204 | | - * Use the helper function to retrieve sp. |
|---|
| 205 | | - */ |
|---|
| 206 | | - if (offset == offsetof(struct pt_regs, sp) && |
|---|
| 207 | | - regs->cs == __KERNEL_CS) |
|---|
| 208 | | - return kernel_stack_pointer(regs); |
|---|
| 209 | | - |
|---|
| 210 | 252 | /* The selector fields are 16-bit. */ |
|---|
| 211 | 253 | if (offset == offsetof(struct pt_regs, cs) || |
|---|
| 212 | 254 | offset == offsetof(struct pt_regs, ss) || |
|---|
| .. | .. |
|---|
| 232 | 274 | static inline int regs_within_kernel_stack(struct pt_regs *regs, |
|---|
| 233 | 275 | unsigned long addr) |
|---|
| 234 | 276 | { |
|---|
| 235 | | - return ((addr & ~(THREAD_SIZE - 1)) == |
|---|
| 236 | | - (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))); |
|---|
| 277 | + return ((addr & ~(THREAD_SIZE - 1)) == (regs->sp & ~(THREAD_SIZE - 1))); |
|---|
| 237 | 278 | } |
|---|
| 238 | 279 | |
|---|
| 239 | 280 | /** |
|---|
| .. | .. |
|---|
| 247 | 288 | */ |
|---|
| 248 | 289 | static inline unsigned long *regs_get_kernel_stack_nth_addr(struct pt_regs *regs, unsigned int n) |
|---|
| 249 | 290 | { |
|---|
| 250 | | - unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); |
|---|
| 291 | + unsigned long *addr = (unsigned long *)regs->sp; |
|---|
| 251 | 292 | |
|---|
| 252 | 293 | addr += n; |
|---|
| 253 | 294 | if (regs_within_kernel_stack(regs, (unsigned long)addr)) |
|---|
| .. | .. |
|---|
| 257 | 298 | } |
|---|
| 258 | 299 | |
|---|
| 259 | 300 | /* To avoid include hell, we can't include uaccess.h */ |
|---|
| 260 | | -extern long probe_kernel_read(void *dst, const void *src, size_t size); |
|---|
| 301 | +extern long copy_from_kernel_nofault(void *dst, const void *src, size_t size); |
|---|
| 261 | 302 | |
|---|
| 262 | 303 | /** |
|---|
| 263 | 304 | * regs_get_kernel_stack_nth() - get Nth entry of the stack |
|---|
| .. | .. |
|---|
| 277 | 318 | |
|---|
| 278 | 319 | addr = regs_get_kernel_stack_nth_addr(regs, n); |
|---|
| 279 | 320 | if (addr) { |
|---|
| 280 | | - ret = probe_kernel_read(&val, addr, sizeof(val)); |
|---|
| 321 | + ret = copy_from_kernel_nofault(&val, addr, sizeof(val)); |
|---|
| 281 | 322 | if (!ret) |
|---|
| 282 | 323 | return val; |
|---|
| 283 | 324 | } |
|---|
| 284 | 325 | return 0; |
|---|
| 326 | +} |
|---|
| 327 | + |
|---|
| 328 | +/** |
|---|
| 329 | + * regs_get_kernel_argument() - get Nth function argument in kernel |
|---|
| 330 | + * @regs: pt_regs of that context |
|---|
| 331 | + * @n: function argument number (start from 0) |
|---|
| 332 | + * |
|---|
| 333 | + * regs_get_argument() returns @n th argument of the function call. |
|---|
| 334 | + * Note that this chooses most probably assignment, in some case |
|---|
| 335 | + * it can be incorrect. |
|---|
| 336 | + * This is expected to be called from kprobes or ftrace with regs |
|---|
| 337 | + * where the top of stack is the return address. |
|---|
| 338 | + */ |
|---|
| 339 | +static inline unsigned long regs_get_kernel_argument(struct pt_regs *regs, |
|---|
| 340 | + unsigned int n) |
|---|
| 341 | +{ |
|---|
| 342 | + static const unsigned int argument_offs[] = { |
|---|
| 343 | +#ifdef __i386__ |
|---|
| 344 | + offsetof(struct pt_regs, ax), |
|---|
| 345 | + offsetof(struct pt_regs, dx), |
|---|
| 346 | + offsetof(struct pt_regs, cx), |
|---|
| 347 | +#define NR_REG_ARGUMENTS 3 |
|---|
| 348 | +#else |
|---|
| 349 | + offsetof(struct pt_regs, di), |
|---|
| 350 | + offsetof(struct pt_regs, si), |
|---|
| 351 | + offsetof(struct pt_regs, dx), |
|---|
| 352 | + offsetof(struct pt_regs, cx), |
|---|
| 353 | + offsetof(struct pt_regs, r8), |
|---|
| 354 | + offsetof(struct pt_regs, r9), |
|---|
| 355 | +#define NR_REG_ARGUMENTS 6 |
|---|
| 356 | +#endif |
|---|
| 357 | + }; |
|---|
| 358 | + |
|---|
| 359 | + if (n >= NR_REG_ARGUMENTS) { |
|---|
| 360 | + n -= NR_REG_ARGUMENTS - 1; |
|---|
| 361 | + return regs_get_kernel_stack_nth(regs, n); |
|---|
| 362 | + } else |
|---|
| 363 | + return regs_get_register(regs, argument_offs[n]); |
|---|
| 285 | 364 | } |
|---|
| 286 | 365 | |
|---|
| 287 | 366 | #define arch_has_single_step() (1) |
|---|
| .. | .. |
|---|
| 291 | 370 | #define arch_has_block_step() (boot_cpu_data.x86 >= 6) |
|---|
| 292 | 371 | #endif |
|---|
| 293 | 372 | |
|---|
| 294 | | -#define ARCH_HAS_USER_SINGLE_STEP_INFO |
|---|
| 295 | | - |
|---|
| 296 | | -/* |
|---|
| 297 | | - * When hitting ptrace_stop(), we cannot return using SYSRET because |
|---|
| 298 | | - * that does not restore the full CPU state, only a minimal set. The |
|---|
| 299 | | - * ptracer can change arbitrary register values, which is usually okay |
|---|
| 300 | | - * because the usual ptrace stops run off the signal delivery path which |
|---|
| 301 | | - * forces IRET; however, ptrace_event() stops happen in arbitrary places |
|---|
| 302 | | - * in the kernel and don't force IRET path. |
|---|
| 303 | | - * |
|---|
| 304 | | - * So force IRET path after a ptrace stop. |
|---|
| 305 | | - */ |
|---|
| 306 | | -#define arch_ptrace_stop_needed(code, info) \ |
|---|
| 307 | | -({ \ |
|---|
| 308 | | - force_iret(); \ |
|---|
| 309 | | - false; \ |
|---|
| 310 | | -}) |
|---|
| 373 | +#define ARCH_HAS_USER_SINGLE_STEP_REPORT |
|---|
| 311 | 374 | |
|---|
| 312 | 375 | struct user_desc; |
|---|
| 313 | 376 | extern int do_get_thread_area(struct task_struct *p, int idx, |
|---|
| .. | .. |
|---|
| 315 | 378 | extern int do_set_thread_area(struct task_struct *p, int idx, |
|---|
| 316 | 379 | struct user_desc __user *info, int can_allocate); |
|---|
| 317 | 380 | |
|---|
| 381 | +#ifdef CONFIG_X86_64 |
|---|
| 382 | +# define do_set_thread_area_64(p, s, t) do_arch_prctl_64(p, s, t) |
|---|
| 383 | +#else |
|---|
| 384 | +# define do_set_thread_area_64(p, s, t) (0) |
|---|
| 385 | +#endif |
|---|
| 386 | + |
|---|
| 318 | 387 | #endif /* !__ASSEMBLY__ */ |
|---|
| 319 | 388 | #endif /* _ASM_X86_PTRACE_H */ |
|---|