From: Waldemar Kozaczuk <jwkozac...@gmail.com>
Committer: Waldemar Kozaczuk <jwkozac...@gmail.com>
Branch: master

aarch64: handle AT_HWCAP in getauxval

As the issue #1129 explains, starting with version 10.1.0,
the GCC compiler enables usage of outline atomics based on LSE instructions
and also adds runtime detection of this optional cpu feature which is handled by
the init function init_have_lse_atomics (part of libgcc.a).
The init_have_lse_atomics calls __getauxval to fetch AT_HWCAP
and checks for presense of HWCAP_ATOMICS flag. The __getauxval
in OSv does not handle __getauxval and shows a warning (getauxval() stubbed).

This patch builds on the code of processor::features_str() and adds new
hwcap32() function that returns 32-bit integer representing relevant CPU
features. This new function is called by __getauxval() for aarch64.

Besides making the annoying warning go away, this patch also makes
OSv take advantage of Armv8.1-A platforms that implement CAS functions
based on LSE instructions.

Fixes #1129

Signed-off-by: Waldemar Kozaczuk <jwkozac...@gmail.com>

---
diff --git a/arch/aarch64/cpuid.cc b/arch/aarch64/cpuid.cc
--- a/arch/aarch64/cpuid.cc
+++ b/arch/aarch64/cpuid.cc
@@ -21,8 +21,16 @@ static const char *hwcap_str[HWCAP_BIT_N] = {
     [HWCAP_BIT_SHA1] = "sha1",
     [HWCAP_BIT_SHA2] = "sha2",
     [HWCAP_BIT_CRC32] = "crc32",
+    [HWCAP_BIT_ATOMIC] = "atomics",
 };
 
