[RISCV] Add RVVConstraint to SiFive custom matrix multiply instructions. (#124055)
[llvm-project.git] / lldb / source / Plugins / Process / elf-core / RegisterContextPOSIXCore_arm64.cpp
blob2ddf8440aeb035274b9a5a327d48935e121d52f5
1 //===-- RegisterContextPOSIXCore_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 //===----------------------------------------------------------------------===//
9 #include "RegisterContextPOSIXCore_arm64.h"
10 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
12 #include "Plugins/Process/Utility/AuxVector.h"
13 #include "Plugins/Process/Utility/RegisterFlagsDetector_arm64.h"
14 #include "Plugins/Process/elf-core/ProcessElfCore.h"
15 #include "Plugins/Process/elf-core/RegisterUtilities.h"
16 #include "lldb/Target/Thread.h"
17 #include "lldb/Utility/RegisterValue.h"
19 #include <memory>
21 using namespace lldb_private;
23 std::unique_ptr<RegisterContextCorePOSIX_arm64>
24 RegisterContextCorePOSIX_arm64::Create(Thread &thread, const ArchSpec &arch,
25 const DataExtractor &gpregset,
26 llvm::ArrayRef<CoreNote> notes) {
27 Flags opt_regsets = RegisterInfoPOSIX_arm64::eRegsetMaskDefault;
29 DataExtractor ssve_data =
30 getRegset(notes, arch.GetTriple(), AARCH64_SSVE_Desc);
31 if (ssve_data.GetByteSize() >= sizeof(sve::user_sve_header))
32 opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSSVE);
34 DataExtractor sve_data = getRegset(notes, arch.GetTriple(), AARCH64_SVE_Desc);
35 if (sve_data.GetByteSize() >= sizeof(sve::user_sve_header))
36 opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE);
38 // Pointer Authentication register set data is based on struct
39 // user_pac_mask declared in ptrace.h. See reference implementation
40 // in Linux kernel source at arch/arm64/include/uapi/asm/ptrace.h.
41 DataExtractor pac_data = getRegset(notes, arch.GetTriple(), AARCH64_PAC_Desc);
42 if (pac_data.GetByteSize() >= sizeof(uint64_t) * 2)
43 opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskPAuth);
45 DataExtractor tls_data = getRegset(notes, arch.GetTriple(), AARCH64_TLS_Desc);
46 // A valid note will always contain at least one register, "tpidr". It may
47 // expand in future.
48 if (tls_data.GetByteSize() >= sizeof(uint64_t))
49 opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskTLS);
51 DataExtractor za_data = getRegset(notes, arch.GetTriple(), AARCH64_ZA_Desc);
52 // Nothing if ZA is not present, just the header if it is disabled.
53 if (za_data.GetByteSize() >= sizeof(sve::user_za_header))
54 opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskZA);
56 DataExtractor mte_data = getRegset(notes, arch.GetTriple(), AARCH64_MTE_Desc);
57 if (mte_data.GetByteSize() >= sizeof(uint64_t))
58 opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskMTE);
60 DataExtractor zt_data = getRegset(notes, arch.GetTriple(), AARCH64_ZT_Desc);
61 // Although ZT0 can be in a disabled state like ZA can, the kernel reports
62 // its content as 0s in that state. Therefore even a disabled ZT0 will have
63 // a note containing those 0s. ZT0 is a 512 bit / 64 byte register.
64 if (zt_data.GetByteSize() >= 64)
65 opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskZT);
67 DataExtractor fpmr_data =
68 getRegset(notes, arch.GetTriple(), AARCH64_FPMR_Desc);
69 if (fpmr_data.GetByteSize() >= sizeof(uint64_t))
70 opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskFPMR);
72 auto register_info_up =
73 std::make_unique<RegisterInfoPOSIX_arm64>(arch, opt_regsets);
74 return std::unique_ptr<RegisterContextCorePOSIX_arm64>(
75 new RegisterContextCorePOSIX_arm64(thread, std::move(register_info_up),
76 gpregset, notes));
79 RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64(
80 Thread &thread, std::unique_ptr<RegisterInfoPOSIX_arm64> register_info,
81 const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes)
82 : RegisterContextPOSIX_arm64(thread, std::move(register_info)) {
83 ::memset(&m_sme_pseudo_regs, 0, sizeof(m_sme_pseudo_regs));
85 ProcessElfCore *process =
86 static_cast<ProcessElfCore *>(thread.GetProcess().get());
87 llvm::Triple::OSType os = process->GetArchitecture().GetTriple().getOS();
88 if ((os == llvm::Triple::Linux) || (os == llvm::Triple::FreeBSD)) {
89 AuxVector aux_vec(process->GetAuxvData());
90 std::optional<uint64_t> auxv_at_hwcap = aux_vec.GetAuxValue(
91 os == llvm::Triple::FreeBSD ? AuxVector::AUXV_FREEBSD_AT_HWCAP
92 : AuxVector::AUXV_AT_HWCAP);
93 std::optional<uint64_t> auxv_at_hwcap2 =
94 aux_vec.GetAuxValue(AuxVector::AUXV_AT_HWCAP2);
96 m_register_flags_detector.DetectFields(auxv_at_hwcap.value_or(0),
97 auxv_at_hwcap2.value_or(0));
98 m_register_flags_detector.UpdateRegisterInfo(GetRegisterInfo(),
99 GetRegisterCount());
102 m_gpr_data.SetData(std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
103 gpregset.GetByteSize()));
104 m_gpr_data.SetByteOrder(gpregset.GetByteOrder());
106 const llvm::Triple &target_triple =
107 m_register_info_up->GetTargetArchitecture().GetTriple();
108 m_fpr_data = getRegset(notes, target_triple, FPR_Desc);
110 if (m_register_info_up->IsSSVEPresent()) {
111 m_sve_data = getRegset(notes, target_triple, AARCH64_SSVE_Desc);
112 lldb::offset_t flags_offset = 12;
113 uint16_t flags = m_sve_data.GetU32(&flags_offset);
114 if ((flags & sve::ptrace_regs_mask) == sve::ptrace_regs_sve)
115 m_sve_state = SVEState::Streaming;
118 if (m_sve_state != SVEState::Streaming && m_register_info_up->IsSVEPresent())
119 m_sve_data = getRegset(notes, target_triple, AARCH64_SVE_Desc);
121 if (m_register_info_up->IsPAuthPresent())
122 m_pac_data = getRegset(notes, target_triple, AARCH64_PAC_Desc);
124 if (m_register_info_up->IsTLSPresent())
125 m_tls_data = getRegset(notes, target_triple, AARCH64_TLS_Desc);
127 if (m_register_info_up->IsZAPresent())
128 m_za_data = getRegset(notes, target_triple, AARCH64_ZA_Desc);
130 if (m_register_info_up->IsMTEPresent())
131 m_mte_data = getRegset(notes, target_triple, AARCH64_MTE_Desc);
133 if (m_register_info_up->IsZTPresent())
134 m_zt_data = getRegset(notes, target_triple, AARCH64_ZT_Desc);
136 if (m_register_info_up->IsFPMRPresent())
137 m_fpmr_data = getRegset(notes, target_triple, AARCH64_FPMR_Desc);
139 ConfigureRegisterContext();
142 RegisterContextCorePOSIX_arm64::~RegisterContextCorePOSIX_arm64() = default;
144 bool RegisterContextCorePOSIX_arm64::ReadGPR() { return true; }
146 bool RegisterContextCorePOSIX_arm64::ReadFPR() { return false; }
148 bool RegisterContextCorePOSIX_arm64::WriteGPR() {
149 assert(0);
150 return false;
153 bool RegisterContextCorePOSIX_arm64::WriteFPR() {
154 assert(0);
155 return false;
158 const uint8_t *RegisterContextCorePOSIX_arm64::GetSVEBuffer(uint64_t offset) {
159 return m_sve_data.GetDataStart() + offset;
162 void RegisterContextCorePOSIX_arm64::ConfigureRegisterContext() {
163 if (m_sve_data.GetByteSize() > sizeof(sve::user_sve_header)) {
164 uint64_t sve_header_field_offset = 8;
165 m_sve_vector_length = m_sve_data.GetU16(&sve_header_field_offset);
167 if (m_sve_state != SVEState::Streaming) {
168 sve_header_field_offset = 12;
169 uint16_t sve_header_flags_field =
170 m_sve_data.GetU16(&sve_header_field_offset);
171 if ((sve_header_flags_field & sve::ptrace_regs_mask) ==
172 sve::ptrace_regs_fpsimd)
173 m_sve_state = SVEState::FPSIMD;
174 else if ((sve_header_flags_field & sve::ptrace_regs_mask) ==
175 sve::ptrace_regs_sve)
176 m_sve_state = SVEState::Full;
179 if (!sve::vl_valid(m_sve_vector_length)) {
180 m_sve_state = SVEState::Disabled;
181 m_sve_vector_length = 0;
183 } else
184 m_sve_state = SVEState::Disabled;
186 if (m_sve_state != SVEState::Disabled)
187 m_register_info_up->ConfigureVectorLengthSVE(
188 sve::vq_from_vl(m_sve_vector_length));
190 if (m_sve_state == SVEState::Streaming)
191 m_sme_pseudo_regs.ctrl_reg |= 1;
193 if (m_za_data.GetByteSize() >= sizeof(sve::user_za_header)) {
194 lldb::offset_t vlen_offset = 8;
195 uint16_t svl = m_za_data.GetU16(&vlen_offset);
196 m_sme_pseudo_regs.svg_reg = svl / 8;
197 m_register_info_up->ConfigureVectorLengthZA(svl / 16);
199 // If there is register data then ZA is active. The size of the note may be
200 // misleading here so we use the size field of the embedded header.
201 lldb::offset_t size_offset = 0;
202 uint32_t size = m_za_data.GetU32(&size_offset);
203 if (size > sizeof(sve::user_za_header))
204 m_sme_pseudo_regs.ctrl_reg |= 1 << 1;
208 uint32_t RegisterContextCorePOSIX_arm64::CalculateSVEOffset(
209 const RegisterInfo *reg_info) {
210 // Start of Z0 data is after GPRs plus 8 bytes of vg register
211 uint32_t sve_reg_offset = LLDB_INVALID_INDEX32;
212 if (m_sve_state == SVEState::FPSIMD) {
213 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
214 sve_reg_offset = sve::ptrace_fpsimd_offset + (reg - GetRegNumSVEZ0()) * 16;
215 } else if (m_sve_state == SVEState::Full ||
216 m_sve_state == SVEState::Streaming) {
217 uint32_t sve_z0_offset = GetGPRSize() + 16;
218 sve_reg_offset =
219 sve::SigRegsOffset() + reg_info->byte_offset - sve_z0_offset;
222 return sve_reg_offset;
225 bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
226 RegisterValue &value) {
227 Status error;
228 lldb::offset_t offset;
230 offset = reg_info->byte_offset;
231 if (offset + reg_info->byte_size <= GetGPRSize()) {
232 value.SetFromMemoryData(*reg_info, m_gpr_data.GetDataStart() + offset,
233 reg_info->byte_size, lldb::eByteOrderLittle, error);
234 return error.Success();
237 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
238 if (reg == LLDB_INVALID_REGNUM)
239 return false;
241 if (IsFPR(reg)) {
242 if (m_sve_state == SVEState::Disabled) {
243 // SVE is disabled take legacy route for FPU register access
244 offset -= GetGPRSize();
245 if (offset < m_fpr_data.GetByteSize()) {
246 value.SetFromMemoryData(*reg_info, m_fpr_data.GetDataStart() + offset,
247 reg_info->byte_size, lldb::eByteOrderLittle,
248 error);
249 return error.Success();
251 } else {
252 // FPSR and FPCR will be located right after Z registers in
253 // SVEState::FPSIMD while in SVEState::Full/SVEState::Streaming they will
254 // be located at the end of register data after an alignment correction
255 // based on currently selected vector length.
256 uint32_t sve_reg_num = LLDB_INVALID_REGNUM;
257 if (reg == GetRegNumFPSR()) {
258 sve_reg_num = reg;
259 if (m_sve_state == SVEState::Full || m_sve_state == SVEState::Streaming)
260 offset = sve::PTraceFPSROffset(sve::vq_from_vl(m_sve_vector_length));
261 else if (m_sve_state == SVEState::FPSIMD)
262 offset = sve::ptrace_fpsimd_offset + (32 * 16);
263 } else if (reg == GetRegNumFPCR()) {
264 sve_reg_num = reg;
265 if (m_sve_state == SVEState::Full || m_sve_state == SVEState::Streaming)
266 offset = sve::PTraceFPCROffset(sve::vq_from_vl(m_sve_vector_length));
267 else if (m_sve_state == SVEState::FPSIMD)
268 offset = sve::ptrace_fpsimd_offset + (32 * 16) + 4;
269 } else {
270 // Extract SVE Z register value register number for this reg_info
271 if (reg_info->value_regs &&
272 reg_info->value_regs[0] != LLDB_INVALID_REGNUM)
273 sve_reg_num = reg_info->value_regs[0];
274 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
277 assert(sve_reg_num != LLDB_INVALID_REGNUM);
278 assert(offset < m_sve_data.GetByteSize());
279 value.SetFromMemoryData(*reg_info, GetSVEBuffer(offset),
280 reg_info->byte_size, lldb::eByteOrderLittle,
281 error);
283 } else if (IsSVE(reg)) {
284 if (IsSVEVG(reg)) {
285 value = GetSVERegVG();
286 return true;
289 switch (m_sve_state) {
290 case SVEState::FPSIMD: {
291 // In FPSIMD state SVE payload mirrors legacy fpsimd struct and so just
292 // copy 16 bytes of v register to the start of z register. All other
293 // SVE register will be set to zero.
294 uint64_t byte_size = 1;
295 uint8_t zeros = 0;
296 const uint8_t *src = &zeros;
297 if (IsSVEZ(reg)) {
298 byte_size = 16;
299 offset = CalculateSVEOffset(reg_info);
300 assert(offset < m_sve_data.GetByteSize());
301 src = GetSVEBuffer(offset);
303 value.SetFromMemoryData(*reg_info, src, byte_size, lldb::eByteOrderLittle,
304 error);
305 } break;
306 case SVEState::Full:
307 case SVEState::Streaming:
308 offset = CalculateSVEOffset(reg_info);
309 assert(offset < m_sve_data.GetByteSize());
310 value.SetFromMemoryData(*reg_info, GetSVEBuffer(offset),
311 reg_info->byte_size, lldb::eByteOrderLittle,
312 error);
313 break;
314 case SVEState::Disabled:
315 default:
316 return false;
318 } else if (IsPAuth(reg)) {
319 offset = reg_info->byte_offset - m_register_info_up->GetPAuthOffset();
320 assert(offset < m_pac_data.GetByteSize());
321 value.SetFromMemoryData(*reg_info, m_pac_data.GetDataStart() + offset,
322 reg_info->byte_size, lldb::eByteOrderLittle, error);
323 } else if (IsTLS(reg)) {
324 offset = reg_info->byte_offset - m_register_info_up->GetTLSOffset();
325 assert(offset < m_tls_data.GetByteSize());
326 value.SetFromMemoryData(*reg_info, m_tls_data.GetDataStart() + offset,
327 reg_info->byte_size, lldb::eByteOrderLittle, error);
328 } else if (IsMTE(reg)) {
329 offset = reg_info->byte_offset - m_register_info_up->GetMTEOffset();
330 assert(offset < m_mte_data.GetByteSize());
331 value.SetFromMemoryData(*reg_info, m_mte_data.GetDataStart() + offset,
332 reg_info->byte_size, lldb::eByteOrderLittle, error);
333 } else if (IsSME(reg)) {
334 // If you had SME in the process, active or otherwise, there will at least
335 // be a ZA header. No header, no SME at all.
336 if (m_za_data.GetByteSize() < sizeof(sve::user_za_header))
337 return false;
339 if (m_register_info_up->IsSMERegZA(reg)) {
340 // Don't use the size of the note to tell whether ZA is enabled. There may
341 // be non-register padding data after the header. Use the embedded
342 // header's size field instead.
343 lldb::offset_t size_offset = 0;
344 uint32_t size = m_za_data.GetU32(&size_offset);
345 bool za_enabled = size > sizeof(sve::user_za_header);
347 size_t za_note_size = m_za_data.GetByteSize();
348 // For a disabled ZA we fake a value of all 0s.
349 if (!za_enabled) {
350 uint64_t svl = m_sme_pseudo_regs.svg_reg * 8;
351 za_note_size = sizeof(sve::user_za_header) + (svl * svl);
354 const uint8_t *src = nullptr;
355 std::vector<uint8_t> disabled_za_data;
357 if (za_enabled)
358 src = m_za_data.GetDataStart();
359 else {
360 disabled_za_data.resize(za_note_size);
361 std::fill(disabled_za_data.begin(), disabled_za_data.end(), 0);
362 src = disabled_za_data.data();
365 value.SetFromMemoryData(*reg_info, src + sizeof(sve::user_za_header),
366 reg_info->byte_size, lldb::eByteOrderLittle,
367 error);
368 } else if (m_register_info_up->IsSMERegZT(reg)) {
369 value.SetFromMemoryData(*reg_info, m_zt_data.GetDataStart(),
370 reg_info->byte_size, lldb::eByteOrderLittle,
371 error);
372 } else {
373 offset = reg_info->byte_offset - m_register_info_up->GetSMEOffset();
374 assert(offset < sizeof(m_sme_pseudo_regs));
375 // Host endian since these values are derived instead of being read from a
376 // core file note.
377 value.SetFromMemoryData(
378 *reg_info, reinterpret_cast<uint8_t *>(&m_sme_pseudo_regs) + offset,
379 reg_info->byte_size, lldb_private::endian::InlHostByteOrder(), error);
381 } else if (IsFPMR(reg)) {
382 offset = reg_info->byte_offset - m_register_info_up->GetFPMROffset();
383 assert(offset < m_fpmr_data.GetByteSize());
384 value.SetFromMemoryData(*reg_info, m_fpmr_data.GetDataStart() + offset,
385 reg_info->byte_size, lldb::eByteOrderLittle, error);
386 } else
387 return false;
389 return error.Success();
392 bool RegisterContextCorePOSIX_arm64::ReadAllRegisterValues(
393 lldb::WritableDataBufferSP &data_sp) {
394 return false;
397 bool RegisterContextCorePOSIX_arm64::WriteRegister(const RegisterInfo *reg_info,
398 const RegisterValue &value) {
399 return false;
402 bool RegisterContextCorePOSIX_arm64::WriteAllRegisterValues(
403 const lldb::DataBufferSP &data_sp) {
404 return false;
407 bool RegisterContextCorePOSIX_arm64::HardwareSingleStep(bool enable) {
408 return false;