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 "ptrace_user.h" | |
9 | #include "uml-config.h" | |
10 | #include "skas_ptregs.h" | |
11 | #include "registers.h" | |
13c06be3 | 12 | #include "longjmp.h" |
1da177e4 LT |
13 | #include "user.h" |
14 | ||
15 | /* These are set once at boot time and not changed thereafter */ | |
16 | ||
17 | static unsigned long exec_regs[HOST_FRAME_SIZE]; | |
18 | static unsigned long exec_fp_regs[HOST_FP_SIZE]; | |
19 | ||
20 | void init_thread_registers(union uml_pt_regs *to) | |
21 | { | |
22 | memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs)); | |
23 | memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp)); | |
24 | } | |
25 | ||
26 | static int move_registers(int pid, int int_op, int fp_op, | |
27 | union uml_pt_regs *regs) | |
28 | { | |
29 | if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) | |
6c59e2f5 | 30 | return -errno; |
1da177e4 LT |
31 | |
32 | if(ptrace(fp_op, pid, 0, regs->skas.fp) < 0) | |
6c59e2f5 | 33 | return -errno; |
1da177e4 | 34 | |
6c59e2f5 | 35 | return 0; |
1da177e4 LT |
36 | } |
37 | ||
38 | void save_registers(int pid, union uml_pt_regs *regs) | |
39 | { | |
40 | int err; | |
41 | ||
42 | err = move_registers(pid, PTRACE_GETREGS, PTRACE_GETFPREGS, regs); | |
43 | if(err) | |
44 | panic("save_registers - saving registers failed, errno = %d\n", | |
45 | -err); | |
46 | } | |
47 | ||
48 | void restore_registers(int pid, union uml_pt_regs *regs) | |
49 | { | |
50 | int err; | |
51 | ||
52 | err = move_registers(pid, PTRACE_SETREGS, PTRACE_SETFPREGS, regs); | |
53 | if(err) | |
54 | panic("restore_registers - saving registers failed, " | |
55 | "errno = %d\n", -err); | |
56 | } | |
57 | ||
58 | void init_registers(int pid) | |
59 | { | |
60 | int err; | |
61 | ||
62 | err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); | |
63 | if(err) | |
64 | panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", | |
2ace87b9 | 65 | errno); |
1da177e4 LT |
66 | |
67 | err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); | |
68 | if(err) | |
69 | panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", | |
2ace87b9 | 70 | errno); |
1da177e4 LT |
71 | } |
72 | ||
e2216feb | 73 | void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) |
d67b569f JD |
74 | { |
75 | memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long)); | |
e2216feb JD |
76 | if(fp_regs != NULL) |
77 | memcpy(fp_regs, exec_fp_regs, | |
78 | HOST_FP_SIZE * sizeof(unsigned long)); | |
d67b569f JD |
79 | } |
80 | ||
75e29b18 | 81 | unsigned long get_thread_reg(int reg, jmp_buf *buf) |
fad1c45c | 82 | { |
75e29b18 JD |
83 | switch(reg){ |
84 | case RIP: return buf[0]->__rip; | |
85 | case RSP: return buf[0]->__rsp; | |
86 | case RBP: return buf[0]->__rbp; | |
87 | default: | |
88 | printk("get_thread_regs - unknown register %d\n", reg); | |
89 | return 0; | |
90 | } | |
fad1c45c | 91 | } |