1 /*
  2  * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved.
  3  * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved.
  4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  5  *
  6  * This code is free software; you can redistribute it and/or modify it
  7  * under the terms of the GNU General Public License version 2 only, as
  8  * published by the Free Software Foundation.
  9  *
 10  * This code is distributed in the hope that it will be useful, but WITHOUT
 11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 13  * version 2 for more details (a copy is included in the LICENSE file that
 14  * accompanied this code).
 15  *
 16  * You should have received a copy of the GNU General Public License version
 17  * 2 along with this work; if not, write to the Free Software Foundation,
 18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 19  *
 20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 21  * or visit www.oracle.com if you need additional information or have any
 22  * questions.
 23  *
 24  */
 25 
 26 #include "precompiled.hpp"
 27 #include "asm/register.hpp"
 28 #include "runtime/os.hpp"
 29 #include "runtime/os.inline.hpp"
 30 #include "runtime/vm_version.hpp"
 31 
 32 #include <asm/hwcap.h>
 33 #include <sys/auxv.h>
 34 
 35 #ifndef HWCAP_ISA_I
 36 #define HWCAP_ISA_I  (1 << ('I' - 'A'))
 37 #endif
 38 
 39 #ifndef HWCAP_ISA_M
 40 #define HWCAP_ISA_M  (1 << ('M' - 'A'))
 41 #endif
 42 
 43 #ifndef HWCAP_ISA_A
 44 #define HWCAP_ISA_A  (1 << ('A' - 'A'))
 45 #endif
 46 
 47 #ifndef HWCAP_ISA_F
 48 #define HWCAP_ISA_F  (1 << ('F' - 'A'))
 49 #endif
 50 
 51 #ifndef HWCAP_ISA_D
 52 #define HWCAP_ISA_D  (1 << ('D' - 'A'))
 53 #endif
 54 
 55 #ifndef HWCAP_ISA_C
 56 #define HWCAP_ISA_C  (1 << ('C' - 'A'))
 57 #endif
 58 
 59 #ifndef HWCAP_ISA_V
 60 #define HWCAP_ISA_V  (1 << ('V' - 'A'))
 61 #endif
 62 
 63 #define read_csr(csr)                                           \
 64 ({                                                              \
 65         register unsigned long __v;                             \
 66         __asm__ __volatile__ ("csrr %0, %1"                     \
 67                               : "=r" (__v)                      \
 68                               : "i" (csr)                       \
 69                               : "memory");                      \
 70         __v;                                                    \
 71 })
 72 
 73 uint32_t VM_Version::get_current_vector_length() {
 74   assert(_features & CPU_V, "should not call this");
 75   return (uint32_t)read_csr(CSR_VLENB);
 76 }
 77 
 78 void VM_Version::get_os_cpu_info() {
 79 
 80   uint64_t auxv = getauxval(AT_HWCAP);
 81 
 82   static_assert(CPU_I == HWCAP_ISA_I, "Flag CPU_I must follow Linux HWCAP");
 83   static_assert(CPU_M == HWCAP_ISA_M, "Flag CPU_M must follow Linux HWCAP");
 84   static_assert(CPU_A == HWCAP_ISA_A, "Flag CPU_A must follow Linux HWCAP");
 85   static_assert(CPU_F == HWCAP_ISA_F, "Flag CPU_F must follow Linux HWCAP");
 86   static_assert(CPU_D == HWCAP_ISA_D, "Flag CPU_D must follow Linux HWCAP");
 87   static_assert(CPU_C == HWCAP_ISA_C, "Flag CPU_C must follow Linux HWCAP");
 88   static_assert(CPU_V == HWCAP_ISA_V, "Flag CPU_V must follow Linux HWCAP");
 89 
 90   // RISC-V has four bit-manipulation ISA-extensions: Zba/Zbb/Zbc/Zbs.
 91   // Availability for those extensions could not be queried from HWCAP.
 92   // TODO: Add proper detection for those extensions.
 93   _features = auxv & (
 94       HWCAP_ISA_I |
 95       HWCAP_ISA_M |
 96       HWCAP_ISA_A |
 97       HWCAP_ISA_F |
 98       HWCAP_ISA_D |
 99       HWCAP_ISA_C |
100       HWCAP_ISA_V);
101 
102   if (FILE *f = fopen("/proc/cpuinfo", "r")) {
103     char buf[512], *p;
104     while (fgets(buf, sizeof (buf), f) != NULL) {
105       if ((p = strchr(buf, ':')) != NULL) {
106         if (strncmp(buf, "uarch", sizeof "uarch" - 1) == 0) {
107           char* uarch = os::strdup(p + 2);
108           uarch[strcspn(uarch, "\n")] = '\0';
109           _uarch = uarch;
110           break;
111         }
112       }
113     }
114     fclose(f);
115   }
116 }