Implement the functions feenableexcept(), fedisableexcept() and fegetexcept(), non-standard glibc functions which allows controlling which FPU events generate a floating point exception.
Signed-off-by: Nadav Har'El <[email protected]> --- arch/aarch64/feexcept.cc | 34 ++++++++++++++++++++++++ arch/x64/feexcept.cc | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ Makefile | 1 + 3 files changed, 104 insertions(+) create mode 100644 arch/aarch64/feexcept.cc create mode 100644 arch/x64/feexcept.cc diff --git a/arch/aarch64/feexcept.cc b/arch/aarch64/feexcept.cc new file mode 100644 index 0000000..647f0a5 --- /dev/null +++ b/arch/aarch64/feexcept.cc @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2017 ScyllaDB, Ltd. + * + * This work is open source software, licensed under the terms of the + * BSD license as described in the LICENSE file in the top-level directory. + */ + +#include <osv/types.h> +#include <osv/stubbing.hh> +#include <fenv.h> +// Note that musl's fenv.h does not define feenableexcept and friends, so +// we need to 'extern "C"' them here, as no header file does this. + +extern "C" +int feenableexcept(int mask) +{ + WARN_STUBBED(); + // The feenableexcept says it returns -1 on failure. + return -1; +} + +extern "C" +int fedisableexcept(int mask) +{ + WARN_STUBBED(); + return -1; +} + +extern "C" +int fegetexcept() +{ + WARN_STUBBED(); + return -1; +} diff --git a/arch/x64/feexcept.cc b/arch/x64/feexcept.cc new file mode 100644 index 0000000..38399d8 --- /dev/null +++ b/arch/x64/feexcept.cc @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2017 ScyllaDB, Ltd. + * + * This work is open source software, licensed under the terms of the + * BSD license as described in the LICENSE file in the top-level directory. + */ + +#include <osv/types.h> +#include <fenv.h> +// Note that musl's fenv.h does not define feenableexcept and friends, so +// we need to 'extern "C"' them here, as no header file does this. + +extern "C" +int feenableexcept(int mask) +{ + // The feenableexcept() manual page suggests that -1 should be returned + // on failure, and theoretically this could include the case that invalid + // bits are passed in mask. But in practice, the Linux implementation + // simply ignores invalid bits, and never returns -1. + mask &= FE_ALL_EXCEPT; + + // Update the the x87 control word. Note that: + // 1. We need to leave the other bits (non-exception related) unchanged. + // 2. A 1 bit means disable exception (opposite of our "mask") + // 3. This function is supposed to only enable exceptions. + // not those to enable (as "mask" specifies) + u16 cw; + asm volatile("fstcw %0" : "=m"(cw)); + // Save the previous set of enabled exceptions, for returning later. + int ret = (~cw) & FE_ALL_EXCEPT; + cw &= ~mask; + asm volatile("fldcw %0" : : "m"(cw)); + + // Also update the SSE control and status register (here the relevant + // bits start at bit 7). + u32 csr; + asm volatile("stmxcsr %0" : "=m"(csr)); + csr &= ~(mask << 7); + asm volatile("ldmxcsr %0" : : "m"(csr)); + + return ret; +} + +extern "C" +int fedisableexcept(int mask) +{ + mask &= FE_ALL_EXCEPT; + + u16 cw; + asm volatile("fstcw %0" : "=m"(cw)); + int ret = (~cw) & FE_ALL_EXCEPT; + cw |= mask; + asm volatile("fldcw %0" : : "m"(cw)); + + u32 csr; + asm volatile("stmxcsr %0" : "=m"(csr)); + csr |= mask << 7; + asm volatile("ldmxcsr %0" : : "m"(csr)); + + return ret; +} + +extern "C" +int fegetexcept() +{ + u16 cw; + asm volatile("fstcw %0" : "=m"(cw)); + return (~cw) & FE_ALL_EXCEPT; +} diff --git a/Makefile b/Makefile index 7ee113b..c0d8254 100644 --- a/Makefile +++ b/Makefile @@ -849,6 +849,7 @@ objects += arch/$(arch)/interrupt.o objects += arch/$(arch)/pci.o objects += arch/$(arch)/msi.o objects += arch/$(arch)/power.o +objects += arch/$(arch)/feexcept.o $(out)/arch/x64/string-ssse3.o: CXXFLAGS += -mssse3 -- 2.9.3 -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
