1 /* The kernel calls that are implemented in this file: 2 * m_type: SYS_SETMCONTEXT 3 * m_type: SYS_GETMCONTEXT 4 * 5 * The parameters for SYS_SETMCONTEXT kernel call are: 6 * m_lsys_krn_sys_setmcontext.endpt # proc endpoint doing call 7 * m_lsys_krn_sys_setmcontext.ctx_ptr # pointer to mcontext structure 8 * 9 * The parameters for SYS_GETMCONTEXT kernel call are: 10 * m_lsys_krn_sys_getmcontext.endpt # proc endpoint doing call 11 * m_lsys_krn_sys_getmcontext.ctx_ptr # pointer to mcontext structure 12 */ 13 14 #include "kernel/system.h" 15 #include <string.h> 16 #include <assert.h> 17 #include <machine/mcontext.h> 18 19 #if USE_MCONTEXT 20 /*===========================================================================* 21 * do_getmcontext * 22 *===========================================================================*/ 23 int do_getmcontext(struct proc * caller, message * m_ptr) 24 { 25 /* Retrieve machine context of a process */ 26 27 register struct proc *rp; 28 int proc_nr, r; 29 mcontext_t mc; 30 31 if (!isokendpt(m_ptr->m_lsys_krn_sys_getmcontext.endpt, &proc_nr)) 32 return(EINVAL); 33 if (iskerneln(proc_nr)) return(EPERM); 34 rp = proc_addr(proc_nr); 35 36 #if defined(__i386__) 37 if (!proc_used_fpu(rp)) 38 return(OK); /* No state to copy */ 39 #endif 40 41 /* Get the mcontext structure into our address space. */ 42 if ((r = data_copy(m_ptr->m_lsys_krn_sys_getmcontext.endpt, 43 m_ptr->m_lsys_krn_sys_getmcontext.ctx_ptr, KERNEL, 44 (vir_bytes) &mc, (phys_bytes) sizeof(mcontext_t))) != OK) 45 return(r); 46 47 mc.mc_flags = 0; 48 #if defined(__i386__) 49 /* Copy FPU state */ 50 if (proc_used_fpu(rp)) { 51 /* make sure that the FPU context is saved into proc structure first */ 52 save_fpu(rp); 53 mc.mc_flags = (rp->p_misc_flags & MF_FPU_INITIALIZED) ? _MC_FPU_SAVED : 0; 54 assert(sizeof(mc.__fpregs.__fp_reg_set) == FPU_XFP_SIZE); 55 memcpy(&(mc.__fpregs.__fp_reg_set), rp->p_seg.fpu_state, FPU_XFP_SIZE); 56 } 57 #endif 58 59 60 /* Copy the mcontext structure to the user's address space. */ 61 if ((r = data_copy(KERNEL, (vir_bytes) &mc, 62 m_ptr->m_lsys_krn_sys_getmcontext.endpt, 63 m_ptr->m_lsys_krn_sys_getmcontext.ctx_ptr, 64 (phys_bytes) sizeof(mcontext_t))) != OK) 65 return(r); 66 67 return(OK); 68 } 69 70 71 /*===========================================================================* 72 * do_setmcontext * 73 *===========================================================================*/ 74 int do_setmcontext(struct proc * caller, message * m_ptr) 75 { 76 /* Set machine context of a process */ 77 78 register struct proc *rp; 79 int proc_nr, r; 80 mcontext_t mc; 81 82 if (!isokendpt(m_ptr->m_lsys_krn_sys_setmcontext.endpt, &proc_nr)) return(EINVAL); 83 rp = proc_addr(proc_nr); 84 85 /* Get the mcontext structure into our address space. */ 86 if ((r = data_copy(m_ptr->m_lsys_krn_sys_setmcontext.endpt, 87 m_ptr->m_lsys_krn_sys_setmcontext.ctx_ptr, KERNEL, 88 (vir_bytes) &mc, (phys_bytes) sizeof(mcontext_t))) != OK) 89 return(r); 90 91 #if defined(__i386__) 92 /* Copy FPU state */ 93 if (mc.mc_flags & _MC_FPU_SAVED) { 94 rp->p_misc_flags |= MF_FPU_INITIALIZED; 95 assert(sizeof(mc.__fpregs.__fp_reg_set) == FPU_XFP_SIZE); 96 memcpy(rp->p_seg.fpu_state, &(mc.__fpregs.__fp_reg_set), FPU_XFP_SIZE); 97 } else 98 rp->p_misc_flags &= ~MF_FPU_INITIALIZED; 99 /* force reloading FPU in either case */ 100 release_fpu(rp); 101 #endif 102 103 return(OK); 104 } 105 106 #endif 107