• J
    powerpc: fix exception clearing in e500 SPE float emulation · 640e9225
    Joseph Myers 提交于
    The e500 SPE floating-point emulation code clears existing exceptions
    (__FPU_FPSCR &= ~FP_EX_MASK;) before ORing in the exceptions from the
    emulated operation.  However, these exception bits are the "sticky",
    cumulative exception bits, and should only be cleared by the user
    program setting SPEFSCR, not implicitly by any floating-point
    instruction (whether executed purely by the hardware or emulated).
    The spurious clearing of these bits shows up as missing exceptions in
    glibc testing.
    
    Fixing this, however, is not as simple as just not clearing the bits,
    because while the bits may be from previous floating-point operations
    (in which case they should not be cleared), the processor can also set
    the sticky bits itself before the interrupt for an exception occurs,
    and this can happen in cases when IEEE 754 semantics are that the
    sticky bit should not be set.  Specifically, the "invalid" sticky bit
    is set in various cases with non-finite operands, where IEEE 754
    semantics do not involve raising such an exception, and the
    "underflow" sticky bit is set in cases of exact underflow, whereas
    IEEE 754 semantics are that this flag is set only for inexact
    underflow.  Thus, for correct emulation the kernel needs to know the
    setting of these two sticky bits before the instruction being
    emulated.
    
    When a floating-point operation raises an exception, the kernel can
    note the state of the sticky bits immediately afterwards.  Some
    <fenv.h> functions that affect the state of these bits, such as
    fesetenv and feholdexcept, need to use prctl with PR_GET_FPEXC and
    PR_SET_FPEXC anyway, and so it is natural to record the state of those
    bits during that call into the kernel and so avoid any need for a
    separate call into the kernel to inform it of a change to those bits.
    Thus, the interface I chose to use (in this patch and the glibc port)
    is that one of those prctl calls must be made after any userspace
    change to those sticky bits, other than through a floating-point
    operation that traps into the kernel anyway.  feclearexcept and
    fesetexceptflag duly make those calls, which would not be required
    were it not for this issue.
    
    The previous EGLIBC port, and the uClibc code copied from it, is
    fundamentally broken as regards any use of prctl for floating-point
    exceptions because it didn't use the PR_FP_EXC_SW_ENABLE bit in its
    prctl calls (and did various worse things, such as passing a pointer
    when prctl expected an integer).  If you avoid anything where prctl is
    used, the clearing of sticky bits still means it will never give
    anything approximating correct exception semantics with existing
    kernels.  I don't believe the patch makes things any worse for
    existing code that doesn't try to inform the kernel of changes to
    sticky bits - such code may get incorrect exceptions in some cases,
    but it would have done so anyway in other cases.
    Signed-off-by: NJoseph Myers <joseph@codesourcery.com>
    Signed-off-by: NScott Wood <scottwood@freescale.com>
    640e9225
processor.h 13.8 KB