2 * Copyright (c) 2005 Peter Wemm
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include "opt_compat.h"
34 #include <sys/param.h>
36 #include <sys/fcntl.h>
37 #include <sys/imgact.h>
38 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/mutex.h>
43 #include <sys/namei.h>
44 #include <sys/pioctl.h>
46 #include <sys/procfs.h>
47 #include <sys/resourcevar.h>
48 #include <sys/systm.h>
49 #include <sys/signalvar.h>
52 #include <sys/syscall.h>
53 #include <sys/sysctl.h>
54 #include <sys/sysent.h>
55 #include <sys/vnode.h>
58 #include <vm/vm_kern.h>
59 #include <vm/vm_param.h>
61 #include <vm/vm_map.h>
62 #include <vm/vm_object.h>
63 #include <vm/vm_extern.h>
65 #include <compat/freebsd32/freebsd32_util.h>
66 #include <compat/freebsd32/freebsd32_proto.h>
67 #include <machine/fpu.h>
68 #include <machine/psl.h>
69 #include <machine/segments.h>
70 #include <machine/specialreg.h>
71 #include <machine/frame.h>
72 #include <machine/md_var.h>
73 #include <machine/pcb.h>
74 #include <machine/cpufunc.h>
76 #define CS_SECURE(cs) (ISPL(cs) == SEL_UPL)
77 #define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
80 fill_regs32(struct thread
*td
, struct reg32
*regs
)
85 if (tp
->tf_flags
& TF_HASSEGS
) {
86 regs
->r_gs
= tp
->tf_gs
;
87 regs
->r_fs
= tp
->tf_fs
;
88 regs
->r_es
= tp
->tf_es
;
89 regs
->r_ds
= tp
->tf_ds
;
93 regs
->r_es
= _udatasel
;
94 regs
->r_ds
= _udatasel
;
96 regs
->r_edi
= tp
->tf_rdi
;
97 regs
->r_esi
= tp
->tf_rsi
;
98 regs
->r_ebp
= tp
->tf_rbp
;
99 regs
->r_ebx
= tp
->tf_rbx
;
100 regs
->r_edx
= tp
->tf_rdx
;
101 regs
->r_ecx
= tp
->tf_rcx
;
102 regs
->r_eax
= tp
->tf_rax
;
103 regs
->r_eip
= tp
->tf_rip
;
104 regs
->r_cs
= tp
->tf_cs
;
105 regs
->r_eflags
= tp
->tf_rflags
;
106 regs
->r_esp
= tp
->tf_rsp
;
107 regs
->r_ss
= tp
->tf_ss
;
112 set_regs32(struct thread
*td
, struct reg32
*regs
)
114 struct trapframe
*tp
;
117 if (!EFL_SECURE(regs
->r_eflags
, tp
->tf_rflags
) || !CS_SECURE(regs
->r_cs
))
119 tp
->tf_gs
= regs
->r_gs
;
120 tp
->tf_fs
= regs
->r_fs
;
121 tp
->tf_es
= regs
->r_es
;
122 tp
->tf_ds
= regs
->r_ds
;
123 set_pcb_flags(td
->td_pcb
, PCB_FULL_IRET
);
124 tp
->tf_flags
= TF_HASSEGS
;
125 tp
->tf_rdi
= regs
->r_edi
;
126 tp
->tf_rsi
= regs
->r_esi
;
127 tp
->tf_rbp
= regs
->r_ebp
;
128 tp
->tf_rbx
= regs
->r_ebx
;
129 tp
->tf_rdx
= regs
->r_edx
;
130 tp
->tf_rcx
= regs
->r_ecx
;
131 tp
->tf_rax
= regs
->r_eax
;
132 tp
->tf_rip
= regs
->r_eip
;
133 tp
->tf_cs
= regs
->r_cs
;
134 tp
->tf_rflags
= regs
->r_eflags
;
135 tp
->tf_rsp
= regs
->r_esp
;
136 tp
->tf_ss
= regs
->r_ss
;
141 fill_fpregs32(struct thread
*td
, struct fpreg32
*regs
)
143 struct savefpu
*sv_fpu
;
144 struct save87
*sv_87
;
145 struct env87
*penv_87
;
146 struct envxmm
*penv_xmm
;
149 bzero(regs
, sizeof(*regs
));
150 sv_87
= (struct save87
*)regs
;
151 penv_87
= &sv_87
->sv_env
;
153 sv_fpu
= get_pcb_user_save_td(td
);
154 penv_xmm
= &sv_fpu
->sv_env
;
156 /* FPU control/status */
157 penv_87
->en_cw
= penv_xmm
->en_cw
;
158 penv_87
->en_sw
= penv_xmm
->en_sw
;
159 penv_87
->en_tw
= penv_xmm
->en_tw
;
161 * XXX for en_fip/fcs/foo/fos, check if the fxsave format
162 * uses the old-style layout for 32 bit user apps. If so,
163 * read the ip and operand segment registers from there.
164 * For now, use the process's %cs/%ds.
166 penv_87
->en_fip
= penv_xmm
->en_rip
;
167 penv_87
->en_fcs
= td
->td_frame
->tf_cs
;
168 penv_87
->en_opcode
= penv_xmm
->en_opcode
;
169 penv_87
->en_foo
= penv_xmm
->en_rdp
;
170 /* Entry into the kernel always sets TF_HASSEGS */
171 penv_87
->en_fos
= td
->td_frame
->tf_ds
;
174 for (i
= 0; i
< 8; ++i
)
175 sv_87
->sv_ac
[i
] = sv_fpu
->sv_fp
[i
].fp_acc
;
181 set_fpregs32(struct thread
*td
, struct fpreg32
*regs
)
183 struct save87
*sv_87
= (struct save87
*)regs
;
184 struct env87
*penv_87
= &sv_87
->sv_env
;
185 struct savefpu
*sv_fpu
= get_pcb_user_save_td(td
);
186 struct envxmm
*penv_xmm
= &sv_fpu
->sv_env
;
189 /* FPU control/status */
190 penv_xmm
->en_cw
= penv_87
->en_cw
;
191 penv_xmm
->en_sw
= penv_87
->en_sw
;
192 penv_xmm
->en_tw
= penv_87
->en_tw
;
193 penv_xmm
->en_rip
= penv_87
->en_fip
;
194 /* penv_87->en_fcs and en_fos ignored, see above */
195 penv_xmm
->en_opcode
= penv_87
->en_opcode
;
196 penv_xmm
->en_rdp
= penv_87
->en_foo
;
199 for (i
= 0; i
< 8; ++i
)
200 sv_fpu
->sv_fp
[i
].fp_acc
= sv_87
->sv_ac
[i
];
201 for (i
= 8; i
< 16; ++i
)
202 bzero(&sv_fpu
->sv_fp
[i
].fp_acc
, sizeof(sv_fpu
->sv_fp
[i
].fp_acc
));
209 fill_dbregs32(struct thread
*td
, struct dbreg32
*regs
)
214 err
= fill_dbregs(td
, &dr
);
215 for (i
= 0; i
< 8; i
++)
216 regs
->dr
[i
] = dr
.dr
[i
];
221 set_dbregs32(struct thread
*td
, struct dbreg32
*regs
)
226 for (i
= 0; i
< 8; i
++)
227 dr
.dr
[i
] = regs
->dr
[i
];
228 for (i
= 8; i
< 16; i
++)
230 return (set_dbregs(td
, &dr
));