Skip to content

Commit

Permalink
Save and restore rbx across cpuid on Windows
Browse files Browse the repository at this point in the history
Summary:
We need to preserve `rbx` across the call to `cpuid` on Windows. This becomes obvious when compiling under ASan where presumably due to high register pressure, we end up in a situation where `rbx` is clobbered by `cpuid` but the compiler did not expect it to be clobbered.

This is fixed in clang upstream here:
llvm/llvm-project#49477
https://reviews.llvm.org/D101338

However we use an older compiler (LLVM12.0.1) which does not have the patch yet.

Reviewed By: yfeldblum

Differential Revision: D35229538

fbshipit-source-id: 265835fb0e79e3a209dbce4fe82e8baa43e3d6ba
  • Loading branch information
mattjgalloway authored and facebook-github-bot committed Apr 8, 2022
1 parent ecc04a0 commit f22f88b
Showing 1 changed file with 35 additions and 0 deletions.
35 changes: 35 additions & 0 deletions folly/CpuId.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class CpuId {
// statically linked binaries which don't depend on the PLT)
FOLLY_ALWAYS_INLINE CpuId() {
#if defined(_MSC_VER) && (FOLLY_X64 || defined(_M_IX86))
#if !defined(__clang__)
int reg[4];
__cpuid(static_cast<int*>(reg), 0);
const int n = reg[0];
Expand All @@ -55,6 +56,40 @@ class CpuId {
f7b_ = uint32_t(reg[1]);
f7c_ = uint32_t(reg[2]);
}
#else
// Clang compiler has a bug (fixed in https://reviews.llvm.org/D101338) in
// which the `__cpuid` intrinsic does not save and restore `rbx` as it needs
// to due to being a reserved register. So in that case, do the `cpuid`
// ourselves. Clang supports inline assembly anyway.
uint32_t n;
__asm__(
"pushq %%rbx\n\t"
"cpuid\n\t"
"popq %%rbx\n\t"
: "=a"(n)
: "a"(0)
: "rcx", "rdx");
if (n >= 1) {
uint32_t f1a;
__asm__(
"pushq %%rbx\n\t"
"cpuid\n\t"
"popq %%rbx\n\t"
: "=a"(f1a), "=c"(f1c_), "=d"(f1d_)
: "a"(1)
:);
}
if (n >= 7) {
__asm__(
"pushq %%rbx\n\t"
"cpuid\n\t"
"movq %%rbx, %%rax\n\t"
"popq %%rbx"
: "=a"(f7b_), "=c"(f7c_)
: "a"(7), "c"(0)
: "rdx");
}
#endif
#elif defined(__i386__) && defined(__PIC__) && !defined(__clang__) && \
defined(__GNUC__)
// The following block like the normal cpuid branch below, but gcc
Expand Down

0 comments on commit f22f88b

Please sign in to comment.