Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for FreeBSD on x86 #163

Merged
merged 8 commits into from
Jul 2, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,14 @@ flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3
<a name="support"></a>
## What's supported

| | x86³ | ARM | AArch64 | MIPS⁴ | POWER |
|---------|:----:|:-------:|:-------:|:------:|:-------:|
| Android | yes² | yes¹ | yes¹ | yes¹ | N/A |
| iOS | N/A | not yet | not yet | N/A | N/A |
| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ |
| MacOs | yes² | N/A | not yet | N/A | no |
| Windows | yes² | not yet | not yet | N/A | N/A |
| | x86³ | ARM | AArch64 | MIPS⁴ | POWER |
|---------|-:-:--|-:-:-----|-:-:-----|-:-:-----|-:-:-----|
| Android | yes² | yes¹ | yes¹ | yes¹ | N/A |
| iOS | N/A | not yet | not yet | N/A | N/A |
| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ |
| MacOs | yes² | N/A | not yet | N/A | no |
| Windows | yes² | not yet | not yet | N/A | N/A |
| FreeBSD | yes² | not yet | not yet | not yet | not yet |

1. **Features revealed from Linux.** We gather data from several sources
depending on availability:
Expand Down
4 changes: 4 additions & 0 deletions include/cpu_features_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@
#define CPU_FEATURES_OS_DARWIN
#endif

#if (defined(__freebsd__) || defined(__FreeBSD__))
#define CPU_FEATURES_OS_FREEBSD
#endif

