[libyuv] Disable SME on iOS

Apple processors (such as A18/A19) may report
hw.optional.arm.FEAT_SME = 1 even when the XNU kernel on iOS disables
EL0 (user-mode) SME execution (hw.optional.arm.sme_max_svl_b == 0),
which causes SMSTART or RDSVL to fault with EXC_BAD_INSTRUCTION.
Gate SME/SME2 flags on have_feature("hw.optional.arm.sme_max_svl_b")
being nonzero. See https://github.com/pytorch/cpuinfo/issues/432 and
https://github.com/pytorch/cpuinfo/pull/433.

Also add SME2 detection test in cpu_test.cc and LIBYUV_DISABLE_SME2
environment variable support in unit_test.cc.

Test: libyuv_unittest --gtest_filter=*TestLinuxAArch64*
Bug: 8339302
Change-Id: If3e4d425ebaa89bf27965295ebdb43b844797ca1
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8428226
Reviewed-by: Wan-Teh Chang <wtc@google.com>
Commit-Queue: Frank Barchard <fbarchard@google.com>
This commit is contained in:
Frank Barchard 2026-09-18 15:52:45 -07:00 committed by libyuv-scoped@luci-project-accounts.iam.gserviceaccount.com
parent 38eb2b48f9
commit 749f9742bb
3 changed files with 17 additions and 3 deletions

View File

@ -248,12 +248,14 @@ LIBYUV_API SAFEBUFFERS int AArch64CpuCaps() {
static bool have_feature(const char* feature) { static bool have_feature(const char* feature) {
// For more information on sysctlbyname(), see: // For more information on sysctlbyname(), see:
// https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics
// If feature is "hw.optional.arm.sme_max_svl_b", this function returns
// whether the value of sme_max_svl_b is nonzero.
int64_t feature_present = 0; int64_t feature_present = 0;
size_t size = sizeof(feature_present); size_t size = sizeof(feature_present);
if (sysctlbyname(feature, &feature_present, &size, NULL, 0) != 0) { if (sysctlbyname(feature, &feature_present, &size, NULL, 0) != 0) {
return false; return false;
} }
return feature_present; return feature_present != 0;
} }
// For AArch64, but public to allow testing on any CPU. // For AArch64, but public to allow testing on any CPU.
@ -265,7 +267,14 @@ LIBYUV_API SAFEBUFFERS int AArch64CpuCaps() {
features |= kCpuHasNeonDotProd; features |= kCpuHasNeonDotProd;
if (have_feature("hw.optional.arm.FEAT_I8MM")) { if (have_feature("hw.optional.arm.FEAT_I8MM")) {
features |= kCpuHasNeonI8MM; features |= kCpuHasNeonI8MM;
if (have_feature("hw.optional.arm.FEAT_SME")) { // An Apple processor may have SME hardware (e.g. A18/A19), but the XNU
// kernel only enables EL0 execution if sme_max_svl_b is nonzero.
// macOS and iPadOS (e.g. on M4) support and enable user-mode SME, but iOS
// disables user-mode SME, which causes SMSTART to trigger an
// EXC_BAD_INSTRUCTION fault. See
// https://github.com/pytorch/cpuinfo/issues/432.
if (have_feature("hw.optional.arm.sme_max_svl_b") &&
have_feature("hw.optional.arm.FEAT_SME")) {
features |= kCpuHasSME; features |= kCpuHasSME;
if (have_feature("hw.optional.arm.FEAT_SME2")) { if (have_feature("hw.optional.arm.FEAT_SME2")) {
features |= kCpuHasSME2; features |= kCpuHasSME2;

View File

@ -366,7 +366,9 @@ TEST_F(LibYUVBaseTest, TestLinuxAArch64) {
expected |= kCpuHasSME; expected |= kCpuHasSME;
ASSERT_EQ(expected, AArch64CpuCaps(0x3fffffffU, 0x82f3ffU)); ASSERT_EQ(expected, AArch64CpuCaps(0x3fffffffU, 0x82f3ffU));
// TODO: Check for SME2 feature detection from Apple M4 // Check for SME2 feature detection.
expected |= kCpuHasSME2;
ASSERT_EQ(expected, AArch64CpuCaps(0x3fffffffU, 0x200082f3ffULL));
} }
#endif #endif

View File

@ -89,6 +89,9 @@ static int TestCpuEnv(int cpu_info) {
if (TestEnv("LIBYUV_DISABLE_SME")) { if (TestEnv("LIBYUV_DISABLE_SME")) {
cpu_info &= ~libyuv::kCpuHasSME; cpu_info &= ~libyuv::kCpuHasSME;
} }
if (TestEnv("LIBYUV_DISABLE_SME2")) {
cpu_info &= ~libyuv::kCpuHasSME2;
}
#endif #endif
#if defined(__longarch__) && defined(__linux__) #if defined(__longarch__) && defined(__linux__)
if (TestEnv("LIBYUV_DISABLE_LSX")) { if (TestEnv("LIBYUV_DISABLE_LSX")) {