diff --git a/lib/rpmrc.c b/lib/rpmrc.c index 1b47dc3..6a71923 100644 --- a/lib/rpmrc.c +++ b/lib/rpmrc.c @@ -17,6 +17,13 @@ #define __power_pc() 0 #endif +#if defined(__linux) +#if defined(__arm__) || defined(__sparc__) +#include +#define NEED_HWCAP 1 +#endif +#endif + #include /* RPM_MACTABLE*, Rc-prototypes */ #include #include @@ -707,6 +714,40 @@ exit: return rc; } +#if defined(NEED_HWCAP) +/* hwcap defs are scattered in strange places, define what we need here */ +#define HWC_SPARC_BLKINIT (1 << 6) +#define HWC_ARM_NEON (1 << 12) +#define HWC_ARM_VFPv3 (1 << 13) + +static uint64_t hwcaps(uint64_t have_caps) +{ + static uint64_t cached_caps = 0; + static int oneshot = 1; + + if (oneshot) { + int fd = open("/proc/self/auxv", O_RDONLY); + + if (fd == -1) { + rpmlog(RPMLOG_WARNING, + _("Failed to read auxiliary vector, /proc not mounted?\n")); + } else { + ElfW(auxv_t) auxv; + while (read(fd, &auxv, sizeof(auxv)) == sizeof(auxv)) { + if (auxv.a_type == AT_NULL) + break; + if (auxv.a_type == AT_HWCAP) { + cached_caps = auxv.a_un.a_val; + break; + } + } + close(fd); + } + oneshot = 0; /* only try once even if it fails */ + } + return have_caps ? (cached_caps & have_caps) : cached_caps; +} +#endif /* NEED_HWCAP */ # if defined(__linux__) && defined(__i386__) #include @@ -1123,8 +1164,33 @@ static void defaultMachine(const char ** arch, personality(oldpers); } } + + /* Supposed to detect Sun4v aka Niagara */ + if (hwcaps(HWC_SPARC_BLKINIT)) { + if (rstreq(un.machine, "sparcv9") || rstreq(un.machine, "sparc")) { + strcpy(un.machine, "sparcv9v"); + } else if (rstreq(un.machine, "sparc64")) { + strcpy(un.machine, "sparc64v"); + } + } # endif /* sparc*-linux */ +# if defined(__linux__) && defined(__arm__) + if (rstreq(un.machine, "armv7l")) { + if (hwcaps((HWC_ARM_NEON | HWC_ARM_VFPv3))) { + strcpy(un.machine, "armv7hnl"); + } else if (hwcaps(HWC_ARM_VFPv3)) { + strcpy(un.machine, "armv7hl"); + } + } else if (rstreq(un.machine, "armv6l")) { + if (hwcaps((HWC_ARM_NEON | HWC_ARM_VFPv3))) { + strcpy(un.machine, "armv6hnl"); + } else if (hwcaps(HWC_ARM_VFPv3)) { + strcpy(un.machine, "armv6hl"); + } + } +# endif /* arm*-linux */ + # if defined(__GNUC__) && defined(__alpha__) { unsigned long amask, implver;