base/system/cpu/private/linux_impl/cpu_features.cpp¶
CPU Feature Detection Implementation (Linux) More...
Functions¶
| Name | |
|---|---|
| void | query_cpu_features(std::vector< std::string > & feats) Internal Linux Query for CPU features. |
Detailed Description¶
CPU Feature Detection Implementation (Linux)
Author: Charliechen114514 (chengh1922@mails.jlu.edu.cn)
Version: 0.1
Date: 2026-02-22
Copyright: Copyright © 2026
Functions Documentation¶
function query_cpu_features¶
Internal Linux Query for CPU features.
Parameters:
- feats Output parameter to store detected CPU feature names.
Exceptions:
- None (error reporting via return code if applicable).
Since: 0.1
Note: None.
Warning: None.
Internal Windows Query for CPU features.
Source code¶
#include "cpu_features.h"
#if defined(__x86_64__) || defined(__i386__)
# include <cpuid.h>
#else
# include "base/linux/proc_parser.h"
# include <fstream>
#endif
#include <string>
#include <vector>
namespace {
#if defined(__x86_64__) || defined(__i386__)
// x86/x64_64 CPUID based feature detection
inline unsigned long long read_xcr0() noexcept {
unsigned long long xcr0;
__asm__ __volatile__("xgetbv" : "=a"(xcr0) : "c"(0) : "edx");
return xcr0;
}
void addFeatureIfSupported(bool condition, const char* name, std::vector<std::string>& feats) {
if (condition) {
feats.emplace_back(name);
}
}
void query_x86_features(std::vector<std::string>& feats) {
unsigned int eax, ebx, ecx, edx;
// CPUID leaf 1, subleaf 0
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
// SSE / AES / FMA from ECX
addFeatureIfSupported(ecx & (1 << 25), "aes", feats);
addFeatureIfSupported(ecx & (1 << 12), "fma", feats);
// AVX needs OS support
bool osxsave = ecx & (1 << 27);
bool avx_support = ecx & (1 << 28);
if (osxsave && avx_support) {
unsigned long long xcr = read_xcr0();
if ((xcr & 0x6) == 0x6) {
feats.emplace_back("avx");
}
}
}
// CPUID leaf 7, subleaf 0
if (__get_cpuid_count(7, 0, &eax, &ebx, &ecx, &edx)) {
addFeatureIfSupported(ebx & (1 << 5), "avx2", feats);
addFeatureIfSupported(ebx & (1 << 16), "avx512f", feats);
addFeatureIfSupported(ebx & (1 << 29), "sha_ni", feats);
// Check for specific AVX-512 extensions
if (ebx & (1 << 16)) {
addFeatureIfSupported(ebx & (1 << 17), "avx512dq", feats);
addFeatureIfSupported(ebx & (1 << 28), "avx512cd", feats);
addFeatureIfSupported(ebx & (1 << 30), "avx512bw", feats);
addFeatureIfSupported(ebx & (1 << 31), "avx512vl", feats);
}
}
}
#elif defined(__aarch64__) || defined(__arm__)
// ARM feature detection from /proc/cpuinfo
// Helper: Parse space-separated features from a string_view (zero-copy)
void parse_features_line(std::string_view features_str, std::vector<std::string>& feats) {
size_t start = 0;
while (start < features_str.size()) {
// Skip whitespace
start = features_str.find_first_not_of(" \t", start);
if (start == std::string_view::npos) {
break;
}
// Find end of feature name
const size_t end = features_str.find_first_of(" \t", start);
if (end == std::string_view::npos) {
// Last feature - take the rest
const std::string_view feature = cf::trim_whitespace(features_str.substr(start));
if (!feature.empty()) {
feats.emplace_back(feature);
}
break;
}
// Extract feature
const std::string_view feature = features_str.substr(start, end - start);
if (!feature.empty()) {
feats.emplace_back(feature);
}
start = end + 1;
}
}
void query_arm_features(std::vector<std::string>& feats) {
std::ifstream cpuinfo("/proc/cpuinfo");
if (!cpuinfo.is_open()) {
return;
}
std::string line;
while (std::getline(cpuinfo, line)) {
const std::string_view line_sv(line);
// Check for "Features" line in ARM cpuinfo
if (line_sv.find("Features") == 0 || line_sv.find("flags") == 0) {
const std::string_view features = cf::parse_cpuinfo_field(line_sv, "Features");
if (features.empty()) {
// Try "flags" field
const std::string_view flags = cf::parse_cpuinfo_field(line_sv, "flags");
if (!flags.empty()) {
parse_features_line(flags, feats);
}
} else {
parse_features_line(features, feats);
}
break;
}
}
}
#else
// Other architectures - minimal implementation
void query_generic_features(std::vector<std::string>& feats) {
std::ifstream cpuinfo("/proc/cpuinfo");
if (!cpuinfo.is_open()) {
return;
}
std::string line;
while (std::getline(cpuinfo, line)) {
const std::string_view line_sv(line);
if (line_sv.find("flags") == 0 || line_sv.find("Features") == 0) {
const std::string_view features = cf::parse_cpuinfo_field(line_sv, "flags");
if (features.empty()) {
const std::string_view features_alt = cf::parse_cpuinfo_field(line_sv, "Features");
if (!features_alt.empty()) {
// Re-use ARM parser
parse_features_line(features_alt, feats);
}
} else {
parse_features_line(features, feats);
}
break;
}
}
}
#endif
} // namespace
void query_cpu_features(std::vector<std::string>& feats) {
#if defined(__x86_64__) || defined(__i386__)
query_x86_features(feats);
#elif defined(__aarch64__) || defined(__arm__)
query_arm_features(feats);
#else
query_generic_features(feats);
#endif
}
Updated on 2026-03-09 at 10:14:01 +0000