From 749f9742bb0e8a191316691860f48c42d651f755 Mon Sep 17 00:00:00 2001 From: Frank Barchard Date: Fri, 18 Sep 2026 15:52:45 -0700 Subject: [PATCH] [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 Commit-Queue: Frank Barchard --- source/cpu_id.cc | 13 +++++++++++-- unit_test/cpu_test.cc | 4 +++- unit_test/unit_test.cc | 3 +++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/source/cpu_id.cc b/source/cpu_id.cc index 0cc46b10a..bebe4796c 100644 --- a/source/cpu_id.cc +++ b/source/cpu_id.cc @@ -248,12 +248,14 @@ LIBYUV_API SAFEBUFFERS int AArch64CpuCaps() { static bool have_feature(const char* feature) { // For more information on sysctlbyname(), see: // 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; size_t size = sizeof(feature_present); if (sysctlbyname(feature, &feature_present, &size, NULL, 0) != 0) { return false; } - return feature_present; + return feature_present != 0; } // For AArch64, but public to allow testing on any CPU. @@ -265,7 +267,14 @@ LIBYUV_API SAFEBUFFERS int AArch64CpuCaps() { features |= kCpuHasNeonDotProd; if (have_feature("hw.optional.arm.FEAT_I8MM")) { 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; if (have_feature("hw.optional.arm.FEAT_SME2")) { features |= kCpuHasSME2; diff --git a/unit_test/cpu_test.cc b/unit_test/cpu_test.cc index cc5dfd077..77c7ffee8 100644 --- a/unit_test/cpu_test.cc +++ b/unit_test/cpu_test.cc @@ -366,7 +366,9 @@ TEST_F(LibYUVBaseTest, TestLinuxAArch64) { expected |= kCpuHasSME; 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 diff --git a/unit_test/unit_test.cc b/unit_test/unit_test.cc index cd22d1996..1dcb216f0 100644 --- a/unit_test/unit_test.cc +++ b/unit_test/unit_test.cc @@ -89,6 +89,9 @@ static int TestCpuEnv(int cpu_info) { if (TestEnv("LIBYUV_DISABLE_SME")) { cpu_info &= ~libyuv::kCpuHasSME; } + if (TestEnv("LIBYUV_DISABLE_SME2")) { + cpu_info &= ~libyuv::kCpuHasSME2; + } #endif #if defined(__longarch__) && defined(__linux__) if (TestEnv("LIBYUV_DISABLE_LSX")) {