Skip to content

Commit

Permalink
Detect ARM feature level
Browse files Browse the repository at this point in the history
  • Loading branch information
TheTumultuousUnicornOfDarkness committed Jun 23, 2024
1 parent 0dd570f commit 7778d96
Show file tree
Hide file tree
Showing 7 changed files with 551 additions and 318 deletions.
2 changes: 1 addition & 1 deletion cpuid_tool/cpuid_tool.c
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,7 @@ int main(int argc, char** argv)
for (cpu_type_index = 0; cpu_type_index < data.num_cpu_types; cpu_type_index++) {
fprintf(fout, "CPU Info for type #%d:\n------------------\n", cpu_type_index);
fprintf(fout, " arch : %s\n", cpu_architecture_str(data.cpu_types[cpu_type_index].architecture));
fprintf(fout, " feat_level : %s\n", cpu_feature_level_str(data.cpu_types[cpu_type_index].feature_level));
fprintf(fout, " purpose : %s\n", cpu_purpose_str(data.cpu_types[cpu_type_index].purpose));
fprintf(fout, " vendor_str : `%s'\n", data.cpu_types[cpu_type_index].vendor_str);
fprintf(fout, " vendor id : %d\n", (int) data.cpu_types[cpu_type_index].vendor);
Expand All @@ -759,7 +760,6 @@ int main(int argc, char** argv)
}
else if (data.cpu_types[cpu_type_index].architecture == ARCHITECTURE_ARM) {
fprintf(fout, " implementer: %d (%02Xh)\n", data.cpu_types[cpu_type_index].implementer, data.cpu_types[cpu_type_index].implementer);
fprintf(fout, " arch_ver : %d (%02Xh)\n", data.cpu_types[cpu_type_index].architecture_version, data.cpu_types[cpu_type_index].architecture_version);
fprintf(fout, " variant : %d (%02Xh)\n", data.cpu_types[cpu_type_index].variant, data.cpu_types[cpu_type_index].variant);
fprintf(fout, " part_num : %d (%02Xh)\n", data.cpu_types[cpu_type_index].part_num, data.cpu_types[cpu_type_index].part_num);
fprintf(fout, " revision : %d (%02Xh)\n", data.cpu_types[cpu_type_index].revision, data.cpu_types[cpu_type_index].revision);
Expand Down
10 changes: 7 additions & 3 deletions libcpuid/check-consistency.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,9 @@ def checkEnumSize(enumName, constantName):

files_code = {}

rexp1 = re.compile('.*flags\[(CPU_FEATURE_[^\]]+)\]\s+=\s+1.*') # e.g. "data->flags[CPU_FEATURE_MPAM] = 1;"
rexp2 = re.compile('.*(CPU_FEATURE_[^ }]+).*') # e.g. "{ 28, CPU_FEATURE_HT },"
rexp1 = re.compile(r'.*flags\[(CPU_FEATURE_[^\]]+)\]\s*=\s*1.*') # e.g. "data->flags[CPU_FEATURE_MPAM] = 1;"
rexp2 = re.compile(r'.*(CPU_FEATURE_[^ ,]+)\s*,\s*FEATURE_LEVEL_ARM_.*') # e.g. "{ 35, 32, 0b0101, CPU_FEATURE_SPEV1P4, FEATURE_LEVEL_ARM_V8_8_A, -1 },"
rexp3 = re.compile(r'.*(CPU_FEATURE_[^ }]+).*') # e.g. "{ 28, CPU_FEATURE_HT },"

for fn in glob.glob("%s/*.c" % sys.argv[1]):
f = open(fn, "rt")
Expand All @@ -121,6 +122,9 @@ def checkEnumSize(enumName, constantName):
elif rexp2.match(s):
entry = rexp2.findall(s)[0]
files_code[fn].append(entry)
elif rexp3.match(s):
entry = rexp3.findall(s)[0]
files_code[fn].append(entry)

f.close()

Expand Down Expand Up @@ -151,7 +155,7 @@ def checkEnumSize(enumName, constantName):
print("")

print("Checking processor definitions:")
cache_exp = re.compile(".*([\(/ ][0-9]+K).*")
cache_exp = re.compile(r".*([\(/ ][0-9]+K).*")
# Check whether CPU codenames for consistency:
# - Codenames should not exceed 31 characters
# - Check for common typos
Expand Down
51 changes: 51 additions & 0 deletions libcpuid/cpuid_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ static void cpu_id_t_constructor(struct cpu_id_t* id)
{
memset(id, 0, sizeof(struct cpu_id_t));
id->architecture = ARCHITECTURE_UNKNOWN;
id->feature_level = FEATURE_LEVEL_UNKNOWN;
id->vendor = VENDOR_UNKNOWN;
id->l1_data_cache = id->l1_instruction_cache = id->l2_cache = id->l3_cache = id->l4_cache = -1;
id->l1_assoc = id->l1_data_assoc = id->l1_instruction_assoc = id->l2_assoc = id->l3_assoc = id->l4_assoc = -1;
Expand Down Expand Up @@ -1614,6 +1615,55 @@ const char* cpu_architecture_str(cpu_architecture_t architecture)
return "";
}

const char* cpu_feature_level_str(cpu_feature_level_t level)
{
const struct { cpu_feature_level_t level; const char* name; }
matchtable[] = {
{ FEATURE_LEVEL_UNKNOWN, "unknown" },
{ FEATURE_LEVEL_ARM_V1, "ARMv1" },
{ FEATURE_LEVEL_ARM_V2, "ARMv2" },
{ FEATURE_LEVEL_ARM_V3, "ARMv3" },
{ FEATURE_LEVEL_ARM_V4, "ARMv4" },
{ FEATURE_LEVEL_ARM_V4T, "ARMv4T" },
{ FEATURE_LEVEL_ARM_V5, "ARMv5" },
{ FEATURE_LEVEL_ARM_V5T, "ARMv5T" },
{ FEATURE_LEVEL_ARM_V5TE, "ARMv5TE" },
{ FEATURE_LEVEL_ARM_V5TEJ, "ARMv5TEJ" },
{ FEATURE_LEVEL_ARM_V6, "ARMv6" },
{ FEATURE_LEVEL_ARM_V6_M, "ARMv6-M" },
{ FEATURE_LEVEL_ARM_V7_A, "ARMv7-A" },
{ FEATURE_LEVEL_ARM_V7_M, "ARMv7-M" },
{ FEATURE_LEVEL_ARM_V7_R, "ARMv7-R" },
{ FEATURE_LEVEL_ARM_V7E_M, "ARMv7E-M" },
{ FEATURE_LEVEL_ARM_V8_0_A, "ARMv8.0-A" },
{ FEATURE_LEVEL_ARM_V8_0_M, "ARMv8.0-M" },
{ FEATURE_LEVEL_ARM_V8_0_R, "ARMv8.0-R" },
{ FEATURE_LEVEL_ARM_V8_1_A, "ARMv8.1-A" },
{ FEATURE_LEVEL_ARM_V8_1_M, "ARMv8.1-M" },
{ FEATURE_LEVEL_ARM_V8_2_A, "ARMv8.2-A" },
{ FEATURE_LEVEL_ARM_V8_3_A, "ARMv8.3-A" },
{ FEATURE_LEVEL_ARM_V8_4_A, "ARMv8.4-A" },
{ FEATURE_LEVEL_ARM_V8_5_A, "ARMv8.5-A" },
{ FEATURE_LEVEL_ARM_V8_6_A, "ARMv8.6-A" },
{ FEATURE_LEVEL_ARM_V8_7_A, "ARMv8.7-A" },
{ FEATURE_LEVEL_ARM_V8_8_A, "ARMv8.8-A" },
{ FEATURE_LEVEL_ARM_V8_9_A, "ARMv8.9-A" },
{ FEATURE_LEVEL_ARM_V9_0_A, "ARMv9.0-A" },
{ FEATURE_LEVEL_ARM_V9_1_A, "ARMv9.1-A" },
{ FEATURE_LEVEL_ARM_V9_2_A, "ARMv9.2-A" },
{ FEATURE_LEVEL_ARM_V9_3_A, "ARMv9.3-A" },
{ FEATURE_LEVEL_ARM_V9_4_A, "ARMv9.4-A" },
};
unsigned i, n = COUNT_OF(matchtable);
if (n != (NUM_CPU_FEATURE_LEVELS - FEATURE_LEVEL_ARM_V1) + 1) {
warnf("Warning: incomplete library, feature level matchtable size differs from the actual number of levels.\n");
}
for (i = 0; i < n; i++)
if (matchtable[i].level == level)
return matchtable[i].name;
return "";
}

const char* cpu_purpose_str(cpu_purpose_t purpose)
{
const struct { cpu_purpose_t purpose; const char* name; }
Expand Down Expand Up @@ -1791,6 +1841,7 @@ const char* cpu_feature_str(cpu_feature_t feature)
{ CPU_FEATURE_ETS2, "ets2" },
{ CPU_FEATURE_FP, "fp" },
{ CPU_FEATURE_MIXEDEND, "mixedend" },
{ CPU_FEATURE_MIXEDENDEL0, "mixedendel0" },
{ CPU_FEATURE_PMULL, "pmull" },
{ CPU_FEATURE_PMUV3, "pmuv3" },
{ CPU_FEATURE_SHA1, "sha1" },
Expand Down
1 change: 1 addition & 0 deletions libcpuid/exports.def
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,4 @@ affinity_mask_str @41
cpuid_free_system_id @42
affinity_mask_str_r @43
cpuid_get_hypervisor @44
cpu_feature_level_str @45
92 changes: 74 additions & 18 deletions libcpuid/libcpuid.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,50 @@ typedef enum {
} cpu_architecture_t;
#define NUM_CPU_ARCHITECTURES NUM_CPU_ARCHITECTURES

/**
* @brief CPU architecture
*/
typedef enum {
/* TODO: add x86 levels */
FEATURE_LEVEL_ARM_V1 = 100, /*!< ARMv1 */
FEATURE_LEVEL_ARM_V2, /*!< ARMv2 */
FEATURE_LEVEL_ARM_V3, /*!< ARMv3 */
FEATURE_LEVEL_ARM_V4, /*!< ARMv4 */
FEATURE_LEVEL_ARM_V4T, /*!< ARMv4T */
FEATURE_LEVEL_ARM_V5, /*!< ARMv5 (obsolete) */
FEATURE_LEVEL_ARM_V5T, /*!< ARMv5T */
FEATURE_LEVEL_ARM_V5TE, /*!< ARMv5TE */
FEATURE_LEVEL_ARM_V5TEJ, /*!< ARMv5TEJ */
FEATURE_LEVEL_ARM_V6, /*!< ARMv6 */
FEATURE_LEVEL_ARM_V6_M, /*!< ARMv6-M */
FEATURE_LEVEL_ARM_V7_A, /*!< ARMv7-A */
FEATURE_LEVEL_ARM_V7_M, /*!< ARMv7-M */
FEATURE_LEVEL_ARM_V7_R, /*!< ARMv7-R */
FEATURE_LEVEL_ARM_V7E_M, /*!< ARMv7E-M */
FEATURE_LEVEL_ARM_V8_0_A, /*!< ARMv8.0-A */
FEATURE_LEVEL_ARM_V8_0_M, /*!< ARMv8.0-M */
FEATURE_LEVEL_ARM_V8_0_R, /*!< ARMv8.0-R */
FEATURE_LEVEL_ARM_V8_1_A, /*!< ARMv8.1-A */
FEATURE_LEVEL_ARM_V8_1_M, /*!< ARMv8.1-M */
FEATURE_LEVEL_ARM_V8_2_A, /*!< ARMv8.2-A */
FEATURE_LEVEL_ARM_V8_3_A, /*!< ARMv8.3-A */
FEATURE_LEVEL_ARM_V8_4_A, /*!< ARMv8.4-A */
FEATURE_LEVEL_ARM_V8_5_A, /*!< ARMv8.5-A */
FEATURE_LEVEL_ARM_V8_6_A, /*!< ARMv8.6-A */
FEATURE_LEVEL_ARM_V8_7_A, /*!< ARMv8.7-A */
FEATURE_LEVEL_ARM_V8_8_A, /*!< ARMv8.8-A */
FEATURE_LEVEL_ARM_V8_9_A, /*!< ARMv8.9-A */
FEATURE_LEVEL_ARM_V9_0_A, /*!< ARMv9.0-A */
FEATURE_LEVEL_ARM_V9_1_A, /*!< ARMv9.1-A */
FEATURE_LEVEL_ARM_V9_2_A, /*!< ARMv9.2-A */
FEATURE_LEVEL_ARM_V9_3_A, /*!< ARMv9.3-A */
FEATURE_LEVEL_ARM_V9_4_A, /*!< ARMv9.4-A */

NUM_CPU_FEATURE_LEVELS, /*!< Valid feature level ids: 0..NUM_CPU_FEATURE_LEVELS - 1 */
FEATURE_LEVEL_UNKNOWN = -1,
} cpu_feature_level_t;
#define NUM_CPU_FEATURE_LEVELS NUM_CPU_FEATURE_LEVELS

/**
* @brief CPU purpose
*/
Expand Down Expand Up @@ -375,6 +419,13 @@ struct cpu_id_t {
/** contains the CPU architecture ID (e.g. ARCHITECTURE_X86) */
cpu_architecture_t architecture;

/**
* contains the CPU feature level,
* also know as microarchitecture levels (x86)
* and architecture version (ARM)
*/
cpu_feature_level_t feature_level;

/** contains the CPU vendor string, e.g. "GenuineIntel" */
char vendor_str[VENDOR_STR_MAX];

Expand Down Expand Up @@ -554,9 +605,6 @@ struct cpu_id_t {
/** ARM CPU implementer code */
uint8_t implementer;

/** ARM CPU architecture version */
uint8_t architecture_version;

/** ARM CPU variant number */
uint8_t variant;

Expand Down Expand Up @@ -728,21 +776,22 @@ typedef enum {
CPU_FEATURE_AVX512VBMI, /*!< AVX-512 Vector Bit ManipulationInstructions (version 1) */
CPU_FEATURE_AVX512VBMI2, /*!< AVX-512 Vector Bit ManipulationInstructions (version 2) */
CPU_FEATURE_HYPERVISOR, /*!< Hypervisor present (always zero on physical CPUs) */
CPU_FEATURE_ASID16, /*!< ARM: 16 bit ASID (ARMv8.0 architecture extension) */
CPU_FEATURE_ADVSIMD, /*!< ARM: Advanced SIMD Extension (ARMv8.0 architecture extension) */
CPU_FEATURE_CRC32, /*!< ARM: CRC32 instructions (ARMv8.0 architecture extension) */
CPU_FEATURE_CSV2_1P1, /*!< ARM: Cache Speculation Variant 2 (ARMv8.0 architecture extension) */
CPU_FEATURE_CSV2_1P2, /*!< ARM: Cache Speculation Variant 2 version 1.2 (ARMv8.0 architecture extension) */
CPU_FEATURE_CSV2_2, /*!< ARM: Cache Speculation Variant 2 version 2 (ARMv8.0 architecture extension) */
CPU_FEATURE_CSV2_3, /*!< ARM: Cache Speculation Variant 2 version 3 (ARMv8.0 architecture extension) */
CPU_FEATURE_DOUBLELOCK, /*!< ARM: Double Lock (ARMv8.0 architecture extension) */
CPU_FEATURE_ETS2, /*!< ARM: Enhanced Translation Synchronization (ARMv8.0 architecture extension) */
CPU_FEATURE_FP, /*!< ARM: Floating Point extensions (ARMv8.0 architecture extension) */
CPU_FEATURE_MIXEDEND, /*!< ARM: Mixed-endian support at EL0 (ARMv8.0 architecture extension) */
CPU_FEATURE_PMULL, /*!< ARM: Advanced SIMD PMULL instructions (ARMv8.0 architecture extension) */
CPU_FEATURE_PMUV3, /*!< ARM: PMU extension version 3 (ARMv8.0 architecture extension) */
CPU_FEATURE_SHA1, /*!< ARM: Advanced SIMD SHA1 instructions (ARMv8.0 architecture extension) */
CPU_FEATURE_SHA256, /*!< ARM: Advanced SIMD SHA256 instructions (ARMv8.0 architecture extension) */
CPU_FEATURE_ASID16, /*!< ARM: 16 bit ASID */
CPU_FEATURE_ADVSIMD, /*!< ARM: Advanced SIMD Extension */
CPU_FEATURE_CRC32, /*!< ARM: CRC32 instructions */
CPU_FEATURE_CSV2_1P1, /*!< ARM: Cache Speculation Variant 2 */
CPU_FEATURE_CSV2_1P2, /*!< ARM: Cache Speculation Variant 2 version 1.2 */
CPU_FEATURE_CSV2_2, /*!< ARM: Cache Speculation Variant 2 version 2 */
CPU_FEATURE_CSV2_3, /*!< ARM: Cache Speculation Variant 2 version 3 */
CPU_FEATURE_DOUBLELOCK, /*!< ARM: Double Lock */
CPU_FEATURE_ETS2, /*!< ARM: Enhanced Translation Synchronization */
CPU_FEATURE_FP, /*!< ARM: Floating Point extensions */
CPU_FEATURE_MIXEDEND, /*!< ARM: Mixed-endian support */
CPU_FEATURE_MIXEDENDEL0, /*!< ARM: Mixed-endian support at EL0 */
CPU_FEATURE_PMULL, /*!< ARM: Advanced SIMD PMULL instructions */
CPU_FEATURE_PMUV3, /*!< ARM: PMU extension version 3 */
CPU_FEATURE_SHA1, /*!< ARM: Advanced SIMD SHA1 instructions */
CPU_FEATURE_SHA256, /*!< ARM: Advanced SIMD SHA256 instructions */
CPU_FEATURE_HAFDBS, /*!< ARM: Hardware management of the Access flag and dirty state */
CPU_FEATURE_HPDS, /*!< ARM: Hierarchical permission disables in translations tables */
CPU_FEATURE_LOR, /*!< ARM: Limited ordering regions */
Expand Down Expand Up @@ -1197,6 +1246,13 @@ int cpu_request_core_type(cpu_purpose_t purpose, struct cpu_raw_data_array_t* ra
*/
const char* cpu_architecture_str(cpu_architecture_t architecture);

/**
* @brief Returns the short textual representation of a CPU feature level
* @param level - the feature level, whose textual representation is wanted.
* @returns a constant string like "ARMv8.0-A", "ARMv9.4-A", etc.
*/
const char* cpu_feature_level_str(cpu_feature_level_t level);

/**
* @brief Returns the short textual representation of a CPU purpose
* @param purpose - the purpose, whose textual representation is wanted.
Expand Down
1 change: 1 addition & 0 deletions libcpuid/libcpuid.sym
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ affinity_mask_str
cpuid_free_system_id
affinity_mask_str_r
cpuid_get_hypervisor
cpu_feature_level_str
Loading

0 comments on commit 7778d96

Please sign in to comment.