diff options
Diffstat (limited to 'src/arm')
-rw-r--r-- | src/arm/cache.c | 52 | ||||
-rw-r--r-- | src/arm/linux/aarch32-isa.c | 22 | ||||
-rw-r--r-- | src/arm/linux/aarch64-isa.c | 23 | ||||
-rw-r--r-- | src/arm/linux/api.h | 8 | ||||
-rw-r--r-- | src/arm/linux/chipset.c | 117 | ||||
-rw-r--r-- | src/arm/linux/clusters.c | 10 | ||||
-rw-r--r-- | src/arm/linux/cpuinfo.c | 21 | ||||
-rw-r--r-- | src/arm/linux/init.c | 10 | ||||
-rw-r--r-- | src/arm/mach/init.c | 9 | ||||
-rw-r--r-- | src/arm/midr.h | 6 | ||||
-rw-r--r-- | src/arm/tlb.c | 2 | ||||
-rw-r--r-- | src/arm/uarch.c | 10 |
12 files changed, 235 insertions, 55 deletions
diff --git a/src/arm/cache.c b/src/arm/cache.c index e9102ed..446b02b 100644 --- a/src/arm/cache.c +++ b/src/arm/cache.c @@ -635,6 +635,13 @@ void cpuinfo_arm_decode_cache( break; } break; + case cpuinfo_arm_chipset_series_broadcom_bcm: + switch (chipset->model) { + case 2837: /* BCM2837 */ + l2_size = 512 * 1024; + break; + } + break; case cpuinfo_arm_chipset_series_samsung_exynos: l1_size = 32 * 1024; break; @@ -922,11 +929,13 @@ void cpuinfo_arm_decode_cache( * | MediaTek Helio X23 | 2(+4+4) | ? | ? | ? | | * | MediaTek Helio X25 | 2(+4+4) | ? | ? | ? | | * | MediaTek Helio X27 | 2(+4+4) | ? | ? | ? | | + * | Broadcom BCM2711 | 4 | 32K | 48K | 1M | [4] | * +---------------------+---------+-----------+-----------+------------+-----------+ * * [1] http://pdadb.net/index.php?m=processor&id=578&c=qualcomm_snapdragon_618_msm8956__snapdragon_650 * [2] http://pdadb.net/index.php?m=processor&id=667&c=qualcomm_snapdragon_620_apq8076__snapdragon_652 * [3] http://pdadb.net/index.php?m=processor&id=692&c=qualcomm_snapdragon_653_msm8976sg__msm8976_pro + * [4] https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2711/README.md */ uint32_t l2_size; switch (chipset->series) { @@ -1447,23 +1456,24 @@ void cpuinfo_arm_decode_cache( .line_size = 64 /* assumption */ }; break; - case cpuinfo_uarch_taishanv110: + case cpuinfo_uarch_taishan_v110: /* - * Kunpeng920 series CPU designed by Huawei hisilicon for server, - * L1 and L2 cache is private to each core, L3 is shared with all cores. - * +--------------------+-------+-----------+-----------+-----------+----------+------------+ - * | Processor model | Cores | L1D cache | L1I cache | L2 cache | L3 cache | Reference | - * +--------------------+-------+-----------+-----------+-----------+----------+------------+ - * | Kunpeng920-3226 | 32 | 64K | 64K | 512K | 32M | [1] | - * +--------------------+-------+-----------+-----------+-----------+----------+------------+ - * | Kunpeng920-4826 | 48 | 64K | 64K | 512K | 48M | [2] | - * +--------------------+-------+-----------+-----------+-----------+----------+------------+ - * | Kunpeng920-6426 | 64 | 64K | 64K | 512K | 64M | [3] | - * +--------------------+-------+-----------+-----------+-----------+----------+------------+ - * - * [1] https://en.wikichip.org/wiki/hisilicon/kunpeng/920-3226 - * [2] https://en.wikichip.org/wiki/hisilicon/kunpeng/920-4826 - * [3] https://en.wikichip.org/wiki/hisilicon/kunpeng/920-6426 + * It features private 64 KiB L1 instruction and data caches as well as 512 KiB of private L2. [1] + * + * +------------------+-------+-----------+-----------+-----------+----------+-----------+ + * | Processor model | Cores | L1D cache | L1I cache | L2 cache | L3 cache | Reference | + * +------------------+-------+-----------+-----------+-----------+----------+-----------+ + * | Kunpeng 920-3226 | 32 | 64K | 64K | 512K | 32M | [2] | + * +------------------+-------+-----------+-----------+-----------+----------+-----------+ + * | Kunpeng 920-4826 | 48 | 64K | 64K | 512K | 48M | [3] | + * +------------------+-------+-----------+-----------+-----------+----------+-----------+ + * | Kunpeng 920-6426 | 64 | 64K | 64K | 512K | 64M | [4] | + * +------------------+-------+-----------+-----------+-----------+----------+-----------+ + * + * [1] https://en.wikichip.org/wiki/hisilicon/microarchitectures/taishan_v110 + * [2] https://en.wikichip.org/wiki/hisilicon/kunpeng/920-3226 + * [3] https://en.wikichip.org/wiki/hisilicon/kunpeng/920-4826 + * [4] https://en.wikichip.org/wiki/hisilicon/kunpeng/920-6426 */ *l1i = (struct cpuinfo_cache) { .size = 64 * 1024, @@ -1481,11 +1491,11 @@ void cpuinfo_arm_decode_cache( .line_size = 128 /* assumption */, .flags = CPUINFO_CACHE_INCLUSIVE /* assumption */, }; - *l3 = (struct cpuinfo_cache) { - .size = cluster_cores * 1024 * 1024, - .associativity = 16 /* assumption */, - .line_size = 128 /* assumption */, - }; + *l3 = (struct cpuinfo_cache) { + .size = cluster_cores * 1024 * 1024, + .associativity = 16 /* assumption */, + .line_size = 128 /* assumption */, + }; break; #endif case cpuinfo_uarch_cortex_a12: diff --git a/src/arm/linux/aarch32-isa.c b/src/arm/linux/aarch32-isa.c index 6e659f5..41f9972 100644 --- a/src/arm/linux/aarch32-isa.c +++ b/src/arm/linux/aarch32-isa.c @@ -78,18 +78,24 @@ void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo( /* * NEON VDOT instructions are not indicated in /proc/cpuinfo. - * Use a MIDR-based heuristic to whitelist processors known to support it: - * - Processors with Qualcomm-modified Cortex-A76 cores - * - Kirin 980 processor + * Use a MIDR-based heuristic to whitelist processors known to support it. */ switch (midr & (CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK)) { + case UINT32_C(0x4100D0B0): /* Cortex-A76 */ + case UINT32_C(0x4100D0D0): /* Cortex-A77 */ + case UINT32_C(0x4100D0E0): /* Cortex-A76AE */ + case UINT32_C(0x4800D400): /* Cortex-A76 (HiSilicon) */ case UINT32_C(0x51008040): /* Kryo 485 Gold (Cortex-A76) */ + case UINT32_C(0x51008050): /* Kryo 485 Silver (Cortex-A55) */ + case UINT32_C(0x53000030): /* Exynos-M4 */ + case UINT32_C(0x53000040): /* Exynos-M5 */ isa->dot = true; break; - default: - if (chipset->series == cpuinfo_arm_chipset_series_hisilicon_kirin && chipset->model == 980) { - isa->dot = true; - } + case UINT32_C(0x4100D050): /* Cortex A55: revision 1 or later only */ + isa->dot = !!(midr_get_variant(midr) >= 1); + break; + case UINT32_C(0x4100D0A0): /* Cortex A75: revision 2 or later only */ + isa->dot = !!(midr_get_variant(midr) >= 2); break; } } else { @@ -194,7 +200,7 @@ void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo( CPUINFO_ARM_LINUX_FEATURE_VFPD32 | CPUINFO_ARM_LINUX_FEATURE_VFPV4 | CPUINFO_ARM_LINUX_FEATURE_NEON; if ((architecture_version >= 7) || (features & vfpv3_mask)) { isa->vfpv3 = true; - + const uint32_t d32_mask = CPUINFO_ARM_LINUX_FEATURE_VFPD32 | CPUINFO_ARM_LINUX_FEATURE_NEON; if (features & d32_mask) { isa->d32 = true; diff --git a/src/arm/linux/aarch64-isa.c b/src/arm/linux/aarch64-isa.c index f193e81..619cda5 100644 --- a/src/arm/linux/aarch64-isa.c +++ b/src/arm/linux/aarch64-isa.c @@ -67,21 +67,32 @@ void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo( } /* * Many phones ship with an old kernel configuration that doesn't report UDOT/SDOT instructions. - * Use a MIDR-based heuristic to whitelist processors known to support it: - * - Processors with Qualcomm-modified Cortex-A76 cores - * - Kirin 980 processor + * Use a MIDR-based heuristic to whitelist processors known to support it. */ switch (midr & (CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK)) { + case UINT32_C(0x4100D060): /* Cortex-A65 */ + case UINT32_C(0x4100D0B0): /* Cortex-A76 */ + case UINT32_C(0x4100D0C0): /* Neoverse N1 */ + case UINT32_C(0x4100D0D0): /* Cortex-A77 */ + case UINT32_C(0x4100D0E0): /* Cortex-A76AE */ + case UINT32_C(0x4100D4A0): /* Neoverse E1 */ + case UINT32_C(0x4800D400): /* Cortex-A76 (HiSilicon) */ case UINT32_C(0x51008040): /* Kryo 485 Gold (Cortex-A76) */ + case UINT32_C(0x51008050): /* Kryo 485 Silver (Cortex-A55) */ + case UINT32_C(0x53000030): /* Exynos-M4 */ + case UINT32_C(0x53000040): /* Exynos-M5 */ isa->dot = true; break; + case UINT32_C(0x4100D050): /* Cortex A55: revision 1 or later only */ + isa->dot = !!(midr_get_variant(midr) >= 1); + break; + case UINT32_C(0x4100D0A0): /* Cortex A75: revision 2 or later only */ + isa->dot = !!(midr_get_variant(midr) >= 2); + break; default: if (features & CPUINFO_ARM_LINUX_FEATURE_ASIMDDP) { isa->dot = true; } - if (chipset->series == cpuinfo_arm_chipset_series_hisilicon_kirin && chipset->model == 980) { - isa->dot = true; - } break; } if (features & CPUINFO_ARM_LINUX_FEATURE_JSCVT) { diff --git a/src/arm/linux/api.h b/src/arm/linux/api.h index f99da66..2597e49 100644 --- a/src/arm/linux/api.h +++ b/src/arm/linux/api.h @@ -11,6 +11,8 @@ /* No hard limit in the kernel, maximum length observed on non-rogue kernels is 64 */ #define CPUINFO_HARDWARE_VALUE_MAX 64 +/* No hard limit in the kernel, maximum length on Raspberry Pi is 8. Add 1 symbol to detect overly large revision strings */ +#define CPUINFO_REVISION_VALUE_MAX 9 #ifdef __ANDROID__ /* As per include/sys/system_properties.h in Android NDK */ @@ -259,6 +261,7 @@ static inline bool cpuinfo_arm_linux_processor_not_equals( CPUINFO_INTERNAL bool cpuinfo_arm_linux_parse_proc_cpuinfo( char hardware[restrict static CPUINFO_HARDWARE_VALUE_MAX], + char revision[restrict static CPUINFO_REVISION_VALUE_MAX], uint32_t max_processors_count, struct cpuinfo_arm_linux_processor processors[restrict static max_processors_count]); @@ -297,6 +300,7 @@ CPUINFO_INTERNAL bool cpuinfo_arm_linux_parse_proc_cpuinfo( CPUINFO_INTERNAL struct cpuinfo_arm_chipset cpuinfo_arm_linux_decode_chipset( const char hardware[restrict static CPUINFO_HARDWARE_VALUE_MAX], + const char revision[restrict static CPUINFO_REVISION_VALUE_MAX], uint32_t cores, uint32_t max_cpu_freq_max); #endif @@ -327,6 +331,10 @@ CPUINFO_INTERNAL struct cpuinfo_arm_chipset CPUINFO_INTERNAL struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_from_ro_hardware_chipname( const char ro_hardware_chipname[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]); +#else + CPUINFO_INTERNAL struct cpuinfo_arm_chipset + cpuinfo_arm_linux_decode_chipset_from_proc_cpuinfo_revision( + const char proc_cpuinfo_revision[restrict static CPUINFO_REVISION_VALUE_MAX]); #endif CPUINFO_INTERNAL bool cpuinfo_arm_linux_detect_core_clusters_by_heuristic( diff --git a/src/arm/linux/chipset.c b/src/arm/linux/chipset.c index 35058d9..e36283c 100644 --- a/src/arm/linux/chipset.c +++ b/src/arm/linux/chipset.c @@ -1012,11 +1012,58 @@ write_chipset: } /** + * Tries to match /BCM\d{4}$/ signature for Broadcom BCM chipsets. + * If match successful, extracts model information into \p chipset argument. + * + * @param start - start of the /proc/cpuinfo Hardware string to match. + * @param end - end of the /proc/cpuinfo Hardware string to match. + * @param[out] chipset - location where chipset information will be stored upon a successful match. + * + * @returns true if signature matched, false otherwise. + */ +static bool match_bcm( + const char* start, const char* end, + struct cpuinfo_arm_chipset chipset[restrict static 1]) +{ + /* Expect exactly 7 symbols: "BCM" (3 symbols) + 4-digit model number */ + if (start + 7 != end) { + return false; + } + + /* Check that the string starts with "BCM". + * The first three characters are loaded and compared as a 24-bit little endian word. + */ + const uint32_t expected_bcm = load_u24le(start); + if (expected_bcm != UINT32_C(0x004D4342) /* "MCB" = reverse("BCM") */) { + return false; + } + + /* Validate and parse 4-digit model number */ + uint32_t model = 0; + for (uint32_t i = 3; i < 7; i++) { + const uint32_t digit = (uint32_t) (uint8_t) start[i] - '0'; + if (digit >= 10) { + /* Not really a digit */ + return false; + } + model = model * 10 + digit; + } + + /* Return parsed chipset. */ + *chipset = (struct cpuinfo_arm_chipset) { + .vendor = cpuinfo_arm_chipset_vendor_broadcom, + .series = cpuinfo_arm_chipset_series_broadcom_bcm, + .model = model, + }; + return true; +} + +/** * Tries to match /OMAP\d{4}$/ signature for Texas Instruments OMAP chipsets. * If match successful, extracts model information into \p chipset argument. * * @param start - start of the /proc/cpuinfo Hardware string to match. - * @param end - end of the /proc/cpuinfo Hardaware string to match. + * @param end - end of the /proc/cpuinfo Hardware string to match. * @param[out] chipset - location where chipset information will be stored upon a successful match. * * @returns true if signature matched, false otherwise. @@ -2328,6 +2375,14 @@ struct cpuinfo_arm_chipset cpuinfo_arm_linux_decode_chipset_from_proc_cpuinfo_ha return chipset; } + /* Check Broadcom BCM signature */ + if (match_bcm(hardware, hardware_end, &chipset)) { + cpuinfo_log_debug( + "matched Broadcom BCM signature in /proc/cpuinfo Hardware string \"%.*s\"", + (int) hardware_length, hardware); + return chipset; + } + #if CPUINFO_ARCH_ARM /* Check Texas Instruments OMAP signature */ if (match_omap(hardware, hardware_end, &chipset)) { @@ -3713,6 +3768,62 @@ void cpuinfo_arm_chipset_to_string( return chipset; } #else /* !defined(__ANDROID__) */ + /* + * Fix commonly misreported Broadcom BCM models on Raspberry Pi boards. + * + * @param[in,out] chipset - chipset name to fix. + * @param[in] revision - /proc/cpuinfo Revision string. + */ + void cpuinfo_arm_fixup_raspberry_pi_chipset( + struct cpuinfo_arm_chipset chipset[restrict static 1], + const char revision[restrict static CPUINFO_HARDWARE_VALUE_MAX]) + { + const size_t revision_length = strnlen(revision, CPUINFO_REVISION_VALUE_MAX); + + /* Parse revision codes according to https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md */ + #if CPUINFO_ARCH_ARM + if (revision_length == 4) { + /* + * Old-style revision codes. + * All Raspberry Pi models with old-style revision code use Broadcom BCM2835. + */ + + /* BCM2835 often misreported as BCM2708 */ + if (chipset->model == 2708) { + chipset->model = 2835; + } + return; + } + #endif + if ((size_t) (revision_length - 5) <= (size_t) (8 - 5) /* 5 <= length(revision) <= 8 */) { + /* New-style revision codes */ + + uint32_t model = 0; + switch (revision[revision_length - 4]) { + case '0': + /* BCM2835 */ + model = 2835; + break; + case '1': + /* BCM2836 */ + model = 2836; + break; + case '2': + /* BCM2837 */ + model = 2837; + break; + case '3': + /* BCM2711 */ + model = 2711; + break; + } + + if (model != 0) { + chipset->model = model; + chipset->suffix[0] = 0; + } + } + } /* * Decodes chipset name from /proc/cpuinfo Hardware string. @@ -3727,6 +3838,7 @@ void cpuinfo_arm_chipset_to_string( */ struct cpuinfo_arm_chipset cpuinfo_arm_linux_decode_chipset( const char hardware[restrict static CPUINFO_HARDWARE_VALUE_MAX], + const char revision[restrict static CPUINFO_REVISION_VALUE_MAX], uint32_t cores, uint32_t max_cpu_freq_max) { @@ -3736,6 +3848,9 @@ void cpuinfo_arm_chipset_to_string( if (chipset.vendor == cpuinfo_arm_chipset_vendor_unknown) { cpuinfo_log_warning( "chipset detection failed: /proc/cpuinfo Hardware string did not match known signatures"); + } else if (chipset.vendor == cpuinfo_arm_chipset_vendor_broadcom) { + /* Raspberry Pi kernel reports bogus chipset models; detect chipset from RPi revision */ + cpuinfo_arm_fixup_raspberry_pi_chipset(&chipset, revision); } else { cpuinfo_arm_fixup_chipset(&chipset, cores, max_cpu_freq_max); } diff --git a/src/arm/linux/clusters.c b/src/arm/linux/clusters.c index 8daeae5..c7a4045 100644 --- a/src/arm/linux/clusters.c +++ b/src/arm/linux/clusters.c @@ -47,7 +47,7 @@ static inline bool bitmask_all(uint32_t bitfield, uint32_t mask) { * * @param usable_processors - number of processors in the @p processors array with CPUINFO_LINUX_FLAG_VALID flags. * @param max_processors - number of elements in the @p processors array. - * @param[in,out] processors - processor descriptors with pre-parsed POSSIBLE and PRESENT flags, minimum/maximum + * @param[in,out] processors - processor descriptors with pre-parsed POSSIBLE and PRESENT flags, minimum/maximum * frequency, MIDR infromation, and core cluster (package siblings list) information. * * @retval true if the heuristic successfully assigned all processors into clusters of cores. @@ -308,7 +308,7 @@ bool cpuinfo_arm_linux_detect_core_clusters_by_heuristic( * @p processors array have cluster information. * * @param max_processors - number of elements in the @p processors array. - * @param[in,out] processors - processor descriptors with pre-parsed POSSIBLE and PRESENT flags, minimum/maximum + * @param[in,out] processors - processor descriptors with pre-parsed POSSIBLE and PRESENT flags, minimum/maximum * frequency, MIDR infromation, and core cluster (package siblings list) information. * * @retval true if the heuristic successfully assigned all processors into clusters of cores. @@ -466,7 +466,7 @@ new_cluster: * This function should be called after all processors are assigned to core clusters. * * @param max_processors - number of elements in the @p processors array. - * @param[in,out] processors - processor descriptors with pre-parsed POSSIBLE and PRESENT flags, + * @param[in,out] processors - processor descriptors with pre-parsed POSSIBLE and PRESENT flags, * and decoded core cluster (package_leader_id) information. * The function expects the value of processors[i].package_processor_count to be zero. * Upon return, processors[i].package_processor_count will contain the number of logical @@ -482,12 +482,12 @@ void cpuinfo_arm_linux_count_cluster_processors( const uint32_t package_leader_id = processors[i].package_leader_id; processors[package_leader_id].package_processor_count += 1; } - } + } /* Second pass: copy the package_processor_count from the group leader processor */ for (uint32_t i = 0; i < max_processors; i++) { if (bitmask_all(processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) { const uint32_t package_leader_id = processors[i].package_leader_id; processors[i].package_processor_count = processors[package_leader_id].package_processor_count; } - } + } } diff --git a/src/arm/linux/cpuinfo.c b/src/arm/linux/cpuinfo.c index 2df0c6e..90e1631 100644 --- a/src/arm/linux/cpuinfo.c +++ b/src/arm/linux/cpuinfo.c @@ -44,7 +44,7 @@ static uint32_t parse_processor_number( /* * Full list of ARM features reported in /proc/cpuinfo: - * + * * * swp - support for SWP instruction (deprecated in ARMv7, can be removed in future) * * half - support for half-word loads and stores. These instruction are part of ARMv4, * so no need to check it on supported CPUs. @@ -620,7 +620,7 @@ static void parse_cache_number( break; default: cpuinfo_log_warning("invalid %s %.*s is ignored: a value of 16, 32, 64, or 128 expected", - number_name, (int) (number_end - number_start), number_start); + number_name, (int) (number_end - number_start), number_start); } } @@ -631,6 +631,7 @@ static void parse_cache_number( struct proc_cpuinfo_parser_state { char* hardware; + char* revision; uint32_t processor_index; uint32_t max_processors_count; struct cpuinfo_arm_linux_processor* processors; @@ -670,7 +671,7 @@ static bool parse_line( if (line_start == line_end) { return true; } - + /* Search for ':' on the line. */ const char* separator = line_start; for (; separator != line_end; separator++) { @@ -791,7 +792,17 @@ static bool parse_line( memcpy(state->hardware, value_start, value_length); cpuinfo_log_debug("parsed /proc/cpuinfo Hardware = \"%.*s\"", (int) value_length, value_start); } else if (memcmp(line_start, "Revision", key_length) == 0) { - /* Board revision, no use for now */ + size_t value_length = value_end - value_start; + if (value_length > CPUINFO_REVISION_VALUE_MAX) { + cpuinfo_log_info( + "length of Revision value \"%.*s\" in /proc/cpuinfo exceeds limit (%d): truncating to the limit", + (int) value_length, value_start, CPUINFO_REVISION_VALUE_MAX); + value_length = CPUINFO_REVISION_VALUE_MAX; + } else { + state->revision[value_length] = '\0'; + } + memcpy(state->revision, value_start, value_length); + cpuinfo_log_debug("parsed /proc/cpuinfo Revision = \"%.*s\"", (int) value_length, value_start); } else { goto unknown; } @@ -881,11 +892,13 @@ static bool parse_line( bool cpuinfo_arm_linux_parse_proc_cpuinfo( char hardware[restrict static CPUINFO_HARDWARE_VALUE_MAX], + char revision[restrict static CPUINFO_REVISION_VALUE_MAX], uint32_t max_processors_count, struct cpuinfo_arm_linux_processor processors[restrict static max_processors_count]) { struct proc_cpuinfo_parser_state state = { .hardware = hardware, + .revision = revision, .processor_index = 0, .max_processors_count = max_processors_count, .processors = processors, diff --git a/src/arm/linux/init.c b/src/arm/linux/init.c index 6272abf..89d957e 100644 --- a/src/arm/linux/init.c +++ b/src/arm/linux/init.c @@ -167,8 +167,9 @@ void cpuinfo_arm_linux_init(void) { struct cpuinfo_android_properties android_properties; cpuinfo_arm_android_parse_properties(&android_properties); #else - char proc_cpuinfo_hardware[CPUINFO_HARDWARE_VALUE_MAX] = { 0 }; + char proc_cpuinfo_hardware[CPUINFO_HARDWARE_VALUE_MAX]; #endif + char proc_cpuinfo_revision[CPUINFO_REVISION_VALUE_MAX]; if (!cpuinfo_arm_linux_parse_proc_cpuinfo( #if defined(__ANDROID__) @@ -176,6 +177,7 @@ void cpuinfo_arm_linux_init(void) { #else proc_cpuinfo_hardware, #endif + proc_cpuinfo_revision, arm_linux_processors_count, arm_linux_processors)) { cpuinfo_log_error("failed to parse processor information from /proc/cpuinfo"); @@ -228,10 +230,8 @@ void cpuinfo_arm_linux_init(void) { const struct cpuinfo_arm_chipset chipset = cpuinfo_arm_android_decode_chipset(&android_properties, valid_processors, 0); #else - const struct cpuinfo_arm_chipset chipset = { - .vendor = cpuinfo_arm_chipset_vendor_unknown, - .series = cpuinfo_arm_chipset_series_unknown, - }; + const struct cpuinfo_arm_chipset chipset = + cpuinfo_arm_linux_decode_chipset(proc_cpuinfo_hardware, proc_cpuinfo_revision, valid_processors, 0); #endif #if CPUINFO_ARCH_ARM diff --git a/src/arm/mach/init.c b/src/arm/mach/init.c index b6c4a7b..e912de6 100644 --- a/src/arm/mach/init.c +++ b/src/arm/mach/init.c @@ -348,6 +348,15 @@ void cpuinfo_arm_mach_init(void) { cpuinfo_isa.fp16arith = true; } + /* + * There does not yet seem to exist an OS mechanism to detect support for + * ARMv8.2 optional dot-product instructions, so we currently whitelist CPUs + * known to support these instruction. + */ + if (cpu_family == CPUFAMILY_ARM_LIGHTNING_THUNDER) { + cpuinfo_isa.dot = true; + } + uint32_t num_clusters = 1; for (uint32_t i = 0; i < mach_topology.cores; i++) { cores[i] = (struct cpuinfo_core) { diff --git a/src/arm/midr.h b/src/arm/midr.h index 3d3aaa9..2638517 100644 --- a/src/arm/midr.h +++ b/src/arm/midr.h @@ -190,22 +190,28 @@ inline static uint32_t midr_score_core(uint32_t midr) { case UINT32_C(0x4100D0A0): /* Cortex-A75 */ case UINT32_C(0x4100D090): /* Cortex-A73 */ case UINT32_C(0x4100D080): /* Cortex-A72 */ +#if CPUINFO_ARCH_ARM case UINT32_C(0x4100C0F0): /* Cortex-A15 */ case UINT32_C(0x4100C0E0): /* Cortex-A17 */ case UINT32_C(0x4100C0D0): /* Rockchip RK3288 cores */ case UINT32_C(0x4100C0C0): /* Cortex-A12 */ +#endif /* CPUINFO_ARCH_ARM */ /* These cores are always in big role */ return 5; case UINT32_C(0x4100D070): /* Cortex-A57 */ /* Cortex-A57 can be in LITTLE role w.r.t. Denver 2, or in big role w.r.t. Cortex-A53 */ return 4; +#if CPUINFO_ARCH_ARM64 case UINT32_C(0x4100D060): /* Cortex-A65 */ +#endif /* CPUINFO_ARCH_ARM64 */ case UINT32_C(0x4100D050): /* Cortex-A55 */ case UINT32_C(0x4100D030): /* Cortex-A53 */ /* Cortex-A53 is usually in LITTLE role, but can be in big role w.r.t. Cortex-A35 */ return 2; case UINT32_C(0x4100D040): /* Cortex-A35 */ +#if CPUINFO_ARCH_ARM case UINT32_C(0x4100C070): /* Cortex-A7 */ +#endif /* CPUINFO_ARCH_ARM */ case UINT32_C(0x51008050): /* Kryo 485 Silver */ case UINT32_C(0x51008030): /* Kryo 385 Silver */ case UINT32_C(0x51008010): /* Kryo 260 / 280 Silver */ diff --git a/src/arm/tlb.c b/src/arm/tlb.c index ba42a3e..9beb832 100644 --- a/src/arm/tlb.c +++ b/src/arm/tlb.c @@ -6,7 +6,7 @@ switch (uarch) { * Cortex-A5 Technical Reference Manual: * 6.3.1. Micro TLB * The first level of caching for the page table information is a micro TLB of - * 10 entries that is implemented on each of the instruction and data sides. + * 10 entries that is implemented on each of the instruction and data sides. * 6.3.2. Main TLB * Misses from the instruction and data micro TLBs are handled by a unified main TLB. * The main TLB is 128-entry two-way set-associative. diff --git a/src/arm/uarch.c b/src/arm/uarch.c index e8b4c5e..0d7a7d7 100644 --- a/src/arm/uarch.c +++ b/src/arm/uarch.c @@ -88,8 +88,8 @@ void cpuinfo_arm_decode_vendor_uarch( case 0xD0D: *uarch = cpuinfo_uarch_cortex_a77; break; - case 0xD0E: - *uarch = cpuinfo_uarch_cortex_a76ae; + case 0xD0E: /* Cortex-A76AE */ + *uarch = cpuinfo_uarch_cortex_a76; break; case 0xD41: /* Cortex-A78 */ *uarch = cpuinfo_uarch_cortex_a78; @@ -158,9 +158,11 @@ void cpuinfo_arm_decode_vendor_uarch( case 'H': *vendor = cpuinfo_vendor_huawei; switch (midr_get_part(midr)) { - case 0xD01: /* Kunpeng920 ARM-base CPU*/ - *uarch = cpuinfo_uarch_taishanv110; +#if CPUINFO_ARCH_ARM64 && !defined(__ANDROID__) + case 0xD01: /* Kunpeng 920 series */ + *uarch = cpuinfo_uarch_taishan_v110; break; +#endif case 0xD40: /* Kirin 980 Big/Medium cores -> Cortex-A76 */ *vendor = cpuinfo_vendor_arm; *uarch = cpuinfo_uarch_cortex_a76; |