+#define IS_FP_SET(PFR)     (!(PFR & (0x0f << 16)))
+#define IS_ASIMD_SET(PFR)  (!(PFR & (0x0f << 20)))
+#define IS_SHA1_SET(ISAR)  (((ISAR >> 8) & 0x0f) == 1)
+#define IS_SHA2_SET(ISAR)  (((ISAR >> 12) & 0x0f) == 1)
+#define IS_CRC32_SET(ISAR) (((ISAR >> 16) & 0x0f) == 1)
+#define IS_ATOMIC_SET(ISAR) (((ISAR >> 20) & 0x0f) == 2)
+
 const std::string& features_str()
 {
     static std::string cpuid_str;
@@ -36,11 +44,11 @@ const std::string& features_str()
     asm volatile ("mrs %0, ID_AA64PFR0_EL1" : "=r"(pfr));
     asm volatile ("mrs %0, ID_AA64ISAR0_EL1" : "=r"(isar));
 
-    if (!(pfr & (0x0f << 16))) {
+    if (IS_FP_SET(pfr)) {
         cpuid_str += std::string(hwcap_str[HWCAP_BIT_FP]) + std::string(" ");
     }
 
-    if (!(pfr & (0x0f << 20))) {
+    if (IS_ASIMD_SET(pfr)) {
         cpuid_str += std::string(hwcap_str[HWCAP_BIT_ASIMD]) + std::string(" 
");
     }
 
@@ -56,18 +64,22 @@ const std::string& features_str()
         ;
     }
 
-    if (((isar >> 8) & 0x0f) == 1) {
+    if (IS_SHA1_SET(isar)) {
         cpuid_str += std::string(hwcap_str[HWCAP_BIT_SHA1]) + std::string(" ");
     }
 
-    if (((isar >> 12) & 0x0f) == 1) {
+    if (IS_SHA2_SET(isar)) {
         cpuid_str += std::string(hwcap_str[HWCAP_BIT_SHA2]) + std::string(" ");
     }
 
-    if (((isar >> 16) & 0x0f) == 1) {
+    if (IS_CRC32_SET(isar)) {
         cpuid_str += std::string(hwcap_str[HWCAP_BIT_CRC32]) + std::string(" 
");
     }
 
+    if (IS_ATOMIC_SET(isar)) {
+        cpuid_str += std::string(hwcap_str[HWCAP_BIT_ATOMIC]) + std::string(" 
");
+    }
+
     // we support of course the AArch64 instruction set. Adding
     // this at the end simplifies things like the .size() check above
     // and avoids ending with a space, while also conveying a more
@@ -77,6 +89,46 @@ const std::string& features_str()
     return cpuid_str;
 }
 
+#define HWCAP_BIT_CPUID 11
+
+const unsigned long hwcap32()
+{
+    static unsigned long hwcap32;
+    if (hwcap32) {
+        return hwcap32;
+    }
+
+    u64 isar; /* Instruction Set Attribute Register 0 */
+    u64 pfr; /* Processor Feature Register 0 */
+
+    asm volatile ("mrs %0, ID_AA64PFR0_EL1" : "=r"(pfr));
+    asm volatile ("mrs %0, ID_AA64ISAR0_EL1" : "=r"(isar));
+
+    hwcap32 |= IS_FP_SET(pfr) << HWCAP_BIT_FP;
+    hwcap32 |= IS_ASIMD_SET(pfr) << HWCAP_BIT_ASIMD;
+
+    unsigned int nibble = (isar >> 4) & 0x0f;
+    switch (nibble) {
+    case 2:
+        hwcap32 |= 1 << HWCAP_BIT_PMULL;
+        /* fallthrough: case 2 also implies case 1. */
+    case 1:
+        hwcap32 |= 1 << HWCAP_BIT_AES;
+        break;
+    default:
+        ;
+    }
+
+    hwcap32 |= IS_SHA1_SET(isar) << HWCAP_BIT_SHA1;
+    hwcap32 |= IS_SHA2_SET(isar) << HWCAP_BIT_SHA2;
+    hwcap32 |= IS_CRC32_SET(isar) << HWCAP_BIT_CRC32;
+    hwcap32 |= IS_ATOMIC_SET(isar) << HWCAP_BIT_ATOMIC;
+
+    hwcap32 |= 1 << HWCAP_BIT_CPUID;
+
+    return hwcap32;
+}
+
 void process_cpuid(features_type& features)
 {
     xen::get_features(features);
diff --git a/arch/aarch64/cpuid.hh b/arch/aarch64/cpuid.hh
--- a/arch/aarch64/cpuid.hh
+++ b/arch/aarch64/cpuid.hh
@@ -13,6 +13,7 @@
 namespace processor {
 
 extern const std::string& features_str();
+extern const unsigned long hwcap32();
 
 /* bit positions would be compatible with Linux hwcap AT_HWCAP */
 enum hwcap_bit {
@@ -24,6 +25,7 @@ enum hwcap_bit {
     HWCAP_BIT_SHA1 = 5,
     HWCAP_BIT_SHA2 = 6,
     HWCAP_BIT_CRC32 = 7,
+    HWCAP_BIT_ATOMIC = 8,
 
     HWCAP_BIT_N
 };
diff --git a/core/elf.cc b/core/elf.cc
--- a/core/elf.cc
+++ b/core/elf.cc
@@ -31,6 +31,7 @@
 
 #include "arch.hh"
 #include "arch-elf.hh"
+#include "cpuid.hh"
 
 #if CONF_debug_elf
 #define elf_debug(format,...) kprintf("ELF [tid:%d, mod:%d, %s]: " format, 
sched::thread::current()->id(), _module_index, _pathname.c_str(), ##__VA_ARGS__)
@@ -1919,6 +1920,10 @@ unsigned long getauxval(unsigned long type)
         return sysconf(_SC_PAGESIZE);
     case AT_CLKTCK:
         return sysconf(_SC_CLK_TCK);
+#ifdef __aarch64__
+    case AT_HWCAP:
+        return processor::hwcap32();
+#endif
 
     // Unimplemented, man page says we should return 0
     case AT_PHDR:
@@ -1928,7 +1933,9 @@ unsigned long getauxval(unsigned long type)
     case AT_ENTRY:
     case AT_EXECFD:
     case AT_EXECFN:
+#ifdef __x86_64__
     case AT_HWCAP:
+#endif
     case AT_ICACHEBSIZE:
     case AT_RANDOM:
     case AT_SECURE:

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/000000000000e91d0305c1febe72%40google.com.

Reply via email to