does gcc's __builtin_cpu_supports check for OS support?
Asked Answered
C

2

9

GCC compiler provides a set of builtins to test some processor features, like availability of certain instruction sets. But, according to this thread we also may know certain cpu features may be not enabled by OS. So the question is: do __builtin_cpu_supports intrinsics also check if OS has enabled certain processor feature?

Cyte answered 8/2, 2018 at 4:31 Comment(6)
This is a good question. Some people disable AVX because of throttling for performance testing. I think with some Xeon Silver processors AVX512 can even cause worse performance on average due to sever throttling. I have not looked into this in a while. I think with some BIOS versions AVX and higher can be disabled. Otherwise it can be disabled by the OS (though I'm not sure how). I don't know what CPUID reports if AVX is disabled at the BIOS level but probably CPUID still reports AVX.Patellate
With windows here is how you disable AVX superuser.com/a/623738/230553. I'm not sure how to do this with Linux. But if you find how you can easy test __builtin_cpu_supports and answer your question.Patellate
Sadly this question was closed https://mcmap.net/q/25179/-how-do-i-disable-avx-instructions-on-a-linux-computer-closed/2542702Patellate
I think you have to add noxsave to the kernel options for Linux.Patellate
@Zboson, the question is indeed not "how to enable/disable avx", but how to check if it is enabled by OSCyte
I know. But by disabling AVX I can test if __builtin_cpu_supports checks the OS.Patellate
P
5

No.

I disabled AVX on my Skylake system by adding noxsave to the Linux kernel boot options. When I do cat /proc/cpuinfo AVX (and AVX2) no longer appear and when I run code with AVX instructions it crashes. This tells me that AVX has been disabled by the OS.

However, when I compile and run the following code

#include <stdio.h>

int main(void) {
  __builtin_cpu_init();
  printf("%d\n", __builtin_cpu_supports ("sse"));
  printf("%d\n", __builtin_cpu_supports ("avx"));
}

it returns 8 and 512. This means that __builtin_cpu_supports does not check to see if AVX was disabled by the OS.

Patellate answered 13/2, 2018 at 10:41 Comment(9)
This really shows that GCC does not check if OSXSAVE is defined. After that the OS needs to be tested as well https://mcmap.net/q/25180/-what-is-the-minimum-version-of-os-x-for-use-with-avx-avx2.Patellate
This should probably be considered a gcc bug; Usually you really want to know whether AVX is actually usable, not whether just the CPU supports it. If you really want to differentiate between supported by the CPU but not usable, that's when using CPUID manually should be needed. I assume most existing code that uses __builtin_cpu_supports ("avx") assumes that code compiled with -mavx can run if it's true.Thermobarograph
@PeterCordes, it should be considered a bug. I certainly expected it to check if AVX was enabled by the OS in my answer here. BTW, what is xsave and xgetbv. Why are there two methods to disable AVX? I guess disabling xsave is more restrictive. How do you disable AVX without disabling xsave.Patellate
You're asking how an OS in general could disable AVX support while still using one of the xsave* instructions to save SSE/FPU/MPX registers on context switches? I think an OS could still just use the instruction without setting the control-register bit that indicates that the OS promises to do that, so AVX instructions would still fault. IDK if Linux has an option to do that. Or maybe still set that bit, but not enable saving ymm upper halves with xsetbv. xgetbv is an instruction for reading extended control-registers..Thermobarograph
@PeterCordes, what I mean is why does if ((xgetbv(0) & 6) != 6) test for if AVX is enabled by the OS.Patellate
That expression is testing 2 bits in extended control-register 0 to see if they're both set. I think those are the bits the OS has to set with xsetbv to promise that it will use xsave to save ymm upper halves on context switches, so it's safe for the CPU to allow AVX instructions to execute. You can look up the exact meaning of those bits if you want.Thermobarograph
@PeterCordes how can the OS block instructions? I mean I could see how things would crash in context switches but isn't it possible that you could use AVX for example only for reads which would not crash.Patellate
AVX instructions fault if those bits aren't set. AVX is just designed this way, so AVX-aware user-space programs on AVX-unaware kernels at worst fault with #UD (SIGILL) instead of silent data corruption. SSE has a similar control bit: the OS has to set a bit in a control register or else SSE instructions fault. You can see this bit as a promise to save/restore xmm regs. But Intel unfortunately didn't include a clean way for user-space to detect if the OS had set that bit. That was new with AVX. https://mcmap.net/q/16183/-which-versions-of-windows-support-require-which-cpu-multimedia-extensions-how-to-check-if-sse-or-avx-are-fully-usableThermobarograph
Anyway, the point of all this is so silent data corruption on context switch is not a likely failure mode. That can generally only happen with an AVX-aware but buggy kernel.Thermobarograph
M
3

Yes, it does. There was a bug in GCC but it was fixed around GCC 8: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85100

Melmela answered 21/10, 2022 at 14:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.