summaryrefslogtreecommitdiff
path: root/liboil
diff options
context:
space:
mode:
authorDavid Schleef <ds@ginger.bigkitten.com>2008-03-13 00:23:21 -0700
committerDavid Schleef <ds@ginger.bigkitten.com>2008-03-13 00:23:21 -0700
commitdf0e54862b788e44e4bc21fab4c10032be664056 (patch)
treef4cbe90e4620e8f28763c7111b67de324ad67cf1 /liboil
parent3952640898d5b767e30ef6e96267384602824c05 (diff)
Use /proc/self/auxv to test for altivec on Linux. Patch from #14914
Diffstat (limited to 'liboil')
-rw-r--r--liboil/liboilcpu-powerpc.c79
1 files changed, 68 insertions, 11 deletions
diff --git a/liboil/liboilcpu-powerpc.c b/liboil/liboilcpu-powerpc.c
index a0f029f..6ae591b 100644
--- a/liboil/liboilcpu-powerpc.c
+++ b/liboil/liboilcpu-powerpc.c
@@ -34,15 +34,20 @@
#include <liboil/liboilfault.h>
#include <liboil/liboilutils.h>
-//#include <unistd.h>
-//#include <fcntl.h>
-//#include <stdlib.h>
-//#include <string.h>
-//#include <stdio.h>
-//#include <setjmp.h>
-//#include <signal.h>
-//#include <sys/time.h>
-//#include <time.h>
+#if defined(__linux__)
+#include <linux/auxvec.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#ifndef PPC_FEATURE_HAS_ALTIVEC
+/* From linux-2.6/include/asm-powerpc/cputable.h */
+#define PPC_FEATURE_HAS_ALTIVEC 0x10000000
+#endif
+
+#endif
#if defined(__FreeBSD__)
#include <sys/types.h>
@@ -67,7 +72,7 @@ test_altivec (void * ignored)
}
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-void
+static void
oil_check_altivec_sysctl_freebsd (void)
{
int ret, av;
@@ -82,7 +87,7 @@ oil_check_altivec_sysctl_freebsd (void)
#endif
#if defined(__APPLE__)
-void
+static void
oil_check_altivec_sysctl_darwin (void)
{
int ret, vu;
@@ -96,6 +101,56 @@ oil_check_altivec_sysctl_darwin (void)
}
#endif
+#if defined(__linux__)
+static void
+oil_check_altivec_proc_auxv (void)
+{
+ static int available = -1;
+ int new_avail = 0;
+ unsigned long buf[64];
+ ssize_t count;
+ int fd, i;
+
+ /* Flags already set */
+ if (available != -1) {
+ return;
+ }
+
+ fd = open("/proc/self/auxv", O_RDONLY);
+ if (fd < 0) {
+ goto out;
+ }
+
+more:
+ count = read(fd, buf, sizeof(buf));
+ if (count < 0) {
+ goto out_close;
+ }
+
+ for (i=0; i < (count / sizeof(unsigned long)); i += 2) {
+ if (buf[i] == AT_HWCAP) {
+ new_avail = !!(buf[i+1] & PPC_FEATURE_HAS_ALTIVEC);
+ goto out_close;
+ } else if (buf[i] == AT_NULL) {
+ goto out_close;
+ }
+ }
+
+ if (count == sizeof(buf)) {
+ goto more;
+ }
+
+out_close:
+ close(fd);
+
+out:
+ available = new_avail;
+ if (available) {
+ oil_cpu_flags |= OIL_IMPL_FLAG_ALTIVEC;
+ }
+}
+#endif
+
void
oil_check_altivec_fault (void)
{
@@ -114,6 +169,8 @@ oil_cpu_detect_arch(void)
oil_check_altivec_sysctl_freebsd();
#elif defined(__APPLE__)
oil_check_altivec_sysctl_darwin();
+#elif defined(__linux__)
+ oil_check_altivec_proc_auxv();
#else
oil_check_altivec_fault();
#endif