Path: blob/main/contrib/llvm-project/compiler-rt/lib/builtins/cpu_model/riscv.c
213799 views
//=== cpu_model/riscv.c - Update RISC-V Feature Bits Structure -*- C -*-======//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "cpu_model.h"910#define RISCV_FEATURE_BITS_LENGTH 211struct {12unsigned length;13unsigned long long features[RISCV_FEATURE_BITS_LENGTH];14} __riscv_feature_bits __attribute__((visibility("hidden"), nocommon));1516struct {17unsigned mvendorid;18unsigned long long marchid;19unsigned long long mimpid;20} __riscv_cpu_model __attribute__((visibility("hidden"), nocommon));2122// NOTE: Should sync-up with RISCVFeatures.td23// TODO: Maybe generate a header from tablegen then include it.24#define A_GROUPID 025#define A_BITMASK (1ULL << 0)26#define B_GROUPID 027#define B_BITMASK (1ULL << 1)28#define C_GROUPID 029#define C_BITMASK (1ULL << 2)30#define D_GROUPID 031#define D_BITMASK (1ULL << 3)32#define E_GROUPID 033#define E_BITMASK (1ULL << 4)34#define F_GROUPID 035#define F_BITMASK (1ULL << 5)36#define H_GROUPID 037#define H_BITMASK (1ULL << 7)38#define I_GROUPID 039#define I_BITMASK (1ULL << 8)40#define M_GROUPID 041#define M_BITMASK (1ULL << 12)42#define Q_GROUPID 043#define Q_BITMASK (1ULL << 16)44#define V_GROUPID 045#define V_BITMASK (1ULL << 21)46#define ZACAS_GROUPID 047#define ZACAS_BITMASK (1ULL << 26)48#define ZBA_GROUPID 049#define ZBA_BITMASK (1ULL << 27)50#define ZBB_GROUPID 051#define ZBB_BITMASK (1ULL << 28)52#define ZBC_GROUPID 053#define ZBC_BITMASK (1ULL << 29)54#define ZBKB_GROUPID 055#define ZBKB_BITMASK (1ULL << 30)56#define ZBKC_GROUPID 057#define ZBKC_BITMASK (1ULL << 31)58#define ZBKX_GROUPID 059#define ZBKX_BITMASK (1ULL << 32)60#define ZBS_GROUPID 061#define ZBS_BITMASK (1ULL << 33)62#define ZFA_GROUPID 063#define ZFA_BITMASK (1ULL << 34)64#define ZFH_GROUPID 065#define ZFH_BITMASK (1ULL << 35)66#define ZFHMIN_GROUPID 067#define ZFHMIN_BITMASK (1ULL << 36)68#define ZICBOZ_GROUPID 069#define ZICBOZ_BITMASK (1ULL << 37)70#define ZICOND_GROUPID 071#define ZICOND_BITMASK (1ULL << 38)72#define ZIHINTNTL_GROUPID 073#define ZIHINTNTL_BITMASK (1ULL << 39)74#define ZIHINTPAUSE_GROUPID 075#define ZIHINTPAUSE_BITMASK (1ULL << 40)76#define ZKND_GROUPID 077#define ZKND_BITMASK (1ULL << 41)78#define ZKNE_GROUPID 079#define ZKNE_BITMASK (1ULL << 42)80#define ZKNH_GROUPID 081#define ZKNH_BITMASK (1ULL << 43)82#define ZKSED_GROUPID 083#define ZKSED_BITMASK (1ULL << 44)84#define ZKSH_GROUPID 085#define ZKSH_BITMASK (1ULL << 45)86#define ZKT_GROUPID 087#define ZKT_BITMASK (1ULL << 46)88#define ZTSO_GROUPID 089#define ZTSO_BITMASK (1ULL << 47)90#define ZVBB_GROUPID 091#define ZVBB_BITMASK (1ULL << 48)92#define ZVBC_GROUPID 093#define ZVBC_BITMASK (1ULL << 49)94#define ZVFH_GROUPID 095#define ZVFH_BITMASK (1ULL << 50)96#define ZVFHMIN_GROUPID 097#define ZVFHMIN_BITMASK (1ULL << 51)98#define ZVKB_GROUPID 099#define ZVKB_BITMASK (1ULL << 52)100#define ZVKG_GROUPID 0101#define ZVKG_BITMASK (1ULL << 53)102#define ZVKNED_GROUPID 0103#define ZVKNED_BITMASK (1ULL << 54)104#define ZVKNHA_GROUPID 0105#define ZVKNHA_BITMASK (1ULL << 55)106#define ZVKNHB_GROUPID 0107#define ZVKNHB_BITMASK (1ULL << 56)108#define ZVKSED_GROUPID 0109#define ZVKSED_BITMASK (1ULL << 57)110#define ZVKSH_GROUPID 0111#define ZVKSH_BITMASK (1ULL << 58)112#define ZVKT_GROUPID 0113#define ZVKT_BITMASK (1ULL << 59)114#define ZVE32X_GROUPID 0115#define ZVE32X_BITMASK (1ULL << 60)116#define ZVE32F_GROUPID 0117#define ZVE32F_BITMASK (1ULL << 61)118#define ZVE64X_GROUPID 0119#define ZVE64X_BITMASK (1ULL << 62)120#define ZVE64F_GROUPID 0121#define ZVE64F_BITMASK (1ULL << 63)122#define ZVE64D_GROUPID 1123#define ZVE64D_BITMASK (1ULL << 0)124#define ZIMOP_GROUPID 1125#define ZIMOP_BITMASK (1ULL << 1)126#define ZCA_GROUPID 1127#define ZCA_BITMASK (1ULL << 2)128#define ZCB_GROUPID 1129#define ZCB_BITMASK (1ULL << 3)130#define ZCD_GROUPID 1131#define ZCD_BITMASK (1ULL << 4)132#define ZCF_GROUPID 1133#define ZCF_BITMASK (1ULL << 5)134#define ZCMOP_GROUPID 1135#define ZCMOP_BITMASK (1ULL << 6)136#define ZAWRS_GROUPID 1137#define ZAWRS_BITMASK (1ULL << 7)138#define ZILSD_GROUPID 1139#define ZILSD_BITMASK (1ULL << 8)140#define ZCLSD_GROUPID 1141#define ZCLSD_BITMASK (1ULL << 9)142#define ZCMP_GROUPID 1143#define ZCMP_BITMASK (1ULL << 10)144145#if defined(__linux__)146147// The RISC-V hwprobe interface is documented here:148// <https://docs.kernel.org/arch/riscv/hwprobe.html>.149150static long syscall_impl_5_args(long number, long arg1, long arg2, long arg3,151long arg4, long arg5) {152register long a7 __asm__("a7") = number;153register long a0 __asm__("a0") = arg1;154register long a1 __asm__("a1") = arg2;155register long a2 __asm__("a2") = arg3;156register long a3 __asm__("a3") = arg4;157register long a4 __asm__("a4") = arg5;158__asm__ __volatile__("ecall\n\t"159: "=r"(a0)160: "r"(a7), "r"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4)161: "memory");162return a0;163}164165#define RISCV_HWPROBE_KEY_MVENDORID 0166#define RISCV_HWPROBE_KEY_MARCHID 1167#define RISCV_HWPROBE_KEY_MIMPID 2168#define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3169#define RISCV_HWPROBE_BASE_BEHAVIOR_IMA (1ULL << 0)170#define RISCV_HWPROBE_KEY_IMA_EXT_0 4171#define RISCV_HWPROBE_IMA_FD (1ULL << 0)172#define RISCV_HWPROBE_IMA_C (1ULL << 1)173#define RISCV_HWPROBE_IMA_V (1ULL << 2)174#define RISCV_HWPROBE_EXT_ZBA (1ULL << 3)175#define RISCV_HWPROBE_EXT_ZBB (1ULL << 4)176#define RISCV_HWPROBE_EXT_ZBS (1ULL << 5)177#define RISCV_HWPROBE_EXT_ZICBOZ (1ULL << 6)178#define RISCV_HWPROBE_EXT_ZBC (1ULL << 7)179#define RISCV_HWPROBE_EXT_ZBKB (1ULL << 8)180#define RISCV_HWPROBE_EXT_ZBKC (1ULL << 9)181#define RISCV_HWPROBE_EXT_ZBKX (1ULL << 10)182#define RISCV_HWPROBE_EXT_ZKND (1ULL << 11)183#define RISCV_HWPROBE_EXT_ZKNE (1ULL << 12)184#define RISCV_HWPROBE_EXT_ZKNH (1ULL << 13)185#define RISCV_HWPROBE_EXT_ZKSED (1ULL << 14)186#define RISCV_HWPROBE_EXT_ZKSH (1ULL << 15)187#define RISCV_HWPROBE_EXT_ZKT (1ULL << 16)188#define RISCV_HWPROBE_EXT_ZVBB (1ULL << 17)189#define RISCV_HWPROBE_EXT_ZVBC (1ULL << 18)190#define RISCV_HWPROBE_EXT_ZVKB (1ULL << 19)191#define RISCV_HWPROBE_EXT_ZVKG (1ULL << 20)192#define RISCV_HWPROBE_EXT_ZVKNED (1ULL << 21)193#define RISCV_HWPROBE_EXT_ZVKNHA (1ULL << 22)194#define RISCV_HWPROBE_EXT_ZVKNHB (1ULL << 23)195#define RISCV_HWPROBE_EXT_ZVKSED (1ULL << 24)196#define RISCV_HWPROBE_EXT_ZVKSH (1ULL << 25)197#define RISCV_HWPROBE_EXT_ZVKT (1ULL << 26)198#define RISCV_HWPROBE_EXT_ZFH (1ULL << 27)199#define RISCV_HWPROBE_EXT_ZFHMIN (1ULL << 28)200#define RISCV_HWPROBE_EXT_ZIHINTNTL (1ULL << 29)201#define RISCV_HWPROBE_EXT_ZVFH (1ULL << 30)202#define RISCV_HWPROBE_EXT_ZVFHMIN (1ULL << 31)203#define RISCV_HWPROBE_EXT_ZFA (1ULL << 32)204#define RISCV_HWPROBE_EXT_ZTSO (1ULL << 33)205#define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34)206#define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35)207#define RISCV_HWPROBE_EXT_ZIHINTPAUSE (1ULL << 36)208#define RISCV_HWPROBE_EXT_ZVE32X (1ULL << 37)209#define RISCV_HWPROBE_EXT_ZVE32F (1ULL << 38)210#define RISCV_HWPROBE_EXT_ZVE64X (1ULL << 39)211#define RISCV_HWPROBE_EXT_ZVE64F (1ULL << 40)212#define RISCV_HWPROBE_EXT_ZVE64D (1ULL << 41)213#define RISCV_HWPROBE_EXT_ZIMOP (1ULL << 42)214#define RISCV_HWPROBE_EXT_ZCA (1ULL << 43)215#define RISCV_HWPROBE_EXT_ZCB (1ULL << 44)216#define RISCV_HWPROBE_EXT_ZCD (1ULL << 45)217#define RISCV_HWPROBE_EXT_ZCF (1ULL << 46)218#define RISCV_HWPROBE_EXT_ZCMOP (1ULL << 47)219#define RISCV_HWPROBE_EXT_ZAWRS (1ULL << 48)220#define RISCV_HWPROBE_KEY_CPUPERF_0 5221#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)222#define RISCV_HWPROBE_MISALIGNED_EMULATED (1ULL << 0)223#define RISCV_HWPROBE_MISALIGNED_SLOW (2 << 0)224#define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0)225#define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0)226#define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0)227#define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6228/* Increase RISCV_HWPROBE_MAX_KEY when adding items. */229230struct riscv_hwprobe {231long long key;232unsigned long long value;233};234235#define __NR_riscv_hwprobe 258236static long initHwProbe(struct riscv_hwprobe *Hwprobes, int len) {237return syscall_impl_5_args(__NR_riscv_hwprobe, (long)Hwprobes, len, 0, 0, 0);238}239240#define SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(EXTNAME) \241SET_SINGLE_IMAEXT_RISCV_FEATURE(RISCV_HWPROBE_EXT_##EXTNAME, EXTNAME)242243#define SET_SINGLE_IMAEXT_RISCV_FEATURE(HWPROBE_BITMASK, EXT) \244SET_SINGLE_RISCV_FEATURE(IMAEXT0Value &HWPROBE_BITMASK, EXT)245246#define SET_SINGLE_RISCV_FEATURE(COND, EXT) \247if (COND) { \248SET_RISCV_FEATURE(EXT); \249}250251#define SET_RISCV_FEATURE(EXT) features[EXT##_GROUPID] |= EXT##_BITMASK252253static void initRISCVFeature(struct riscv_hwprobe Hwprobes[]) {254255// Note: If a hwprobe key is unknown to the kernel, its key field256// will be cleared to -1, and its value set to 0.257// This unsets all extension bitmask bits.258259// Init VendorID, ArchID, ImplID260__riscv_cpu_model.mvendorid = Hwprobes[2].value;261__riscv_cpu_model.marchid = Hwprobes[3].value;262__riscv_cpu_model.mimpid = Hwprobes[4].value;263264// Init standard extension265// TODO: Maybe Extension implied generate from tablegen?266267unsigned long long features[RISCV_FEATURE_BITS_LENGTH];268int i;269270for (i = 0; i < RISCV_FEATURE_BITS_LENGTH; i++)271features[i] = 0;272273// Check RISCV_HWPROBE_KEY_BASE_BEHAVIOR274unsigned long long BaseValue = Hwprobes[0].value;275if (BaseValue & RISCV_HWPROBE_BASE_BEHAVIOR_IMA) {276SET_RISCV_FEATURE(I);277SET_RISCV_FEATURE(M);278SET_RISCV_FEATURE(A);279}280281// Check RISCV_HWPROBE_KEY_IMA_EXT_0282unsigned long long IMAEXT0Value = Hwprobes[1].value;283if (IMAEXT0Value & RISCV_HWPROBE_IMA_FD) {284SET_RISCV_FEATURE(F);285SET_RISCV_FEATURE(D);286}287288SET_SINGLE_IMAEXT_RISCV_FEATURE(RISCV_HWPROBE_IMA_C, C);289SET_SINGLE_IMAEXT_RISCV_FEATURE(RISCV_HWPROBE_IMA_V, V);290SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBA);291SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBB);292SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBS);293SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZICBOZ);294SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBC);295SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBKB);296SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBKC);297SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBKX);298SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKND);299SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKNE);300SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKNH);301SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKSED);302SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKSH);303SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKT);304SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVBB);305SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVBC);306SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKB);307SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKG);308SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKNED);309SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKNHA);310SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKNHB);311SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKSED);312SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKSH);313SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKT);314SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZFH);315SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZFHMIN);316SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZIHINTNTL);317SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZIHINTPAUSE);318SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVFH);319SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVFHMIN);320SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZFA);321SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZTSO);322SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZACAS);323SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZICOND);324SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE32X);325SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE32F);326SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE64X);327SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE64F);328SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE64D);329SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZIMOP);330SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCA);331SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCB);332SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCD);333SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCF);334SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCMOP);335SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZAWRS);336337for (i = 0; i < RISCV_FEATURE_BITS_LENGTH; i++)338__riscv_feature_bits.features[i] = features[i];339}340341#endif // defined(__linux__)342343static int FeaturesBitCached = 0;344345void __init_riscv_feature_bits(void *);346static void __init_riscv_feature_bits_ctor(void) CONSTRUCTOR_ATTRIBUTE;347348// A constructor function that sets __riscv_feature_bits349// to the right values. This needs to run only once. This constructor is given350// the highest priority and it should run before constructors without the351// priority set. However, it still runs after ifunc initializers and needs to352// be called explicitly there.353354static void CONSTRUCTOR_ATTRIBUTE __init_riscv_feature_bits_ctor(void) {355__init_riscv_feature_bits(0);356}357358// PlatformArgs allows the platform to provide pre-computed data and access it359// without extra effort. For example, Linux could pass the vDSO object to avoid360// an extra system call.361void __init_riscv_feature_bits(void *PlatformArgs) {362363if (FeaturesBitCached)364return;365366__riscv_feature_bits.length = RISCV_FEATURE_BITS_LENGTH;367368#if defined(__linux__)369struct riscv_hwprobe Hwprobes[] = {370{RISCV_HWPROBE_KEY_BASE_BEHAVIOR, 0}, {RISCV_HWPROBE_KEY_IMA_EXT_0, 0},371{RISCV_HWPROBE_KEY_MVENDORID, 0}, {RISCV_HWPROBE_KEY_MARCHID, 0},372{RISCV_HWPROBE_KEY_MIMPID, 0},373};374if (initHwProbe(Hwprobes, sizeof(Hwprobes) / sizeof(Hwprobes[0])))375return;376377initRISCVFeature(Hwprobes);378#endif // defined(__linux__)379380FeaturesBitCached = 1;381}382383384