1146818Sdfr/*- 2146818Sdfr * Copyright (c) 2005 Doug Rabson 3146818Sdfr * All rights reserved. 4146818Sdfr * 5146818Sdfr * Redistribution and use in source and binary forms, with or without 6146818Sdfr * modification, are permitted provided that the following conditions 7146818Sdfr * are met: 8146818Sdfr * 1. Redistributions of source code must retain the above copyright 9146818Sdfr * notice, this list of conditions and the following disclaimer. 10146818Sdfr * 2. Redistributions in binary form must reproduce the above copyright 11146818Sdfr * notice, this list of conditions and the following disclaimer in the 12146818Sdfr * documentation and/or other materials provided with the distribution. 13146818Sdfr * 14146818Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15146818Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16146818Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17146818Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18146818Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19146818Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20146818Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21146818Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22146818Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23146818Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24146818Sdfr * SUCH DAMAGE. 25146818Sdfr * 26146818Sdfr */ 27146818Sdfr 28146818Sdfr#include <sys/cdefs.h> 29146818Sdfr__FBSDID("$FreeBSD: stable/11/sys/i386/i386/ptrace_machdep.c 314210 2017-02-24 16:02:01Z kib $"); 30146818Sdfr 31148694Stobez#include "opt_cpu.h" 32148694Stobez 33146818Sdfr#include <sys/param.h> 34146818Sdfr#include <sys/systm.h> 35273995Sjhb#include <sys/malloc.h> 36146818Sdfr#include <sys/proc.h> 37146818Sdfr#include <sys/ptrace.h> 38284919Skib#include <machine/frame.h> 39146818Sdfr#include <machine/md_var.h> 40146818Sdfr#include <machine/pcb.h> 41146818Sdfr 42273995Sjhbstatic int 43273995Sjhbcpu_ptrace_xstate(struct thread *td, int req, void *addr, int data) 44273995Sjhb{ 45274817Sjhb struct ptrace_xstate_info info; 46273995Sjhb char *savefpu; 47273995Sjhb int error; 48273995Sjhb 49273995Sjhb if (!use_xsave) 50273995Sjhb return (EOPNOTSUPP); 51273995Sjhb 52273995Sjhb switch (req) { 53274817Sjhb case PT_GETXSTATE_OLD: 54273995Sjhb npxgetregs(td); 55273995Sjhb savefpu = (char *)(get_pcb_user_save_td(td) + 1); 56273995Sjhb error = copyout(savefpu, addr, 57273995Sjhb cpu_max_ext_state_size - sizeof(union savefpu)); 58273995Sjhb break; 59273995Sjhb 60274817Sjhb case PT_SETXSTATE_OLD: 61273995Sjhb if (data > cpu_max_ext_state_size - sizeof(union savefpu)) { 62273995Sjhb error = EINVAL; 63273995Sjhb break; 64273995Sjhb } 65273995Sjhb savefpu = malloc(data, M_TEMP, M_WAITOK); 66273995Sjhb error = copyin(addr, savefpu, data); 67273995Sjhb if (error == 0) { 68273995Sjhb npxgetregs(td); 69273995Sjhb error = npxsetxstate(td, savefpu, data); 70273995Sjhb } 71273995Sjhb free(savefpu, M_TEMP); 72273995Sjhb break; 73273995Sjhb 74274817Sjhb case PT_GETXSTATE_INFO: 75274817Sjhb if (data != sizeof(info)) { 76274817Sjhb error = EINVAL; 77274817Sjhb break; 78274817Sjhb } 79274817Sjhb info.xsave_len = cpu_max_ext_state_size; 80274817Sjhb info.xsave_mask = xsave_mask; 81274817Sjhb error = copyout(&info, addr, data); 82274817Sjhb break; 83274817Sjhb 84274817Sjhb case PT_GETXSTATE: 85274817Sjhb npxgetregs(td); 86274817Sjhb savefpu = (char *)(get_pcb_user_save_td(td)); 87274817Sjhb error = copyout(savefpu, addr, cpu_max_ext_state_size); 88274817Sjhb break; 89274817Sjhb 90274817Sjhb case PT_SETXSTATE: 91278976Sjhb if (data < sizeof(union savefpu) || 92278976Sjhb data > cpu_max_ext_state_size) { 93274817Sjhb error = EINVAL; 94274817Sjhb break; 95274817Sjhb } 96274817Sjhb savefpu = malloc(data, M_TEMP, M_WAITOK); 97274817Sjhb error = copyin(addr, savefpu, data); 98274817Sjhb if (error == 0) 99274817Sjhb error = npxsetregs(td, (union savefpu *)savefpu, 100274817Sjhb savefpu + sizeof(union savefpu), data - 101274817Sjhb sizeof(union savefpu)); 102274817Sjhb free(savefpu, M_TEMP); 103274817Sjhb break; 104274817Sjhb 105273995Sjhb default: 106273995Sjhb error = EINVAL; 107273995Sjhb break; 108273995Sjhb } 109273995Sjhb 110273995Sjhb return (error); 111273995Sjhb} 112273995Sjhb 113284919Skibstatic int 114284919Skibcpu_ptrace_xmm(struct thread *td, int req, void *addr, int data) 115146818Sdfr{ 116159087Sdavidxu struct savexmm *fpstate; 117146818Sdfr int error; 118146818Sdfr 119146818Sdfr if (!cpu_fxsr) 120146818Sdfr return (EINVAL); 121146818Sdfr 122273995Sjhb fpstate = &get_pcb_user_save_td(td)->sv_xmm; 123146818Sdfr switch (req) { 124146818Sdfr case PT_GETXMMREGS: 125238675Skib npxgetregs(td); 126159087Sdavidxu error = copyout(fpstate, addr, sizeof(*fpstate)); 127146818Sdfr break; 128146818Sdfr 129146818Sdfr case PT_SETXMMREGS: 130238675Skib npxgetregs(td); 131159087Sdavidxu error = copyin(addr, fpstate, sizeof(*fpstate)); 132159087Sdavidxu fpstate->sv_env.en_mxcsr &= cpu_mxcsr_mask; 133146818Sdfr break; 134146818Sdfr 135274817Sjhb case PT_GETXSTATE_OLD: 136274817Sjhb case PT_SETXSTATE_OLD: 137274817Sjhb case PT_GETXSTATE_INFO: 138273995Sjhb case PT_GETXSTATE: 139273995Sjhb case PT_SETXSTATE: 140273995Sjhb error = cpu_ptrace_xstate(td, req, addr, data); 141273995Sjhb break; 142273995Sjhb 143146818Sdfr default: 144146818Sdfr return (EINVAL); 145146818Sdfr } 146146818Sdfr 147146818Sdfr return (error); 148146818Sdfr} 149284919Skib 150284919Skibint 151284919Skibcpu_ptrace(struct thread *td, int req, void *addr, int data) 152284919Skib{ 153284919Skib struct segment_descriptor *sdp, sd; 154284919Skib register_t r; 155284919Skib int error; 156284919Skib 157284919Skib switch (req) { 158284919Skib case PT_GETXMMREGS: 159284919Skib case PT_SETXMMREGS: 160284919Skib case PT_GETXSTATE_OLD: 161284919Skib case PT_SETXSTATE_OLD: 162284919Skib case PT_GETXSTATE_INFO: 163284919Skib case PT_GETXSTATE: 164284919Skib case PT_SETXSTATE: 165284919Skib error = cpu_ptrace_xmm(td, req, addr, data); 166284919Skib break; 167284919Skib 168284919Skib case PT_GETFSBASE: 169284919Skib case PT_GETGSBASE: 170284919Skib sdp = req == PT_GETFSBASE ? &td->td_pcb->pcb_fsd : 171284919Skib &td->td_pcb->pcb_gsd; 172284919Skib r = sdp->sd_hibase << 24 | sdp->sd_lobase; 173284919Skib error = copyout(&r, addr, sizeof(r)); 174284919Skib break; 175284919Skib 176284919Skib case PT_SETFSBASE: 177284919Skib case PT_SETGSBASE: 178284919Skib error = copyin(addr, &r, sizeof(r)); 179284919Skib if (error != 0) 180284919Skib break; 181284919Skib fill_based_sd(&sd, r); 182284919Skib if (req == PT_SETFSBASE) { 183284919Skib td->td_pcb->pcb_fsd = sd; 184284919Skib td->td_frame->tf_fs = GSEL(GUFS_SEL, SEL_UPL); 185284919Skib } else { 186284919Skib td->td_pcb->pcb_gsd = sd; 187284919Skib td->td_pcb->pcb_gs = GSEL(GUGS_SEL, SEL_UPL); 188284919Skib } 189284919Skib break; 190284919Skib 191284919Skib default: 192284919Skib return (EINVAL); 193284919Skib } 194284919Skib 195284919Skib return (error); 196284919Skib} 197