riscv64: pass a pointer to __riscv_hwprobe() to ifunc resolvers.

This way, callees don't need to worry about whether or not their
reference to __riscv_hwprobe() has been resolved before their ifunc
resolver is called.

This matches the current glibc proposal from rivos.

Test: treehugger
Change-Id: I0d5244aa837d0d1f0e6bd7d22091dfedb8a55bdb
diff --git a/libc/bionic/bionic_call_ifunc_resolver.cpp b/libc/bionic/bionic_call_ifunc_resolver.cpp
index 0b12088..d5a812c 100644
--- a/libc/bionic/bionic_call_ifunc_resolver.cpp
+++ b/libc/bionic/bionic_call_ifunc_resolver.cpp
@@ -28,6 +28,7 @@
 
 #include "private/bionic_call_ifunc_resolver.h"
 #include <sys/auxv.h>
+#include <sys/hwprobe.h>
 #include <sys/ifunc.h>
 
 #include "bionic/macros.h"
@@ -51,20 +52,15 @@
   return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(arg._hwcap | _IFUNC_ARG_HWCAP, &arg);
 #elif defined(__arm__)
   typedef ElfW(Addr) (*ifunc_resolver_t)(unsigned long);
-  static unsigned long hwcap;
-  static bool initialized = false;
-  if (!initialized) {
-    initialized = true;
-    hwcap = getauxval(AT_HWCAP);
-  }
+  static unsigned long hwcap = getauxval(AT_HWCAP);
   return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(hwcap);
 #elif defined(__riscv)
-  // The pointer argument is currently unused, but reserved for future
+  // The third argument is currently unused, but reserved for future
   // expansion. If we pass nullptr from the beginning, it'll be easier
   // to recognize if/when we pass actual data (and matches glibc).
-  typedef ElfW(Addr) (*ifunc_resolver_t)(uint64_t, void*);
+  typedef ElfW(Addr) (*ifunc_resolver_t)(uint64_t, __riscv_hwprobe_t, void*);
   static uint64_t hwcap = getauxval(AT_HWCAP);
-  return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(hwcap, nullptr);
+  return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(hwcap, __riscv_hwprobe, nullptr);
 #else
   typedef ElfW(Addr) (*ifunc_resolver_t)(void);
   return reinterpret_cast<ifunc_resolver_t>(resolver_addr)();