summaryrefslogtreecommitdiff
path: root/volk
diff options
context:
space:
mode:
authorNick Foster <nick@ettus.com>2012-04-15 16:03:27 -0700
committerJohnathan Corgan <jcorgan@corganenterprises.com>2012-04-16 08:25:23 -0700
commitc3f2c30a54c75575f464afdd7cd11a017fb07695 (patch)
tree6889936b1b11ae77fbdcdfb6da17cb7ea840422f /volk
parent04e2ebb979942cada74f10ea022342716c6851bf (diff)
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.
Diffstat (limited to 'volk')
-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 effd90d331..53db3e577b 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 2be1123a80..4bd1ce5b1b 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 2d0916fb36..95a6722f29 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;
+}