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(
44d37349f3SPavel Labath     const ArchSpec &target_arch, NativeThreadProtocol &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);
49e85e6021STamas Berghammer   case llvm::Triple::aarch64:
50a8f3ae7cSJonas Devlieghere     return std::make_unique<NativeRegisterContextLinux_arm64>(target_arch,
51d37349f3SPavel Labath                                                                native_thread);
52e85e6021STamas Berghammer   default:
53ea1b6b17SPavel Labath     llvm_unreachable("have no register context for architecture");
54e85e6021STamas Berghammer   }
55068f8a7eSTamas Berghammer }
56068f8a7eSTamas Berghammer 
57b9c1b51eSKate Stone NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
58d37349f3SPavel Labath     const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
59f5ca2756SMichał Górny     : NativeRegisterContextRegisterInfo(
60f5ca2756SMichał Górny           native_thread, new RegisterInfoPOSIX_arm64(target_arch)) {
611e209fccSTamas Berghammer   ::memset(&m_fpr, 0, sizeof(m_fpr));
621e209fccSTamas Berghammer   ::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64));
63ea8c25a8SOmair Javaid   ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
64*771c4c9cSMichał Górny   ::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs));
65567ba6c4SMuhammad Omair Javaid   ::memset(&m_sve_header, 0, sizeof(m_sve_header));
66ea8c25a8SOmair Javaid 
67ea8c25a8SOmair Javaid   // 16 is just a maximum value, query hardware for actual watchpoint count
68ea8c25a8SOmair Javaid   m_max_hwp_supported = 16;
69ea8c25a8SOmair Javaid   m_max_hbp_supported = 16;
70567ba6c4SMuhammad Omair Javaid 
71ea8c25a8SOmair Javaid   m_refresh_hwdebug_info = true;
72b6f9d7b8SMuhammad Omair Javaid 
73b6f9d7b8SMuhammad Omair Javaid   m_gpr_is_valid = false;
74b6f9d7b8SMuhammad Omair Javaid   m_fpu_is_valid = false;
75567ba6c4SMuhammad Omair Javaid   m_sve_buffer_is_valid = false;
76567ba6c4SMuhammad Omair Javaid   m_sve_header_is_valid = false;
77567ba6c4SMuhammad Omair Javaid 
78567ba6c4SMuhammad Omair Javaid   // SVE is not enabled until we query user_sve_header
79567ba6c4SMuhammad Omair Javaid   m_sve_state = SVEState::Unknown;
801e209fccSTamas Berghammer }
811e209fccSTamas Berghammer 
827fa7b81bSMuhammad Omair Javaid RegisterInfoPOSIX_arm64 &
837fa7b81bSMuhammad Omair Javaid NativeRegisterContextLinux_arm64::GetRegisterInfo() const {
847fa7b81bSMuhammad Omair Javaid   return static_cast<RegisterInfoPOSIX_arm64 &>(*m_register_info_interface_up);
857fa7b81bSMuhammad Omair Javaid }
867fa7b81bSMuhammad Omair Javaid 
87b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount() const {
887fa7b81bSMuhammad Omair Javaid   return GetRegisterInfo().GetRegisterSetCount();
891e209fccSTamas Berghammer }
901e209fccSTamas Berghammer 
91db264a6dSTamas Berghammer const RegisterSet *
92b9c1b51eSKate Stone NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index) const {
937fa7b81bSMuhammad Omair Javaid   return GetRegisterInfo().GetRegisterSet(set_index);
941e209fccSTamas Berghammer }
951e209fccSTamas Berghammer 
96b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount() const {
97cec93c35STamas Berghammer   uint32_t count = 0;
987fa7b81bSMuhammad Omair Javaid   for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
997fa7b81bSMuhammad Omair Javaid     count += GetRegisterSet(set_index)->num_registers;
100cec93c35STamas Berghammer   return count;
101cec93c35STamas Berghammer }
102cec93c35STamas Berghammer 
10397206d57SZachary Turner Status
10497206d57SZachary Turner NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info,
10597206d57SZachary Turner                                                RegisterValue &reg_value) {
10697206d57SZachary Turner   Status error;
1071e209fccSTamas Berghammer 
108b9c1b51eSKate Stone   if (!reg_info) {
1091e209fccSTamas Berghammer     error.SetErrorString("reg_info NULL");
1101e209fccSTamas Berghammer     return error;
1111e209fccSTamas Berghammer   }
1121e209fccSTamas Berghammer 
1131e209fccSTamas Berghammer   const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
1141e209fccSTamas Berghammer 
115b6f9d7b8SMuhammad Omair Javaid   if (reg == LLDB_INVALID_REGNUM)
116b6f9d7b8SMuhammad Omair Javaid     return Status("no lldb regnum for %s", reg_info && reg_info->name
117b6f9d7b8SMuhammad Omair Javaid                                                ? reg_info->name
118b6f9d7b8SMuhammad Omair Javaid                                                : "<unknown register>");
119b6f9d7b8SMuhammad Omair Javaid 
120b6f9d7b8SMuhammad Omair Javaid   uint8_t *src;
1214283320bSMuhammad Omair Javaid   uint32_t offset = LLDB_INVALID_INDEX32;
122567ba6c4SMuhammad Omair Javaid   uint64_t sve_vg;
123567ba6c4SMuhammad Omair Javaid   std::vector<uint8_t> sve_reg_non_live;
124b6f9d7b8SMuhammad Omair Javaid 
125b6f9d7b8SMuhammad Omair Javaid   if (IsGPR(reg)) {
126b6f9d7b8SMuhammad Omair Javaid     error = ReadGPR();
127b6f9d7b8SMuhammad Omair Javaid     if (error.Fail())
128b6f9d7b8SMuhammad Omair Javaid       return error;
129b6f9d7b8SMuhammad Omair Javaid 
130b6f9d7b8SMuhammad Omair Javaid     offset = reg_info->byte_offset;
131b6f9d7b8SMuhammad Omair Javaid     assert(offset < GetGPRSize());
132b6f9d7b8SMuhammad Omair Javaid     src = (uint8_t *)GetGPRBuffer() + offset;
133b6f9d7b8SMuhammad Omair Javaid 
134b6f9d7b8SMuhammad Omair Javaid   } else if (IsFPR(reg)) {
135567ba6c4SMuhammad Omair Javaid     if (m_sve_state == SVEState::Disabled) {
136567ba6c4SMuhammad Omair Javaid       // SVE is disabled take legacy route for FPU register access
137068f8a7eSTamas Berghammer       error = ReadFPR();
138068f8a7eSTamas Berghammer       if (error.Fail())
1391e209fccSTamas Berghammer         return error;
140567ba6c4SMuhammad Omair Javaid 
141b6f9d7b8SMuhammad Omair Javaid       offset = CalculateFprOffset(reg_info);
142b6f9d7b8SMuhammad Omair Javaid       assert(offset < GetFPRSize());
143b6f9d7b8SMuhammad Omair Javaid       src = (uint8_t *)GetFPRBuffer() + offset;
144567ba6c4SMuhammad Omair Javaid     } else {
145567ba6c4SMuhammad Omair Javaid       // SVE enabled, we will read and cache SVE ptrace data
146567ba6c4SMuhammad Omair Javaid       error = ReadAllSVE();
147567ba6c4SMuhammad Omair Javaid       if (error.Fail())
148567ba6c4SMuhammad Omair Javaid         return error;
149567ba6c4SMuhammad Omair Javaid 
150567ba6c4SMuhammad Omair Javaid       // FPSR and FPCR will be located right after Z registers in
151567ba6c4SMuhammad Omair Javaid       // SVEState::FPSIMD while in SVEState::Full they will be located at the
152567ba6c4SMuhammad Omair Javaid       // end of register data after an alignment correction based on currently
153567ba6c4SMuhammad Omair Javaid       // selected vector length.
154567ba6c4SMuhammad Omair Javaid       uint32_t sve_reg_num = LLDB_INVALID_REGNUM;
155567ba6c4SMuhammad Omair Javaid       if (reg == GetRegisterInfo().GetRegNumFPSR()) {
156567ba6c4SMuhammad Omair Javaid         sve_reg_num = reg;
157567ba6c4SMuhammad Omair Javaid         if (m_sve_state == SVEState::Full)
158567ba6c4SMuhammad Omair Javaid           offset = SVE_PT_SVE_FPSR_OFFSET(sve_vq_from_vl(m_sve_header.vl));
159567ba6c4SMuhammad Omair Javaid         else if (m_sve_state == SVEState::FPSIMD)
160567ba6c4SMuhammad Omair Javaid           offset = SVE_PT_FPSIMD_OFFSET + (32 * 16);
161567ba6c4SMuhammad Omair Javaid       } else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
162567ba6c4SMuhammad Omair Javaid         sve_reg_num = reg;
163567ba6c4SMuhammad Omair Javaid         if (m_sve_state == SVEState::Full)
164567ba6c4SMuhammad Omair Javaid           offset = SVE_PT_SVE_FPCR_OFFSET(sve_vq_from_vl(m_sve_header.vl));
165567ba6c4SMuhammad Omair Javaid         else if (m_sve_state == SVEState::FPSIMD)
166567ba6c4SMuhammad Omair Javaid           offset = SVE_PT_FPSIMD_OFFSET + (32 * 16) + 4;
167567ba6c4SMuhammad Omair Javaid       } else {
168567ba6c4SMuhammad Omair Javaid         // Extract SVE Z register value register number for this reg_info
169567ba6c4SMuhammad Omair Javaid         if (reg_info->value_regs &&
170567ba6c4SMuhammad Omair Javaid             reg_info->value_regs[0] != LLDB_INVALID_REGNUM)
171567ba6c4SMuhammad Omair Javaid           sve_reg_num = reg_info->value_regs[0];
172567ba6c4SMuhammad Omair Javaid         offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
173567ba6c4SMuhammad Omair Javaid       }
174567ba6c4SMuhammad Omair Javaid 
175567ba6c4SMuhammad Omair Javaid       assert(offset < GetSVEBufferSize());
176567ba6c4SMuhammad Omair Javaid       src = (uint8_t *)GetSVEBuffer() + offset;
177567ba6c4SMuhammad Omair Javaid     }
178567ba6c4SMuhammad Omair Javaid   } else if (IsSVE(reg)) {
179567ba6c4SMuhammad Omair Javaid 
180567ba6c4SMuhammad Omair Javaid     if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown)
181567ba6c4SMuhammad Omair Javaid       return Status("SVE disabled or not supported");
182567ba6c4SMuhammad Omair Javaid 
183567ba6c4SMuhammad Omair Javaid     if (GetRegisterInfo().IsSVERegVG(reg)) {
184567ba6c4SMuhammad Omair Javaid       sve_vg = GetSVERegVG();
185567ba6c4SMuhammad Omair Javaid       src = (uint8_t *)&sve_vg;
186567ba6c4SMuhammad Omair Javaid     } else {
187567ba6c4SMuhammad Omair Javaid       // SVE enabled, we will read and cache SVE ptrace data
188567ba6c4SMuhammad Omair Javaid       error = ReadAllSVE();
189567ba6c4SMuhammad Omair Javaid       if (error.Fail())
190567ba6c4SMuhammad Omair Javaid         return error;
191567ba6c4SMuhammad Omair Javaid 
192567ba6c4SMuhammad Omair Javaid       if (m_sve_state == SVEState::FPSIMD) {
193567ba6c4SMuhammad Omair Javaid         // In FPSIMD state SVE payload mirrors legacy fpsimd struct and so
194567ba6c4SMuhammad Omair Javaid         // just copy 16 bytes of v register to the start of z register. All
195567ba6c4SMuhammad Omair Javaid         // other SVE register will be set to zero.
196567ba6c4SMuhammad Omair Javaid         sve_reg_non_live.resize(reg_info->byte_size, 0);
197567ba6c4SMuhammad Omair Javaid         src = sve_reg_non_live.data();
198567ba6c4SMuhammad Omair Javaid 
199567ba6c4SMuhammad Omair Javaid         if (GetRegisterInfo().IsSVEZReg(reg)) {
200567ba6c4SMuhammad Omair Javaid           offset = CalculateSVEOffset(reg_info);
201567ba6c4SMuhammad Omair Javaid           assert(offset < GetSVEBufferSize());
202567ba6c4SMuhammad Omair Javaid           ::memcpy(sve_reg_non_live.data(), (uint8_t *)GetSVEBuffer() + offset,
203567ba6c4SMuhammad Omair Javaid                    16);
204567ba6c4SMuhammad Omair Javaid         }
205567ba6c4SMuhammad Omair Javaid       } else {
206567ba6c4SMuhammad Omair Javaid         offset = CalculateSVEOffset(reg_info);
207567ba6c4SMuhammad Omair Javaid         assert(offset < GetSVEBufferSize());
208567ba6c4SMuhammad Omair Javaid         src = (uint8_t *)GetSVEBuffer() + offset;
209567ba6c4SMuhammad Omair Javaid       }
210567ba6c4SMuhammad Omair Javaid     }
211b6f9d7b8SMuhammad Omair Javaid   } else
212b6f9d7b8SMuhammad Omair Javaid     return Status("failed - register wasn't recognized to be a GPR or an FPR, "
213b6f9d7b8SMuhammad Omair Javaid                   "write strategy unknown");
2141e209fccSTamas Berghammer 
215b9c1b51eSKate Stone   reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size,
216b9c1b51eSKate Stone                               eByteOrderLittle, error);
2171e209fccSTamas Berghammer 
2181e209fccSTamas Berghammer   return error;
2191e209fccSTamas Berghammer }
2201e209fccSTamas Berghammer 
22197206d57SZachary Turner Status NativeRegisterContextLinux_arm64::WriteRegister(
222b9c1b51eSKate Stone     const RegisterInfo *reg_info, const RegisterValue &reg_value) {
223b6f9d7b8SMuhammad Omair Javaid   Status error;
224b6f9d7b8SMuhammad Omair Javaid 
2251e209fccSTamas Berghammer   if (!reg_info)
22697206d57SZachary Turner     return Status("reg_info NULL");
2271e209fccSTamas Berghammer 
228b6f9d7b8SMuhammad Omair Javaid   const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
229b6f9d7b8SMuhammad Omair Javaid 
230b6f9d7b8SMuhammad Omair Javaid   if (reg == LLDB_INVALID_REGNUM)
23197206d57SZachary Turner     return Status("no lldb regnum for %s", reg_info && reg_info->name
232b9c1b51eSKate Stone                                                ? reg_info->name
233b9c1b51eSKate Stone                                                : "<unknown register>");
2341e209fccSTamas Berghammer 
235b6f9d7b8SMuhammad Omair Javaid   uint8_t *dst;
2364283320bSMuhammad Omair Javaid   uint32_t offset = LLDB_INVALID_INDEX32;
237567ba6c4SMuhammad Omair Javaid   std::vector<uint8_t> sve_reg_non_live;
2381e209fccSTamas Berghammer 
239b6f9d7b8SMuhammad Omair Javaid   if (IsGPR(reg)) {
240b6f9d7b8SMuhammad Omair Javaid     error = ReadGPR();
241068f8a7eSTamas Berghammer     if (error.Fail())
242068f8a7eSTamas Berghammer       return error;
2431e209fccSTamas Berghammer 
244567ba6c4SMuhammad Omair Javaid     assert(reg_info->byte_offset < GetGPRSize());
245567ba6c4SMuhammad Omair Javaid     dst = (uint8_t *)GetGPRBuffer() + reg_info->byte_offset;
246b6f9d7b8SMuhammad Omair Javaid     ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
247b6f9d7b8SMuhammad Omair Javaid 
248b6f9d7b8SMuhammad Omair Javaid     return WriteGPR();
249b6f9d7b8SMuhammad Omair Javaid   } else if (IsFPR(reg)) {
250567ba6c4SMuhammad Omair Javaid     if (m_sve_state == SVEState::Disabled) {
251567ba6c4SMuhammad Omair Javaid       // SVE is disabled take legacy route for FPU register access
252b6f9d7b8SMuhammad Omair Javaid       error = ReadFPR();
253b6f9d7b8SMuhammad Omair Javaid       if (error.Fail())
254b6f9d7b8SMuhammad Omair Javaid         return error;
255567ba6c4SMuhammad Omair Javaid 
256b6f9d7b8SMuhammad Omair Javaid       offset = CalculateFprOffset(reg_info);
257b6f9d7b8SMuhammad Omair Javaid       assert(offset < GetFPRSize());
258b6f9d7b8SMuhammad Omair Javaid       dst = (uint8_t *)GetFPRBuffer() + offset;
259b6f9d7b8SMuhammad Omair Javaid       ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
260b6f9d7b8SMuhammad Omair Javaid 
261b6f9d7b8SMuhammad Omair Javaid       return WriteFPR();
262567ba6c4SMuhammad Omair Javaid     } else {
263567ba6c4SMuhammad Omair Javaid       // SVE enabled, we will read and cache SVE ptrace data
264567ba6c4SMuhammad Omair Javaid       error = ReadAllSVE();
265567ba6c4SMuhammad Omair Javaid       if (error.Fail())
266567ba6c4SMuhammad Omair Javaid         return error;
267567ba6c4SMuhammad Omair Javaid 
268567ba6c4SMuhammad Omair Javaid       // FPSR and FPCR will be located right after Z registers in
269567ba6c4SMuhammad Omair Javaid       // SVEState::FPSIMD while in SVEState::Full they will be located at the
270567ba6c4SMuhammad Omair Javaid       // end of register data after an alignment correction based on currently
271567ba6c4SMuhammad Omair Javaid       // selected vector length.
272567ba6c4SMuhammad Omair Javaid       uint32_t sve_reg_num = LLDB_INVALID_REGNUM;
273567ba6c4SMuhammad Omair Javaid       if (reg == GetRegisterInfo().GetRegNumFPSR()) {
274567ba6c4SMuhammad Omair Javaid         sve_reg_num = reg;
275567ba6c4SMuhammad Omair Javaid         if (m_sve_state == SVEState::Full)
276567ba6c4SMuhammad Omair Javaid           offset = SVE_PT_SVE_FPSR_OFFSET(sve_vq_from_vl(m_sve_header.vl));
277567ba6c4SMuhammad Omair Javaid         else if (m_sve_state == SVEState::FPSIMD)
278567ba6c4SMuhammad Omair Javaid           offset = SVE_PT_FPSIMD_OFFSET + (32 * 16);
279567ba6c4SMuhammad Omair Javaid       } else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
280567ba6c4SMuhammad Omair Javaid         sve_reg_num = reg;
281567ba6c4SMuhammad Omair Javaid         if (m_sve_state == SVEState::Full)
282567ba6c4SMuhammad Omair Javaid           offset = SVE_PT_SVE_FPCR_OFFSET(sve_vq_from_vl(m_sve_header.vl));
283567ba6c4SMuhammad Omair Javaid         else if (m_sve_state == SVEState::FPSIMD)
284567ba6c4SMuhammad Omair Javaid           offset = SVE_PT_FPSIMD_OFFSET + (32 * 16) + 4;
285567ba6c4SMuhammad Omair Javaid       } else {
286567ba6c4SMuhammad Omair Javaid         // Extract SVE Z register value register number for this reg_info
287567ba6c4SMuhammad Omair Javaid         if (reg_info->value_regs &&
288567ba6c4SMuhammad Omair Javaid             reg_info->value_regs[0] != LLDB_INVALID_REGNUM)
289567ba6c4SMuhammad Omair Javaid           sve_reg_num = reg_info->value_regs[0];
290567ba6c4SMuhammad Omair Javaid         offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
291b6f9d7b8SMuhammad Omair Javaid       }
292b6f9d7b8SMuhammad Omair Javaid 
293567ba6c4SMuhammad Omair Javaid       assert(offset < GetSVEBufferSize());
294567ba6c4SMuhammad Omair Javaid       dst = (uint8_t *)GetSVEBuffer() + offset;
295567ba6c4SMuhammad Omair Javaid       ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
296567ba6c4SMuhammad Omair Javaid       return WriteAllSVE();
297567ba6c4SMuhammad Omair Javaid     }
298567ba6c4SMuhammad Omair Javaid   } else if (IsSVE(reg)) {
299567ba6c4SMuhammad Omair Javaid     if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown)
300567ba6c4SMuhammad Omair Javaid       return Status("SVE disabled or not supported");
301567ba6c4SMuhammad Omair Javaid     else {
302567ba6c4SMuhammad Omair Javaid       // Target has SVE enabled, we will read and cache SVE ptrace data
303567ba6c4SMuhammad Omair Javaid       error = ReadAllSVE();
304567ba6c4SMuhammad Omair Javaid       if (error.Fail())
305b6f9d7b8SMuhammad Omair Javaid         return error;
306567ba6c4SMuhammad Omair Javaid 
307e448ad78SMuhammad Omair Javaid       if (GetRegisterInfo().IsSVERegVG(reg)) {
308e448ad78SMuhammad Omair Javaid         uint64_t vg_value = reg_value.GetAsUInt64();
309e448ad78SMuhammad Omair Javaid 
310e448ad78SMuhammad Omair Javaid         if (sve_vl_valid(vg_value * 8)) {
311e448ad78SMuhammad Omair Javaid           if (m_sve_header_is_valid && vg_value == GetSVERegVG())
312e448ad78SMuhammad Omair Javaid             return error;
313e448ad78SMuhammad Omair Javaid 
314e448ad78SMuhammad Omair Javaid           SetSVERegVG(vg_value);
315e448ad78SMuhammad Omair Javaid 
316e448ad78SMuhammad Omair Javaid           error = WriteSVEHeader();
317e448ad78SMuhammad Omair Javaid           if (error.Success())
318e448ad78SMuhammad Omair Javaid             ConfigureRegisterContext();
319e448ad78SMuhammad Omair Javaid 
320e448ad78SMuhammad Omair Javaid           if (m_sve_header_is_valid && vg_value == GetSVERegVG())
321e448ad78SMuhammad Omair Javaid             return error;
322e448ad78SMuhammad Omair Javaid         }
323e448ad78SMuhammad Omair Javaid 
324e448ad78SMuhammad Omair Javaid         return Status("SVE vector length update failed.");
325e448ad78SMuhammad Omair Javaid       }
326e448ad78SMuhammad Omair Javaid 
327567ba6c4SMuhammad Omair Javaid       // If target supports SVE but currently in FPSIMD mode.
328567ba6c4SMuhammad Omair Javaid       if (m_sve_state == SVEState::FPSIMD) {
329567ba6c4SMuhammad Omair Javaid         // Here we will check if writing this SVE register enables
330567ba6c4SMuhammad Omair Javaid         // SVEState::Full
331567ba6c4SMuhammad Omair Javaid         bool set_sve_state_full = false;
332567ba6c4SMuhammad Omair Javaid         const uint8_t *reg_bytes = (const uint8_t *)reg_value.GetBytes();
333567ba6c4SMuhammad Omair Javaid         if (GetRegisterInfo().IsSVEZReg(reg)) {
334567ba6c4SMuhammad Omair Javaid           for (uint32_t i = 16; i < reg_info->byte_size; i++) {
335567ba6c4SMuhammad Omair Javaid             if (reg_bytes[i]) {
336567ba6c4SMuhammad Omair Javaid               set_sve_state_full = true;
337567ba6c4SMuhammad Omair Javaid               break;
338567ba6c4SMuhammad Omair Javaid             }
339567ba6c4SMuhammad Omair Javaid           }
340567ba6c4SMuhammad Omair Javaid         } else if (GetRegisterInfo().IsSVEPReg(reg) ||
341567ba6c4SMuhammad Omair Javaid                    reg == GetRegisterInfo().GetRegNumSVEFFR()) {
342567ba6c4SMuhammad Omair Javaid           for (uint32_t i = 0; i < reg_info->byte_size; i++) {
343567ba6c4SMuhammad Omair Javaid             if (reg_bytes[i]) {
344567ba6c4SMuhammad Omair Javaid               set_sve_state_full = true;
345567ba6c4SMuhammad Omair Javaid               break;
346567ba6c4SMuhammad Omair Javaid             }
347567ba6c4SMuhammad Omair Javaid           }
348567ba6c4SMuhammad Omair Javaid         }
349567ba6c4SMuhammad Omair Javaid 
350567ba6c4SMuhammad Omair Javaid         if (!set_sve_state_full && GetRegisterInfo().IsSVEZReg(reg)) {
351567ba6c4SMuhammad Omair Javaid           // We are writing a Z register which is zero beyond 16 bytes so copy
352567ba6c4SMuhammad Omair Javaid           // first 16 bytes only as SVE payload mirrors legacy fpsimd structure
353567ba6c4SMuhammad Omair Javaid           offset = CalculateSVEOffset(reg_info);
354567ba6c4SMuhammad Omair Javaid           assert(offset < GetSVEBufferSize());
355567ba6c4SMuhammad Omair Javaid           dst = (uint8_t *)GetSVEBuffer() + offset;
356567ba6c4SMuhammad Omair Javaid           ::memcpy(dst, reg_value.GetBytes(), 16);
357567ba6c4SMuhammad Omair Javaid 
358567ba6c4SMuhammad Omair Javaid           return WriteAllSVE();
359567ba6c4SMuhammad Omair Javaid         } else
360567ba6c4SMuhammad Omair Javaid           return Status("SVE state change operation not supported");
361567ba6c4SMuhammad Omair Javaid       } else {
362567ba6c4SMuhammad Omair Javaid         offset = CalculateSVEOffset(reg_info);
363567ba6c4SMuhammad Omair Javaid         assert(offset < GetSVEBufferSize());
364567ba6c4SMuhammad Omair Javaid         dst = (uint8_t *)GetSVEBuffer() + offset;
365567ba6c4SMuhammad Omair Javaid         ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
366567ba6c4SMuhammad Omair Javaid         return WriteAllSVE();
367567ba6c4SMuhammad Omair Javaid       }
368567ba6c4SMuhammad Omair Javaid     }
369567ba6c4SMuhammad Omair Javaid   }
370567ba6c4SMuhammad Omair Javaid 
371567ba6c4SMuhammad Omair Javaid   return Status("Failed to write register value");
3721e209fccSTamas Berghammer }
3731e209fccSTamas Berghammer 
37497206d57SZachary Turner Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues(
375b9c1b51eSKate Stone     lldb::DataBufferSP &data_sp) {
37697206d57SZachary Turner   Status error;
3771e209fccSTamas Berghammer 
378db264a6dSTamas Berghammer   data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
379567ba6c4SMuhammad Omair Javaid 
380068f8a7eSTamas Berghammer   error = ReadGPR();
381068f8a7eSTamas Berghammer   if (error.Fail())
3821e209fccSTamas Berghammer     return error;
3831e209fccSTamas Berghammer 
384068f8a7eSTamas Berghammer   error = ReadFPR();
385068f8a7eSTamas Berghammer   if (error.Fail())
3861e209fccSTamas Berghammer     return error;
387567ba6c4SMuhammad Omair Javaid 
3881e209fccSTamas Berghammer   uint8_t *dst = data_sp->GetBytes();
389b6f9d7b8SMuhammad Omair Javaid   ::memcpy(dst, GetGPRBuffer(), GetGPRSize());
3901e209fccSTamas Berghammer   dst += GetGPRSize();
391b6f9d7b8SMuhammad Omair Javaid   ::memcpy(dst, GetFPRBuffer(), GetFPRSize());
3921e209fccSTamas Berghammer 
3931e209fccSTamas Berghammer   return error;
3941e209fccSTamas Berghammer }
3951e209fccSTamas Berghammer 
39697206d57SZachary Turner Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
397b9c1b51eSKate Stone     const lldb::DataBufferSP &data_sp) {
39897206d57SZachary Turner   Status error;
3991e209fccSTamas Berghammer 
400b9c1b51eSKate Stone   if (!data_sp) {
401b9c1b51eSKate Stone     error.SetErrorStringWithFormat(
402b9c1b51eSKate Stone         "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided",
403b9c1b51eSKate Stone         __FUNCTION__);
4041e209fccSTamas Berghammer     return error;
4051e209fccSTamas Berghammer   }
4061e209fccSTamas Berghammer 
407b9c1b51eSKate Stone   if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
408b9c1b51eSKate Stone     error.SetErrorStringWithFormat(
409b9c1b51eSKate Stone         "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched "
410b9c1b51eSKate Stone         "data size, expected %" PRIu64 ", actual %" PRIu64,
411b9c1b51eSKate Stone         __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
4121e209fccSTamas Berghammer     return error;
4131e209fccSTamas Berghammer   }
4141e209fccSTamas Berghammer 
4151e209fccSTamas Berghammer   uint8_t *src = data_sp->GetBytes();
416b9c1b51eSKate Stone   if (src == nullptr) {
417b9c1b51eSKate Stone     error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s "
418b9c1b51eSKate Stone                                    "DataBuffer::GetBytes() returned a null "
419b9c1b51eSKate Stone                                    "pointer",
420b9c1b51eSKate Stone                                    __FUNCTION__);
4211e209fccSTamas Berghammer     return error;
4221e209fccSTamas Berghammer   }
423b6f9d7b8SMuhammad Omair Javaid   ::memcpy(GetGPRBuffer(), src, GetRegisterInfoInterface().GetGPRSize());
4241e209fccSTamas Berghammer 
425068f8a7eSTamas Berghammer   error = WriteGPR();
426068f8a7eSTamas Berghammer   if (error.Fail())
4271e209fccSTamas Berghammer     return error;
4281e209fccSTamas Berghammer 
4291e209fccSTamas Berghammer   src += GetRegisterInfoInterface().GetGPRSize();
430b6f9d7b8SMuhammad Omair Javaid   ::memcpy(GetFPRBuffer(), src, GetFPRSize());
4311e209fccSTamas Berghammer 
432068f8a7eSTamas Berghammer   error = WriteFPR();
4331e209fccSTamas Berghammer   if (error.Fail())
4341e209fccSTamas Berghammer     return error;
4351e209fccSTamas Berghammer 
4361e209fccSTamas Berghammer   return error;
4371e209fccSTamas Berghammer }
4381e209fccSTamas Berghammer 
439b9c1b51eSKate Stone bool NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const {
4407fa7b81bSMuhammad Omair Javaid   if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
4417fa7b81bSMuhammad Omair Javaid       RegisterInfoPOSIX_arm64::GPRegSet)
4427fa7b81bSMuhammad Omair Javaid     return true;
4437fa7b81bSMuhammad Omair Javaid   return false;
4441e209fccSTamas Berghammer }
4451e209fccSTamas Berghammer 
446b9c1b51eSKate Stone bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const {
4477fa7b81bSMuhammad Omair Javaid   if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
4487fa7b81bSMuhammad Omair Javaid       RegisterInfoPOSIX_arm64::FPRegSet)
4497fa7b81bSMuhammad Omair Javaid     return true;
4507fa7b81bSMuhammad Omair Javaid   return false;
4511e209fccSTamas Berghammer }
4521e209fccSTamas Berghammer 
453567ba6c4SMuhammad Omair Javaid bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const {
454567ba6c4SMuhammad Omair Javaid   if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
455567ba6c4SMuhammad Omair Javaid       RegisterInfoPOSIX_arm64::SVERegSet)
456567ba6c4SMuhammad Omair Javaid     return true;
457567ba6c4SMuhammad Omair Javaid   return false;
458567ba6c4SMuhammad Omair Javaid }
459567ba6c4SMuhammad Omair Javaid 
460*771c4c9cSMichał Górny llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
461b9c1b51eSKate Stone   if (!m_refresh_hwdebug_info) {
462*771c4c9cSMichał Górny     return llvm::Error::success();
4631fd2a8cfSOmair Javaid   }
4641fd2a8cfSOmair Javaid 
465c7512fdcSPavel Labath   ::pid_t tid = m_thread.GetID();
466ea8c25a8SOmair Javaid 
467c7512fdcSPavel Labath   int regset = NT_ARM_HW_WATCH;
468c7512fdcSPavel Labath   struct iovec ioVec;
469c7512fdcSPavel Labath   struct user_hwdebug_state dreg_state;
47097206d57SZachary Turner   Status error;
471c7512fdcSPavel Labath 
472c7512fdcSPavel Labath   ioVec.iov_base = &dreg_state;
473c7512fdcSPavel Labath   ioVec.iov_len = sizeof(dreg_state);
474b9c1b51eSKate Stone   error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,
475b9c1b51eSKate Stone                                             &ioVec, ioVec.iov_len);
4763a56363aSOmair Javaid 
4773a56363aSOmair Javaid   if (error.Fail())
478*771c4c9cSMichał Górny     return error.ToError();
4793a56363aSOmair Javaid 
4801fd2a8cfSOmair Javaid   m_max_hwp_supported = dreg_state.dbg_info & 0xff;
481c7512fdcSPavel Labath 
482c7512fdcSPavel Labath   regset = NT_ARM_HW_BREAK;
483b9c1b51eSKate Stone   error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,
484b9c1b51eSKate Stone                                             &ioVec, ioVec.iov_len);
4851fd2a8cfSOmair Javaid 
4863a56363aSOmair Javaid   if (error.Fail())
487*771c4c9cSMichał Górny     return error.ToError();
4883a56363aSOmair Javaid 
4893a56363aSOmair Javaid   m_max_hbp_supported = dreg_state.dbg_info & 0xff;
4901fd2a8cfSOmair Javaid   m_refresh_hwdebug_info = false;
491c7512fdcSPavel Labath 
492*771c4c9cSMichał Górny   return llvm::Error::success();
493ea8c25a8SOmair Javaid }
494068f8a7eSTamas Berghammer 
495*771c4c9cSMichał Górny llvm::Error
496*771c4c9cSMichał Górny NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
497c7512fdcSPavel Labath   struct iovec ioVec;
498c7512fdcSPavel Labath   struct user_hwdebug_state dreg_state;
499*771c4c9cSMichał Górny   int regset;
500c7512fdcSPavel Labath 
501c7512fdcSPavel Labath   memset(&dreg_state, 0, sizeof(dreg_state));
502c7512fdcSPavel Labath   ioVec.iov_base = &dreg_state;
503c7512fdcSPavel Labath 
504*771c4c9cSMichał Górny   switch (hwbType) {
505*771c4c9cSMichał Górny   case eDREGTypeWATCH:
506*771c4c9cSMichał Górny     regset = NT_ARM_HW_WATCH;
507b9c1b51eSKate Stone     ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
508b9c1b51eSKate Stone                     (sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported);
5091fd2a8cfSOmair Javaid 
510b9c1b51eSKate Stone     for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
5111fd2a8cfSOmair Javaid       dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address;
5121fd2a8cfSOmair Javaid       dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control;
5131fd2a8cfSOmair Javaid     }
514*771c4c9cSMichał Górny     break;
515*771c4c9cSMichał Górny   case eDREGTypeBREAK:
516*771c4c9cSMichał Górny     regset = NT_ARM_HW_BREAK;
517b9c1b51eSKate Stone     ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
518b9c1b51eSKate Stone                     (sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported);
5191fd2a8cfSOmair Javaid 
520b9c1b51eSKate Stone     for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
521*771c4c9cSMichał Górny       dreg_state.dbg_regs[i].addr = m_hbp_regs[i].address;
522*771c4c9cSMichał Górny       dreg_state.dbg_regs[i].ctrl = m_hbp_regs[i].control;
5231fd2a8cfSOmair Javaid     }
524*771c4c9cSMichał Górny     break;
525068f8a7eSTamas Berghammer   }
526068f8a7eSTamas Berghammer 
527b9c1b51eSKate Stone   return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),
528*771c4c9cSMichał Górny                                            &regset, &ioVec, ioVec.iov_len)
529*771c4c9cSMichał Górny       .ToError();
530c7512fdcSPavel Labath }
531c7512fdcSPavel Labath 
5323f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::ReadGPR() {
533b6f9d7b8SMuhammad Omair Javaid   Status error;
534b6f9d7b8SMuhammad Omair Javaid 
535567ba6c4SMuhammad Omair Javaid   if (m_gpr_is_valid)
536567ba6c4SMuhammad Omair Javaid     return error;
537b6f9d7b8SMuhammad Omair Javaid 
538567ba6c4SMuhammad Omair Javaid   struct iovec ioVec;
5393f3673eaSPavel Labath   ioVec.iov_base = GetGPRBuffer();
54026b8ea2eSMuhammad Omair Javaid   ioVec.iov_len = GetGPRBufferSize();
541b6f9d7b8SMuhammad Omair Javaid 
54226b8ea2eSMuhammad Omair Javaid   error = ReadRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS);
543b6f9d7b8SMuhammad Omair Javaid 
544b6f9d7b8SMuhammad Omair Javaid   if (error.Success())
545b6f9d7b8SMuhammad Omair Javaid     m_gpr_is_valid = true;
546b6f9d7b8SMuhammad Omair Javaid 
547b6f9d7b8SMuhammad Omair Javaid   return error;
548068f8a7eSTamas Berghammer }
549068f8a7eSTamas Berghammer 
5503f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::WriteGPR() {
551567ba6c4SMuhammad Omair Javaid   Status error = ReadGPR();
552567ba6c4SMuhammad Omair Javaid   if (error.Fail())
553567ba6c4SMuhammad Omair Javaid     return error;
554567ba6c4SMuhammad Omair Javaid 
555c7512fdcSPavel Labath   struct iovec ioVec;
5563f3673eaSPavel Labath   ioVec.iov_base = GetGPRBuffer();
55726b8ea2eSMuhammad Omair Javaid   ioVec.iov_len = GetGPRBufferSize();
558b6f9d7b8SMuhammad Omair Javaid 
559567ba6c4SMuhammad Omair Javaid   m_gpr_is_valid = false;
560567ba6c4SMuhammad Omair Javaid 
56126b8ea2eSMuhammad Omair Javaid   return WriteRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS);
562068f8a7eSTamas Berghammer }
563068f8a7eSTamas Berghammer 
5643f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::ReadFPR() {
565b6f9d7b8SMuhammad Omair Javaid   Status error;
566b6f9d7b8SMuhammad Omair Javaid 
567567ba6c4SMuhammad Omair Javaid   if (m_fpu_is_valid)
568567ba6c4SMuhammad Omair Javaid     return error;
569b6f9d7b8SMuhammad Omair Javaid 
570567ba6c4SMuhammad Omair Javaid   struct iovec ioVec;
5713f3673eaSPavel Labath   ioVec.iov_base = GetFPRBuffer();
5723f3673eaSPavel Labath   ioVec.iov_len = GetFPRSize();
573b6f9d7b8SMuhammad Omair Javaid 
574b6f9d7b8SMuhammad Omair Javaid   error = ReadRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
575b6f9d7b8SMuhammad Omair Javaid 
576b6f9d7b8SMuhammad Omair Javaid   if (error.Success())
577b6f9d7b8SMuhammad Omair Javaid     m_fpu_is_valid = true;
578b6f9d7b8SMuhammad Omair Javaid 
579b6f9d7b8SMuhammad Omair Javaid   return error;
580068f8a7eSTamas Berghammer }
581068f8a7eSTamas Berghammer 
5823f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::WriteFPR() {
583567ba6c4SMuhammad Omair Javaid   Status error = ReadFPR();
584567ba6c4SMuhammad Omair Javaid   if (error.Fail())
585567ba6c4SMuhammad Omair Javaid     return error;
586567ba6c4SMuhammad Omair Javaid 
587c7512fdcSPavel Labath   struct iovec ioVec;
5883f3673eaSPavel Labath   ioVec.iov_base = GetFPRBuffer();
5893f3673eaSPavel Labath   ioVec.iov_len = GetFPRSize();
590b6f9d7b8SMuhammad Omair Javaid 
591567ba6c4SMuhammad Omair Javaid   m_fpu_is_valid = false;
592567ba6c4SMuhammad Omair Javaid 
5933f3673eaSPavel Labath   return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
594068f8a7eSTamas Berghammer }
595068f8a7eSTamas Berghammer 
596b6f9d7b8SMuhammad Omair Javaid void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() {
597b6f9d7b8SMuhammad Omair Javaid   m_gpr_is_valid = false;
598b6f9d7b8SMuhammad Omair Javaid   m_fpu_is_valid = false;
599567ba6c4SMuhammad Omair Javaid   m_sve_buffer_is_valid = false;
600567ba6c4SMuhammad Omair Javaid   m_sve_header_is_valid = false;
601567ba6c4SMuhammad Omair Javaid 
602567ba6c4SMuhammad Omair Javaid   // Update SVE registers in case there is change in configuration.
603567ba6c4SMuhammad Omair Javaid   ConfigureRegisterContext();
604567ba6c4SMuhammad Omair Javaid }
605567ba6c4SMuhammad Omair Javaid 
606567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
607567ba6c4SMuhammad Omair Javaid   Status error;
608567ba6c4SMuhammad Omair Javaid 
609567ba6c4SMuhammad Omair Javaid   if (m_sve_header_is_valid)
610567ba6c4SMuhammad Omair Javaid     return error;
611567ba6c4SMuhammad Omair Javaid 
612567ba6c4SMuhammad Omair Javaid   struct iovec ioVec;
613567ba6c4SMuhammad Omair Javaid   ioVec.iov_base = GetSVEHeader();
614567ba6c4SMuhammad Omair Javaid   ioVec.iov_len = GetSVEHeaderSize();
615567ba6c4SMuhammad Omair Javaid 
616567ba6c4SMuhammad Omair Javaid   error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE);
617567ba6c4SMuhammad Omair Javaid 
618567ba6c4SMuhammad Omair Javaid   m_sve_header_is_valid = true;
619567ba6c4SMuhammad Omair Javaid 
620567ba6c4SMuhammad Omair Javaid   return error;
621567ba6c4SMuhammad Omair Javaid }
622567ba6c4SMuhammad Omair Javaid 
623567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::WriteSVEHeader() {
624567ba6c4SMuhammad Omair Javaid   Status error;
625567ba6c4SMuhammad Omair Javaid 
626567ba6c4SMuhammad Omair Javaid   error = ReadSVEHeader();
627567ba6c4SMuhammad Omair Javaid   if (error.Fail())
628567ba6c4SMuhammad Omair Javaid     return error;
629567ba6c4SMuhammad Omair Javaid 
630567ba6c4SMuhammad Omair Javaid   struct iovec ioVec;
631567ba6c4SMuhammad Omair Javaid   ioVec.iov_base = GetSVEHeader();
632567ba6c4SMuhammad Omair Javaid   ioVec.iov_len = GetSVEHeaderSize();
633567ba6c4SMuhammad Omair Javaid 
634567ba6c4SMuhammad Omair Javaid   m_sve_buffer_is_valid = false;
635567ba6c4SMuhammad Omair Javaid   m_sve_header_is_valid = false;
636567ba6c4SMuhammad Omair Javaid   m_fpu_is_valid = false;
637567ba6c4SMuhammad Omair Javaid 
638567ba6c4SMuhammad Omair Javaid   return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE);
639567ba6c4SMuhammad Omair Javaid }
640567ba6c4SMuhammad Omair Javaid 
641567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::ReadAllSVE() {
642567ba6c4SMuhammad Omair Javaid   Status error;
643567ba6c4SMuhammad Omair Javaid 
644567ba6c4SMuhammad Omair Javaid   if (m_sve_buffer_is_valid)
645567ba6c4SMuhammad Omair Javaid     return error;
646567ba6c4SMuhammad Omair Javaid 
647567ba6c4SMuhammad Omair Javaid   struct iovec ioVec;
648567ba6c4SMuhammad Omair Javaid   ioVec.iov_base = GetSVEBuffer();
649567ba6c4SMuhammad Omair Javaid   ioVec.iov_len = GetSVEBufferSize();
650567ba6c4SMuhammad Omair Javaid 
651567ba6c4SMuhammad Omair Javaid   error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE);
652567ba6c4SMuhammad Omair Javaid 
653567ba6c4SMuhammad Omair Javaid   if (error.Success())
654567ba6c4SMuhammad Omair Javaid     m_sve_buffer_is_valid = true;
655567ba6c4SMuhammad Omair Javaid 
656567ba6c4SMuhammad Omair Javaid   return error;
657567ba6c4SMuhammad Omair Javaid }
658567ba6c4SMuhammad Omair Javaid 
659567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::WriteAllSVE() {
660567ba6c4SMuhammad Omair Javaid   Status error;
661567ba6c4SMuhammad Omair Javaid 
662567ba6c4SMuhammad Omair Javaid   error = ReadAllSVE();
663567ba6c4SMuhammad Omair Javaid   if (error.Fail())
664567ba6c4SMuhammad Omair Javaid     return error;
665567ba6c4SMuhammad Omair Javaid 
666567ba6c4SMuhammad Omair Javaid   struct iovec ioVec;
667567ba6c4SMuhammad Omair Javaid 
668567ba6c4SMuhammad Omair Javaid   ioVec.iov_base = GetSVEBuffer();
669567ba6c4SMuhammad Omair Javaid   ioVec.iov_len = GetSVEBufferSize();
670567ba6c4SMuhammad Omair Javaid 
671567ba6c4SMuhammad Omair Javaid   m_sve_buffer_is_valid = false;
672567ba6c4SMuhammad Omair Javaid   m_sve_header_is_valid = false;
673567ba6c4SMuhammad Omair Javaid   m_fpu_is_valid = false;
674567ba6c4SMuhammad Omair Javaid 
675567ba6c4SMuhammad Omair Javaid   return WriteRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE);
676567ba6c4SMuhammad Omair Javaid }
677567ba6c4SMuhammad Omair Javaid 
678567ba6c4SMuhammad Omair Javaid void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
679567ba6c4SMuhammad Omair Javaid   // Read SVE configuration data and configure register infos.
680567ba6c4SMuhammad Omair Javaid   if (!m_sve_header_is_valid && m_sve_state != SVEState::Disabled) {
681567ba6c4SMuhammad Omair Javaid     Status error = ReadSVEHeader();
682567ba6c4SMuhammad Omair Javaid     if (!error.Success() && m_sve_state == SVEState::Unknown) {
683567ba6c4SMuhammad Omair Javaid       m_sve_state = SVEState::Disabled;
684567ba6c4SMuhammad Omair Javaid       GetRegisterInfo().ConfigureVectorRegisterInfos(
685567ba6c4SMuhammad Omair Javaid           RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64);
686567ba6c4SMuhammad Omair Javaid     } else {
687567ba6c4SMuhammad Omair Javaid       if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD)
688567ba6c4SMuhammad Omair Javaid         m_sve_state = SVEState::FPSIMD;
689567ba6c4SMuhammad Omair Javaid       else if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE)
690567ba6c4SMuhammad Omair Javaid         m_sve_state = SVEState::Full;
691567ba6c4SMuhammad Omair Javaid 
692567ba6c4SMuhammad Omair Javaid       uint32_t vq = RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64SVE;
693567ba6c4SMuhammad Omair Javaid       if (sve_vl_valid(m_sve_header.vl))
694567ba6c4SMuhammad Omair Javaid         vq = sve_vq_from_vl(m_sve_header.vl);
695567ba6c4SMuhammad Omair Javaid       GetRegisterInfo().ConfigureVectorRegisterInfos(vq);
696567ba6c4SMuhammad Omair Javaid       m_sve_ptrace_payload.resize(SVE_PT_SIZE(vq, SVE_PT_REGS_SVE));
697567ba6c4SMuhammad Omair Javaid     }
698567ba6c4SMuhammad Omair Javaid   }
699b6f9d7b8SMuhammad Omair Javaid }
700b6f9d7b8SMuhammad Omair Javaid 
701b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset(
702b9c1b51eSKate Stone     const RegisterInfo *reg_info) const {
7037fa7b81bSMuhammad Omair Javaid   return reg_info->byte_offset - GetGPRSize();
704c40e7b17STamas Berghammer }
705c40e7b17STamas Berghammer 
706567ba6c4SMuhammad Omair Javaid uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset(
707567ba6c4SMuhammad Omair Javaid     const RegisterInfo *reg_info) const {
708567ba6c4SMuhammad Omair Javaid   // Start of Z0 data is after GPRs plus 8 bytes of vg register
709567ba6c4SMuhammad Omair Javaid   uint32_t sve_reg_offset = LLDB_INVALID_INDEX32;
710567ba6c4SMuhammad Omair Javaid   if (m_sve_state == SVEState::FPSIMD) {
711567ba6c4SMuhammad Omair Javaid     const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
712567ba6c4SMuhammad Omair Javaid     sve_reg_offset =
713567ba6c4SMuhammad Omair Javaid         SVE_PT_FPSIMD_OFFSET + (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16;
714567ba6c4SMuhammad Omair Javaid   } else if (m_sve_state == SVEState::Full) {
715661e4040SMuhammad Omair Javaid     uint32_t sve_z0_offset = GetGPRSize() + 16;
716567ba6c4SMuhammad Omair Javaid     sve_reg_offset =
717567ba6c4SMuhammad Omair Javaid         SVE_SIG_REGS_OFFSET + reg_info->byte_offset - sve_z0_offset;
718567ba6c4SMuhammad Omair Javaid   }
719567ba6c4SMuhammad Omair Javaid   return sve_reg_offset;
720567ba6c4SMuhammad Omair Javaid }
721567ba6c4SMuhammad Omair Javaid 
722567ba6c4SMuhammad Omair Javaid void *NativeRegisterContextLinux_arm64::GetSVEBuffer() {
723567ba6c4SMuhammad Omair Javaid   if (m_sve_state == SVEState::FPSIMD)
724567ba6c4SMuhammad Omair Javaid     return m_sve_ptrace_payload.data() + SVE_PT_FPSIMD_OFFSET;
725567ba6c4SMuhammad Omair Javaid 
726567ba6c4SMuhammad Omair Javaid   return m_sve_ptrace_payload.data();
727567ba6c4SMuhammad Omair Javaid }
728567ba6c4SMuhammad Omair Javaid 
7294e8aeb97SMuhammad Omair Javaid std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters(
7304e8aeb97SMuhammad Omair Javaid     ExpeditedRegs expType) const {
7314e8aeb97SMuhammad Omair Javaid   std::vector<uint32_t> expedited_reg_nums =
7324e8aeb97SMuhammad Omair Javaid       NativeRegisterContext::GetExpeditedRegisters(expType);
7334e8aeb97SMuhammad Omair Javaid   if (m_sve_state == SVEState::FPSIMD || m_sve_state == SVEState::Full)
7344e8aeb97SMuhammad Omair Javaid     expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG());
7354e8aeb97SMuhammad Omair Javaid 
7364e8aeb97SMuhammad Omair Javaid   return expedited_reg_nums;
7374e8aeb97SMuhammad Omair Javaid }
7384e8aeb97SMuhammad Omair Javaid 
739068f8a7eSTamas Berghammer #endif // defined (__arm64__) || defined (__aarch64__)
740