////////////////////////////////////////////////////////////////////////////////
// Compilers
////////////////////////////////////////////////////////////////////////////////
Expand Down
40 changes: 39 additions & 1 deletion src/cpuinfo_x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@
// microarchitectures.
#if defined(CPU_FEATURES_OS_WINDOWS)
#include <windows.h> // IsProcessorFeaturePresent
#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) || \
defined(CPU_FEATURES_OS_FREEBSD)
#include "internal/filesystem.h" // Needed to parse /proc/cpuinfo
#include "internal/stack_line_reader.h" // Needed to parse /proc/cpuinfo
#include "internal/string_view.h" // Needed to parse /proc/cpuinfo
Expand Down Expand Up @@ -1330,6 +1331,43 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info,
features->ssse3 = GetDarwinSysCtlByName("hw.optional.supplementalsse3");
features->sse4_1 = GetDarwinSysCtlByName("hw.optional.sse4_1");
features->sse4_2 = GetDarwinSysCtlByName("hw.optional.sse4_2");
#elif defined(CPU_FEATURES_OS_FREEBSD)
// Handling FreeBSD platform through parsing /var/run/dmesg.boot.
const int fd = CpuFeatures_OpenFile("/var/run/dmesg.boot");
if (fd >= 0) {
StackLineReader reader;
StackLineReader_Initialize(&reader, fd);
for (;;) {
Copy link
Collaborator

@Mizux Mizux Jun 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, is there any difference with using while (true) { ?
EDIT: you're using for (;;) also just below so for consistency, we should at least use the same semantic in both cases.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No difference between for(;;) and while(true). We could use either one.

const LineResult result = StackLineReader_NextLine(&reader);
const StringView line = result.line;
const bool is_feature =
CpuFeatures_StringView_StartsWith(line, str(" Features="));
const bool is_feature2 =
CpuFeatures_StringView_StartsWith(line, str(" Features2="));
if (is_feature || is_feature2) {
// Lines of interests are of the following form:
// " Features=0x1783fbff<PSE36,MMX,FXSR,SSE,SSE2,HTT>"
// We replace '<', '>' and ',' with space so we can search by
// whitespace separated word.
for (size_t i = 0; i < line.size; ++i) {
if (line.ptr[i] == '<' || line.ptr[i] == '>' || line.ptr[i] == ',')
line.ptr[i] == ' ';
}
if (is_feature) {
features->sse = CpuFeatures_StringView_HasWord(line, "SSE");
features->sse2 = CpuFeatures_StringView_HasWord(line, "SSE2");
}
if (is_feature2) {
features->sse3 = CpuFeatures_StringView_HasWord(line, "SSE3");
features->ssse3 = CpuFeatures_StringView_HasWord(line, "SSSE3");
features->sse4_1 = CpuFeatures_StringView_HasWord(line, "SSE4.1");
features->sse4_2 = CpuFeatures_StringView_HasWord(line, "SSE4.2");
}
}
if (result.eof) break;
}
CpuFeatures_CloseFile(fd);
}
#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
// Handling Linux platform through /proc/cpuinfo.
const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
Expand Down
64 changes: 43 additions & 21 deletions test/cpuinfo_x86_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -666,21 +666,29 @@ TEST_F(CpuidX86Test, Nehalem) {
PF_XMMI64_INSTRUCTIONS_AVAILABLE);
g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
PF_SSE3_INSTRUCTIONS_AVAILABLE);
#endif // CPU_FEATURES_OS_WINDOWS
#if defined(CPU_FEATURES_OS_DARWIN)
#elif defined(CPU_FEATURES_OS_DARWIN)
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse2");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse3");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.supplementalsse3");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_1");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_2");
#endif // CPU_FEATURES_OS_DARWIN
#if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
#elif defined(CPU_FEATURES_OS_FREEBSD)
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/var/run/dmesg.boot", R"(
---<<BOOT>>---
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though this will be moot when the branch goes EOL at the end of September, FreeBSD 11 does not have this line in dmesg.boot.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack. It was present in a dump of a FreeBSD 12.2-RELEASE r366954 GENERIC amd64

---<<BOOT>>---
Copyright (c) 1992-2020 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
	The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
FreeBSD 12.2-RELEASE r366954 GENERIC amd64
FreeBSD clang version 10.0.1 ([email protected]:llvm/llvm-project.git llvmorg-10.0.1-0-gef32c611aa2)
VT(vga): text 80x25
module vtnet already present!
CPU: Intel(R) Core(TM) i7-10710U CPU @ 1.10GHz (1607.96-MHz K8-class CPU)
  Origin="GenuineIntel"  Id=0xa0660  Family=0x6  Model=0xa6  Stepping=0
  Features=0x1783fbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,FXSR,SSE,SSE2,HTT>
  Features2=0x5eda2203<SSE3,PCLMULQDQ,SSSE3,CX16,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,AESNI,XSAVE,OSXSAVE,AVX,RDRAND>
  AMD Features=0x28100800<SYSCALL,NX,RDTSCP,LM>
  AMD Features2=0x121<LAHF,ABM,Prefetch>
  Structured Extended Features=0x842421<FSGSBASE,AVX2,INVPCID,NFPUSG,RDSEED,CLFLUSHOPT>
  Structured Extended Features3=0x30000400<MD_CLEAR,L1DFL,ARCH_CAP>
  TSC: P-state invariant
real memory  = 2147418112 (2047 MB)
avail memory = 2044313600 (1949 MB)

FWIW we don't use this line but it's a representative input.

Copyright (c) 1992-2020 The FreeBSD Project.
FreeBSD is a registered trademark of The FreeBSD Foundation.
Features=0x1783fbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,FXSR,SSE,SSE2,HTT>
Features2=0x5eda2203<SSE3,PCLMULQDQ,SSSE3,CX16,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,AESNI,XSAVE,OSXSAVE,RDRAND>
real memory = 2147418112 (2047 MB)
)");
#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(processor :
flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
)");
#endif // CPU_FEATURES_OS_LINUX_OR_ANDROID
#endif
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x000106A2, 0x00100800, 0x00BCE3BD, 0xBFEBFBFF}},
Expand Down Expand Up @@ -723,13 +731,13 @@ flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
EXPECT_TRUE(info.features.sse);
EXPECT_TRUE(info.features.sse2);
EXPECT_TRUE(info.features.sse3);
#ifndef CPU_FEATURES_OS_WINDOWS
#if !defined(CPU_FEATURES_OS_WINDOWS)
// Currently disabled on Windows as IsProcessorFeaturePresent do not support
// feature detection > sse3.
EXPECT_TRUE(info.features.ssse3);
EXPECT_TRUE(info.features.sse4_1);
EXPECT_TRUE(info.features.sse4_2);
#endif // CPU_FEATURES_OS_WINDOWS
#endif // !defined(CPU_FEATURES_OS_WINDOWS)
}

// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0030673_Silvermont3_CPUID.txt
Expand All @@ -743,21 +751,28 @@ TEST_F(CpuidX86Test, Atom) {
PF_XMMI64_INSTRUCTIONS_AVAILABLE);
g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
PF_SSE3_INSTRUCTIONS_AVAILABLE);
#endif // CPU_FEATURES_OS_WINDOWS
#if defined(CPU_FEATURES_OS_DARWIN)
#elif defined(CPU_FEATURES_OS_DARWIN)
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse2");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse3");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.supplementalsse3");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_1");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_2");
#endif // CPU_FEATURES_OS_DARWIN
#if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
#elif defined(CPU_FEATURES_OS_FREEBSD)
fs.CreateFile("/var/run/dmesg.boot", R"(
---<<BOOT>>---
Copyright (c) 1992-2020 The FreeBSD Project.
FreeBSD is a registered trademark of The FreeBSD Foundation.
Features=0x1783fbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,FXSR,SSE,SSE2,HTT>
Features2=0x5eda2203<SSE3,PCLMULQDQ,SSSE3,CX16,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,AESNI,XSAVE,OSXSAVE,RDRAND>
real memory = 2147418112 (2047 MB)
)");
#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(
flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
)");
#endif // CPU_FEATURES_OS_LINUX_OR_ANDROID
#endif
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x00030673, 0x00100800, 0x41D8E3BF, 0xBFEBFBFF}},
Expand Down Expand Up @@ -800,13 +815,13 @@ flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
EXPECT_TRUE(info.features.sse);
EXPECT_TRUE(info.features.sse2);
EXPECT_TRUE(info.features.sse3);
#ifndef CPU_FEATURES_OS_WINDOWS
#if !defined(CPU_FEATURES_OS_WINDOWS)
// Currently disabled on Windows as IsProcessorFeaturePresent do not support
// feature detection > sse3.
EXPECT_TRUE(info.features.ssse3);
EXPECT_TRUE(info.features.sse4_1);
EXPECT_TRUE(info.features.sse4_2);
#endif // CPU_FEATURES_OS_WINDOWS
#endif // !defined(CPU_FEATURES_OS_WINDOWS)
}

// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0000673_P3_KatmaiDP_CPUID.txt
Expand All @@ -816,16 +831,23 @@ TEST_F(CpuidX86Test, P3) {
#if defined(CPU_FEATURES_OS_WINDOWS)
g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
PF_XMMI_INSTRUCTIONS_AVAILABLE);
#endif // CPU_FEATURES_OS_WINDOWS
#if defined(CPU_FEATURES_OS_DARWIN)
#elif defined(CPU_FEATURES_OS_DARWIN)
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse");
#endif // CPU_FEATURES_OS_DARWIN
#if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
#elif defined(CPU_FEATURES_OS_FREEBSD)
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/var/run/dmesg.boot", R"(
---<<BOOT>>---
Copyright (c) 1992-2020 The FreeBSD Project.
FreeBSD is a registered trademark of The FreeBSD Foundation.
Features=0x1783fbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,FXSR,SSE>
real memory = 2147418112 (2047 MB)
)");
#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(
flags : fpu mmx sse
)");
#endif // CPU_FEATURES_OS_LINUX_OR_ANDROID
#endif
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x00000003, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x00000673, 0x00000000, 0x00000000, 0x0387FBFF}},
Expand All @@ -848,13 +870,13 @@ flags : fpu mmx sse
EXPECT_TRUE(info.features.sse);
EXPECT_FALSE(info.features.sse2);
EXPECT_FALSE(info.features.sse3);
#ifndef CPU_FEATURES_OS_WINDOWS
#if !defined(CPU_FEATURES_OS_WINDOWS)
// Currently disabled on Windows as IsProcessorFeaturePresent do not support
// feature detection > sse3.
EXPECT_FALSE(info.features.ssse3);
EXPECT_FALSE(info.features.sse4_1);
EXPECT_FALSE(info.features.sse4_2);
#endif // CPU_FEATURES_OS_WINDOWS
#endif // !defined(CPU_FEATURES_OS_WINDOWS)
}

// TODO(user): test what happens when xsave/osxsave are not present.
Expand Down