From 54c6b53ee27d3dba2b876a0d3ab0ef1dfd22b716 Mon Sep 17 00:00:00 2001 From: David Smith Date: Fri, 6 Oct 2017 10:32:53 -0500 Subject: [PATCH] Add a PR20516 workaround by using kallsyms_lookup_name to find udelay_simple. * runtime/linux/common_session_state.h (stp_session_init): Use kallsyms_lookup_name() to find udelay_simple() if it exists but isn't exported. * runtime/linux/runtime.h: Ditto. * buildrun.cxx (compile_pass): Add an new autoconf test for udelay_simple(). * runtime/linux/autoconf-udelay_simple.c: New file. --- buildrun.cxx | 4 +++- runtime/linux/autoconf-udelay_simple.c | 6 ++++++ runtime/linux/common_session_state.h | 10 ++++++++++ runtime/linux/runtime.h | 7 ++++++- 4 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 runtime/linux/autoconf-udelay_simple.c diff --git a/buildrun.cxx b/buildrun.cxx index dd0759344..a72f05d9b 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -447,7 +447,9 @@ compile_pass (systemtap_session& s) output_exportconf(s, o, "vmalloc_node", "STAPCONF_VMALLOC_NODE"); // RHBZ1233912 - s390 temporary workaround for non-atomic udelay() - output_exportconf(s, o, "udelay_simple", "STAPCONF_UDELAY_SIMPLE"); + output_exportconf(s, o, "udelay_simple", "STAPCONF_UDELAY_SIMPLE_EXPORTED"); + output_autoconf(s, o, "autoconf-udelay_simple.c", "STAPCONF_UDELAY_SIMPLE", + NULL); output_autoconf(s, o, "autoconf-tracepoint-strings.c", "STAPCONF_TRACEPOINT_STRINGS", NULL); output_autoconf(s, o, "autoconf-timerfd.c", "STAPCONF_TIMERFD_H", NULL); diff --git a/runtime/linux/autoconf-udelay_simple.c b/runtime/linux/autoconf-udelay_simple.c new file mode 100644 index 000000000..3a7b19fb3 --- /dev/null +++ b/runtime/linux/autoconf-udelay_simple.c @@ -0,0 +1,6 @@ +#include + +void foo (unsigned long long usecs) +{ + udelay_simple(usecs); +} diff --git a/runtime/linux/common_session_state.h b/runtime/linux/common_session_state.h index f52300685..444349080 100644 --- a/runtime/linux/common_session_state.h +++ b/runtime/linux/common_session_state.h @@ -78,5 +78,15 @@ static int stp_session_init(void) g_refresh_timing = _stp_stat_init(STAT_OP_MIN, STAT_OP_MAX, STAT_OP_AVG, STAT_OP_VARIANCE, 0, NULL); #endif +#if defined(STAPCONF_UDELAY_SIMPLE) && !defined(STAPCONF_UDELAY_SIMPLE_EXPORTED) + // PR20516: Some s390 kernels that have udelay_simple() don't + // have it exported. Note that we have to do this early since + // other init routines could call udelay(). + kallsyms_udelay_simple = (void *)kallsyms_lookup_name("udelay_simple"); + if (kallsyms_udelay_simple == NULL) { + _stp_error("couldn't find udelay_simple"); + return 1; + } +#endif return 0; } diff --git a/runtime/linux/runtime.h b/runtime/linux/runtime.h index 1ba777d9c..9c585a20d 100644 --- a/runtime/linux/runtime.h +++ b/runtime/linux/runtime.h @@ -62,9 +62,14 @@ #define STP_TRANSPORT_VERSION 1 #endif -#ifdef STAPCONF_UDELAY_SIMPLE +#if defined(STAPCONF_UDELAY_SIMPLE_EXPORTED) #undef udelay #define udelay(x) udelay_simple(x) +#elif defined(STAPCONF_UDELAY_SIMPLE) +#undef udelay +static void *kallsyms_udelay_simple; +typedef typeof(&udelay_simple) udelay_simple_fn; +#define udelay(x) ((* (udelay_simple_fn)(kallsyms_udelay_simple))((x))) #endif #ifndef clamp -- 2.43.5