--- mesa-18.3.2/src/util/u_cpu_detect.c.old 2019-01-17 11:26:23.000000000 +0000 +++ mesa-18.3.2/src/util/u_cpu_detect.c 2019-02-22 19:23:26.620000000 +0000 @@ -41,6 +41,9 @@ #if defined(PIPE_ARCH_PPC) #if defined(PIPE_OS_APPLE) #include <sys/sysctl.h> +#elif defined(PIPE_OS_LINUX) +#include <asm/cputable.h> +#include <linux/auxvec.h> #else #include <signal.h> #include <setjmp.h> @@ -92,7 +95,7 @@ #endif -#if defined(PIPE_ARCH_PPC) && !defined(PIPE_OS_APPLE) +#if defined(PIPE_ARCH_PPC) && !defined(PIPE_OS_APPLE) && !defined(PIPE_OS_LINUX) static jmp_buf __lv_powerpc_jmpbuf; static volatile sig_atomic_t __lv_powerpc_canjump = 0; @@ -126,7 +129,43 @@ util_cpu_caps.has_altivec = 1; } } -#else /* !PIPE_OS_APPLE */ +#elif defined(PIPE_OS_LINUX) + /* Taken from FFmpeg 4.1.1 (LGPL-2.1+) */ + // The linux kernel could have the altivec support disabled + // even if the cpu has it. + int i, ret = 0; + int fd = open("/proc/self/auxv", O_RDONLY); + unsigned long buf[64] = { 0 }; + ssize_t count; + boolean enable_vsx = TRUE; + /* VSX instructions can be explicitly enabled/disabled via GALLIVM_VSX=1 or 0 */ + char *env_vsx = getenv("GALLIVM_VSX"); + if (env_vsx && env_vsx[0] == '0') { + enable_vsx = FALSE; + } + + if (fd < 0) + return 0; + + while ((count = read(fd, buf, sizeof(buf))) > 0) { + for (i = 0; i < count / sizeof(*buf); i += 2) { + if (buf[i] == AT_NULL) + goto out; + if (buf[i] == AT_HWCAP) { + if (buf[i + 1] & PPC_FEATURE_HAS_ALTIVEC) + util_cpu_caps.has_altivec = 1; +#ifdef PPC_FEATURE_HAS_VSX + if (enable_vsx && buf[i + 1] & PPC_FEATURE_HAS_VSX) + util_cpu_caps.has_vsx = 1; +#endif + goto out; + } + } + } + +out: + close(fd); +#else /* !PIPE_OS_APPLE, !PIPE_OS_LINUX */ /* not on Apple/Darwin, do it the brute-force way */ /* this is borrowed from the libmpeg2 library */ signal(SIGILL, sigill_handler);