2f892aca91
There seems to have been a broken assumption in the fpu context restoring code. It restores the context of the running process, without guarantee that the current process is the one that will be scheduled. This caused fpu saving for a different process to be triggered without fpu hardware being enabled, causing an fpu exception in the kernel. This practically only shows up with DEBUG_RACE on. Fix my thruby+me. The fix . is to only set the fpu-in-use-by-this-process flag in the exception handler, and then take care of fpu restoring when actually returning to userspace And the patch . translates fpu saving and restoring to c in arch_system.c, getting rid of a juicy chunk of assembly . makes osfxsr_feature private to arch_system.c . removes most of the arch dependent code from do_sigsend
97 lines
2.9 KiB
C
97 lines
2.9 KiB
C
/* The kernel call that is implemented in this file:
|
|
* m_type: SYS_SIGSEND
|
|
*
|
|
* The parameters for this kernel call are:
|
|
* m2_i1: SIG_ENDPT # process to call signal handler
|
|
* m2_p1: SIG_CTXT_PTR # pointer to sigcontext structure
|
|
* m2_i3: SIG_FLAGS # flags for S_SIGRETURN call
|
|
*
|
|
*/
|
|
|
|
#include "kernel/system.h"
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
#include <sys/sigcontext.h>
|
|
|
|
#if USE_SIGSEND
|
|
|
|
/*===========================================================================*
|
|
* do_sigsend *
|
|
*===========================================================================*/
|
|
PUBLIC int do_sigsend(struct proc * caller, message * m_ptr)
|
|
{
|
|
/* Handle sys_sigsend, POSIX-style signal handling. */
|
|
|
|
struct sigmsg smsg;
|
|
register struct proc *rp;
|
|
struct sigcontext sc, *scp;
|
|
struct sigframe fr, *frp;
|
|
int proc_nr, r;
|
|
|
|
if (!isokendpt(m_ptr->SIG_ENDPT, &proc_nr)) return(EINVAL);
|
|
if (iskerneln(proc_nr)) return(EPERM);
|
|
rp = proc_addr(proc_nr);
|
|
|
|
/* Get the sigmsg structure into our address space. */
|
|
if((r=data_copy_vmcheck(caller, caller->p_endpoint,
|
|
(vir_bytes) m_ptr->SIG_CTXT_PTR, KERNEL, (vir_bytes) &smsg,
|
|
(phys_bytes) sizeof(struct sigmsg))) != OK)
|
|
return r;
|
|
|
|
/* Compute the user stack pointer where sigcontext will be stored. */
|
|
scp = (struct sigcontext *) smsg.sm_stkptr - 1;
|
|
|
|
/* Copy the registers to the sigcontext structure. */
|
|
memcpy(&sc.sc_regs, (char *) &rp->p_reg, sizeof(sigregs));
|
|
#if (_MINIX_CHIP == _CHIP_INTEL)
|
|
if(rp->p_misc_flags & MF_FPU_INITIALIZED)
|
|
memcpy(&sc.sc_fpu_state, rp->p_fpu_state.fpu_save_area_p,
|
|
FPU_XFP_SIZE);
|
|
#endif
|
|
|
|
/* Finish the sigcontext initialization. */
|
|
sc.sc_mask = smsg.sm_mask;
|
|
sc.sc_flags = 0 | rp->p_misc_flags & MF_FPU_INITIALIZED;
|
|
|
|
/* Copy the sigcontext structure to the user's stack. */
|
|
if((r=data_copy_vmcheck(caller, KERNEL, (vir_bytes) &sc, m_ptr->SIG_ENDPT,
|
|
(vir_bytes) scp, (vir_bytes) sizeof(struct sigcontext))) != OK)
|
|
return r;
|
|
|
|
/* Initialize the sigframe structure. */
|
|
frp = (struct sigframe *) scp - 1;
|
|
fr.sf_scpcopy = scp;
|
|
fr.sf_retadr2= (void (*)()) rp->p_reg.pc;
|
|
fr.sf_fp = rp->p_reg.fp;
|
|
rp->p_reg.fp = (reg_t) &frp->sf_fp;
|
|
fr.sf_scp = scp;
|
|
|
|
fpu_sigcontext(rp, &fr, &sc);
|
|
|
|
fr.sf_signo = smsg.sm_signo;
|
|
fr.sf_retadr = (void (*)()) smsg.sm_sigreturn;
|
|
|
|
/* Copy the sigframe structure to the user's stack. */
|
|
if((r=data_copy_vmcheck(caller, KERNEL, (vir_bytes) &fr,
|
|
m_ptr->SIG_ENDPT, (vir_bytes) frp,
|
|
(vir_bytes) sizeof(struct sigframe))) != OK)
|
|
return r;
|
|
|
|
/* Reset user registers to execute the signal handler. */
|
|
rp->p_reg.sp = (reg_t) frp;
|
|
rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
|
|
|
|
/* Signal handler should get clean FPU. */
|
|
rp->p_misc_flags &= ~MF_FPU_INITIALIZED;
|
|
|
|
if(!RTS_ISSET(rp, RTS_PROC_STOP)) {
|
|
printf("system: warning: sigsend a running process\n");
|
|
printf("caller stack: ");
|
|
proc_stacktrace(caller);
|
|
}
|
|
|
|
return(OK);
|
|
}
|
|
|
|
#endif /* USE_SIGSEND */
|
|
|