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 &reg : 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 &reg : 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, &reg.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 }