383 lines · c
1//=== cpu_model/riscv.c - Update RISC-V Feature Bits Structure -*- C -*-======//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "cpu_model.h"10 11#define RISCV_FEATURE_BITS_LENGTH 212struct {13 unsigned length;14 unsigned long long features[RISCV_FEATURE_BITS_LENGTH];15} __riscv_feature_bits __attribute__((visibility("hidden"), nocommon));16 17struct {18 unsigned mvendorid;19 unsigned long long marchid;20 unsigned long long mimpid;21} __riscv_cpu_model __attribute__((visibility("hidden"), nocommon));22 23// NOTE: Should sync-up with RISCVFeatures.td24// TODO: Maybe generate a header from tablegen then include it.25#define A_GROUPID 026#define A_BITMASK (1ULL << 0)27#define B_GROUPID 028#define B_BITMASK (1ULL << 1)29#define C_GROUPID 030#define C_BITMASK (1ULL << 2)31#define D_GROUPID 032#define D_BITMASK (1ULL << 3)33#define E_GROUPID 034#define E_BITMASK (1ULL << 4)35#define F_GROUPID 036#define F_BITMASK (1ULL << 5)37#define H_GROUPID 038#define H_BITMASK (1ULL << 7)39#define I_GROUPID 040#define I_BITMASK (1ULL << 8)41#define M_GROUPID 042#define M_BITMASK (1ULL << 12)43#define Q_GROUPID 044#define Q_BITMASK (1ULL << 16)45#define V_GROUPID 046#define V_BITMASK (1ULL << 21)47#define ZACAS_GROUPID 048#define ZACAS_BITMASK (1ULL << 26)49#define ZBA_GROUPID 050#define ZBA_BITMASK (1ULL << 27)51#define ZBB_GROUPID 052#define ZBB_BITMASK (1ULL << 28)53#define ZBC_GROUPID 054#define ZBC_BITMASK (1ULL << 29)55#define ZBKB_GROUPID 056#define ZBKB_BITMASK (1ULL << 30)57#define ZBKC_GROUPID 058#define ZBKC_BITMASK (1ULL << 31)59#define ZBKX_GROUPID 060#define ZBKX_BITMASK (1ULL << 32)61#define ZBS_GROUPID 062#define ZBS_BITMASK (1ULL << 33)63#define ZFA_GROUPID 064#define ZFA_BITMASK (1ULL << 34)65#define ZFH_GROUPID 066#define ZFH_BITMASK (1ULL << 35)67#define ZFHMIN_GROUPID 068#define ZFHMIN_BITMASK (1ULL << 36)69#define ZICBOZ_GROUPID 070#define ZICBOZ_BITMASK (1ULL << 37)71#define ZICOND_GROUPID 072#define ZICOND_BITMASK (1ULL << 38)73#define ZIHINTNTL_GROUPID 074#define ZIHINTNTL_BITMASK (1ULL << 39)75#define ZIHINTPAUSE_GROUPID 076#define ZIHINTPAUSE_BITMASK (1ULL << 40)77#define ZKND_GROUPID 078#define ZKND_BITMASK (1ULL << 41)79#define ZKNE_GROUPID 080#define ZKNE_BITMASK (1ULL << 42)81#define ZKNH_GROUPID 082#define ZKNH_BITMASK (1ULL << 43)83#define ZKSED_GROUPID 084#define ZKSED_BITMASK (1ULL << 44)85#define ZKSH_GROUPID 086#define ZKSH_BITMASK (1ULL << 45)87#define ZKT_GROUPID 088#define ZKT_BITMASK (1ULL << 46)89#define ZTSO_GROUPID 090#define ZTSO_BITMASK (1ULL << 47)91#define ZVBB_GROUPID 092#define ZVBB_BITMASK (1ULL << 48)93#define ZVBC_GROUPID 094#define ZVBC_BITMASK (1ULL << 49)95#define ZVFH_GROUPID 096#define ZVFH_BITMASK (1ULL << 50)97#define ZVFHMIN_GROUPID 098#define ZVFHMIN_BITMASK (1ULL << 51)99#define ZVKB_GROUPID 0100#define ZVKB_BITMASK (1ULL << 52)101#define ZVKG_GROUPID 0102#define ZVKG_BITMASK (1ULL << 53)103#define ZVKNED_GROUPID 0104#define ZVKNED_BITMASK (1ULL << 54)105#define ZVKNHA_GROUPID 0106#define ZVKNHA_BITMASK (1ULL << 55)107#define ZVKNHB_GROUPID 0108#define ZVKNHB_BITMASK (1ULL << 56)109#define ZVKSED_GROUPID 0110#define ZVKSED_BITMASK (1ULL << 57)111#define ZVKSH_GROUPID 0112#define ZVKSH_BITMASK (1ULL << 58)113#define ZVKT_GROUPID 0114#define ZVKT_BITMASK (1ULL << 59)115#define ZVE32X_GROUPID 0116#define ZVE32X_BITMASK (1ULL << 60)117#define ZVE32F_GROUPID 0118#define ZVE32F_BITMASK (1ULL << 61)119#define ZVE64X_GROUPID 0120#define ZVE64X_BITMASK (1ULL << 62)121#define ZVE64F_GROUPID 0122#define ZVE64F_BITMASK (1ULL << 63)123#define ZVE64D_GROUPID 1124#define ZVE64D_BITMASK (1ULL << 0)125#define ZIMOP_GROUPID 1126#define ZIMOP_BITMASK (1ULL << 1)127#define ZCA_GROUPID 1128#define ZCA_BITMASK (1ULL << 2)129#define ZCB_GROUPID 1130#define ZCB_BITMASK (1ULL << 3)131#define ZCD_GROUPID 1132#define ZCD_BITMASK (1ULL << 4)133#define ZCF_GROUPID 1134#define ZCF_BITMASK (1ULL << 5)135#define ZCMOP_GROUPID 1136#define ZCMOP_BITMASK (1ULL << 6)137#define ZAWRS_GROUPID 1138#define ZAWRS_BITMASK (1ULL << 7)139#define ZILSD_GROUPID 1140#define ZILSD_BITMASK (1ULL << 8)141#define ZCLSD_GROUPID 1142#define ZCLSD_BITMASK (1ULL << 9)143#define ZCMP_GROUPID 1144#define ZCMP_BITMASK (1ULL << 10)145 146#if defined(__linux__)147 148// The RISC-V hwprobe interface is documented here:149// <https://docs.kernel.org/arch/riscv/hwprobe.html>.150 151static long syscall_impl_5_args(long number, long arg1, long arg2, long arg3,152 long arg4, long arg5) {153 register long a7 __asm__("a7") = number;154 register long a0 __asm__("a0") = arg1;155 register long a1 __asm__("a1") = arg2;156 register long a2 __asm__("a2") = arg3;157 register long a3 __asm__("a3") = arg4;158 register long a4 __asm__("a4") = arg5;159 __asm__ __volatile__("ecall\n\t"160 : "=r"(a0)161 : "r"(a7), "r"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4)162 : "memory");163 return a0;164}165 166#define RISCV_HWPROBE_KEY_MVENDORID 0167#define RISCV_HWPROBE_KEY_MARCHID 1168#define RISCV_HWPROBE_KEY_MIMPID 2169#define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3170#define RISCV_HWPROBE_BASE_BEHAVIOR_IMA (1ULL << 0)171#define RISCV_HWPROBE_KEY_IMA_EXT_0 4172#define RISCV_HWPROBE_IMA_FD (1ULL << 0)173#define RISCV_HWPROBE_IMA_C (1ULL << 1)174#define RISCV_HWPROBE_IMA_V (1ULL << 2)175#define RISCV_HWPROBE_EXT_ZBA (1ULL << 3)176#define RISCV_HWPROBE_EXT_ZBB (1ULL << 4)177#define RISCV_HWPROBE_EXT_ZBS (1ULL << 5)178#define RISCV_HWPROBE_EXT_ZICBOZ (1ULL << 6)179#define RISCV_HWPROBE_EXT_ZBC (1ULL << 7)180#define RISCV_HWPROBE_EXT_ZBKB (1ULL << 8)181#define RISCV_HWPROBE_EXT_ZBKC (1ULL << 9)182#define RISCV_HWPROBE_EXT_ZBKX (1ULL << 10)183#define RISCV_HWPROBE_EXT_ZKND (1ULL << 11)184#define RISCV_HWPROBE_EXT_ZKNE (1ULL << 12)185#define RISCV_HWPROBE_EXT_ZKNH (1ULL << 13)186#define RISCV_HWPROBE_EXT_ZKSED (1ULL << 14)187#define RISCV_HWPROBE_EXT_ZKSH (1ULL << 15)188#define RISCV_HWPROBE_EXT_ZKT (1ULL << 16)189#define RISCV_HWPROBE_EXT_ZVBB (1ULL << 17)190#define RISCV_HWPROBE_EXT_ZVBC (1ULL << 18)191#define RISCV_HWPROBE_EXT_ZVKB (1ULL << 19)192#define RISCV_HWPROBE_EXT_ZVKG (1ULL << 20)193#define RISCV_HWPROBE_EXT_ZVKNED (1ULL << 21)194#define RISCV_HWPROBE_EXT_ZVKNHA (1ULL << 22)195#define RISCV_HWPROBE_EXT_ZVKNHB (1ULL << 23)196#define RISCV_HWPROBE_EXT_ZVKSED (1ULL << 24)197#define RISCV_HWPROBE_EXT_ZVKSH (1ULL << 25)198#define RISCV_HWPROBE_EXT_ZVKT (1ULL << 26)199#define RISCV_HWPROBE_EXT_ZFH (1ULL << 27)200#define RISCV_HWPROBE_EXT_ZFHMIN (1ULL << 28)201#define RISCV_HWPROBE_EXT_ZIHINTNTL (1ULL << 29)202#define RISCV_HWPROBE_EXT_ZVFH (1ULL << 30)203#define RISCV_HWPROBE_EXT_ZVFHMIN (1ULL << 31)204#define RISCV_HWPROBE_EXT_ZFA (1ULL << 32)205#define RISCV_HWPROBE_EXT_ZTSO (1ULL << 33)206#define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34)207#define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35)208#define RISCV_HWPROBE_EXT_ZIHINTPAUSE (1ULL << 36)209#define RISCV_HWPROBE_EXT_ZVE32X (1ULL << 37)210#define RISCV_HWPROBE_EXT_ZVE32F (1ULL << 38)211#define RISCV_HWPROBE_EXT_ZVE64X (1ULL << 39)212#define RISCV_HWPROBE_EXT_ZVE64F (1ULL << 40)213#define RISCV_HWPROBE_EXT_ZVE64D (1ULL << 41)214#define RISCV_HWPROBE_EXT_ZIMOP (1ULL << 42)215#define RISCV_HWPROBE_EXT_ZCA (1ULL << 43)216#define RISCV_HWPROBE_EXT_ZCB (1ULL << 44)217#define RISCV_HWPROBE_EXT_ZCD (1ULL << 45)218#define RISCV_HWPROBE_EXT_ZCF (1ULL << 46)219#define RISCV_HWPROBE_EXT_ZCMOP (1ULL << 47)220#define RISCV_HWPROBE_EXT_ZAWRS (1ULL << 48)221#define RISCV_HWPROBE_KEY_CPUPERF_0 5222#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)223#define RISCV_HWPROBE_MISALIGNED_EMULATED (1ULL << 0)224#define RISCV_HWPROBE_MISALIGNED_SLOW (2 << 0)225#define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0)226#define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0)227#define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0)228#define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6229/* Increase RISCV_HWPROBE_MAX_KEY when adding items. */230 231struct riscv_hwprobe {232 long long key;233 unsigned long long value;234};235 236#define __NR_riscv_hwprobe 258237static long initHwProbe(struct riscv_hwprobe *Hwprobes, int len) {238 return syscall_impl_5_args(__NR_riscv_hwprobe, (long)Hwprobes, len, 0, 0, 0);239}240 241#define SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(EXTNAME) \242 SET_SINGLE_IMAEXT_RISCV_FEATURE(RISCV_HWPROBE_EXT_##EXTNAME, EXTNAME)243 244#define SET_SINGLE_IMAEXT_RISCV_FEATURE(HWPROBE_BITMASK, EXT) \245 SET_SINGLE_RISCV_FEATURE(IMAEXT0Value &HWPROBE_BITMASK, EXT)246 247#define SET_SINGLE_RISCV_FEATURE(COND, EXT) \248 if (COND) { \249 SET_RISCV_FEATURE(EXT); \250 }251 252#define SET_RISCV_FEATURE(EXT) features[EXT##_GROUPID] |= EXT##_BITMASK253 254static void initRISCVFeature(struct riscv_hwprobe Hwprobes[]) {255 256 // Note: If a hwprobe key is unknown to the kernel, its key field257 // will be cleared to -1, and its value set to 0.258 // This unsets all extension bitmask bits.259 260 // Init VendorID, ArchID, ImplID261 __riscv_cpu_model.mvendorid = Hwprobes[2].value;262 __riscv_cpu_model.marchid = Hwprobes[3].value;263 __riscv_cpu_model.mimpid = Hwprobes[4].value;264 265 // Init standard extension266 // TODO: Maybe Extension implied generate from tablegen?267 268 unsigned long long features[RISCV_FEATURE_BITS_LENGTH];269 int i;270 271 for (i = 0; i < RISCV_FEATURE_BITS_LENGTH; i++)272 features[i] = 0;273 274 // Check RISCV_HWPROBE_KEY_BASE_BEHAVIOR275 unsigned long long BaseValue = Hwprobes[0].value;276 if (BaseValue & RISCV_HWPROBE_BASE_BEHAVIOR_IMA) {277 SET_RISCV_FEATURE(I);278 SET_RISCV_FEATURE(M);279 SET_RISCV_FEATURE(A);280 }281 282 // Check RISCV_HWPROBE_KEY_IMA_EXT_0283 unsigned long long IMAEXT0Value = Hwprobes[1].value;284 if (IMAEXT0Value & RISCV_HWPROBE_IMA_FD) {285 SET_RISCV_FEATURE(F);286 SET_RISCV_FEATURE(D);287 }288 289 SET_SINGLE_IMAEXT_RISCV_FEATURE(RISCV_HWPROBE_IMA_C, C);290 SET_SINGLE_IMAEXT_RISCV_FEATURE(RISCV_HWPROBE_IMA_V, V);291 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBA);292 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBB);293 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBS);294 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZICBOZ);295 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBC);296 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBKB);297 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBKC);298 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBKX);299 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKND);300 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKNE);301 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKNH);302 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKSED);303 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKSH);304 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKT);305 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVBB);306 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVBC);307 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKB);308 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKG);309 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKNED);310 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKNHA);311 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKNHB);312 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKSED);313 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKSH);314 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKT);315 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZFH);316 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZFHMIN);317 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZIHINTNTL);318 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZIHINTPAUSE);319 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVFH);320 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVFHMIN);321 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZFA);322 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZTSO);323 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZACAS);324 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZICOND);325 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE32X);326 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE32F);327 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE64X);328 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE64F);329 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE64D);330 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZIMOP);331 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCA);332 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCB);333 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCD);334 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCF);335 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCMOP);336 SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZAWRS);337 338 for (i = 0; i < RISCV_FEATURE_BITS_LENGTH; i++)339 __riscv_feature_bits.features[i] = features[i];340}341 342#endif // defined(__linux__)343 344static int FeaturesBitCached = 0;345 346void __init_riscv_feature_bits(void *);347static void __init_riscv_feature_bits_ctor(void) CONSTRUCTOR_ATTRIBUTE;348 349// A constructor function that sets __riscv_feature_bits350// to the right values. This needs to run only once. This constructor is given351// the highest priority and it should run before constructors without the352// priority set. However, it still runs after ifunc initializers and needs to353// be called explicitly there.354 355static void CONSTRUCTOR_ATTRIBUTE __init_riscv_feature_bits_ctor(void) {356 __init_riscv_feature_bits(0);357}358 359// PlatformArgs allows the platform to provide pre-computed data and access it360// without extra effort. For example, Linux could pass the vDSO object to avoid361// an extra system call.362void __init_riscv_feature_bits(void *PlatformArgs) {363 364 if (FeaturesBitCached)365 return;366 367 __riscv_feature_bits.length = RISCV_FEATURE_BITS_LENGTH;368 369#if defined(__linux__)370 struct riscv_hwprobe Hwprobes[] = {371 {RISCV_HWPROBE_KEY_BASE_BEHAVIOR, 0}, {RISCV_HWPROBE_KEY_IMA_EXT_0, 0},372 {RISCV_HWPROBE_KEY_MVENDORID, 0}, {RISCV_HWPROBE_KEY_MARCHID, 0},373 {RISCV_HWPROBE_KEY_MIMPID, 0},374 };375 if (initHwProbe(Hwprobes, sizeof(Hwprobes) / sizeof(Hwprobes[0])))376 return;377 378 initRISCVFeature(Hwprobes);379#endif // defined(__linux__)380 381 FeaturesBitCached = 1;382}383