blob: 41bfe84e11ab0e2bfad89a2e4e1d994f1c8fc288 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Copyright (C) 2004 PathScale, Inc
Jeff Dikef0c4cad2007-10-16 01:27:18 -07003 * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 * Licensed under the GPL
5 */
6
7#include <errno.h>
Al Viro3787fa62008-05-21 06:32:11 +01008#include <sys/ptrace.h>
Richard Weinberger38b64ae2011-08-18 21:58:07 +02009#ifdef __i386__
Jeff Dike14c8a772008-06-12 15:21:40 -070010#include <sys/user.h>
Richard Weinberger38b64ae2011-08-18 21:58:07 +020011#endif
Al Viro37185b32012-10-08 03:27:32 +010012#include <longjmp.h>
13#include <sysdep/ptrace_user.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014
Linus Torvalds1da177e2005-04-16 15:20:36 -070015int save_fp_registers(int pid, unsigned long *fp_regs)
16{
Jeff Dikef0c4cad2007-10-16 01:27:18 -070017 if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
Jeff Dike6c59e2f2007-02-10 01:44:26 -080018 return -errno;
19 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070020}
21
22int restore_fp_registers(int pid, unsigned long *fp_regs)
23{
Jeff Dikef0c4cad2007-10-16 01:27:18 -070024 if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
Jeff Dike6c59e2f2007-02-10 01:44:26 -080025 return -errno;
26 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070027}
28
Al Viro51d34742011-08-18 20:03:49 +010029#ifdef __i386__
30int have_fpx_regs = 1;
Jeff Dikea5f6096c2007-10-16 01:27:15 -070031int save_fpx_registers(int pid, unsigned long *fp_regs)
32{
Jeff Dikef0c4cad2007-10-16 01:27:18 -070033 if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0)
Jeff Dikea5f6096c2007-10-16 01:27:15 -070034 return -errno;
35 return 0;
36}
37
38int restore_fpx_registers(int pid, unsigned long *fp_regs)
39{
Jeff Dikef0c4cad2007-10-16 01:27:18 -070040 if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0)
Jeff Dikea5f6096c2007-10-16 01:27:15 -070041 return -errno;
42 return 0;
43}
44
Jeff Dike2f56deb2008-02-23 15:23:49 -080045int get_fp_registers(int pid, unsigned long *regs)
46{
47 if (have_fpx_regs)
48 return save_fpx_registers(pid, regs);
49 else
50 return save_fp_registers(pid, regs);
51}
52
53int put_fp_registers(int pid, unsigned long *regs)
54{
55 if (have_fpx_regs)
56 return restore_fpx_registers(pid, regs);
57 else
58 return restore_fp_registers(pid, regs);
59}
60
Jeff Dikea5f6096c2007-10-16 01:27:15 -070061void arch_init_registers(int pid)
62{
Jeff Dike14c8a772008-06-12 15:21:40 -070063 struct user_fpxregs_struct fpx_regs;
Jeff Dikea5f6096c2007-10-16 01:27:15 -070064 int err;
65
Jeff Dike47906dd2008-05-12 14:01:50 -070066 err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs);
Jeff Dike5134d8f2008-02-08 04:22:08 -080067 if (!err)
Jeff Dikea5f6096c2007-10-16 01:27:15 -070068 return;
69
Jeff Dike5134d8f2008-02-08 04:22:08 -080070 if (errno != EIO)
Jeff Dikea5f6096c2007-10-16 01:27:15 -070071 panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
72 errno);
73
74 have_fpx_regs = 0;
75}
Al Viro51d34742011-08-18 20:03:49 +010076#else
77
78int get_fp_registers(int pid, unsigned long *regs)
79{
80 return save_fp_registers(pid, regs);
81}
82
83int put_fp_registers(int pid, unsigned long *regs)
84{
85 return restore_fp_registers(pid, regs);
86}
87
88#endif
89
90unsigned long get_thread_reg(int reg, jmp_buf *buf)
91{
92 switch (reg) {
93#ifdef __i386__
Al Viroa10c95d2011-08-18 20:12:09 +010094 case HOST_IP:
Al Viro51d34742011-08-18 20:03:49 +010095 return buf[0]->__eip;
Al Viroa10c95d2011-08-18 20:12:09 +010096 case HOST_SP:
Al Viro51d34742011-08-18 20:03:49 +010097 return buf[0]->__esp;
Al Viroa10c95d2011-08-18 20:12:09 +010098 case HOST_BP:
Al Viro51d34742011-08-18 20:03:49 +010099 return buf[0]->__ebp;
100#else
Al Viroa10c95d2011-08-18 20:12:09 +0100101 case HOST_IP:
Al Viro51d34742011-08-18 20:03:49 +0100102 return buf[0]->__rip;
Al Viroa10c95d2011-08-18 20:12:09 +0100103 case HOST_SP:
Al Viro51d34742011-08-18 20:03:49 +0100104 return buf[0]->__rsp;
Al Viroa10c95d2011-08-18 20:12:09 +0100105 case HOST_BP:
Al Viro51d34742011-08-18 20:03:49 +0100106 return buf[0]->__rbp;
107#endif
108 default:
109 printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
110 reg);
111 return 0;
112 }
113}