1 //===-- RegisterFlagsDetector_arm64.cpp -----------------------------------===// 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "RegisterFlagsDetector_arm64.h" 10 #include "lldb/lldb-private-types.h" 11 12 // This file is built on all systems because it is used by native processes and 13 // core files, so we manually define the needed HWCAP values here. 14 // These values are the same for Linux and FreeBSD. 15 16 #define HWCAP_FPHP (1ULL << 9) 17 #define HWCAP_ASIMDHP (1ULL << 10) 18 #define HWCAP_DIT (1ULL << 24) 19 #define HWCAP_SSBS (1ULL << 28) 20 #define HWCAP_GCS (1ULL << 32) 21 22 #define HWCAP2_BTI (1ULL << 17) 23 #define HWCAP2_MTE (1ULL << 18) 24 #define HWCAP2_AFP (1ULL << 20) 25 #define HWCAP2_SME (1ULL << 23) 26 #define HWCAP2_EBF16 (1ULL << 32) 27 #define HWCAP2_FPMR (1ULL << 48) 28 29 using namespace lldb_private; 30 31 Arm64RegisterFlagsDetector::Fields 32 Arm64RegisterFlagsDetector::DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2) { 33 (void)hwcap; 34 35 if (!(hwcap2 & HWCAP2_FPMR)) 36 return {}; 37 38 static const FieldEnum fp8_format_enum("fp8_format_enum", { 39 {0, "FP8_E5M2"}, 40 {1, "FP8_E4M3"}, 41 }); 42 return { 43 {"LSCALE2", 32, 37}, 44 {"NSCALE", 24, 31}, 45 {"LSCALE", 16, 22}, 46 {"OSC", 15}, 47 {"OSM", 14}, 48 {"F8D", 6, 8, &fp8_format_enum}, 49 {"F8S2", 3, 5, &fp8_format_enum}, 50 {"F8S1", 0, 2, &fp8_format_enum}, 51 }; 52 } 53 54 Arm64RegisterFlagsDetector::Fields 55 Arm64RegisterFlagsDetector::DetectGCSFeatureFields(uint64_t hwcap, 56 uint64_t hwcap2) { 57 (void)hwcap2; 58 59 if (!(hwcap & HWCAP_GCS)) 60 return {}; 61 62 return { 63 {"PUSH", 2}, 64 {"WRITE", 1}, 65 {"ENABLE", 0}, 66 }; 67 } 68 69 Arm64RegisterFlagsDetector::Fields 70 Arm64RegisterFlagsDetector::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) { 71 (void)hwcap; 72 73 if (!(hwcap2 & HWCAP2_SME)) 74 return {}; 75 76 // Represents the pseudo register that lldb-server builds, which itself 77 // matches the architectural register SCVR. The fields match SVCR in the Arm 78 // manual. 79 return { 80 {"ZA", 1}, 81 {"SM", 0}, 82 }; 83 } 84 85 Arm64RegisterFlagsDetector::Fields 86 Arm64RegisterFlagsDetector::DetectMTECtrlFields(uint64_t hwcap, 87 uint64_t hwcap2) { 88 (void)hwcap; 89 90 if (!(hwcap2 & HWCAP2_MTE)) 91 return {}; 92 93 // Represents the contents of NT_ARM_TAGGED_ADDR_CTRL and the value passed 94 // to prctl(PR_TAGGED_ADDR_CTRL...). Fields are derived from the defines 95 // used to build the value. 96 97 static const FieldEnum tcf_enum( 98 "tcf_enum", 99 {{0, "TCF_NONE"}, {1, "TCF_SYNC"}, {2, "TCF_ASYNC"}, {3, "TCF_ASYMM"}}); 100 return {{"TAGS", 3, 18}, // 16 bit bitfield shifted up by PR_MTE_TAG_SHIFT. 101 {"TCF", 1, 2, &tcf_enum}, 102 {"TAGGED_ADDR_ENABLE", 0}}; 103 } 104 105 Arm64RegisterFlagsDetector::Fields 106 Arm64RegisterFlagsDetector::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2) { 107 static const FieldEnum rmode_enum( 108 "rmode_enum", {{0, "RN"}, {1, "RP"}, {2, "RM"}, {3, "RZ"}}); 109 110 std::vector<RegisterFlags::Field> fpcr_fields{ 111 {"AHP", 26}, {"DN", 25}, {"FZ", 24}, {"RMode", 22, 23, &rmode_enum}, 112 // Bits 21-20 are "Stride" which is unused in AArch64 state. 113 }; 114 115 // FEAT_FP16 is indicated by the presence of FPHP (floating point half 116 // precision) and ASIMDHP (Advanced SIMD half precision) features. 117 if ((hwcap & HWCAP_FPHP) && (hwcap & HWCAP_ASIMDHP)) 118 fpcr_fields.push_back({"FZ16", 19}); 119 120 // Bits 18-16 are "Len" which is unused in AArch64 state. 121 122 fpcr_fields.push_back({"IDE", 15}); 123 124 // Bit 14 is unused. 125 if (hwcap2 & HWCAP2_EBF16) 126 fpcr_fields.push_back({"EBF", 13}); 127 128 fpcr_fields.push_back({"IXE", 12}); 129 fpcr_fields.push_back({"UFE", 11}); 130 fpcr_fields.push_back({"OFE", 10}); 131 fpcr_fields.push_back({"DZE", 9}); 132 fpcr_fields.push_back({"IOE", 8}); 133 // Bits 7-3 reserved. 134 135 if (hwcap2 & HWCAP2_AFP) { 136 fpcr_fields.push_back({"NEP", 2}); 137 fpcr_fields.push_back({"AH", 1}); 138 fpcr_fields.push_back({"FIZ", 0}); 139 } 140 141 return fpcr_fields; 142 } 143 144 Arm64RegisterFlagsDetector::Fields 145 Arm64RegisterFlagsDetector::DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2) { 146 // fpsr's contents are constant. 147 (void)hwcap; 148 (void)hwcap2; 149 150 return { 151 // Bits 31-28 are N/Z/C/V, only used by AArch32. 152 {"QC", 27}, 153 // Bits 26-8 reserved. 154 {"IDC", 7}, 155 // Bits 6-5 reserved. 156 {"IXC", 4}, 157 {"UFC", 3}, 158 {"OFC", 2}, 159 {"DZC", 1}, 160 {"IOC", 0}, 161 }; 162 } 163 164 Arm64RegisterFlagsDetector::Fields 165 Arm64RegisterFlagsDetector::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2) { 166 // The fields here are a combination of the Arm manual's SPSR_EL1, 167 // plus a few changes where Linux has decided not to make use of them at all, 168 // or at least not from userspace. 169 170 // Status bits that are always present. 171 std::vector<RegisterFlags::Field> cpsr_fields{ 172 {"N", 31}, {"Z", 30}, {"C", 29}, {"V", 28}, 173 // Bits 27-26 reserved. 174 }; 175 176 if (hwcap2 & HWCAP2_MTE) 177 cpsr_fields.push_back({"TCO", 25}); 178 if (hwcap & HWCAP_DIT) 179 cpsr_fields.push_back({"DIT", 24}); 180 181 // UAO and PAN are bits 23 and 22 and have no meaning for userspace so 182 // are treated as reserved by the kernels. 183 184 cpsr_fields.push_back({"SS", 21}); 185 cpsr_fields.push_back({"IL", 20}); 186 // Bits 19-14 reserved. 187 188 // Bit 13, ALLINT, requires FEAT_NMI that isn't relevant to userspace, and we 189 // can't detect either, don't show this field. 190 if (hwcap & HWCAP_SSBS) 191 cpsr_fields.push_back({"SSBS", 12}); 192 if (hwcap2 & HWCAP2_BTI) 193 cpsr_fields.push_back({"BTYPE", 10, 11}); 194 195 cpsr_fields.push_back({"D", 9}); 196 cpsr_fields.push_back({"A", 8}); 197 cpsr_fields.push_back({"I", 7}); 198 cpsr_fields.push_back({"F", 6}); 199 // Bit 5 reserved 200 // Called "M" in the ARMARM. 201 cpsr_fields.push_back({"nRW", 4}); 202 // This is a 4 bit field M[3:0] in the ARMARM, we split it into parts. 203 cpsr_fields.push_back({"EL", 2, 3}); 204 // Bit 1 is unused and expected to be 0. 205 cpsr_fields.push_back({"SP", 0}); 206 207 return cpsr_fields; 208 } 209 210 void Arm64RegisterFlagsDetector::DetectFields(uint64_t hwcap, uint64_t hwcap2) { 211 for (auto ® : m_registers) 212 reg.m_flags.SetFields(reg.m_detector(hwcap, hwcap2)); 213 m_has_detected = true; 214 } 215 216 void Arm64RegisterFlagsDetector::UpdateRegisterInfo( 217 const RegisterInfo *reg_info, uint32_t num_regs) { 218 assert(m_has_detected && 219 "Must call DetectFields before updating register info."); 220 221 // Register names will not be duplicated, so we do not want to compare against 222 // one if it has already been found. Each time we find one, we erase it from 223 // this list. 224 std::vector<std::pair<llvm::StringRef, const RegisterFlags *>> 225 search_registers; 226 for (const auto ® : m_registers) { 227 // It is possible that a register is all extension dependent fields, and 228 // none of them are present. 229 if (reg.m_flags.GetFields().size()) 230 search_registers.push_back({reg.m_name, ®.m_flags}); 231 } 232 233 // Walk register information while there are registers we know need 234 // to be updated. Example: 235 // Register information: [a, b, c, d] 236 // To be patched: [b, c] 237 // * a != b, a != c, do nothing and move on. 238 // * b == b, patch b, new patch list is [c], move on. 239 // * c == c, patch c, patch list is empty, exit early without looking at d. 240 for (uint32_t idx = 0; idx < num_regs && search_registers.size(); 241 ++idx, ++reg_info) { 242 auto reg_it = std::find_if( 243 search_registers.cbegin(), search_registers.cend(), 244 [reg_info](auto reg) { return reg.first == reg_info->name; }); 245 246 if (reg_it != search_registers.end()) { 247 // Attach the field information. 248 reg_info->flags_type = reg_it->second; 249 // We do not expect to see this name again so don't look for it again. 250 search_registers.erase(reg_it); 251 } 252 } 253 254 // We do not assert that search_registers is empty here, because it may 255 // contain registers from optional extensions that are not present on the 256 // current target. 257 } 258