summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Foster2012-04-15 16:03:27 -0700
committerJohnathan Corgan2012-04-16 08:25:23 -0700
commitc3f2c30a54c75575f464afdd7cd11a017fb07695 (patch)
tree6889936b1b11ae77fbdcdfb6da17cb7ea840422f
parent04e2ebb979942cada74f10ea022342716c6851bf (diff)
downloadgnuradio-c3f2c30a54c75575f464afdd7cd11a017fb07695.tar.gz
gnuradio-c3f2c30a54c75575f464afdd7cd11a017fb07695.tar.bz2
gnuradio-c3f2c30a54c75575f464afdd7cd11a017fb07695.zip
Volk: add support for checking AVX enable state of OS.
Some systems (notably Xen hypervisor) appear to use XSETBV to disable AVX. This causes SIGILL when running AVX instructions. This commit makes Volk check XCR0 on the AVX arch before proceeding.
-rw-r--r--volk/gen/archs.xml2
-rw-r--r--volk/gen/make_cpuid_c.py40
-rw-r--r--volk/lib/gcc_x86_cpuid.h12
3 files changed, 42 insertions, 12 deletions
diff --git a/volk/gen/archs.xml b/volk/gen/archs.xml
index effd90d33..53db3e577 100644
--- a/volk/gen/archs.xml
+++ b/volk/gen/archs.xml
@@ -148,6 +148,8 @@
<reg>c</reg>
<shift>28</shift>
<flag>mavx</flag>
+ <check>xgetbv</check>
+ <checkval>7</checkval>
<alignment>32</alignment>
</arch>
diff --git a/volk/gen/make_cpuid_c.py b/volk/gen/make_cpuid_c.py
index 2be1123a8..4bd1ce5b1 100644
--- a/volk/gen/make_cpuid_c.py
+++ b/volk/gen/make_cpuid_c.py
@@ -90,20 +90,26 @@ def make_cpuid_c(dom) :
no_test = False;
else:
no_test = False;
- arch = str(domarch.attributes["name"].value);
- op = domarch.getElementsByTagName("op");
+ arch = str(domarch.attributes["name"].value)
+ op = domarch.getElementsByTagName("op")
if op:
- op = str(op[0].firstChild.data);
- reg = domarch.getElementsByTagName("reg");
+ op = str(op[0].firstChild.data)
+ reg = domarch.getElementsByTagName("reg")
if reg:
- reg = str(reg[0].firstChild.data);
- shift = domarch.getElementsByTagName("shift");
+ reg = str(reg[0].firstChild.data)
+ shift = domarch.getElementsByTagName("shift")
if shift:
- shift = str(shift[0].firstChild.data);
- val = domarch.getElementsByTagName("val");
+ shift = str(shift[0].firstChild.data)
+ val = domarch.getElementsByTagName("val")
if val:
- val = str(val[0].firstChild.data);
-
+ val = str(val[0].firstChild.data)
+ check = domarch.getElementsByTagName("check")
+ if check:
+ check = str(check[0].firstChild.data)
+ checkval = domarch.getElementsByTagName("checkval")
+ if checkval:
+ checkval = str(checkval[0].firstChild.data)
+
if no_test:
tempstring = tempstring + """\
int i_can_has_%s () {
@@ -121,13 +127,23 @@ int i_can_has_%s () {
int i_can_has_%s () {
#if defined(VOLK_CPU_x86)
unsigned int e%sx = cpuid_e%sx (%s);
- return ((e%sx >> %s) & 1) == %s;
+ int hwcap = (((e%sx >> %s) & 1) == %s);
+""" % (arch, reg, reg, op, reg, shift, val)
+
+ if check and checkval:
+ tempstring += """\
+ if (hwcap == 0) return 0;
+ hwcap &= (%s() == %s);
+""" % (check, checkval)
+
+ tempstring += """\
+ return hwcap;
#else
return 0;
#endif
}
-""" % (arch, reg, reg, op, reg, shift, val)
+"""
elif op == "0x80000001":
tempstring = tempstring + """\
diff --git a/volk/lib/gcc_x86_cpuid.h b/volk/lib/gcc_x86_cpuid.h
index 2d0916fb3..95a6722f2 100644
--- a/volk/lib/gcc_x86_cpuid.h
+++ b/volk/lib/gcc_x86_cpuid.h
@@ -176,3 +176,15 @@ __get_cpuid (unsigned int __level,
__cpuid (__level, *__eax, *__ebx, *__ecx, *__edx);
return 1;
}
+
+/* Return Intel AVX extended CPU capabilities register.
+ * This function will bomb on non-AVX-capable machines, so
+ * check for AVX capability before executing.
+ */
+static __inline unsigned int
+xgetbv(void)
+{
+ unsigned int index, __eax, __edx;
+ __asm__ ("xgetbv" : "=a"(__eax), "=d"(__edx) : "c" (index));
+ return __eax;
+}