// Copyright 2017 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "cpuinfo_arm.h" #include "filesystem_for_testing.h" #include "gtest/gtest.h" #include "hwcaps_for_testing.h" namespace cpu_features { namespace { void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); } TEST(CpuinfoArmTest, FromHardwareCap) { SetHardwareCapabilities(ARM_HWCAP_NEON, ARM_HWCAP2_AES | ARM_HWCAP2_CRC32); GetEmptyFilesystem(); // disabling /proc/cpuinfo const auto info = GetArmInfo(); EXPECT_TRUE(info.features.vfp); // triggered by vfpv3 EXPECT_TRUE(info.features.vfpv3); // triggered by neon EXPECT_TRUE(info.features.neon); EXPECT_TRUE(info.features.aes); EXPECT_TRUE(info.features.crc32); EXPECT_FALSE(info.features.vfpv4); EXPECT_FALSE(info.features.iwmmxt); EXPECT_FALSE(info.features.crunch); EXPECT_FALSE(info.features.thumbee); EXPECT_FALSE(info.features.vfpv3d16); EXPECT_FALSE(info.features.idiva); EXPECT_FALSE(info.features.idivt); EXPECT_FALSE(info.features.pmull); EXPECT_FALSE(info.features.sha1); EXPECT_FALSE(info.features.sha2); // check some random features with EnumValue(): EXPECT_TRUE(GetArmFeaturesEnumValue(&info.features, ARM_VFP)); EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, ARM_VFPV4)); // out of bound EnumValue() check EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, (ArmFeaturesEnum)~0x0)); } TEST(CpuinfoArmTest, ODroidFromCpuInfo) { DisableHardwareCapabilities(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(processor : 0 model name : ARMv7 Processor rev 3 (v71) BogoMIPS : 120.00 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x2 CPU part : 0xc0f CPU revision : 3)"); const auto info = GetArmInfo(); EXPECT_EQ(info.implementer, 0x41); EXPECT_EQ(info.variant, 0x2); EXPECT_EQ(info.part, 0xc0f); EXPECT_EQ(info.revision, 3); EXPECT_EQ(info.architecture, 7); EXPECT_FALSE(info.features.swp); EXPECT_TRUE(info.features.half); EXPECT_TRUE(info.features.thumb); EXPECT_FALSE(info.features._26bit); EXPECT_TRUE(info.features.fastmult); EXPECT_FALSE(info.features.fpa); EXPECT_TRUE(info.features.vfp); EXPECT_TRUE(info.features.edsp); EXPECT_FALSE(info.features.java); EXPECT_FALSE(info.features.iwmmxt); EXPECT_FALSE(info.features.crunch); EXPECT_FALSE(info.features.thumbee); EXPECT_TRUE(info.features.neon); EXPECT_TRUE(info.features.vfpv3); EXPECT_FALSE(info.features.vfpv3d16); EXPECT_TRUE(info.features.tls); EXPECT_TRUE(info.features.vfpv4); EXPECT_TRUE(info.features.idiva); EXPECT_TRUE(info.features.idivt); EXPECT_TRUE(info.features.vfpd32); EXPECT_TRUE(info.features.lpae); EXPECT_FALSE(info.features.evtstrm); EXPECT_FALSE(info.features.aes); EXPECT_FALSE(info.features.pmull); EXPECT_FALSE(info.features.sha1); EXPECT_FALSE(info.features.sha2); EXPECT_FALSE(info.features.crc32); } // Linux test-case TEST(CpuinfoArmTest, RaspberryPiZeroFromCpuInfo) { DisableHardwareCapabilities(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(processor : 0 model name : ARMv6-compatible processor rev 7 (v6l) BogoMIPS : 697.95 Features : half thumb fastmult vfp edsp java tls CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x0 CPU part : 0xb76 CPU revision : 7 Hardware : BCM2835 Revision : 9000c1 Serial : 000000006cd946f3)"); const auto info = GetArmInfo(); EXPECT_EQ(info.implementer, 0x41); EXPECT_EQ(info.variant, 0x0); EXPECT_EQ(info.part, 0xb76); EXPECT_EQ(info.revision, 7); EXPECT_EQ(info.architecture, 6); EXPECT_FALSE(info.features.swp); EXPECT_TRUE(info.features.half); EXPECT_TRUE(info.features.thumb); EXPECT_FALSE(info.features._26bit); EXPECT_TRUE(info.features.fastmult); EXPECT_FALSE(info.features.fpa); EXPECT_TRUE(info.features.vfp); EXPECT_TRUE(info.features.edsp); EXPECT_TRUE(info.features.java); EXPECT_FALSE(info.features.iwmmxt); EXPECT_FALSE(info.features.crunch); EXPECT_FALSE(info.features.thumbee); EXPECT_FALSE(info.features.neon); EXPECT_FALSE(info.features.vfpv3); EXPECT_FALSE(info.features.vfpv3d16); EXPECT_TRUE(info.features.tls); EXPECT_FALSE(info.features.vfpv4); EXPECT_FALSE(info.features.idiva); EXPECT_FALSE(info.features.idivt); EXPECT_FALSE(info.features.vfpd32); EXPECT_FALSE(info.features.lpae); EXPECT_FALSE(info.features.evtstrm); EXPECT_FALSE(info.features.aes); EXPECT_FALSE(info.features.pmull); EXPECT_FALSE(info.features.sha1); EXPECT_FALSE(info.features.sha2); EXPECT_FALSE(info.features.crc32); } TEST(CpuinfoArmTest, MarvellArmadaFromCpuInfo) { DisableHardwareCapabilities(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(processor : 0 model name : ARMv7 Processor rev 1 (v7l) BogoMIPS : 50.00 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x4 CPU part : 0xc09 CPU revision : 1 processor : 1 model name : ARMv7 Processor rev 1 (v7l) BogoMIPS : 50.00 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x4 CPU part : 0xc09 CPU revision : 1 Hardware : Marvell Armada 380/385 (Device Tree) Revision : 0000 Serial : 0000000000000000)"); const auto info = GetArmInfo(); EXPECT_EQ(info.implementer, 0x41); EXPECT_EQ(info.variant, 0x4); EXPECT_EQ(info.part, 0xc09); EXPECT_EQ(info.revision, 1); EXPECT_EQ(info.architecture, 7); EXPECT_FALSE(info.features.swp); EXPECT_TRUE(info.features.half); EXPECT_TRUE(info.features.thumb); EXPECT_FALSE(info.features._26bit); EXPECT_TRUE(info.features.fastmult); EXPECT_FALSE(info.features.fpa); EXPECT_TRUE(info.features.vfp); EXPECT_TRUE(info.features.edsp); EXPECT_FALSE(info.features.java); EXPECT_FALSE(info.features.iwmmxt); EXPECT_FALSE(info.features.crunch); EXPECT_FALSE(info.features.thumbee); EXPECT_TRUE(info.features.neon); EXPECT_TRUE(info.features.vfpv3); EXPECT_FALSE(info.features.vfpv3d16); EXPECT_TRUE(info.features.tls); EXPECT_FALSE(info.features.vfpv4); EXPECT_FALSE(info.features.idiva); EXPECT_FALSE(info.features.idivt); EXPECT_TRUE(info.features.vfpd32); EXPECT_FALSE(info.features.lpae); EXPECT_FALSE(info.features.evtstrm); EXPECT_FALSE(info.features.aes); EXPECT_FALSE(info.features.pmull); EXPECT_FALSE(info.features.sha1); EXPECT_FALSE(info.features.sha2); EXPECT_FALSE(info.features.crc32); } // Android test-case // http://code.google.com/p/android/issues/detail?id=10812 TEST(CpuinfoArmTest, InvalidArmv7) { DisableHardwareCapabilities(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(Processor : ARMv6-compatible processor rev 6 (v6l) BogoMIPS : 199.47 Features : swp half thumb fastmult vfp edsp java CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x0 CPU part : 0xb76 CPU revision : 6 Hardware : SPICA Revision : 0020 Serial : 33323613546d00ec )"); const auto info = GetArmInfo(); EXPECT_EQ(info.architecture, 6); EXPECT_TRUE(info.features.swp); EXPECT_TRUE(info.features.half); EXPECT_TRUE(info.features.thumb); EXPECT_FALSE(info.features._26bit); EXPECT_TRUE(info.features.fastmult); EXPECT_FALSE(info.features.fpa); EXPECT_TRUE(info.features.vfp); EXPECT_TRUE(info.features.edsp); EXPECT_TRUE(info.features.java); EXPECT_FALSE(info.features.iwmmxt); EXPECT_FALSE(info.features.crunch); EXPECT_FALSE(info.features.thumbee); EXPECT_FALSE(info.features.neon); EXPECT_FALSE(info.features.vfpv3); EXPECT_FALSE(info.features.vfpv3d16); EXPECT_FALSE(info.features.tls); EXPECT_FALSE(info.features.vfpv4); EXPECT_FALSE(info.features.idiva); EXPECT_FALSE(info.features.idivt); EXPECT_FALSE(info.features.vfpd32); EXPECT_FALSE(info.features.lpae); EXPECT_FALSE(info.features.evtstrm); EXPECT_FALSE(info.features.aes); EXPECT_FALSE(info.features.pmull); EXPECT_FALSE(info.features.sha1); EXPECT_FALSE(info.features.sha2); EXPECT_FALSE(info.features.crc32); } // Android test-case // https://crbug.com/341598. TEST(CpuinfoArmTest, InvalidNeon) { auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(Processor: ARMv7 Processory rev 0 (v71) processor: 0 BogoMIPS: 13.50 Processor: 1 BogoMIPS: 13.50 Features: swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt CPU implementer : 0x51 CPU architecture: 7 CPU variant: 0x1 CPU part: 0x04d CPU revision: 0 Hardware: SAMSUNG M2 Revision: 0010 Serial: 00001e030000354e)"); const auto info = GetArmInfo(); EXPECT_TRUE(info.features.swp); EXPECT_FALSE(info.features.neon); } // The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report IDIV // support. TEST(CpuinfoArmTest, Nexus4_0x510006f2) { DisableHardwareCapabilities(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(CPU implementer : 0x51 CPU architecture: 7 CPU variant : 0x0 CPU part : 0x6f CPU revision : 2)"); const auto info = GetArmInfo(); EXPECT_TRUE(info.features.idiva); EXPECT_TRUE(info.features.idivt); EXPECT_EQ(GetArmCpuId(&info), 0x510006f2); } // The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report IDIV // support. TEST(CpuinfoArmTest, Nexus4_0x510006f3) { DisableHardwareCapabilities(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(CPU implementer : 0x51 CPU architecture: 7 CPU variant : 0x0 CPU part : 0x6f CPU revision : 3)"); const auto info = GetArmInfo(); EXPECT_TRUE(info.features.idiva); EXPECT_TRUE(info.features.idivt); EXPECT_EQ(GetArmCpuId(&info), 0x510006f3); } // The emulator-specific Android 4.2 kernel fails to report support for the // 32-bit ARM IDIV instruction. Technically, this is a feature of the virtual // CPU implemented by the emulator. TEST(CpuinfoArmTest, EmulatorSpecificIdiv) { DisableHardwareCapabilities(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(Processor : ARMv7 Processor rev 0 (v7l) BogoMIPS : 629.14 Features : swp half thumb fastmult vfp edsp neon vfpv3 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x0 CPU part : 0xc08 CPU revision : 0 Hardware : Goldfish Revision : 0000 Serial : 0000000000000000)"); const auto info = GetArmInfo(); EXPECT_TRUE(info.features.idiva); } } // namespace } // namespace cpu_features