xref: /minix3/minix/kernel/system/do_mcontext.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
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  *===========================================================================*/
do_getmcontext(struct proc * caller,message * m_ptr)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  *===========================================================================*/
do_setmcontext(struct proc * caller,message * m_ptr)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