1 /*-
2 * Copyright (c) 2005 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD: releng/11.0/sys/i386/i386/ptrace_machdep.c 284919 2015-06-29 07:07:24Z kib $");
30
31 #include "opt_cpu.h"
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/malloc.h>
36 #include <sys/proc.h>
37 #include <sys/ptrace.h>
38 #include <machine/frame.h>
39 #include <machine/md_var.h>
40 #include <machine/pcb.h>
41
42 #if !defined(CPU_DISABLE_SSE) && defined(I686_CPU)
43 #define CPU_ENABLE_SSE
44 #endif
45
46 #ifdef CPU_ENABLE_SSE
47 static int
48 cpu_ptrace_xstate(struct thread *td, int req, void *addr, int data)
49 {
50 struct ptrace_xstate_info info;
51 char *savefpu;
52 int error;
53
54 if (!use_xsave)
55 return (EOPNOTSUPP);
56
57 switch (req) {
58 case PT_GETXSTATE_OLD:
59 npxgetregs(td);
60 savefpu = (char *)(get_pcb_user_save_td(td) + 1);
61 error = copyout(savefpu, addr,
62 cpu_max_ext_state_size - sizeof(union savefpu));
63 break;
64
65 case PT_SETXSTATE_OLD:
66 if (data > cpu_max_ext_state_size - sizeof(union savefpu)) {
67 error = EINVAL;
68 break;
69 }
70 savefpu = malloc(data, M_TEMP, M_WAITOK);
71 error = copyin(addr, savefpu, data);
72 if (error == 0) {
73 npxgetregs(td);
74 error = npxsetxstate(td, savefpu, data);
75 }
76 free(savefpu, M_TEMP);
77 break;
78
79 case PT_GETXSTATE_INFO:
80 if (data != sizeof(info)) {
81 error = EINVAL;
82 break;
83 }
84 info.xsave_len = cpu_max_ext_state_size;
85 info.xsave_mask = xsave_mask;
86 error = copyout(&info, addr, data);
87 break;
88
89 case PT_GETXSTATE:
90 npxgetregs(td);
91 savefpu = (char *)(get_pcb_user_save_td(td));
92 error = copyout(savefpu, addr, cpu_max_ext_state_size);
93 break;
94
95 case PT_SETXSTATE:
96 if (data < sizeof(union savefpu) ||
97 data > cpu_max_ext_state_size) {
98 error = EINVAL;
99 break;
100 }
101 savefpu = malloc(data, M_TEMP, M_WAITOK);
102 error = copyin(addr, savefpu, data);
103 if (error == 0)
104 error = npxsetregs(td, (union savefpu *)savefpu,
105 savefpu + sizeof(union savefpu), data -
106 sizeof(union savefpu));
107 free(savefpu, M_TEMP);
108 break;
109
110 default:
111 error = EINVAL;
112 break;
113 }
114
115 return (error);
116 }
117 #endif
118
119 static int
120 cpu_ptrace_xmm(struct thread *td, int req, void *addr, int data)
121 {
122 #ifdef CPU_ENABLE_SSE
123 struct savexmm *fpstate;
124 int error;
125
126 if (!cpu_fxsr)
127 return (EINVAL);
128
129 fpstate = &get_pcb_user_save_td(td)->sv_xmm;
130 switch (req) {
131 case PT_GETXMMREGS:
132 npxgetregs(td);
133 error = copyout(fpstate, addr, sizeof(*fpstate));
134 break;
135
136 case PT_SETXMMREGS:
137 npxgetregs(td);
138 error = copyin(addr, fpstate, sizeof(*fpstate));
139 fpstate->sv_env.en_mxcsr &= cpu_mxcsr_mask;
140 break;
141
142 case PT_GETXSTATE_OLD:
143 case PT_SETXSTATE_OLD:
144 case PT_GETXSTATE_INFO:
145 case PT_GETXSTATE:
146 case PT_SETXSTATE:
147 error = cpu_ptrace_xstate(td, req, addr, data);
148 break;
149
150 default:
151 return (EINVAL);
152 }
153
154 return (error);
155 #else
156 return (EINVAL);
157 #endif
158 }
159
160 int
161 cpu_ptrace(struct thread *td, int req, void *addr, int data)
162 {
163 struct segment_descriptor *sdp, sd;
164 register_t r;
165 int error;
166
167 switch (req) {
168 case PT_GETXMMREGS:
169 case PT_SETXMMREGS:
170 case PT_GETXSTATE_OLD:
171 case PT_SETXSTATE_OLD:
172 case PT_GETXSTATE_INFO:
173 case PT_GETXSTATE:
174 case PT_SETXSTATE:
175 error = cpu_ptrace_xmm(td, req, addr, data);
176 break;
177
178 case PT_GETFSBASE:
179 case PT_GETGSBASE:
180 sdp = req == PT_GETFSBASE ? &td->td_pcb->pcb_fsd :
181 &td->td_pcb->pcb_gsd;
182 r = sdp->sd_hibase << 24 | sdp->sd_lobase;
183 error = copyout(&r, addr, sizeof(r));
184 break;
185
186 case PT_SETFSBASE:
187 case PT_SETGSBASE:
188 error = copyin(addr, &r, sizeof(r));
189 if (error != 0)
190 break;
191 fill_based_sd(&sd, r);
192 if (req == PT_SETFSBASE) {
193 td->td_pcb->pcb_fsd = sd;
194 td->td_frame->tf_fs = GSEL(GUFS_SEL, SEL_UPL);
195 } else {
196 td->td_pcb->pcb_gsd = sd;
197 td->td_pcb->pcb_gs = GSEL(GUGS_SEL, SEL_UPL);
198 }
199 break;
200
201 default:
202 return (EINVAL);
203 }
204
205 return (error);
206 }
Cache object: ab5f03db486ef2f319add8c3928f0a29
|