Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Copyright (C) 2004 PathScale, Inc | |
3 | * Licensed under the GPL | |
4 | */ | |
5 | ||
6 | #include <errno.h> | |
7 | #include <string.h> | |
8 | #include "sysdep/ptrace_user.h" | |
9 | #include "sysdep/ptrace.h" | |
10 | #include "uml-config.h" | |
11 | #include "skas_ptregs.h" | |
12 | #include "registers.h" | |
13c06be3 | 13 | #include "longjmp.h" |
1da177e4 LT |
14 | #include "user.h" |
15 | ||
16 | /* These are set once at boot time and not changed thereafter */ | |
17 | ||
18 | static unsigned long exec_regs[HOST_FRAME_SIZE]; | |
19 | static unsigned long exec_fp_regs[HOST_FP_SIZE]; | |
20 | static unsigned long exec_fpx_regs[HOST_XFP_SIZE]; | |
21 | static int have_fpx_regs = 1; | |
22 | ||
23 | void init_thread_registers(union uml_pt_regs *to) | |
24 | { | |
25 | memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs)); | |
26 | memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp)); | |
27 | if(have_fpx_regs) | |
28 | memcpy(to->skas.xfp, exec_fpx_regs, sizeof(to->skas.xfp)); | |
29 | } | |
30 | ||
31 | /* XXX These need to use [GS]ETFPXREGS and copy_sc_{to,from}_user_skas needs | |
32 | * to pass in a sufficiently large buffer | |
33 | */ | |
34 | int save_fp_registers(int pid, unsigned long *fp_regs) | |
35 | { | |
36 | if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) | |
6c59e2f5 JD |
37 | return -errno; |
38 | return 0; | |
1da177e4 LT |
39 | } |
40 | ||
41 | int restore_fp_registers(int pid, unsigned long *fp_regs) | |
42 | { | |
43 | if(ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) | |
6c59e2f5 JD |
44 | return -errno; |
45 | return 0; | |
1da177e4 LT |
46 | } |
47 | ||
48 | static int move_registers(int pid, int int_op, union uml_pt_regs *regs, | |
49 | int fp_op, unsigned long *fp_regs) | |
50 | { | |
51 | if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) | |
6c59e2f5 | 52 | return -errno; |
1da177e4 LT |
53 | |
54 | if(ptrace(fp_op, pid, 0, fp_regs) < 0) | |
6c59e2f5 | 55 | return -errno; |
1da177e4 | 56 | |
6c59e2f5 | 57 | return 0; |
1da177e4 LT |
58 | } |
59 | ||
60 | void save_registers(int pid, union uml_pt_regs *regs) | |
61 | { | |
62 | unsigned long *fp_regs; | |
63 | int err, fp_op; | |
64 | ||
65 | if(have_fpx_regs){ | |
66 | fp_op = PTRACE_GETFPXREGS; | |
67 | fp_regs = regs->skas.xfp; | |
68 | } | |
69 | else { | |
70 | fp_op = PTRACE_GETFPREGS; | |
71 | fp_regs = regs->skas.fp; | |
72 | } | |
73 | ||
74 | err = move_registers(pid, PTRACE_GETREGS, regs, fp_op, fp_regs); | |
75 | if(err) | |
76 | panic("save_registers - saving registers failed, errno = %d\n", | |
77 | -err); | |
78 | } | |
79 | ||
80 | void restore_registers(int pid, union uml_pt_regs *regs) | |
81 | { | |
82 | unsigned long *fp_regs; | |
83 | int err, fp_op; | |
84 | ||
85 | if(have_fpx_regs){ | |
86 | fp_op = PTRACE_SETFPXREGS; | |
87 | fp_regs = regs->skas.xfp; | |
88 | } | |
89 | else { | |
90 | fp_op = PTRACE_SETFPREGS; | |
91 | fp_regs = regs->skas.fp; | |
92 | } | |
93 | ||
94 | err = move_registers(pid, PTRACE_SETREGS, regs, fp_op, fp_regs); | |
95 | if(err) | |
96 | panic("restore_registers - saving registers failed, " | |
97 | "errno = %d\n", -err); | |
98 | } | |
99 | ||
100 | void init_registers(int pid) | |
101 | { | |
102 | int err; | |
103 | ||
104 | err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); | |
105 | if(err) | |
106 | panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", | |
2ace87b9 | 107 | errno); |
1da177e4 | 108 | |
6aec3072 | 109 | errno = 0; |
1da177e4 LT |
110 | err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs); |
111 | if(!err) | |
112 | return; | |
6aec3072 AL |
113 | if(errno != EIO) |
114 | panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", | |
115 | errno); | |
1da177e4 LT |
116 | |
117 | have_fpx_regs = 0; | |
1da177e4 LT |
118 | |
119 | err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); | |
120 | if(err) | |
121 | panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", | |
2ace87b9 | 122 | errno); |
1da177e4 LT |
123 | } |
124 | ||
e2216feb | 125 | void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) |
d67b569f JD |
126 | { |
127 | memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long)); | |
e2216feb JD |
128 | if(fp_regs != NULL) |
129 | memcpy(fp_regs, exec_fp_regs, | |
130 | HOST_FP_SIZE * sizeof(unsigned long)); | |
d67b569f JD |
131 | } |
132 | ||
75e29b18 | 133 | unsigned long get_thread_reg(int reg, jmp_buf *buf) |
fad1c45c | 134 | { |
75e29b18 JD |
135 | switch(reg){ |
136 | case EIP: return buf[0]->__eip; | |
137 | case UESP: return buf[0]->__esp; | |
138 | case EBP: return buf[0]->__ebp; | |
139 | default: | |
140 | printk("get_thread_regs - unknown register %d\n", reg); | |
141 | return 0; | |
142 | } | |
fad1c45c | 143 | } |