Changeset 13952


Ignore:
Timestamp:
Jul 10, 2010, 5:10:09 AM (9 years ago)
Author:
rme
Message:

New scheme for dealing with floating point exceptions on x86-64 systems.

Currently, we mask floating point execptions around all foreign function
calls. While this may not be a huge component of FF call overhead, it
makes sense to avoid doing this for what is presumably an exceptional
case.

We now leave floating point exceptions enabled, but the exception
handler in the lisp kernel is prepared to deal with them: it saves
lisp's MXCSR, masks all floating point exceptions, and resumes
execution (after setting a flag in the TCR to note what it has done).
At the end of .SPffcall, we check this flag. If it is set, we
save the fp exception status, and restore lisp's original MXCSR.

Location:
trunk/source
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/source

  • trunk/source/lisp-kernel/constants.h

    r13626 r13952  
    2424#define TCR_FLAG_BIT_FOREIGN_EXCEPTION (fixnumshift+6)
    2525#define TCR_FLAG_BIT_PENDING_SUSPEND (fixnumshift+7)
     26#define TCR_FLAG_BIT_FOREIGN_FPE (fixnumshift+8)
    2627
    2728#define TCR_STATE_FOREIGN (1)
  • trunk/source/lisp-kernel/platform-darwinx8632.h

    r13638 r13952  
    5454/* Note that this yields only the lower half of the MMX reg on x8632 */
    5555#define xpMMXreg(x,n) *(natural *)&(xpMMXvector(x)[n])
    56 
     56#define xpMXCSR(x) (UC_MCONTEXT(x)->__fs.__fpu_mxcsr)
    5757#define SIGNUM_FOR_INTN_TRAP SIGSEGV /* Not really, but our Mach handler fakes that */
    5858#define IS_MAYBE_INT_TRAP(info,xp) ((UC_MCONTEXT(xp)->__es.__trapno == 0xd) && (((UC_MCONTEXT(xp)->__es.__err)&7)==2))
  • trunk/source/lisp-kernel/platform-darwinx8664.h

    r13638 r13952  
    5454/* Note that this yields only the lower half of the MMX reg on x8632 */
    5555#define xpMMXreg(x,n) *(natural *)&(xpMMXvector(x)[n])
     56#define xpMXCSR(x) (UC_MCONTEXT(x)->__fs.__fpu_mxcsr)
    5657#define SIGNUM_FOR_INTN_TRAP SIGSEGV /* Not really, but our Mach handler fakes that */
    5758#define IS_MAYBE_INT_TRAP(info,xp) ((UC_MCONTEXT(xp)->__es.__trapno == 0xd) && (((UC_MCONTEXT(xp)->__es.__err)&7)==2))
  • trunk/source/lisp-kernel/platform-freebsdx8632.h

    r13640 r13952  
    4040#define xpMMXreg(x,n) *((natural *)(&(((struct ccl_savexmm *)(&(x)->uc_mcontext.mc_fpstate))->sv_fp[n])))
    4141#define xpXMMregs(x)(&(((struct ccl_savexmm *)(&(x)->uc_mcontext.mc_fpstate))->sv_xmm[0]))
     42#define xpMXCSR(x) ((struct savefpu *)((x)->uc_mcontext.mc_fpstate)->sv_env.en_mxcsr)
    4243extern void freebsd_sigreturn(ExceptionInformation *);
    4344#define SIGNUM_FOR_INTN_TRAP SIGBUS
  • trunk/source/lisp-kernel/platform-freebsdx8664.h

    r13638 r13952  
    3939#define xpMMXreg(x,n) *((natural *)(&(((struct savefpu *)(&(x)->uc_mcontext.mc_fpstate))->sv_fp[n])))
    4040#define xpXMMregs(x)(&(((struct savefpu *)(&(x)->uc_mcontext.mc_fpstate))->sv_xmm[0]))
     41#define xpMXCSR(x) ((struct savefpu *)((x)->uc_mcontext.mc_fpstate)->sv_env.en_mxcsr)
    4142extern void freebsd_sigreturn(ExceptionInformation *);
    4243#define SIGNUM_FOR_INTN_TRAP SIGBUS
  • trunk/source/lisp-kernel/platform-linuxx8632.h

    r13638 r13952  
    3838#define xpPC(x) (xpGPR(x,Iip))
    3939#define xpMMXreg(x,n)  *((natural *)(&((x)->uc_mcontext.fpregs->_st[n])))
     40/* You're supposed to look at a magic field in the struct _fpstate
     41   to know if there is sse2 state present; we only run on systems
     42   with sse2, so we'll assume it's always there. */
     43#define xpMXCSR(xp) (((struct _fpstate *)((xp)->uc_mcontext.fpregs))->mxcsr)
    4044#define eflags_register(xp) xpGPR(xp,Iflags)
    4145#define SIGNUM_FOR_INTN_TRAP SIGSEGV
  • trunk/source/lisp-kernel/platform-linuxx8664.h

    r13638 r13952  
    3737#define xpPC(x) (xpGPR(x,Iip))
    3838#define xpMMXreg(x,n)  *((natural *)(&((x)->uc_mcontext.fpregs->_st[n])))
     39#define xpMXCSR(xp) ((xp)->uc_mcontext.fpregs->mxcsr)
    3940#define eflags_register(xp) xpGPR(xp,Iflags)
    4041#define SIGNUM_FOR_INTN_TRAP SIGSEGV
  • trunk/source/lisp-kernel/platform-solarisx64.h

    r13638 r13952  
    3737#define eflags_register(xp) xpGPR(xp,Iflags)
    3838#define xpXMMregs(x)(&((x)->uc_mcontext.fpregs.fp_reg_set.fpchip_state.xmm[0]))
     39#define xmMXCSR(x) ((x)->uc_mcontext.fpregs.fp_reg_set.fpchip_state.xstatus)
    3940#define SIGNUM_FOR_INTN_TRAP SIGSEGV
    4041#ifdef X8664
  • trunk/source/lisp-kernel/platform-solarisx86.h

    r13638 r13952  
    3838#define xpXMMregs(x)(&((x)->uc_mcontext.fpregs.fp_reg_set.fpchip_state.xmm[0]))
    3939#define xpMMXreg(x,n)*(natural *)(&(((struct fnsave_state *)(&(((x)->uc_mcontext.fpregs))))->f_st[n]))
     40#define xmMXCSR(x) ((x)->uc_mcontext.fpregs.fp_reg_set.fpchip_state.xstatus)
    4041#define SIGNUM_FOR_INTN_TRAP SIGSEGV
    4142#ifdef X8664
  • trunk/source/lisp-kernel/platform-win32.h

    r13642 r13952  
    3939#define xpFPRvector(x) ((natural *)(&(x->ExtendedRegisters[10*16])))
    4040#define xpMMXreg(x,n)  (*((u64_t *)(&(x->FloatSave.RegisterArea[10*(n)]))))
    41 #define xpMXCSRptr(x) (DWORD *)(&(x->ExtendedRegisters[24]))
     41#define xpMXCSRptr(x) ((DWORD *)(&(x->ExtendedRegisters[24])))
     42#define xpMXCSR(x) (*xpMXCSRptr(x))
    4243
    4344#define SIGNUM_FOR_INTN_TRAP SIGSEGV /* Also fake */
  • trunk/source/lisp-kernel/platform-win64.h

    r13641 r13952  
    3939#define eflags_register(xp) xp->EFlags
    4040#define xpMXCSRptr(x) (DWORD *)(&(x->MxCsr))
    41 
     41#define xpMXCSR(x) ((x)->MxCsr)
    4242
    4343#define SIGNUM_FOR_INTN_TRAP SIGSEGV /* Also fake */
  • trunk/source/lisp-kernel/x86-constants.h

    r13627 r13952  
    1717#include "constants.h"
    1818
     19/* MXCSR bits */
    1920
    20 /* FP exception mask bits */
    21 #define MXCSR_IM_BIT (7)        /* invalid masked when set*/
    22 #define MXCSR_DM_BIT (8)        /* denormals masked when set*
    23 #define MXCSR_ZM_BIT (9)        /* divide-by-zero masked when set */
    24 #define MXCSR_OM_BIT (10)       /* overflow masked when set */
    25 #define MXCSR_UM_BIT (11)       /* underflow masked when set */
    26 #define MXCSR_PM_BIT (12)       /* precision masked when set */
     21enum {
     22  MXCSR_IE_BIT,    /* invalid operation */
     23  MXCSR_DE_BIT,    /* denormal */
     24  MXCSR_ZE_BIT,    /* divide-by-zero */
     25  MXCSR_OE_BIT,    /* overflow */
     26  MXCSR_UE_BIT,    /* underflow */
     27  MXCSR_PE_BIT,    /* precision */
     28  MXCSR_DAZ_BIT,   /* denorms-are-zero (not IEEE) */
     29  MXCSR_IM_BIT,    /* invalid operation masked */
     30  MXCSR_DM_BIT,    /* denormal masked */
     31  MXCSR_ZM_BIT,    /* divide-by-zero masked */
     32  MXCSR_OM_BIT,    /* overflow masked */
     33  MXCSR_UM_BIT,    /* underflow masked */
     34  MXCSR_PM_BIT,    /* precision masked */
     35  MXCSR_RC0_BIT,   /* rounding control bit 0 */
     36  MXCSR_RC1_BIT,   /* rounding control bit 1 */
     37  MXCSR_FZ_BIT     /* flush-to-zero (not IEEE) */
     38};
     39
     40#define MXCSR_STATUS_MASK ((1 << MXCSR_IE_BIT) | \
     41                           (1 << MXCSR_DE_BIT) | \
     42                           (1 << MXCSR_ZE_BIT) | \
     43                           (1 << MXCSR_OE_BIT) | \
     44                           (1 << MXCSR_UE_BIT) | \
     45                           (1 << MXCSR_PE_BIT))
     46
     47#define MXCSR_CONTROL_AND_ROUNDING_MASK ((1<<MXCSR_IM_BIT) | \
     48                                         (1<<MXCSR_DM_BIT) | \
     49                                         (1<<MXCSR_ZM_BIT) | \
     50                                         (1<<MXCSR_OM_BIT) | \
     51                                         (1<<MXCSR_UM_BIT) | \
     52                                         (1<<MXCSR_PM_BIT) | \
     53                                         (1<<MXCSR_RC0_BIT) | \
     54                                         (1<<MXCSR_RC1_BIT))
     55
     56#define MXCSR_CONTROL_MASK ((1<<MXCSR_IM_BIT) | \
     57                            (1<<MXCSR_DM_BIT) | \
     58                            (1<<MXCSR_ZM_BIT) | \
     59                            (1<<MXCSR_OM_BIT) | \
     60                            (1<<MXCSR_UM_BIT) | \
     61                            (1<<MXCSR_PM_BIT))
     62
     63#define MXCSR_WRITE_MASK (~((1<<MXCSR_DAZ_BIT)|(1<<MXCSR_FZ_BIT)))
    2764
    2865/* Bits in the xFLAGS register */
  • trunk/source/lisp-kernel/x86-constants.s

    r13337 r13952  
    136136mxcsr_pe_bit = 5
    137137num_mxcsr_exception_bits = 6
    138        
     138
    139139mxcsr_all_exceptions = ((1<<num_mxcsr_exception_bits)-1)
    140        
     140
     141TCR_FLAG_BIT_FOREIGN = fixnum_shift
     142TCR_FLAG_BIT_AWAITING_PRESET = (fixnum_shift+1)
     143TCR_FLAG_BIT_ALT_SUSPEND = (fixnumshift+2)
     144TCR_FLAG_BIT_PROPAGATE_EXCEPTION = (fixnumshift+3)
     145TCR_FLAG_BIT_SUSPEND_ACK_PENDING = (fixnumshift+4)
     146TCR_FLAG_BIT_PENDING_EXCEPTION = (fixnumshift+5)
     147TCR_FLAG_BIT_FOREIGN_EXCEPTION = (fixnumshift+6)
     148TCR_FLAG_BIT_PENDING_SUSPEND = (fixnumshift+7)       
     149TCR_FLAG_BIT_FOREIGN_FPE = (fixnumshift+8)       
  • trunk/source/lisp-kernel/x86-constants32.s

    r13406 r13952  
    602602         _ends
    603603       
    604 TCR_FLAG_BIT_FOREIGN = fixnum_shift
    605 TCR_FLAG_BIT_AWAITING_PRESET = (fixnum_shift+1)
    606 TCR_FLAG_BIT_ALT_SUSPEND = (fixnumshift+2)
    607 TCR_FLAG_BIT_PROPAGATE_EXCEPTION = (fixnumshift+3)
    608 TCR_FLAG_BIT_SUSPEND_ACK_PENDING = (fixnumshift+4)
    609 TCR_FLAG_BIT_PENDING_EXCEPTION = (fixnumshift+5)
    610 TCR_FLAG_BIT_FOREIGN_EXCEPTION = (fixnumshift+6)
    611 TCR_FLAG_BIT_PENDING_SUSPEND = (fixnumshift+7)
    612 
    613604target_most_positive_fixnum = 536870911
    614605target_most_negative_fixnum = -536870912
  • trunk/source/lisp-kernel/x86-constants64.s

    r13406 r13952  
    10261026
    10271027       
    1028 TCR_FLAG_BIT_FOREIGN = fixnum_shift
    1029 TCR_FLAG_BIT_AWAITING_PRESET = (fixnum_shift+1)
    1030 TCR_FLAG_BIT_ALT_SUSPEND = (fixnumshift+2)
    1031 TCR_FLAG_BIT_PROPAGATE_EXCEPTION = (fixnumshift+3)
    1032 TCR_FLAG_BIT_SUSPEND_ACK_PENDING = (fixnumshift+4)
    1033 TCR_FLAG_BIT_PENDING_EXCEPTION = (fixnumshift+5)
    1034 TCR_FLAG_BIT_FOREIGN_EXCEPTION = (fixnumshift+6)
    1035 TCR_FLAG_BIT_PENDING_SUSPEND = (fixnumshift+7)       
    1036        
    10371028target_most_positive_fixnum = 1152921504606846975
    10381029target_most_negative_fixnum = -1152921504606846976
  • trunk/source/lisp-kernel/x86-exceptions.c

    r13943 r13952  
    942942
    943943Boolean
     944handle_foreign_fpe(TCR *tcr, ExceptionInformation *xp, siginfo_t *info)
     945{
     946#ifdef X8632
     947  return false;
     948#else
     949  int code;
     950
     951#ifdef WINDOWS
     952  if (info->ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO)
     953    return false;
     954#else
     955  if (info->si_code == FPE_INTDIV)
     956    return false;
     957#endif
     958
     959  /*
     960   * Cooperate with .SPffcall to avoid saving and restoring the MXCSR
     961   * around every foreign call.
     962   */
     963    if (! (tcr->flags & (1<<TCR_FLAG_BIT_FOREIGN_FPE))) {
     964      tcr->flags |= (1<<TCR_FLAG_BIT_FOREIGN_FPE);
     965      tcr->lisp_mxcsr = xpMXCSR(xp) & ~MXCSR_STATUS_MASK;
     966    }
     967    xpMXCSR(xp) &= ~MXCSR_STATUS_MASK;
     968    xpMXCSR(xp) |= MXCSR_CONTROL_MASK;
     969    return true;
     970#endif
     971}
     972
     973Boolean
    944974handle_floating_point_exception(TCR *tcr, ExceptionInformation *xp, siginfo_t *info)
    945975{
     
    955985
    956986  if ((fulltag_of(cmain) == fulltag_misc) &&
    957       (header_subtag(header_of(cmain)) == subtag_macptr)) {
     987             (header_subtag(header_of(cmain)) == subtag_macptr)) {
    958988    xcf = create_exception_callback_frame(xp, tcr);
    959989    skip = callback_to_lisp(tcr, cmain, xp, xcf, SIGFPE, code, 0, 0);
     
    10791109
    10801110  if (old_valence != TCR_STATE_LISP) {
    1081     return false;
     1111    if (old_valence == TCR_STATE_FOREIGN && signum == SIGFPE) {
     1112      return handle_foreign_fpe(tcr, context, info);
     1113    } else {
     1114      return false;
     1115    }
    10821116  }
    10831117
  • trunk/source/lisp-kernel/x86-spentry64.s

    r13561 r13952  
    39913991        __(movq $TCR_STATE_FOREIGN,rcontext(tcr.valence))
    39923992        __(movq rcontext(tcr.foreign_sp),%rsp)
    3993         __(stmxcsr rcontext(tcr.lisp_mxcsr))
    39943993        __(emms)
    3995         __(ldmxcsr rcontext(tcr.foreign_mxcsr))
    39963994        __(movq (%rsp),%rbp)
    39973995        __ifdef(`DARWIN_GS_HACK')
     
    40704068        __(clr %fn)
    40714069        __(pxor %fpzero,%fpzero)
     4070
     4071        /* If we got a floating-point exception during the ff-call,
     4072           our handler will have set a flag, preserved lisp's MXCSR,
     4073           and resumed execution with fp exceptions masked. */
     4074        __(btrq $TCR_FLAG_BIT_FOREIGN_FPE,rcontext(tcr.flags))
     4075        __(jnc 1f)
    40724076        __(cmpb $0,C(bogus_fp_exceptions)(%rip))
    40734077        __(je 0f)
     
    40754079        __(jmp 1f)
    407640800:      __(stmxcsr rcontext(tcr.ffi_exception))
     4081        __(ldmxcsr rcontext(tcr.lisp_mxcsr)) /* preserved by the handler */
    407740821:      __(movq rcontext(tcr.save_vsp),%rsp)
    40784083        __(movq rcontext(tcr.save_rbp),%rbp)
     
    40904095        __(pop %temp2)
    40914096        __(pop %temp1)
    4092         __(ldmxcsr rcontext(tcr.lisp_mxcsr))
    40934097        __(check_pending_interrupt(%temp0))
    40944098        __(pop %temp0)
     
    42114215        __(movq $TCR_STATE_FOREIGN,rcontext(tcr.valence))
    42124216        __(movq rcontext(tcr.foreign_sp),%rsp)
    4213         __(stmxcsr rcontext(tcr.lisp_mxcsr))
    42144217        __(emms)
    4215         __(ldmxcsr rcontext(tcr.foreign_mxcsr))
    42164218        __(movq (%rsp),%rbp)
    42174219        __ifdef(`DARWIN_GS_HACK')
     
    42904292        __(clr %fn)
    42914293        __(pxor %fpzero,%fpzero)
     4294        /* Check for fp exceptions as in .SPffcall, above. */
     4295        __(btrq $TCR_FLAG_BIT_FOREIGN_FPE,rcontext(tcr.flags))
     4296        __(jnc 1f)
    42924297        __(cmpb $0,C(bogus_fp_exceptions)(%rip))
    42934298        __(je 0f)
     
    42954300        __(jmp 1f)
    429643010:      __(stmxcsr rcontext(tcr.ffi_exception))
     4302        __(ldmxcsr rcontext(tcr.lisp_mxcsr))
    429743031:      __(movq rcontext(tcr.save_vsp),%rsp)
    42984304        __(movq rcontext(tcr.save_rbp),%rbp)
     
    43104316        __(pop %temp2)
    43114317        __(pop %temp1)
    4312         __(ldmxcsr rcontext(tcr.lisp_mxcsr))
    43134318        __(check_pending_interrupt(%temp0))
    43144319        __(pop %temp0)
Note: See TracChangeset for help on using the changeset viewer.