1330567Sgordon/* $OpenBSD: process_machdep.c,v 1.30 2023/01/30 10:49:05 jsg Exp $ */ 2330567Sgordon/* $NetBSD: process_machdep.c,v 1.22 1996/05/03 19:42:25 christos Exp $ */ 3330567Sgordon 4330567Sgordon/* 5330567Sgordon * Copyright (c) 1995, 1996 Charles M. Hannum. All rights reserved. 6330567Sgordon * Copyright (c) 1993 The Regents of the University of California. 7330567Sgordon * Copyright (c) 1993 Jan-Simon Pendry 8330567Sgordon * All rights reserved. 9258945Sroberto * 10258945Sroberto * This code is derived from software contributed to Berkeley by 11258945Sroberto * Jan-Simon Pendry. 12298770Sdelphij * 13316722Sdelphij * Redistribution and use in source and binary forms, with or without 14258945Sroberto * modification, are permitted provided that the following conditions 15330567Sgordon * are met: 16330567Sgordon * 1. Redistributions of source code must retain the above copyright 17330567Sgordon * notice, this list of conditions and the following disclaimer. 18330567Sgordon * 2. Redistributions in binary form must reproduce the above copyright 19330567Sgordon * notice, this list of conditions and the following disclaimer in the 20330567Sgordon * documentation and/or other materials provided with the distribution. 21330567Sgordon * 3. Neither the name of the University nor the names of its contributors 22330567Sgordon * may be used to endorse or promote products derived from this software 23330567Sgordon * without specific prior written permission. 24330567Sgordon * 25330567Sgordon * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26258945Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27280849Scy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28258945Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29330567Sgordon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30330567Sgordon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31330567Sgordon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32330567Sgordon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33330567Sgordon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34330567Sgordon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35330567Sgordon * SUCH DAMAGE. 36330567Sgordon * 37330567Sgordon * From: 38330567Sgordon * Id: procfs_i386.c,v 4.1 1993/12/17 10:47:45 jsp Rel 39330567Sgordon */ 40330567Sgordon 41330567Sgordon/* 42330567Sgordon * This file may seem a bit stylized, but that so that it's easier to port. 43330567Sgordon * Functions to be implemented here are: 44330567Sgordon * 45330567Sgordon * process_read_regs(proc, regs) 46330567Sgordon * Get the current user-visible register set from the process 47330567Sgordon * and copy it into the regs structure (<machine/reg.h>). 48330567Sgordon * The process is stopped at the time read_regs is called. 49330567Sgordon * 50330567Sgordon * process_write_regs(proc, regs) 51330567Sgordon * Update the current register set from the passed in regs 52330567Sgordon * structure. Take care to avoid clobbering special CPU 53330567Sgordon * registers or privileged bits in the PSL. 54330567Sgordon * The process is stopped at the time write_regs is called. 55330567Sgordon * 56330567Sgordon * process_sstep(proc) 57330567Sgordon * Arrange for the process to trap after executing a single instruction. 58330567Sgordon * 59330567Sgordon * process_set_pc(proc) 60330567Sgordon * Set the process's program counter. 61330567Sgordon */ 62330567Sgordon 63330567Sgordon#include <sys/param.h> 64330567Sgordon#include <sys/systm.h> 65330567Sgordon#include <sys/proc.h> 66330567Sgordon#include <sys/user.h> 67330567Sgordon#include <sys/ptrace.h> 68330567Sgordon 69330567Sgordon#include <machine/psl.h> 70330567Sgordon#include <machine/reg.h> 71330567Sgordon#include <machine/segments.h> 72330567Sgordon 73330567Sgordon#include "npx.h" 74330567Sgordon 75330567Sgordonstatic __inline struct trapframe *process_frame(struct proc *); 76330567Sgordonstatic __inline union savefpu *process_fpframe(struct proc *); 77330567Sgordonvoid process_fninit_xmm(struct savexmm *); 78330567Sgordon 79330567Sgordonstatic __inline struct trapframe * 80330567Sgordonprocess_frame(struct proc *p) 81330567Sgordon{ 82330567Sgordon 83330567Sgordon return (p->p_md.md_regs); 84330567Sgordon} 85330567Sgordon 86330567Sgordonstatic __inline union savefpu * 87330567Sgordonprocess_fpframe(struct proc *p) 88330567Sgordon{ 89330567Sgordon 90330567Sgordon return (&p->p_addr->u_pcb.pcb_savefpu); 91330567Sgordon} 92330567Sgordon 93330567Sgordonvoid 94330567Sgordonprocess_xmm_to_s87(const struct savexmm *sxmm, struct save87 *s87) 95330567Sgordon{ 96330567Sgordon int i; 97330567Sgordon 98330567Sgordon /* FPU control/status */ 99330567Sgordon s87->sv_env.en_cw = sxmm->sv_env.en_cw; 100330567Sgordon s87->sv_env.en_sw = sxmm->sv_env.en_sw; 101330567Sgordon /* tag word handled below */ 102330567Sgordon s87->sv_env.en_fip = sxmm->sv_env.en_fip; 103330567Sgordon s87->sv_env.en_fcs = sxmm->sv_env.en_fcs; 104330567Sgordon s87->sv_env.en_opcode = sxmm->sv_env.en_opcode; 105330567Sgordon s87->sv_env.en_foo = sxmm->sv_env.en_foo; 106330567Sgordon s87->sv_env.en_fos = sxmm->sv_env.en_fos; 107330567Sgordon 108330567Sgordon /* Tag word and registers. */ 109330567Sgordon for (i = 0; i < 8; i++) { 110330567Sgordon if (sxmm->sv_env.en_tw & (1U << i)) 111330567Sgordon s87->sv_env.en_tw &= ~(3U << (i * 2)); 112330567Sgordon else 113330567Sgordon s87->sv_env.en_tw |= (3U << (i * 2)); 114330567Sgordon 115330567Sgordon if (sxmm->sv_ex_tw & (1U << i)) 116330567Sgordon s87->sv_ex_tw &= ~(3U << (i * 2)); 117330567Sgordon else 118330567Sgordon s87->sv_ex_tw |= (3U << (i * 2)); 119330567Sgordon 120330567Sgordon memcpy(&s87->sv_ac[i].fp_bytes, &sxmm->sv_ac[i].fp_bytes, 121330567Sgordon sizeof(s87->sv_ac[i].fp_bytes)); 122330567Sgordon } 123330567Sgordon 124330567Sgordon s87->sv_ex_sw = sxmm->sv_ex_sw; 125330567Sgordon} 126330567Sgordon 127330567Sgordonvoid 128330567Sgordonprocess_fninit_xmm(struct savexmm *sxmm) 129330567Sgordon{ 130258945Sroberto memset(sxmm, 0, sizeof(*sxmm)); 131258945Sroberto sxmm->sv_env.en_cw = __INITIAL_NPXCW__; 132330567Sgordon sxmm->sv_env.en_mxcsr = __INITIAL_MXCSR__; 133330567Sgordon sxmm->sv_env.en_mxcsr_mask = fpu_mxcsr_mask; 134330567Sgordon sxmm->sv_env.en_sw = 0x0000; 135330567Sgordon sxmm->sv_env.en_tw = 0x00; 136330567Sgordon} 137258945Sroberto 138258945Srobertoint 139330567Sgordonprocess_read_regs(struct proc *p, struct reg *regs) 140330567Sgordon{ 141258945Sroberto struct trapframe *tf = process_frame(p); 142330567Sgordon 143258945Sroberto regs->r_gs = tf->tf_gs & 0xffff; 144258945Sroberto regs->r_fs = tf->tf_fs & 0xffff; 145258945Sroberto regs->r_es = tf->tf_es & 0xffff; 146258945Sroberto regs->r_ds = tf->tf_ds & 0xffff; 147330567Sgordon regs->r_eflags = tf->tf_eflags; 148330567Sgordon regs->r_edi = tf->tf_edi; 149330567Sgordon regs->r_esi = tf->tf_esi; 150330567Sgordon regs->r_ebp = tf->tf_ebp; 151330567Sgordon regs->r_ebx = tf->tf_ebx; 152330567Sgordon regs->r_edx = tf->tf_edx; 153330567Sgordon regs->r_ecx = tf->tf_ecx; 154330567Sgordon regs->r_eax = tf->tf_eax; 155330567Sgordon regs->r_eip = tf->tf_eip; 156330567Sgordon regs->r_cs = tf->tf_cs & 0xffff; 157258945Sroberto regs->r_esp = tf->tf_esp; 158258945Sroberto regs->r_ss = tf->tf_ss & 0xffff; 159258945Sroberto 160258945Sroberto return (0); 161330567Sgordon} 162258945Sroberto 163330567Sgordonint 164258945Srobertoprocess_read_fpregs(struct proc *p, struct fpreg *regs) 165258945Sroberto{ 166258945Sroberto union savefpu *frame = process_fpframe(p); 167258945Sroberto 168330567Sgordon if (p->p_md.md_flags & MDP_USEDFPU) { 169330567Sgordon#if NNPX > 0 170330567Sgordon npxsave_proc(p, 1); 171330567Sgordon#endif 172258945Sroberto } else { 173258945Sroberto /* Fake a FNINIT. */ 174330567Sgordon if (i386_use_fxsave) { 175330567Sgordon process_fninit_xmm(&frame->sv_xmm); 176330567Sgordon } else { 177330567Sgordon memset(&frame->sv_87, 0, sizeof(frame->sv_87)); 178330567Sgordon frame->sv_87.sv_env.en_cw = __INITIAL_NPXCW__; 179330567Sgordon frame->sv_87.sv_env.en_sw = 0x0000; 180330567Sgordon frame->sv_87.sv_env.en_tw = 0xffff; 181330567Sgordon } 182330567Sgordon p->p_md.md_flags |= MDP_USEDFPU; 183330567Sgordon } 184330567Sgordon 185330567Sgordon if (i386_use_fxsave) { 186330567Sgordon struct save87 s87; 187330567Sgordon 188330567Sgordon /* XXX Yuck */ 189330567Sgordon process_xmm_to_s87(&frame->sv_xmm, &s87); 190330567Sgordon memcpy(regs, &s87, sizeof(*regs)); 191330567Sgordon } else 192330567Sgordon memcpy(regs, &frame->sv_87, sizeof(*regs)); 193330567Sgordon 194258945Sroberto return (0); 195258945Sroberto} 196258945Sroberto 197258945Sroberto#ifdef PTRACE 198258945Sroberto 199258945Srobertovoid 200258945Srobertoprocess_s87_to_xmm(const struct save87 *s87, struct savexmm *sxmm) 201258945Sroberto{ 202258945Sroberto int i; 203258945Sroberto 204258945Sroberto /* FPU control/status */ 205258945Sroberto sxmm->sv_env.en_cw = s87->sv_env.en_cw; 206258945Sroberto sxmm->sv_env.en_sw = s87->sv_env.en_sw; 207258945Sroberto /* tag word handled below */ 208258945Sroberto sxmm->sv_env.en_fip = s87->sv_env.en_fip; 209258945Sroberto sxmm->sv_env.en_fcs = s87->sv_env.en_fcs; 210258945Sroberto sxmm->sv_env.en_opcode = s87->sv_env.en_opcode; 211258945Sroberto sxmm->sv_env.en_foo = s87->sv_env.en_foo; 212258945Sroberto sxmm->sv_env.en_fos = s87->sv_env.en_fos; 213258945Sroberto 214258945Sroberto /* Tag word and registers. */ 215258945Sroberto for (i = 0; i < 8; i++) { 216330567Sgordon if (((s87->sv_env.en_tw >> (i * 2)) & 3) == 3) 217258945Sroberto sxmm->sv_env.en_tw &= ~(1U << i); 218258945Sroberto else 219258945Sroberto sxmm->sv_env.en_tw |= (1U << i); 220258945Sroberto 221258945Sroberto if (((s87->sv_ex_tw >> (i * 2)) & 3) == 3) 222258945Sroberto sxmm->sv_ex_tw &= ~(1U << i); 223258945Sroberto else 224258945Sroberto sxmm->sv_ex_tw |= (1U << i); 225330567Sgordon 226258945Sroberto memcpy(&sxmm->sv_ac[i].fp_bytes, &s87->sv_ac[i].fp_bytes, 227330567Sgordon sizeof(sxmm->sv_ac[i].fp_bytes)); 228258945Sroberto } 229258945Sroberto 230258945Sroberto sxmm->sv_ex_sw = s87->sv_ex_sw; 231330567Sgordon} 232330567Sgordon 233330567Sgordonint 234258945Srobertoprocess_write_regs(struct proc *p, struct reg *regs) 235280849Scy{ 236258945Sroberto struct trapframe *tf = process_frame(p); 237258945Sroberto 238258945Sroberto /* 239258945Sroberto * Check for security violations. 240280849Scy */ 241258945Sroberto if (((regs->r_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 || 242258945Sroberto !USERMODE(regs->r_cs, regs->r_eflags)) 243258945Sroberto return (EINVAL); 244258945Sroberto 245258945Sroberto tf->tf_gs = regs->r_gs & 0xffff; 246258945Sroberto tf->tf_fs = regs->r_fs & 0xffff; 247258945Sroberto tf->tf_es = regs->r_es & 0xffff; 248280849Scy tf->tf_ds = regs->r_ds & 0xffff; 249258945Sroberto tf->tf_eflags = regs->r_eflags; 250258945Sroberto tf->tf_edi = regs->r_edi; 251258945Sroberto tf->tf_esi = regs->r_esi; 252258945Sroberto tf->tf_ebp = regs->r_ebp; 253258945Sroberto tf->tf_ebx = regs->r_ebx; 254258945Sroberto tf->tf_edx = regs->r_edx; 255258945Sroberto tf->tf_ecx = regs->r_ecx; 256258945Sroberto tf->tf_eax = regs->r_eax; 257258945Sroberto tf->tf_eip = regs->r_eip; 258280849Scy tf->tf_cs = regs->r_cs & 0xffff; 259330567Sgordon tf->tf_esp = regs->r_esp; 260330567Sgordon tf->tf_ss = regs->r_ss & 0xffff; 261330567Sgordon 262258945Sroberto return (0); 263258945Sroberto} 264330567Sgordon 265258945Srobertoint 266258945Srobertoprocess_write_fpregs(struct proc *p, struct fpreg *regs) 267258945Sroberto{ 268258945Sroberto union savefpu *frame = process_fpframe(p); 269258945Sroberto 270258945Sroberto if (p->p_md.md_flags & MDP_USEDFPU) { 271258945Sroberto#if NNPX > 0 272258945Sroberto npxsave_proc(p, 0); 273258945Sroberto#endif 274258945Sroberto } else { 275258945Sroberto /* 276258945Sroberto * Make sure MXCSR and the XMM registers are 277258945Sroberto * initialized to sane defaults. 278258945Sroberto */ 279258945Sroberto if (i386_use_fxsave) 280258945Sroberto process_fninit_xmm(&frame->sv_xmm); 281258945Sroberto p->p_md.md_flags |= MDP_USEDFPU; 282258945Sroberto } 283258945Sroberto 284330567Sgordon if (i386_use_fxsave) { 285330567Sgordon struct save87 s87; 286330567Sgordon 287330567Sgordon /* XXX Yuck. */ 288330567Sgordon memcpy(&s87, regs, sizeof(*regs)); 289330567Sgordon process_s87_to_xmm(&s87, &frame->sv_xmm); 290330567Sgordon } else 291258945Sroberto memcpy(&frame->sv_87, regs, sizeof(*regs)); 292258945Sroberto 293258945Sroberto return (0); 294258945Sroberto} 295258945Sroberto 296258945Srobertoint 297258945Srobertoprocess_read_xmmregs(struct proc *p, struct xmmregs *regs) 298258945Sroberto{ 299258945Sroberto union savefpu *frame = process_fpframe(p); 300258945Sroberto 301330567Sgordon if (!i386_use_fxsave) 302330567Sgordon return (EINVAL); 303330567Sgordon 304330567Sgordon if (p->p_md.md_flags & MDP_USEDFPU) { 305258945Sroberto#if NNPX > 0 306258945Sroberto npxsave_proc(p, 1); 307258945Sroberto#endif 308258945Sroberto } else { 309258945Sroberto /* Fake a FNINIT. */ 310330567Sgordon process_fninit_xmm(&frame->sv_xmm); 311258945Sroberto p->p_md.md_flags |= MDP_USEDFPU; 312258945Sroberto } 313258945Sroberto 314258945Sroberto memcpy(regs, &frame->sv_xmm, sizeof(*regs)); 315330567Sgordon return (0); 316258945Sroberto} 317258945Sroberto 318258945Srobertoint 319258945Srobertoprocess_write_xmmregs(struct proc *p, const struct xmmregs *regs) 320258945Sroberto{ 321258945Sroberto union savefpu *frame = process_fpframe(p); 322258945Sroberto 323258945Sroberto if (!i386_use_fxsave) 324258945Sroberto return (EINVAL); 325258945Sroberto 326258945Sroberto if (p->p_md.md_flags & MDP_USEDFPU) { 327258945Sroberto#if NNPX > 0 328258945Sroberto npxsave_proc(p, 0); 329258945Sroberto#endif 330258945Sroberto } else 331258945Sroberto p->p_md.md_flags |= MDP_USEDFPU; 332258945Sroberto 333258945Sroberto memcpy(&frame->sv_xmm, regs, sizeof(*regs)); 334258945Sroberto frame->sv_xmm.sv_env.en_mxcsr &= fpu_mxcsr_mask; 335258945Sroberto return (0); 336} 337 338int 339process_sstep(struct proc *p, int sstep) 340{ 341 struct trapframe *tf = process_frame(p); 342 343 if (sstep) 344 tf->tf_eflags |= PSL_T; 345 else 346 tf->tf_eflags &= ~PSL_T; 347 348 return (0); 349} 350 351int 352process_set_pc(struct proc *p, caddr_t addr) 353{ 354 struct trapframe *tf = process_frame(p); 355 356 tf->tf_eip = (int)addr; 357 358 return (0); 359} 360 361#endif /* PTRACE */ 362