180814287SRaphael Isemann //===-- NativeRegisterContextLinux_arm64.cpp ------------------------------===//
21e209fccSTamas Berghammer //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61e209fccSTamas Berghammer //
71e209fccSTamas Berghammer //===----------------------------------------------------------------------===//
81e209fccSTamas Berghammer 
9068f8a7eSTamas Berghammer #if defined(__arm64__) || defined(__aarch64__)
10068f8a7eSTamas Berghammer 
11e85e6021STamas Berghammer #include "NativeRegisterContextLinux_arm.h"
121e209fccSTamas Berghammer #include "NativeRegisterContextLinux_arm64.h"
131e209fccSTamas Berghammer 
14068f8a7eSTamas Berghammer 
151e209fccSTamas Berghammer #include "lldb/Host/common/NativeProcessProtocol.h"
16666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h"
176f9e6901SZachary Turner #include "lldb/Utility/Log.h"
18d821c997SPavel Labath #include "lldb/Utility/RegisterValue.h"
1997206d57SZachary Turner #include "lldb/Utility/Status.h"
201e209fccSTamas Berghammer 
21068f8a7eSTamas Berghammer #include "Plugins/Process/Linux/NativeProcessLinux.h"
22068f8a7eSTamas Berghammer #include "Plugins/Process/Linux/Procfs.h"
23e85e6021STamas Berghammer #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
24567ba6c4SMuhammad Omair Javaid #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
25068f8a7eSTamas Berghammer 
26b9c1b51eSKate Stone // System includes - They have to be included after framework includes because
2705097246SAdrian Prantl // they define some macros which collide with variable names in other modules
28068f8a7eSTamas Berghammer #include <sys/socket.h>
29068f8a7eSTamas Berghammer // NT_PRSTATUS and NT_FPREGSET definition
30068f8a7eSTamas Berghammer #include <elf.h>
31567ba6c4SMuhammad Omair Javaid 
32567ba6c4SMuhammad Omair Javaid #ifndef NT_ARM_SVE
33567ba6c4SMuhammad Omair Javaid #define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension */
34567ba6c4SMuhammad Omair Javaid #endif
35068f8a7eSTamas Berghammer 
36068f8a7eSTamas Berghammer #define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize())
371e209fccSTamas Berghammer 
381e209fccSTamas Berghammer using namespace lldb;
391e209fccSTamas Berghammer using namespace lldb_private;
40db264a6dSTamas Berghammer using namespace lldb_private::process_linux;
411e209fccSTamas Berghammer 
42d37349f3SPavel Labath std::unique_ptr<NativeRegisterContextLinux>
43b9c1b51eSKate Stone NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
44d1486e65SPavel Labath     const ArchSpec &target_arch, NativeThreadLinux &native_thread) {
45b9c1b51eSKate Stone   switch (target_arch.GetMachine()) {
46e85e6021STamas Berghammer   case llvm::Triple::arm:
47a8f3ae7cSJonas Devlieghere     return std::make_unique<NativeRegisterContextLinux_arm>(target_arch,
48d37349f3SPavel Labath                                                              native_thread);
49d6d3d21cSMuhammad Omair Javaid   case llvm::Triple::aarch64: {
50d6d3d21cSMuhammad Omair Javaid     // Configure register sets supported by this AArch64 target.
51d6d3d21cSMuhammad Omair Javaid     // Read SVE header to check for SVE support.
52d6d3d21cSMuhammad Omair Javaid     struct user_sve_header sve_header;
53d6d3d21cSMuhammad Omair Javaid     struct iovec ioVec;
54d6d3d21cSMuhammad Omair Javaid     ioVec.iov_base = &sve_header;
55d6d3d21cSMuhammad Omair Javaid     ioVec.iov_len = sizeof(sve_header);
56d6d3d21cSMuhammad Omair Javaid     unsigned int regset = NT_ARM_SVE;
57d6d3d21cSMuhammad Omair Javaid 
58d6d3d21cSMuhammad Omair Javaid     Flags opt_regsets;
59d6d3d21cSMuhammad Omair Javaid     if (NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET,
60d6d3d21cSMuhammad Omair Javaid                                           native_thread.GetID(), &regset,
61d6d3d21cSMuhammad Omair Javaid                                           &ioVec, sizeof(sve_header))
62d6d3d21cSMuhammad Omair Javaid             .Success())
63d6d3d21cSMuhammad Omair Javaid       opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE);
64d6d3d21cSMuhammad Omair Javaid 
65d6d3d21cSMuhammad Omair Javaid     auto register_info_up =
66d6d3d21cSMuhammad Omair Javaid         std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets);
67d6d3d21cSMuhammad Omair Javaid     return std::make_unique<NativeRegisterContextLinux_arm64>(
68d6d3d21cSMuhammad Omair Javaid         target_arch, native_thread, std::move(register_info_up));
69d6d3d21cSMuhammad Omair Javaid   }
70e85e6021STamas Berghammer   default:
71ea1b6b17SPavel Labath     llvm_unreachable("have no register context for architecture");
72e85e6021STamas Berghammer   }
73068f8a7eSTamas Berghammer }
74068f8a7eSTamas Berghammer 
75b9c1b51eSKate Stone NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
76d6d3d21cSMuhammad Omair Javaid     const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
77d6d3d21cSMuhammad Omair Javaid     std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up)
78d6d3d21cSMuhammad Omair Javaid     : NativeRegisterContextRegisterInfo(native_thread,
79*e1d4fb1eSPavel Labath                                         register_info_up.release()),
80*e1d4fb1eSPavel Labath       NativeRegisterContextLinux(native_thread) {
811e209fccSTamas Berghammer   ::memset(&m_fpr, 0, sizeof(m_fpr));
821e209fccSTamas Berghammer   ::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64));
83ea8c25a8SOmair Javaid   ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
84771c4c9cSMichał Górny   ::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs));
85567ba6c4SMuhammad Omair Javaid   ::memset(&m_sve_header, 0, sizeof(m_sve_header));
86ea8c25a8SOmair Javaid 
87ea8c25a8SOmair Javaid   // 16 is just a maximum value, query hardware for actual watchpoint count
88ea8c25a8SOmair Javaid   m_max_hwp_supported = 16;
89ea8c25a8SOmair Javaid   m_max_hbp_supported = 16;
90567ba6c4SMuhammad Omair Javaid 
91ea8c25a8SOmair Javaid   m_refresh_hwdebug_info = true;
92b6f9d7b8SMuhammad Omair Javaid 
93b6f9d7b8SMuhammad Omair Javaid   m_gpr_is_valid = false;
94b6f9d7b8SMuhammad Omair Javaid   m_fpu_is_valid = false;
95567ba6c4SMuhammad Omair Javaid   m_sve_buffer_is_valid = false;
96567ba6c4SMuhammad Omair Javaid   m_sve_header_is_valid = false;
97567ba6c4SMuhammad Omair Javaid 
98d6d3d21cSMuhammad Omair Javaid   if (GetRegisterInfo().IsSVEEnabled())
99567ba6c4SMuhammad Omair Javaid     m_sve_state = SVEState::Unknown;
100d6d3d21cSMuhammad Omair Javaid   else
101d6d3d21cSMuhammad Omair Javaid     m_sve_state = SVEState::Disabled;
1021e209fccSTamas Berghammer }
1031e209fccSTamas Berghammer 
1047fa7b81bSMuhammad Omair Javaid RegisterInfoPOSIX_arm64 &
1057fa7b81bSMuhammad Omair Javaid NativeRegisterContextLinux_arm64::GetRegisterInfo() const {
1067fa7b81bSMuhammad Omair Javaid   return static_cast<RegisterInfoPOSIX_arm64 &>(*m_register_info_interface_up);
1077fa7b81bSMuhammad Omair Javaid }
1087fa7b81bSMuhammad Omair Javaid 
109b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount() const {
1107fa7b81bSMuhammad Omair Javaid   return GetRegisterInfo().GetRegisterSetCount();
1111e209fccSTamas Berghammer }
1121e209fccSTamas Berghammer 
113db264a6dSTamas Berghammer const RegisterSet *
114b9c1b51eSKate Stone NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index) const {
1157fa7b81bSMuhammad Omair Javaid   return GetRegisterInfo().GetRegisterSet(set_index);
1161e209fccSTamas Berghammer }
1171e209fccSTamas Berghammer 
118b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount() const {
119cec93c35STamas Berghammer   uint32_t count = 0;
1207fa7b81bSMuhammad Omair Javaid   for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
1217fa7b81bSMuhammad Omair Javaid     count += GetRegisterSet(set_index)->num_registers;
122cec93c35STamas Berghammer   return count;
123cec93c35STamas Berghammer }
124cec93c35STamas Berghammer 
12597206d57SZachary Turner Status
12697206d57SZachary Turner NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info,
12797206d57SZachary Turner                                                RegisterValue &reg_value) {
12897206d57SZachary Turner   Status error;
1291e209fccSTamas Berghammer 
130b9c1b51eSKate Stone   if (!reg_info) {
1311e209fccSTamas Berghammer     error.SetErrorString("reg_info NULL");
1321e209fccSTamas Berghammer     return error;
1331e209fccSTamas Berghammer   }
1341e209fccSTamas Berghammer 
1351e209fccSTamas Berghammer   const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
1361e209fccSTamas Berghammer 
137b6f9d7b8SMuhammad Omair Javaid   if (reg == LLDB_INVALID_REGNUM)
138b6f9d7b8SMuhammad Omair Javaid     return Status("no lldb regnum for %s", reg_info && reg_info->name
139b6f9d7b8SMuhammad Omair Javaid                                                ? reg_info->name
140b6f9d7b8SMuhammad Omair Javaid                                                : "<unknown register>");
141b6f9d7b8SMuhammad Omair Javaid 
142b6f9d7b8SMuhammad Omair Javaid   uint8_t *src;
1434283320bSMuhammad Omair Javaid   uint32_t offset = LLDB_INVALID_INDEX32;
144567ba6c4SMuhammad Omair Javaid   uint64_t sve_vg;
145567ba6c4SMuhammad Omair Javaid   std::vector<uint8_t> sve_reg_non_live;
146b6f9d7b8SMuhammad Omair Javaid 
147b6f9d7b8SMuhammad Omair Javaid   if (IsGPR(reg)) {
148b6f9d7b8SMuhammad Omair Javaid     error = ReadGPR();
149b6f9d7b8SMuhammad Omair Javaid     if (error.Fail())
150b6f9d7b8SMuhammad Omair Javaid       return error;
151b6f9d7b8SMuhammad Omair Javaid 
152b6f9d7b8SMuhammad Omair Javaid     offset = reg_info->byte_offset;
153b6f9d7b8SMuhammad Omair Javaid     assert(offset < GetGPRSize());
154b6f9d7b8SMuhammad Omair Javaid     src = (uint8_t *)GetGPRBuffer() + offset;
155b6f9d7b8SMuhammad Omair Javaid 
156b6f9d7b8SMuhammad Omair Javaid   } else if (IsFPR(reg)) {
157567ba6c4SMuhammad Omair Javaid     if (m_sve_state == SVEState::Disabled) {
158567ba6c4SMuhammad Omair Javaid       // SVE is disabled take legacy route for FPU register access
159068f8a7eSTamas Berghammer       error = ReadFPR();
160068f8a7eSTamas Berghammer       if (error.Fail())
1611e209fccSTamas Berghammer         return error;
162567ba6c4SMuhammad Omair Javaid 
163b6f9d7b8SMuhammad Omair Javaid       offset = CalculateFprOffset(reg_info);
164b6f9d7b8SMuhammad Omair Javaid       assert(offset < GetFPRSize());
165b6f9d7b8SMuhammad Omair Javaid       src = (uint8_t *)GetFPRBuffer() + offset;
166567ba6c4SMuhammad Omair Javaid     } else {
167567ba6c4SMuhammad Omair Javaid       // SVE enabled, we will read and cache SVE ptrace data
168567ba6c4SMuhammad Omair Javaid       error = ReadAllSVE();
169567ba6c4SMuhammad Omair Javaid       if (error.Fail())
170567ba6c4SMuhammad Omair Javaid         return error;
171567ba6c4SMuhammad Omair Javaid 
172567ba6c4SMuhammad Omair Javaid       // FPSR and FPCR will be located right after Z registers in
173567ba6c4SMuhammad Omair Javaid       // SVEState::FPSIMD while in SVEState::Full they will be located at the
174567ba6c4SMuhammad Omair Javaid       // end of register data after an alignment correction based on currently
175567ba6c4SMuhammad Omair Javaid       // selected vector length.
176567ba6c4SMuhammad Omair Javaid       uint32_t sve_reg_num = LLDB_INVALID_REGNUM;
177567ba6c4SMuhammad Omair Javaid       if (reg == GetRegisterInfo().GetRegNumFPSR()) {
178567ba6c4SMuhammad Omair Javaid         sve_reg_num = reg;
179567ba6c4SMuhammad Omair Javaid         if (m_sve_state == SVEState::Full)
180567ba6c4SMuhammad Omair Javaid           offset = SVE_PT_SVE_FPSR_OFFSET(sve_vq_from_vl(m_sve_header.vl));
181567ba6c4SMuhammad Omair Javaid         else if (m_sve_state == SVEState::FPSIMD)
182567ba6c4SMuhammad Omair Javaid           offset = SVE_PT_FPSIMD_OFFSET + (32 * 16);
183567ba6c4SMuhammad Omair Javaid       } else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
184567ba6c4SMuhammad Omair Javaid         sve_reg_num = reg;
185567ba6c4SMuhammad Omair Javaid         if (m_sve_state == SVEState::Full)
186567ba6c4SMuhammad Omair Javaid           offset = SVE_PT_SVE_FPCR_OFFSET(sve_vq_from_vl(m_sve_header.vl));
187567ba6c4SMuhammad Omair Javaid         else if (m_sve_state == SVEState::FPSIMD)
188567ba6c4SMuhammad Omair Javaid           offset = SVE_PT_FPSIMD_OFFSET + (32 * 16) + 4;
189567ba6c4SMuhammad Omair Javaid       } else {
190567ba6c4SMuhammad Omair Javaid         // Extract SVE Z register value register number for this reg_info
191567ba6c4SMuhammad Omair Javaid         if (reg_info->value_regs &&
192567ba6c4SMuhammad Omair Javaid             reg_info->value_regs[0] != LLDB_INVALID_REGNUM)
193567ba6c4SMuhammad Omair Javaid           sve_reg_num = reg_info->value_regs[0];
194567ba6c4SMuhammad Omair Javaid         offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
195567ba6c4SMuhammad Omair Javaid       }
196567ba6c4SMuhammad Omair Javaid 
197567ba6c4SMuhammad Omair Javaid       assert(offset < GetSVEBufferSize());
198567ba6c4SMuhammad Omair Javaid       src = (uint8_t *)GetSVEBuffer() + offset;
199567ba6c4SMuhammad Omair Javaid     }
200567ba6c4SMuhammad Omair Javaid   } else if (IsSVE(reg)) {
201567ba6c4SMuhammad Omair Javaid 
202567ba6c4SMuhammad Omair Javaid     if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown)
203567ba6c4SMuhammad Omair Javaid       return Status("SVE disabled or not supported");
204567ba6c4SMuhammad Omair Javaid 
205567ba6c4SMuhammad Omair Javaid     if (GetRegisterInfo().IsSVERegVG(reg)) {
206567ba6c4SMuhammad Omair Javaid       sve_vg = GetSVERegVG();
207567ba6c4SMuhammad Omair Javaid       src = (uint8_t *)&sve_vg;
208567ba6c4SMuhammad Omair Javaid     } else {
209567ba6c4SMuhammad Omair Javaid       // SVE enabled, we will read and cache SVE ptrace data
210567ba6c4SMuhammad Omair Javaid       error = ReadAllSVE();
211567ba6c4SMuhammad Omair Javaid       if (error.Fail())
212567ba6c4SMuhammad Omair Javaid         return error;
213567ba6c4SMuhammad Omair Javaid 
214567ba6c4SMuhammad Omair Javaid       if (m_sve_state == SVEState::FPSIMD) {
215567ba6c4SMuhammad Omair Javaid         // In FPSIMD state SVE payload mirrors legacy fpsimd struct and so
216567ba6c4SMuhammad Omair Javaid         // just copy 16 bytes of v register to the start of z register. All
217567ba6c4SMuhammad Omair Javaid         // other SVE register will be set to zero.
218567ba6c4SMuhammad Omair Javaid         sve_reg_non_live.resize(reg_info->byte_size, 0);
219567ba6c4SMuhammad Omair Javaid         src = sve_reg_non_live.data();
220567ba6c4SMuhammad Omair Javaid 
221567ba6c4SMuhammad Omair Javaid         if (GetRegisterInfo().IsSVEZReg(reg)) {
222567ba6c4SMuhammad Omair Javaid           offset = CalculateSVEOffset(reg_info);
223567ba6c4SMuhammad Omair Javaid           assert(offset < GetSVEBufferSize());
224567ba6c4SMuhammad Omair Javaid           ::memcpy(sve_reg_non_live.data(), (uint8_t *)GetSVEBuffer() + offset,
225567ba6c4SMuhammad Omair Javaid                    16);
226567ba6c4SMuhammad Omair Javaid         }
227567ba6c4SMuhammad Omair Javaid       } else {
228567ba6c4SMuhammad Omair Javaid         offset = CalculateSVEOffset(reg_info);
229567ba6c4SMuhammad Omair Javaid         assert(offset < GetSVEBufferSize());
230567ba6c4SMuhammad Omair Javaid         src = (uint8_t *)GetSVEBuffer() + offset;
231567ba6c4SMuhammad Omair Javaid       }
232567ba6c4SMuhammad Omair Javaid     }
233b6f9d7b8SMuhammad Omair Javaid   } else
234b6f9d7b8SMuhammad Omair Javaid     return Status("failed - register wasn't recognized to be a GPR or an FPR, "
235b6f9d7b8SMuhammad Omair Javaid                   "write strategy unknown");
2361e209fccSTamas Berghammer 
237b9c1b51eSKate Stone   reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size,
238b9c1b51eSKate Stone                               eByteOrderLittle, error);
2391e209fccSTamas Berghammer 
2401e209fccSTamas Berghammer   return error;
2411e209fccSTamas Berghammer }
2421e209fccSTamas Berghammer 
24397206d57SZachary Turner Status NativeRegisterContextLinux_arm64::WriteRegister(
244b9c1b51eSKate Stone     const RegisterInfo *reg_info, const RegisterValue &reg_value) {
245b6f9d7b8SMuhammad Omair Javaid   Status error;
246b6f9d7b8SMuhammad Omair Javaid 
2471e209fccSTamas Berghammer   if (!reg_info)
24897206d57SZachary Turner     return Status("reg_info NULL");
2491e209fccSTamas Berghammer 
250b6f9d7b8SMuhammad Omair Javaid   const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
251b6f9d7b8SMuhammad Omair Javaid 
252b6f9d7b8SMuhammad Omair Javaid   if (reg == LLDB_INVALID_REGNUM)
25397206d57SZachary Turner     return Status("no lldb regnum for %s", reg_info && reg_info->name
254b9c1b51eSKate Stone                                                ? reg_info->name
255b9c1b51eSKate Stone                                                : "<unknown register>");
2561e209fccSTamas Berghammer 
257b6f9d7b8SMuhammad Omair Javaid   uint8_t *dst;
2584283320bSMuhammad Omair Javaid   uint32_t offset = LLDB_INVALID_INDEX32;
259567ba6c4SMuhammad Omair Javaid   std::vector<uint8_t> sve_reg_non_live;
2601e209fccSTamas Berghammer 
261b6f9d7b8SMuhammad Omair Javaid   if (IsGPR(reg)) {
262b6f9d7b8SMuhammad Omair Javaid     error = ReadGPR();
263068f8a7eSTamas Berghammer     if (error.Fail())
264068f8a7eSTamas Berghammer       return error;
2651e209fccSTamas Berghammer 
266567ba6c4SMuhammad Omair Javaid     assert(reg_info->byte_offset < GetGPRSize());
267567ba6c4SMuhammad Omair Javaid     dst = (uint8_t *)GetGPRBuffer() + reg_info->byte_offset;
268b6f9d7b8SMuhammad Omair Javaid     ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
269b6f9d7b8SMuhammad Omair Javaid 
270b6f9d7b8SMuhammad Omair Javaid     return WriteGPR();
271b6f9d7b8SMuhammad Omair Javaid   } else if (IsFPR(reg)) {
272567ba6c4SMuhammad Omair Javaid     if (m_sve_state == SVEState::Disabled) {
273567ba6c4SMuhammad Omair Javaid       // SVE is disabled take legacy route for FPU register access
274b6f9d7b8SMuhammad Omair Javaid       error = ReadFPR();
275b6f9d7b8SMuhammad Omair Javaid       if (error.Fail())
276b6f9d7b8SMuhammad Omair Javaid         return error;
277567ba6c4SMuhammad Omair Javaid 
278b6f9d7b8SMuhammad Omair Javaid       offset = CalculateFprOffset(reg_info);
279b6f9d7b8SMuhammad Omair Javaid       assert(offset < GetFPRSize());
280b6f9d7b8SMuhammad Omair Javaid       dst = (uint8_t *)GetFPRBuffer() + offset;
281b6f9d7b8SMuhammad Omair Javaid       ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
282b6f9d7b8SMuhammad Omair Javaid 
283b6f9d7b8SMuhammad Omair Javaid       return WriteFPR();
284567ba6c4SMuhammad Omair Javaid     } else {
285567ba6c4SMuhammad Omair Javaid       // SVE enabled, we will read and cache SVE ptrace data
286567ba6c4SMuhammad Omair Javaid       error = ReadAllSVE();
287567ba6c4SMuhammad Omair Javaid       if (error.Fail())
288567ba6c4SMuhammad Omair Javaid         return error;
289567ba6c4SMuhammad Omair Javaid 
290567ba6c4SMuhammad Omair Javaid       // FPSR and FPCR will be located right after Z registers in
291567ba6c4SMuhammad Omair Javaid       // SVEState::FPSIMD while in SVEState::Full they will be located at the
292567ba6c4SMuhammad Omair Javaid       // end of register data after an alignment correction based on currently
293567ba6c4SMuhammad Omair Javaid       // selected vector length.
294567ba6c4SMuhammad Omair Javaid       uint32_t sve_reg_num = LLDB_INVALID_REGNUM;
295567ba6c4SMuhammad Omair Javaid       if (reg == GetRegisterInfo().GetRegNumFPSR()) {
296567ba6c4SMuhammad Omair Javaid         sve_reg_num = reg;
297567ba6c4SMuhammad Omair Javaid         if (m_sve_state == SVEState::Full)
298567ba6c4SMuhammad Omair Javaid           offset = SVE_PT_SVE_FPSR_OFFSET(sve_vq_from_vl(m_sve_header.vl));
299567ba6c4SMuhammad Omair Javaid         else if (m_sve_state == SVEState::FPSIMD)
300567ba6c4SMuhammad Omair Javaid           offset = SVE_PT_FPSIMD_OFFSET + (32 * 16);
301567ba6c4SMuhammad Omair Javaid       } else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
302567ba6c4SMuhammad Omair Javaid         sve_reg_num = reg;
303567ba6c4SMuhammad Omair Javaid         if (m_sve_state == SVEState::Full)
304567ba6c4SMuhammad Omair Javaid           offset = SVE_PT_SVE_FPCR_OFFSET(sve_vq_from_vl(m_sve_header.vl));
305567ba6c4SMuhammad Omair Javaid         else if (m_sve_state == SVEState::FPSIMD)
306567ba6c4SMuhammad Omair Javaid           offset = SVE_PT_FPSIMD_OFFSET + (32 * 16) + 4;
307567ba6c4SMuhammad Omair Javaid       } else {
308567ba6c4SMuhammad Omair Javaid         // Extract SVE Z register value register number for this reg_info
309567ba6c4SMuhammad Omair Javaid         if (reg_info->value_regs &&
310567ba6c4SMuhammad Omair Javaid             reg_info->value_regs[0] != LLDB_INVALID_REGNUM)
311567ba6c4SMuhammad Omair Javaid           sve_reg_num = reg_info->value_regs[0];
312567ba6c4SMuhammad Omair Javaid         offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
313b6f9d7b8SMuhammad Omair Javaid       }
314b6f9d7b8SMuhammad Omair Javaid 
315567ba6c4SMuhammad Omair Javaid       assert(offset < GetSVEBufferSize());
316567ba6c4SMuhammad Omair Javaid       dst = (uint8_t *)GetSVEBuffer() + offset;
317567ba6c4SMuhammad Omair Javaid       ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
318567ba6c4SMuhammad Omair Javaid       return WriteAllSVE();
319567ba6c4SMuhammad Omair Javaid     }
320567ba6c4SMuhammad Omair Javaid   } else if (IsSVE(reg)) {
321567ba6c4SMuhammad Omair Javaid     if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown)
322567ba6c4SMuhammad Omair Javaid       return Status("SVE disabled or not supported");
323567ba6c4SMuhammad Omair Javaid     else {
324567ba6c4SMuhammad Omair Javaid       // Target has SVE enabled, we will read and cache SVE ptrace data
325567ba6c4SMuhammad Omair Javaid       error = ReadAllSVE();
326567ba6c4SMuhammad Omair Javaid       if (error.Fail())
327b6f9d7b8SMuhammad Omair Javaid         return error;
328567ba6c4SMuhammad Omair Javaid 
329e448ad78SMuhammad Omair Javaid       if (GetRegisterInfo().IsSVERegVG(reg)) {
330e448ad78SMuhammad Omair Javaid         uint64_t vg_value = reg_value.GetAsUInt64();
331e448ad78SMuhammad Omair Javaid 
332e448ad78SMuhammad Omair Javaid         if (sve_vl_valid(vg_value * 8)) {
333e448ad78SMuhammad Omair Javaid           if (m_sve_header_is_valid && vg_value == GetSVERegVG())
334e448ad78SMuhammad Omair Javaid             return error;
335e448ad78SMuhammad Omair Javaid 
336e448ad78SMuhammad Omair Javaid           SetSVERegVG(vg_value);
337e448ad78SMuhammad Omair Javaid 
338e448ad78SMuhammad Omair Javaid           error = WriteSVEHeader();
339e448ad78SMuhammad Omair Javaid           if (error.Success())
340e448ad78SMuhammad Omair Javaid             ConfigureRegisterContext();
341e448ad78SMuhammad Omair Javaid 
342e448ad78SMuhammad Omair Javaid           if (m_sve_header_is_valid && vg_value == GetSVERegVG())
343e448ad78SMuhammad Omair Javaid             return error;
344e448ad78SMuhammad Omair Javaid         }
345e448ad78SMuhammad Omair Javaid 
346e448ad78SMuhammad Omair Javaid         return Status("SVE vector length update failed.");
347e448ad78SMuhammad Omair Javaid       }
348e448ad78SMuhammad Omair Javaid 
349567ba6c4SMuhammad Omair Javaid       // If target supports SVE but currently in FPSIMD mode.
350567ba6c4SMuhammad Omair Javaid       if (m_sve_state == SVEState::FPSIMD) {
351567ba6c4SMuhammad Omair Javaid         // Here we will check if writing this SVE register enables
352567ba6c4SMuhammad Omair Javaid         // SVEState::Full
353567ba6c4SMuhammad Omair Javaid         bool set_sve_state_full = false;
354567ba6c4SMuhammad Omair Javaid         const uint8_t *reg_bytes = (const uint8_t *)reg_value.GetBytes();
355567ba6c4SMuhammad Omair Javaid         if (GetRegisterInfo().IsSVEZReg(reg)) {
356567ba6c4SMuhammad Omair Javaid           for (uint32_t i = 16; i < reg_info->byte_size; i++) {
357567ba6c4SMuhammad Omair Javaid             if (reg_bytes[i]) {
358567ba6c4SMuhammad Omair Javaid               set_sve_state_full = true;
359567ba6c4SMuhammad Omair Javaid               break;
360567ba6c4SMuhammad Omair Javaid             }
361567ba6c4SMuhammad Omair Javaid           }
362567ba6c4SMuhammad Omair Javaid         } else if (GetRegisterInfo().IsSVEPReg(reg) ||
363567ba6c4SMuhammad Omair Javaid                    reg == GetRegisterInfo().GetRegNumSVEFFR()) {
364567ba6c4SMuhammad Omair Javaid           for (uint32_t i = 0; i < reg_info->byte_size; i++) {
365567ba6c4SMuhammad Omair Javaid             if (reg_bytes[i]) {
366567ba6c4SMuhammad Omair Javaid               set_sve_state_full = true;
367567ba6c4SMuhammad Omair Javaid               break;
368567ba6c4SMuhammad Omair Javaid             }
369567ba6c4SMuhammad Omair Javaid           }
370567ba6c4SMuhammad Omair Javaid         }
371567ba6c4SMuhammad Omair Javaid 
372567ba6c4SMuhammad Omair Javaid         if (!set_sve_state_full && GetRegisterInfo().IsSVEZReg(reg)) {
373567ba6c4SMuhammad Omair Javaid           // We are writing a Z register which is zero beyond 16 bytes so copy
374567ba6c4SMuhammad Omair Javaid           // first 16 bytes only as SVE payload mirrors legacy fpsimd structure
375567ba6c4SMuhammad Omair Javaid           offset = CalculateSVEOffset(reg_info);
376567ba6c4SMuhammad Omair Javaid           assert(offset < GetSVEBufferSize());
377567ba6c4SMuhammad Omair Javaid           dst = (uint8_t *)GetSVEBuffer() + offset;
378567ba6c4SMuhammad Omair Javaid           ::memcpy(dst, reg_value.GetBytes(), 16);
379567ba6c4SMuhammad Omair Javaid 
380567ba6c4SMuhammad Omair Javaid           return WriteAllSVE();
381567ba6c4SMuhammad Omair Javaid         } else
382567ba6c4SMuhammad Omair Javaid           return Status("SVE state change operation not supported");
383567ba6c4SMuhammad Omair Javaid       } else {
384567ba6c4SMuhammad Omair Javaid         offset = CalculateSVEOffset(reg_info);
385567ba6c4SMuhammad Omair Javaid         assert(offset < GetSVEBufferSize());
386567ba6c4SMuhammad Omair Javaid         dst = (uint8_t *)GetSVEBuffer() + offset;
387567ba6c4SMuhammad Omair Javaid         ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
388567ba6c4SMuhammad Omair Javaid         return WriteAllSVE();
389567ba6c4SMuhammad Omair Javaid       }
390567ba6c4SMuhammad Omair Javaid     }
391567ba6c4SMuhammad Omair Javaid   }
392567ba6c4SMuhammad Omair Javaid 
393567ba6c4SMuhammad Omair Javaid   return Status("Failed to write register value");
3941e209fccSTamas Berghammer }
3951e209fccSTamas Berghammer 
39697206d57SZachary Turner Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues(
397b9c1b51eSKate Stone     lldb::DataBufferSP &data_sp) {
39897206d57SZachary Turner   Status error;
3991e209fccSTamas Berghammer 
400db264a6dSTamas Berghammer   data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
401567ba6c4SMuhammad Omair Javaid 
402068f8a7eSTamas Berghammer   error = ReadGPR();
403068f8a7eSTamas Berghammer   if (error.Fail())
4041e209fccSTamas Berghammer     return error;
4051e209fccSTamas Berghammer 
406068f8a7eSTamas Berghammer   error = ReadFPR();
407068f8a7eSTamas Berghammer   if (error.Fail())
4081e209fccSTamas Berghammer     return error;
409567ba6c4SMuhammad Omair Javaid 
4101e209fccSTamas Berghammer   uint8_t *dst = data_sp->GetBytes();
411b6f9d7b8SMuhammad Omair Javaid   ::memcpy(dst, GetGPRBuffer(), GetGPRSize());
4121e209fccSTamas Berghammer   dst += GetGPRSize();
413b6f9d7b8SMuhammad Omair Javaid   ::memcpy(dst, GetFPRBuffer(), GetFPRSize());
4141e209fccSTamas Berghammer 
4151e209fccSTamas Berghammer   return error;
4161e209fccSTamas Berghammer }
4171e209fccSTamas Berghammer 
41897206d57SZachary Turner Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
419b9c1b51eSKate Stone     const lldb::DataBufferSP &data_sp) {
42097206d57SZachary Turner   Status error;
4211e209fccSTamas Berghammer 
422b9c1b51eSKate Stone   if (!data_sp) {
423b9c1b51eSKate Stone     error.SetErrorStringWithFormat(
424b9c1b51eSKate Stone         "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided",
425b9c1b51eSKate Stone         __FUNCTION__);
4261e209fccSTamas Berghammer     return error;
4271e209fccSTamas Berghammer   }
4281e209fccSTamas Berghammer 
429b9c1b51eSKate Stone   if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
430b9c1b51eSKate Stone     error.SetErrorStringWithFormat(
431b9c1b51eSKate Stone         "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched "
432b9c1b51eSKate Stone         "data size, expected %" PRIu64 ", actual %" PRIu64,
433b9c1b51eSKate Stone         __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
4341e209fccSTamas Berghammer     return error;
4351e209fccSTamas Berghammer   }
4361e209fccSTamas Berghammer 
4371e209fccSTamas Berghammer   uint8_t *src = data_sp->GetBytes();
438b9c1b51eSKate Stone   if (src == nullptr) {
439b9c1b51eSKate Stone     error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s "
440b9c1b51eSKate Stone                                    "DataBuffer::GetBytes() returned a null "
441b9c1b51eSKate Stone                                    "pointer",
442b9c1b51eSKate Stone                                    __FUNCTION__);
4431e209fccSTamas Berghammer     return error;
4441e209fccSTamas Berghammer   }
445b6f9d7b8SMuhammad Omair Javaid   ::memcpy(GetGPRBuffer(), src, GetRegisterInfoInterface().GetGPRSize());
4461e209fccSTamas Berghammer 
447068f8a7eSTamas Berghammer   error = WriteGPR();
448068f8a7eSTamas Berghammer   if (error.Fail())
4491e209fccSTamas Berghammer     return error;
4501e209fccSTamas Berghammer 
4511e209fccSTamas Berghammer   src += GetRegisterInfoInterface().GetGPRSize();
452b6f9d7b8SMuhammad Omair Javaid   ::memcpy(GetFPRBuffer(), src, GetFPRSize());
4531e209fccSTamas Berghammer 
454068f8a7eSTamas Berghammer   error = WriteFPR();
4551e209fccSTamas Berghammer   if (error.Fail())
4561e209fccSTamas Berghammer     return error;
4571e209fccSTamas Berghammer 
4581e209fccSTamas Berghammer   return error;
4591e209fccSTamas Berghammer }
4601e209fccSTamas Berghammer 
461b9c1b51eSKate Stone bool NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const {
4627fa7b81bSMuhammad Omair Javaid   if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
4637fa7b81bSMuhammad Omair Javaid       RegisterInfoPOSIX_arm64::GPRegSet)
4647fa7b81bSMuhammad Omair Javaid     return true;
4657fa7b81bSMuhammad Omair Javaid   return false;
4661e209fccSTamas Berghammer }
4671e209fccSTamas Berghammer 
468b9c1b51eSKate Stone bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const {
4697fa7b81bSMuhammad Omair Javaid   if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
4707fa7b81bSMuhammad Omair Javaid       RegisterInfoPOSIX_arm64::FPRegSet)
4717fa7b81bSMuhammad Omair Javaid     return true;
4727fa7b81bSMuhammad Omair Javaid   return false;
4731e209fccSTamas Berghammer }
4741e209fccSTamas Berghammer 
475567ba6c4SMuhammad Omair Javaid bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const {
476d6d3d21cSMuhammad Omair Javaid   return GetRegisterInfo().IsSVEReg(reg);
477567ba6c4SMuhammad Omair Javaid }
478567ba6c4SMuhammad Omair Javaid 
479771c4c9cSMichał Górny llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
480b9c1b51eSKate Stone   if (!m_refresh_hwdebug_info) {
481771c4c9cSMichał Górny     return llvm::Error::success();
4821fd2a8cfSOmair Javaid   }
4831fd2a8cfSOmair Javaid 
484c7512fdcSPavel Labath   ::pid_t tid = m_thread.GetID();
485ea8c25a8SOmair Javaid 
486c7512fdcSPavel Labath   int regset = NT_ARM_HW_WATCH;
487c7512fdcSPavel Labath   struct iovec ioVec;
488c7512fdcSPavel Labath   struct user_hwdebug_state dreg_state;
48997206d57SZachary Turner   Status error;
490c7512fdcSPavel Labath 
491c7512fdcSPavel Labath   ioVec.iov_base = &dreg_state;
492c7512fdcSPavel Labath   ioVec.iov_len = sizeof(dreg_state);
493b9c1b51eSKate Stone   error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,
494b9c1b51eSKate Stone                                             &ioVec, ioVec.iov_len);
4953a56363aSOmair Javaid 
4963a56363aSOmair Javaid   if (error.Fail())
497771c4c9cSMichał Górny     return error.ToError();
4983a56363aSOmair Javaid 
4991fd2a8cfSOmair Javaid   m_max_hwp_supported = dreg_state.dbg_info & 0xff;
500c7512fdcSPavel Labath 
501c7512fdcSPavel Labath   regset = NT_ARM_HW_BREAK;
502b9c1b51eSKate Stone   error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,
503b9c1b51eSKate Stone                                             &ioVec, ioVec.iov_len);
5041fd2a8cfSOmair Javaid 
5053a56363aSOmair Javaid   if (error.Fail())
506771c4c9cSMichał Górny     return error.ToError();
5073a56363aSOmair Javaid 
5083a56363aSOmair Javaid   m_max_hbp_supported = dreg_state.dbg_info & 0xff;
5091fd2a8cfSOmair Javaid   m_refresh_hwdebug_info = false;
510c7512fdcSPavel Labath 
511771c4c9cSMichał Górny   return llvm::Error::success();
512ea8c25a8SOmair Javaid }
513068f8a7eSTamas Berghammer 
514771c4c9cSMichał Górny llvm::Error
515771c4c9cSMichał Górny NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
516c7512fdcSPavel Labath   struct iovec ioVec;
517c7512fdcSPavel Labath   struct user_hwdebug_state dreg_state;
518771c4c9cSMichał Górny   int regset;
519c7512fdcSPavel Labath 
520c7512fdcSPavel Labath   memset(&dreg_state, 0, sizeof(dreg_state));
521c7512fdcSPavel Labath   ioVec.iov_base = &dreg_state;
522c7512fdcSPavel Labath 
523771c4c9cSMichał Górny   switch (hwbType) {
524771c4c9cSMichał Górny   case eDREGTypeWATCH:
525771c4c9cSMichał Górny     regset = NT_ARM_HW_WATCH;
526b9c1b51eSKate Stone     ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
527b9c1b51eSKate Stone                     (sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported);
5281fd2a8cfSOmair Javaid 
529b9c1b51eSKate Stone     for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
5301fd2a8cfSOmair Javaid       dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address;
5311fd2a8cfSOmair Javaid       dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control;
5321fd2a8cfSOmair Javaid     }
533771c4c9cSMichał Górny     break;
534771c4c9cSMichał Górny   case eDREGTypeBREAK:
535771c4c9cSMichał Górny     regset = NT_ARM_HW_BREAK;
536b9c1b51eSKate Stone     ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
537b9c1b51eSKate Stone                     (sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported);
5381fd2a8cfSOmair Javaid 
539b9c1b51eSKate Stone     for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
540771c4c9cSMichał Górny       dreg_state.dbg_regs[i].addr = m_hbp_regs[i].address;
541771c4c9cSMichał Górny       dreg_state.dbg_regs[i].ctrl = m_hbp_regs[i].control;
5421fd2a8cfSOmair Javaid     }
543771c4c9cSMichał Górny     break;
544068f8a7eSTamas Berghammer   }
545068f8a7eSTamas Berghammer 
546b9c1b51eSKate Stone   return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),
547771c4c9cSMichał Górny                                            &regset, &ioVec, ioVec.iov_len)
548771c4c9cSMichał Górny       .ToError();
549c7512fdcSPavel Labath }
550c7512fdcSPavel Labath 
5513f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::ReadGPR() {
552b6f9d7b8SMuhammad Omair Javaid   Status error;
553b6f9d7b8SMuhammad Omair Javaid 
554567ba6c4SMuhammad Omair Javaid   if (m_gpr_is_valid)
555567ba6c4SMuhammad Omair Javaid     return error;
556b6f9d7b8SMuhammad Omair Javaid 
557567ba6c4SMuhammad Omair Javaid   struct iovec ioVec;
5583f3673eaSPavel Labath   ioVec.iov_base = GetGPRBuffer();
55926b8ea2eSMuhammad Omair Javaid   ioVec.iov_len = GetGPRBufferSize();
560b6f9d7b8SMuhammad Omair Javaid 
56126b8ea2eSMuhammad Omair Javaid   error = ReadRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS);
562b6f9d7b8SMuhammad Omair Javaid 
563b6f9d7b8SMuhammad Omair Javaid   if (error.Success())
564b6f9d7b8SMuhammad Omair Javaid     m_gpr_is_valid = true;
565b6f9d7b8SMuhammad Omair Javaid 
566b6f9d7b8SMuhammad Omair Javaid   return error;
567068f8a7eSTamas Berghammer }
568068f8a7eSTamas Berghammer 
5693f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::WriteGPR() {
570567ba6c4SMuhammad Omair Javaid   Status error = ReadGPR();
571567ba6c4SMuhammad Omair Javaid   if (error.Fail())
572567ba6c4SMuhammad Omair Javaid     return error;
573567ba6c4SMuhammad Omair Javaid 
574c7512fdcSPavel Labath   struct iovec ioVec;
5753f3673eaSPavel Labath   ioVec.iov_base = GetGPRBuffer();
57626b8ea2eSMuhammad Omair Javaid   ioVec.iov_len = GetGPRBufferSize();
577b6f9d7b8SMuhammad Omair Javaid 
578567ba6c4SMuhammad Omair Javaid   m_gpr_is_valid = false;
579567ba6c4SMuhammad Omair Javaid 
58026b8ea2eSMuhammad Omair Javaid   return WriteRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS);
581068f8a7eSTamas Berghammer }
582068f8a7eSTamas Berghammer 
5833f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::ReadFPR() {
584b6f9d7b8SMuhammad Omair Javaid   Status error;
585b6f9d7b8SMuhammad Omair Javaid 
586567ba6c4SMuhammad Omair Javaid   if (m_fpu_is_valid)
587567ba6c4SMuhammad Omair Javaid     return error;
588b6f9d7b8SMuhammad Omair Javaid 
589567ba6c4SMuhammad Omair Javaid   struct iovec ioVec;
5903f3673eaSPavel Labath   ioVec.iov_base = GetFPRBuffer();
5913f3673eaSPavel Labath   ioVec.iov_len = GetFPRSize();
592b6f9d7b8SMuhammad Omair Javaid 
593b6f9d7b8SMuhammad Omair Javaid   error = ReadRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
594b6f9d7b8SMuhammad Omair Javaid 
595b6f9d7b8SMuhammad Omair Javaid   if (error.Success())
596b6f9d7b8SMuhammad Omair Javaid     m_fpu_is_valid = true;
597b6f9d7b8SMuhammad Omair Javaid 
598b6f9d7b8SMuhammad Omair Javaid   return error;
599068f8a7eSTamas Berghammer }
600068f8a7eSTamas Berghammer 
6013f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::WriteFPR() {
602567ba6c4SMuhammad Omair Javaid   Status error = ReadFPR();
603567ba6c4SMuhammad Omair Javaid   if (error.Fail())
604567ba6c4SMuhammad Omair Javaid     return error;
605567ba6c4SMuhammad Omair Javaid 
606c7512fdcSPavel Labath   struct iovec ioVec;
6073f3673eaSPavel Labath   ioVec.iov_base = GetFPRBuffer();
6083f3673eaSPavel Labath   ioVec.iov_len = GetFPRSize();
609b6f9d7b8SMuhammad Omair Javaid 
610567ba6c4SMuhammad Omair Javaid   m_fpu_is_valid = false;
611567ba6c4SMuhammad Omair Javaid 
6123f3673eaSPavel Labath   return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
613068f8a7eSTamas Berghammer }
614068f8a7eSTamas Berghammer 
615b6f9d7b8SMuhammad Omair Javaid void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() {
616b6f9d7b8SMuhammad Omair Javaid   m_gpr_is_valid = false;
617b6f9d7b8SMuhammad Omair Javaid   m_fpu_is_valid = false;
618567ba6c4SMuhammad Omair Javaid   m_sve_buffer_is_valid = false;
619567ba6c4SMuhammad Omair Javaid   m_sve_header_is_valid = false;
620567ba6c4SMuhammad Omair Javaid 
621567ba6c4SMuhammad Omair Javaid   // Update SVE registers in case there is change in configuration.
622567ba6c4SMuhammad Omair Javaid   ConfigureRegisterContext();
623567ba6c4SMuhammad Omair Javaid }
624567ba6c4SMuhammad Omair Javaid 
625567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
626567ba6c4SMuhammad Omair Javaid   Status error;
627567ba6c4SMuhammad Omair Javaid 
628567ba6c4SMuhammad Omair Javaid   if (m_sve_header_is_valid)
629567ba6c4SMuhammad Omair Javaid     return error;
630567ba6c4SMuhammad Omair Javaid 
631567ba6c4SMuhammad Omair Javaid   struct iovec ioVec;
632567ba6c4SMuhammad Omair Javaid   ioVec.iov_base = GetSVEHeader();
633567ba6c4SMuhammad Omair Javaid   ioVec.iov_len = GetSVEHeaderSize();
634567ba6c4SMuhammad Omair Javaid 
635567ba6c4SMuhammad Omair Javaid   error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE);
636567ba6c4SMuhammad Omair Javaid 
637567ba6c4SMuhammad Omair Javaid   m_sve_header_is_valid = true;
638567ba6c4SMuhammad Omair Javaid 
639567ba6c4SMuhammad Omair Javaid   return error;
640567ba6c4SMuhammad Omair Javaid }
641567ba6c4SMuhammad Omair Javaid 
642567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::WriteSVEHeader() {
643567ba6c4SMuhammad Omair Javaid   Status error;
644567ba6c4SMuhammad Omair Javaid 
645567ba6c4SMuhammad Omair Javaid   error = ReadSVEHeader();
646567ba6c4SMuhammad Omair Javaid   if (error.Fail())
647567ba6c4SMuhammad Omair Javaid     return error;
648567ba6c4SMuhammad Omair Javaid 
649567ba6c4SMuhammad Omair Javaid   struct iovec ioVec;
650567ba6c4SMuhammad Omair Javaid   ioVec.iov_base = GetSVEHeader();
651567ba6c4SMuhammad Omair Javaid   ioVec.iov_len = GetSVEHeaderSize();
652567ba6c4SMuhammad Omair Javaid 
653567ba6c4SMuhammad Omair Javaid   m_sve_buffer_is_valid = false;
654567ba6c4SMuhammad Omair Javaid   m_sve_header_is_valid = false;
655567ba6c4SMuhammad Omair Javaid   m_fpu_is_valid = false;
656567ba6c4SMuhammad Omair Javaid 
657567ba6c4SMuhammad Omair Javaid   return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE);
658567ba6c4SMuhammad Omair Javaid }
659567ba6c4SMuhammad Omair Javaid 
660567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::ReadAllSVE() {
661567ba6c4SMuhammad Omair Javaid   Status error;
662567ba6c4SMuhammad Omair Javaid 
663567ba6c4SMuhammad Omair Javaid   if (m_sve_buffer_is_valid)
664567ba6c4SMuhammad Omair Javaid     return error;
665567ba6c4SMuhammad Omair Javaid 
666567ba6c4SMuhammad Omair Javaid   struct iovec ioVec;
667567ba6c4SMuhammad Omair Javaid   ioVec.iov_base = GetSVEBuffer();
668567ba6c4SMuhammad Omair Javaid   ioVec.iov_len = GetSVEBufferSize();
669567ba6c4SMuhammad Omair Javaid 
670567ba6c4SMuhammad Omair Javaid   error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE);
671567ba6c4SMuhammad Omair Javaid 
672567ba6c4SMuhammad Omair Javaid   if (error.Success())
673567ba6c4SMuhammad Omair Javaid     m_sve_buffer_is_valid = true;
674567ba6c4SMuhammad Omair Javaid 
675567ba6c4SMuhammad Omair Javaid   return error;
676567ba6c4SMuhammad Omair Javaid }
677567ba6c4SMuhammad Omair Javaid 
678567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::WriteAllSVE() {
679567ba6c4SMuhammad Omair Javaid   Status error;
680567ba6c4SMuhammad Omair Javaid 
681567ba6c4SMuhammad Omair Javaid   error = ReadAllSVE();
682567ba6c4SMuhammad Omair Javaid   if (error.Fail())
683567ba6c4SMuhammad Omair Javaid     return error;
684567ba6c4SMuhammad Omair Javaid 
685567ba6c4SMuhammad Omair Javaid   struct iovec ioVec;
686567ba6c4SMuhammad Omair Javaid 
687567ba6c4SMuhammad Omair Javaid   ioVec.iov_base = GetSVEBuffer();
688567ba6c4SMuhammad Omair Javaid   ioVec.iov_len = GetSVEBufferSize();
689567ba6c4SMuhammad Omair Javaid 
690567ba6c4SMuhammad Omair Javaid   m_sve_buffer_is_valid = false;
691567ba6c4SMuhammad Omair Javaid   m_sve_header_is_valid = false;
692567ba6c4SMuhammad Omair Javaid   m_fpu_is_valid = false;
693567ba6c4SMuhammad Omair Javaid 
694567ba6c4SMuhammad Omair Javaid   return WriteRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE);
695567ba6c4SMuhammad Omair Javaid }
696567ba6c4SMuhammad Omair Javaid 
697567ba6c4SMuhammad Omair Javaid void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
698d6d3d21cSMuhammad Omair Javaid   // ConfigureRegisterContext gets called from InvalidateAllRegisters
699d6d3d21cSMuhammad Omair Javaid   // on every stop and configures SVE vector length.
700d6d3d21cSMuhammad Omair Javaid   // If m_sve_state is set to SVEState::Disabled on first stop, code below will
701d6d3d21cSMuhammad Omair Javaid   // be deemed non operational for the lifetime of current process.
702567ba6c4SMuhammad Omair Javaid   if (!m_sve_header_is_valid && m_sve_state != SVEState::Disabled) {
703567ba6c4SMuhammad Omair Javaid     Status error = ReadSVEHeader();
704d6d3d21cSMuhammad Omair Javaid     if (error.Success()) {
705d6d3d21cSMuhammad Omair Javaid       // If SVE is enabled thread can switch between SVEState::FPSIMD and
706d6d3d21cSMuhammad Omair Javaid       // SVEState::Full on every stop.
707567ba6c4SMuhammad Omair Javaid       if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD)
708567ba6c4SMuhammad Omair Javaid         m_sve_state = SVEState::FPSIMD;
709567ba6c4SMuhammad Omair Javaid       else if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE)
710567ba6c4SMuhammad Omair Javaid         m_sve_state = SVEState::Full;
711567ba6c4SMuhammad Omair Javaid 
712d6d3d21cSMuhammad Omair Javaid       // On every stop we configure SVE vector length by calling
713d6d3d21cSMuhammad Omair Javaid       // ConfigureVectorLength regardless of current SVEState of this thread.
714567ba6c4SMuhammad Omair Javaid       uint32_t vq = RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64SVE;
715567ba6c4SMuhammad Omair Javaid       if (sve_vl_valid(m_sve_header.vl))
716567ba6c4SMuhammad Omair Javaid         vq = sve_vq_from_vl(m_sve_header.vl);
717d6d3d21cSMuhammad Omair Javaid 
718d6d3d21cSMuhammad Omair Javaid       GetRegisterInfo().ConfigureVectorLength(vq);
719567ba6c4SMuhammad Omair Javaid       m_sve_ptrace_payload.resize(SVE_PT_SIZE(vq, SVE_PT_REGS_SVE));
720567ba6c4SMuhammad Omair Javaid     }
721567ba6c4SMuhammad Omair Javaid   }
722b6f9d7b8SMuhammad Omair Javaid }
723b6f9d7b8SMuhammad Omair Javaid 
724b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset(
725b9c1b51eSKate Stone     const RegisterInfo *reg_info) const {
7267fa7b81bSMuhammad Omair Javaid   return reg_info->byte_offset - GetGPRSize();
727c40e7b17STamas Berghammer }
728c40e7b17STamas Berghammer 
729567ba6c4SMuhammad Omair Javaid uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset(
730567ba6c4SMuhammad Omair Javaid     const RegisterInfo *reg_info) const {
731567ba6c4SMuhammad Omair Javaid   // Start of Z0 data is after GPRs plus 8 bytes of vg register
732567ba6c4SMuhammad Omair Javaid   uint32_t sve_reg_offset = LLDB_INVALID_INDEX32;
733567ba6c4SMuhammad Omair Javaid   if (m_sve_state == SVEState::FPSIMD) {
734567ba6c4SMuhammad Omair Javaid     const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
735567ba6c4SMuhammad Omair Javaid     sve_reg_offset =
736567ba6c4SMuhammad Omair Javaid         SVE_PT_FPSIMD_OFFSET + (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16;
737567ba6c4SMuhammad Omair Javaid   } else if (m_sve_state == SVEState::Full) {
738661e4040SMuhammad Omair Javaid     uint32_t sve_z0_offset = GetGPRSize() + 16;
739567ba6c4SMuhammad Omair Javaid     sve_reg_offset =
740567ba6c4SMuhammad Omair Javaid         SVE_SIG_REGS_OFFSET + reg_info->byte_offset - sve_z0_offset;
741567ba6c4SMuhammad Omair Javaid   }
742567ba6c4SMuhammad Omair Javaid   return sve_reg_offset;
743567ba6c4SMuhammad Omair Javaid }
744567ba6c4SMuhammad Omair Javaid 
745567ba6c4SMuhammad Omair Javaid void *NativeRegisterContextLinux_arm64::GetSVEBuffer() {
746567ba6c4SMuhammad Omair Javaid   if (m_sve_state == SVEState::FPSIMD)
747567ba6c4SMuhammad Omair Javaid     return m_sve_ptrace_payload.data() + SVE_PT_FPSIMD_OFFSET;
748567ba6c4SMuhammad Omair Javaid 
749567ba6c4SMuhammad Omair Javaid   return m_sve_ptrace_payload.data();
750567ba6c4SMuhammad Omair Javaid }
751567ba6c4SMuhammad Omair Javaid 
7524e8aeb97SMuhammad Omair Javaid std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters(
7534e8aeb97SMuhammad Omair Javaid     ExpeditedRegs expType) const {
7544e8aeb97SMuhammad Omair Javaid   std::vector<uint32_t> expedited_reg_nums =
7554e8aeb97SMuhammad Omair Javaid       NativeRegisterContext::GetExpeditedRegisters(expType);
7564e8aeb97SMuhammad Omair Javaid   if (m_sve_state == SVEState::FPSIMD || m_sve_state == SVEState::Full)
7574e8aeb97SMuhammad Omair Javaid     expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG());
7584e8aeb97SMuhammad Omair Javaid 
7594e8aeb97SMuhammad Omair Javaid   return expedited_reg_nums;
7604e8aeb97SMuhammad Omair Javaid }
7614e8aeb97SMuhammad Omair Javaid 
762068f8a7eSTamas Berghammer #endif // defined (__arm64__) || defined (__aarch64__)
763