mirror of
				https://github.com/google/cpu_features.git
				synced 2025-10-31 05:00:44 +01:00 
			
		
		
		
	Fix a getauxval comment and expand the Krait idiv workaround (#206)
* Fix getauxval comment (API 18 not 20)
getauxval is available in Android starting with API 18, not 20.
The comment about __ANDROID_API__ appears to have been copied from the
NDK's cpufeatures, which always uses dlopen/dlsym and doesn't assume it
can directly call getauxval, even if __ANDROID_API__ is new enough.
With this project, though, when __ANDROID_API__ is 18 or up, the
CMakeLists.txt file would detect that getauxval is available and define
HAVE_STRONG_GETAUXVAL.
* Broaden Qualcomm Krait idiv workaround
Some Qualcomm Krait CPUs have IDIV support but the kernel doesn't
report it. Previously, this code looked for two CPUs:
 - 0x510006F2 (0x51/'Q', variant 0, part 0x06f, rev 2)
 - 0x510006F3 (0x51/'Q', variant 0, part 0x06f, rev 3)
This check misses my 2013 Nexus 7 device, which has this CPU ID:
 - 0x511006f0 (0x51/'Q', variant 1, part 0x06f, rev 0)
My Nexus 7 device doesn't report idiv through AT_HWCAP or through
/proc/cpuinfo (AT_HWCAP is 0x1b0d7).
Expand the check to anything with:
 - implementer 0x51
 - architecture 7
 - part 0x4d or 0x6f
Part 0x4d appears to be a dual-core Krait (e.g. see
https://crbug.com/341598#c43).
This new matching behavior is a subset of what the upstream kernel
does (patch[1] contributed by CodeAurora), and also closely matches the
behavior of pytorch/cpuinfo.
[1] 120ecfafab
			
			
This commit is contained in:
		| @@ -68,13 +68,7 @@ static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) { | ||||
| #elif defined(HAVE_DLFCN_H) | ||||
| // On Android we probe the system's C library for a 'getauxval' function and | ||||
| // call it if it exits, or return 0 for failure. This function is available | ||||
| // since API level 20. | ||||
| // | ||||
| // This code does *NOT* check for '__ANDROID_API__ >= 20' to support the edge | ||||
| // case where some NDK developers use headers for a platform that is newer than | ||||
| // the one really targetted by their application. This is typically done to use | ||||
| // newer native APIs only when running on more recent Android versions, and | ||||
| // requires careful symbol management. | ||||
| // since API level 18. | ||||
| // | ||||
| // Note that getauxval() can't really be re-implemented here, because its | ||||
| // implementation does not parse /proc/self/auxv. Instead it depends on values | ||||
|   | ||||
| @@ -152,13 +152,14 @@ static void FixErrors(ArmInfo* const info, | ||||
|       // https://crbug.com/341598. | ||||
|       info->features.neon = false; | ||||
|       break; | ||||
|     case 0x510006F2: | ||||
|     case 0x510006F3: | ||||
|       // The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report | ||||
|       // IDIV support. | ||||
|       info->features.idiva = true; | ||||
|       info->features.idivt = true; | ||||
|       break; | ||||
|   } | ||||
|  | ||||
|   // Some Qualcomm Krait kernels forget to report IDIV support. | ||||
|   // https://github.com/torvalds/linux/commit/120ecfafabec382c4feb79ff159ef42a39b6d33b | ||||
|   if (info->implementer == 0x51 && info->architecture == 7 && | ||||
|       (info->part == 0x4d || info->part == 0x6f)) { | ||||
|     info->features.idiva = true; | ||||
|     info->features.idivt = true; | ||||
|   } | ||||
|  | ||||
|   // Propagate cpu features. | ||||
|   | ||||
| @@ -327,6 +327,24 @@ CPU revision	: 3)"); | ||||
|   EXPECT_EQ(GetArmCpuId(&info), 0x510006f3); | ||||
| } | ||||
|  | ||||
| // The 2013 Nexus 7 (Qualcomm Krait) kernel configuration forgets to report IDIV | ||||
| // support. | ||||
| TEST(CpuinfoArmTest, Nexus7_2013_0x511006f0) { | ||||
|   ResetHwcaps(); | ||||
|   auto& fs = GetEmptyFilesystem(); | ||||
|   fs.CreateFile("/proc/cpuinfo", | ||||
|                 R"(CPU implementer  : 0x51 | ||||
| CPU architecture: 7 | ||||
| CPU variant : 0x1 | ||||
| CPU part  : 0x06f | ||||
| CPU revision  : 0)"); | ||||
|   const auto info = GetArmInfo(); | ||||
|   EXPECT_TRUE(info.features.idiva); | ||||
|   EXPECT_TRUE(info.features.idivt); | ||||
|  | ||||
|   EXPECT_EQ(GetArmCpuId(&info), 0x511006f0); | ||||
| } | ||||
|  | ||||
| // 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. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Ryan Prichard
					Ryan Prichard