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