Annotation of sys/arch/i386/i386/process_machdep.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: process_machdep.c,v 1.22 2007/05/08 20:26:54 deraadt Exp $ */
2: /* $NetBSD: process_machdep.c,v 1.22 1996/05/03 19:42:25 christos Exp $ */
3:
4: /*
5: * Copyright (c) 1995, 1996 Charles M. Hannum. All rights reserved.
6: * Copyright (c) 1993 The Regents of the University of California.
7: * Copyright (c) 1993 Jan-Simon Pendry
8: * All rights reserved.
9: *
10: * This code is derived from software contributed to Berkeley by
11: * Jan-Simon Pendry.
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. Neither the name of the University nor the names of its contributors
22: * may be used to endorse or promote products derived from this software
23: * without specific prior written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35: * SUCH DAMAGE.
36: *
37: * From:
38: * Id: procfs_i386.c,v 4.1 1993/12/17 10:47:45 jsp Rel
39: */
40:
41: /*
42: * This file may seem a bit stylized, but that so that it's easier to port.
43: * Functions to be implemented here are:
44: *
45: * process_read_regs(proc, regs)
46: * Get the current user-visible register set from the process
47: * and copy it into the regs structure (<machine/reg.h>).
48: * The process is stopped at the time read_regs is called.
49: *
50: * process_write_regs(proc, regs)
51: * Update the current register set from the passed in regs
52: * structure. Take care to avoid clobbering special CPU
53: * registers or privileged bits in the PSL.
54: * The process is stopped at the time write_regs is called.
55: *
56: * process_sstep(proc)
57: * Arrange for the process to trap after executing a single instruction.
58: *
59: * process_set_pc(proc)
60: * Set the process's program counter.
61: */
62:
63: #include <sys/param.h>
64: #include <sys/systm.h>
65: #include <sys/time.h>
66: #include <sys/kernel.h>
67: #include <sys/proc.h>
68: #include <sys/user.h>
69: #include <sys/vnode.h>
70: #include <sys/ptrace.h>
71:
72: #include <machine/psl.h>
73: #include <machine/reg.h>
74: #include <machine/segments.h>
75:
76: #ifdef VM86
77: #include <machine/vm86.h>
78: #endif
79:
80: #include "npx.h"
81:
82: static __inline struct trapframe *process_frame(struct proc *);
83: static __inline union savefpu *process_fpframe(struct proc *);
84: void process_fninit_xmm(struct savexmm *);
85:
86: static __inline struct trapframe *
87: process_frame(struct proc *p)
88: {
89:
90: return (p->p_md.md_regs);
91: }
92:
93: static __inline union savefpu *
94: process_fpframe(struct proc *p)
95: {
96:
97: return (&p->p_addr->u_pcb.pcb_savefpu);
98: }
99:
100: void
101: process_xmm_to_s87(const struct savexmm *sxmm, struct save87 *s87)
102: {
103: int i;
104:
105: /* FPU control/status */
106: s87->sv_env.en_cw = sxmm->sv_env.en_cw;
107: s87->sv_env.en_sw = sxmm->sv_env.en_sw;
108: /* tag word handled below */
109: s87->sv_env.en_fip = sxmm->sv_env.en_fip;
110: s87->sv_env.en_fcs = sxmm->sv_env.en_fcs;
111: s87->sv_env.en_opcode = sxmm->sv_env.en_opcode;
112: s87->sv_env.en_foo = sxmm->sv_env.en_foo;
113: s87->sv_env.en_fos = sxmm->sv_env.en_fos;
114:
115: /* Tag word and registers. */
116: for (i = 0; i < 8; i++) {
117: if (sxmm->sv_env.en_tw & (1U << i))
118: s87->sv_env.en_tw &= ~(3U << (i * 2));
119: else
120: s87->sv_env.en_tw |= (3U << (i * 2));
121:
122: if (sxmm->sv_ex_tw & (1U << i))
123: s87->sv_ex_tw &= ~(3U << (i * 2));
124: else
125: s87->sv_ex_tw |= (3U << (i * 2));
126:
127: memcpy(&s87->sv_ac[i].fp_bytes, &sxmm->sv_ac[i].fp_bytes,
128: sizeof(s87->sv_ac[i].fp_bytes));
129: }
130:
131: s87->sv_ex_sw = sxmm->sv_ex_sw;
132: }
133:
134: void
135: process_fninit_xmm(struct savexmm *sxmm)
136: {
137: /*
138: * The initial control word was already set by setregs(), so
139: * save it temporarily.
140: */
141: uint32_t mxcsr = sxmm->sv_env.en_mxcsr;
142: uint16_t cw = sxmm->sv_env.en_cw;
143:
144: /* XXX Don't zero XMM regs? */
145: memset(sxmm, 0, sizeof(*sxmm));
146: sxmm->sv_env.en_cw = cw;
147: sxmm->sv_env.en_mxcsr = mxcsr;
148: sxmm->sv_env.en_sw = 0x0000;
149: sxmm->sv_env.en_tw = 0x00;
150: }
151:
152: int
153: process_read_regs(struct proc *p, struct reg *regs)
154: {
155: struct trapframe *tf = process_frame(p);
156:
157: #ifdef VM86
158: if (tf->tf_eflags & PSL_VM) {
159: regs->r_gs = tf->tf_vm86_gs & 0xffff;
160: regs->r_fs = tf->tf_vm86_fs & 0xffff;
161: regs->r_es = tf->tf_vm86_es & 0xffff;
162: regs->r_ds = tf->tf_vm86_ds & 0xffff;
163: regs->r_eflags = get_vflags(p);
164: } else
165: #endif
166: {
167: regs->r_gs = tf->tf_gs & 0xffff;
168: regs->r_fs = tf->tf_fs & 0xffff;
169: regs->r_es = tf->tf_es & 0xffff;
170: regs->r_ds = tf->tf_ds & 0xffff;
171: regs->r_eflags = tf->tf_eflags;
172: }
173: regs->r_edi = tf->tf_edi;
174: regs->r_esi = tf->tf_esi;
175: regs->r_ebp = tf->tf_ebp;
176: regs->r_ebx = tf->tf_ebx;
177: regs->r_edx = tf->tf_edx;
178: regs->r_ecx = tf->tf_ecx;
179: regs->r_eax = tf->tf_eax;
180: regs->r_eip = tf->tf_eip;
181: regs->r_cs = tf->tf_cs & 0xffff;
182: regs->r_esp = tf->tf_esp;
183: regs->r_ss = tf->tf_ss & 0xffff;
184:
185: return (0);
186: }
187:
188: int
189: process_read_fpregs(struct proc *p, struct fpreg *regs)
190: {
191: union savefpu *frame = process_fpframe(p);
192:
193: if (p->p_md.md_flags & MDP_USEDFPU) {
194: #if NNPX > 0
195: npxsave_proc(p, 1);
196: #endif
197: } else {
198: /* Fake a FNINIT. */
199: if (i386_use_fxsave) {
200: process_fninit_xmm(&frame->sv_xmm);
201: } else {
202: /*
203: * The initial control word was already set by
204: * setregs(), so save it temporarily.
205: */
206: uint16_t cw = frame->sv_87.sv_env.en_cw;
207:
208: memset(&frame->sv_87, 0, sizeof(frame->sv_87));
209: frame->sv_87.sv_env.en_cw = cw;
210: frame->sv_87.sv_env.en_sw = 0x0000;
211: frame->sv_87.sv_env.en_tw = 0xffff;
212: }
213: p->p_md.md_flags |= MDP_USEDFPU;
214: }
215:
216: if (i386_use_fxsave) {
217: struct save87 s87;
218:
219: /* XXX Yuck */
220: process_xmm_to_s87(&frame->sv_xmm, &s87);
221: memcpy(regs, &s87, sizeof(*regs));
222: } else
223: memcpy(regs, &frame->sv_87, sizeof(*regs));
224:
225: return (0);
226: }
227:
228: #ifdef PTRACE
229:
230: void
231: process_s87_to_xmm(const struct save87 *s87, struct savexmm *sxmm)
232: {
233: int i;
234:
235: /* FPU control/status */
236: sxmm->sv_env.en_cw = s87->sv_env.en_cw;
237: sxmm->sv_env.en_sw = s87->sv_env.en_sw;
238: /* tag word handled below */
239: sxmm->sv_env.en_fip = s87->sv_env.en_fip;
240: sxmm->sv_env.en_fcs = s87->sv_env.en_fcs;
241: sxmm->sv_env.en_opcode = s87->sv_env.en_opcode;
242: sxmm->sv_env.en_foo = s87->sv_env.en_foo;
243: sxmm->sv_env.en_fos = s87->sv_env.en_fos;
244:
245: /* Tag word and registers. */
246: for (i = 0; i < 8; i++) {
247: if (((s87->sv_env.en_tw >> (i * 2)) & 3) == 3)
248: sxmm->sv_env.en_tw &= ~(1U << i);
249: else
250: sxmm->sv_env.en_tw |= (1U << i);
251:
252: if (((s87->sv_ex_tw >> (i * 2)) & 3) == 3)
253: sxmm->sv_ex_tw &= ~(1U << i);
254: else
255: sxmm->sv_ex_tw |= (1U << i);
256:
257: memcpy(&sxmm->sv_ac[i].fp_bytes, &s87->sv_ac[i].fp_bytes,
258: sizeof(sxmm->sv_ac[i].fp_bytes));
259: }
260:
261: sxmm->sv_ex_sw = s87->sv_ex_sw;
262: }
263:
264: int
265: process_write_regs(struct proc *p, struct reg *regs)
266: {
267: struct trapframe *tf = process_frame(p);
268:
269: #ifdef VM86
270: if (tf->tf_eflags & PSL_VM) {
271: tf->tf_vm86_gs = regs->r_gs & 0xffff;
272: tf->tf_vm86_fs = regs->r_fs & 0xffff;
273: tf->tf_vm86_es = regs->r_es & 0xffff;
274: tf->tf_vm86_ds = regs->r_ds & 0xffff;
275: set_vflags(p, regs->r_eflags);
276: } else
277: #endif
278: {
279: /*
280: * Check for security violations.
281: */
282: if (((regs->r_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 ||
283: !USERMODE(regs->r_cs, regs->r_eflags))
284: return (EINVAL);
285:
286: tf->tf_gs = regs->r_gs & 0xffff;
287: tf->tf_fs = regs->r_fs & 0xffff;
288: tf->tf_es = regs->r_es & 0xffff;
289: tf->tf_ds = regs->r_ds & 0xffff;
290: tf->tf_eflags = regs->r_eflags;
291: }
292: tf->tf_edi = regs->r_edi;
293: tf->tf_esi = regs->r_esi;
294: tf->tf_ebp = regs->r_ebp;
295: tf->tf_ebx = regs->r_ebx;
296: tf->tf_edx = regs->r_edx;
297: tf->tf_ecx = regs->r_ecx;
298: tf->tf_eax = regs->r_eax;
299: tf->tf_eip = regs->r_eip;
300: tf->tf_cs = regs->r_cs & 0xffff;
301: tf->tf_esp = regs->r_esp;
302: tf->tf_ss = regs->r_ss & 0xffff;
303:
304: return (0);
305: }
306:
307: int
308: process_write_fpregs(struct proc *p, struct fpreg *regs)
309: {
310: union savefpu *frame = process_fpframe(p);
311:
312: if (p->p_md.md_flags & MDP_USEDFPU) {
313: #if NNPX > 0
314: npxsave_proc(p, 0);
315: #endif
316: } else
317: p->p_md.md_flags |= MDP_USEDFPU;
318:
319: if (i386_use_fxsave) {
320: struct save87 s87;
321:
322: /* XXX Yuck. */
323: memcpy(&s87, regs, sizeof(*regs));
324: process_s87_to_xmm(&s87, &frame->sv_xmm);
325: } else
326: memcpy(&frame->sv_87, regs, sizeof(*regs));
327:
328: return (0);
329: }
330:
331: int
332: process_read_xmmregs(struct proc *p, struct xmmregs *regs)
333: {
334: union savefpu *frame = process_fpframe(p);
335:
336: if (!i386_use_fxsave)
337: return (EINVAL);
338:
339: if (p->p_md.md_flags & MDP_USEDFPU) {
340: #if NNPX > 0
341: npxsave_proc(p, 1);
342: #endif
343: } else {
344: /* Fake a FNINIT. */
345: process_fninit_xmm(&frame->sv_xmm);
346: p->p_md.md_flags |= MDP_USEDFPU;
347: }
348:
349: memcpy(regs, &frame->sv_xmm, sizeof(*regs));
350: return (0);
351: }
352:
353: int
354: process_write_xmmregs(struct proc *p, const struct xmmregs *regs)
355: {
356: union savefpu *frame = process_fpframe(p);
357:
358: if (!i386_use_fxsave)
359: return (EINVAL);
360:
361: if (p->p_md.md_flags & MDP_USEDFPU) {
362: #if NNPX > 0
363: npxsave_proc(p, 0);
364: #endif
365: } else
366: p->p_md.md_flags |= MDP_USEDFPU;
367:
368: memcpy(&frame->sv_xmm, regs, sizeof(*regs));
369: return (0);
370: }
371:
372: int
373: process_sstep(struct proc *p, int sstep)
374: {
375: struct trapframe *tf = process_frame(p);
376:
377: if (sstep)
378: tf->tf_eflags |= PSL_T;
379: else
380: tf->tf_eflags &= ~PSL_T;
381:
382: return (0);
383: }
384:
385: int
386: process_set_pc(struct proc *p, caddr_t addr)
387: {
388: struct trapframe *tf = process_frame(p);
389:
390: tf->tf_eip = (int)addr;
391:
392: return (0);
393: }
394:
395: #endif /* PTRACE */
CVSweb