1 //===-- NativeRegisterContextLinux_arm64.cpp ------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #if defined(__arm64__) || defined(__aarch64__)
10 
11 #include "NativeRegisterContextLinux_arm.h"
12 #include "NativeRegisterContextLinux_arm64.h"
13 
14 
15 #include "lldb/Host/common/NativeProcessProtocol.h"
16 #include "lldb/Utility/DataBufferHeap.h"
17 #include "lldb/Utility/Log.h"
18 #include "lldb/Utility/RegisterValue.h"
19 #include "lldb/Utility/Status.h"
20 
21 #include "Plugins/Process/Linux/NativeProcessLinux.h"
22 #include "Plugins/Process/Linux/Procfs.h"
23 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
24 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
25 
26 // System includes - They have to be included after framework includes because
27 // they define some macros which collide with variable names in other modules
28 #include <sys/socket.h>
29 // NT_PRSTATUS and NT_FPREGSET definition
30 #include <elf.h>
31 
32 #ifndef NT_ARM_SVE
33 #define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension */
34 #endif
35 
36 #ifndef NT_ARM_PAC_MASK
37 #define NT_ARM_PAC_MASK 0x406 /* Pointer authentication code masks */
38 #endif
39 
40 #ifndef NT_ARM_TAGGED_ADDR_CTRL
41 #define NT_ARM_TAGGED_ADDR_CTRL 0x409 /* Tagged address control register */
42 #endif
43 
44 #define HWCAP_PACA (1 << 30)
45 #define HWCAP2_MTE (1 << 18)
46 
47 #define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize())
48 
49 using namespace lldb;
50 using namespace lldb_private;
51 using namespace lldb_private::process_linux;
52 
53 std::unique_ptr<NativeRegisterContextLinux>
54 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
55     const ArchSpec &target_arch, NativeThreadLinux &native_thread) {
56   switch (target_arch.GetMachine()) {
57   case llvm::Triple::arm:
58     return std::make_unique<NativeRegisterContextLinux_arm>(target_arch,
59                                                              native_thread);
60   case llvm::Triple::aarch64: {
61     // Configure register sets supported by this AArch64 target.
62     // Read SVE header to check for SVE support.
63     struct user_sve_header sve_header;
64     struct iovec ioVec;
65     ioVec.iov_base = &sve_header;
66     ioVec.iov_len = sizeof(sve_header);
67     unsigned int regset = NT_ARM_SVE;
68 
69     Flags opt_regsets;
70     if (NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET,
71                                           native_thread.GetID(), &regset,
72                                           &ioVec, sizeof(sve_header))
73             .Success())
74       opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE);
75 
76     NativeProcessLinux &process = native_thread.GetProcess();
77 
78     llvm::Optional<uint64_t> auxv_at_hwcap =
79         process.GetAuxValue(AuxVector::AUXV_AT_HWCAP);
80     if (auxv_at_hwcap && (*auxv_at_hwcap & HWCAP_PACA))
81       opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskPAuth);
82 
83     llvm::Optional<uint64_t> auxv_at_hwcap2 =
84         process.GetAuxValue(AuxVector::AUXV_AT_HWCAP2);
85     if (auxv_at_hwcap2 && (*auxv_at_hwcap2 & HWCAP2_MTE))
86       opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskMTE);
87 
88     auto register_info_up =
89         std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets);
90     return std::make_unique<NativeRegisterContextLinux_arm64>(
91         target_arch, native_thread, std::move(register_info_up));
92   }
93   default:
94     llvm_unreachable("have no register context for architecture");
95   }
96 }
97 
98 NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
99     const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
100     std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up)
101     : NativeRegisterContextRegisterInfo(native_thread,
102                                         register_info_up.release()),
103       NativeRegisterContextLinux(native_thread) {
104   ::memset(&m_fpr, 0, sizeof(m_fpr));
105   ::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64));
106   ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
107   ::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs));
108   ::memset(&m_sve_header, 0, sizeof(m_sve_header));
109   ::memset(&m_pac_mask, 0, sizeof(m_pac_mask));
110 
111   m_mte_ctrl_reg = 0;
112 
113   // 16 is just a maximum value, query hardware for actual watchpoint count
114   m_max_hwp_supported = 16;
115   m_max_hbp_supported = 16;
116 
117   m_refresh_hwdebug_info = true;
118 
119   m_gpr_is_valid = false;
120   m_fpu_is_valid = false;
121   m_sve_buffer_is_valid = false;
122   m_sve_header_is_valid = false;
123   m_pac_mask_is_valid = false;
124   m_mte_ctrl_is_valid = false;
125 
126   if (GetRegisterInfo().IsSVEEnabled())
127     m_sve_state = SVEState::Unknown;
128   else
129     m_sve_state = SVEState::Disabled;
130 }
131 
132 RegisterInfoPOSIX_arm64 &
133 NativeRegisterContextLinux_arm64::GetRegisterInfo() const {
134   return static_cast<RegisterInfoPOSIX_arm64 &>(*m_register_info_interface_up);
135 }
136 
137 uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount() const {
138   return GetRegisterInfo().GetRegisterSetCount();
139 }
140 
141 const RegisterSet *
142 NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index) const {
143   return GetRegisterInfo().GetRegisterSet(set_index);
144 }
145 
146 uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount() const {
147   uint32_t count = 0;
148   for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
149     count += GetRegisterSet(set_index)->num_registers;
150   return count;
151 }
152 
153 Status
154 NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info,
155                                                RegisterValue &reg_value) {
156   Status error;
157 
158   if (!reg_info) {
159     error.SetErrorString("reg_info NULL");
160     return error;
161   }
162 
163   const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
164 
165   if (reg == LLDB_INVALID_REGNUM)
166     return Status("no lldb regnum for %s", reg_info && reg_info->name
167                                                ? reg_info->name
168                                                : "<unknown register>");
169 
170   uint8_t *src;
171   uint32_t offset = LLDB_INVALID_INDEX32;
172   uint64_t sve_vg;
173   std::vector<uint8_t> sve_reg_non_live;
174 
175   if (IsGPR(reg)) {
176     error = ReadGPR();
177     if (error.Fail())
178       return error;
179 
180     offset = reg_info->byte_offset;
181     assert(offset < GetGPRSize());
182     src = (uint8_t *)GetGPRBuffer() + offset;
183 
184   } else if (IsFPR(reg)) {
185     if (m_sve_state == SVEState::Disabled) {
186       // SVE is disabled take legacy route for FPU register access
187       error = ReadFPR();
188       if (error.Fail())
189         return error;
190 
191       offset = CalculateFprOffset(reg_info);
192       assert(offset < GetFPRSize());
193       src = (uint8_t *)GetFPRBuffer() + offset;
194     } else {
195       // SVE enabled, we will read and cache SVE ptrace data
196       error = ReadAllSVE();
197       if (error.Fail())
198         return error;
199 
200       // FPSR and FPCR will be located right after Z registers in
201       // SVEState::FPSIMD while in SVEState::Full they will be located at the
202       // end of register data after an alignment correction based on currently
203       // selected vector length.
204       uint32_t sve_reg_num = LLDB_INVALID_REGNUM;
205       if (reg == GetRegisterInfo().GetRegNumFPSR()) {
206         sve_reg_num = reg;
207         if (m_sve_state == SVEState::Full)
208           offset = SVE_PT_SVE_FPSR_OFFSET(sve_vq_from_vl(m_sve_header.vl));
209         else if (m_sve_state == SVEState::FPSIMD)
210           offset = SVE_PT_FPSIMD_OFFSET + (32 * 16);
211       } else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
212         sve_reg_num = reg;
213         if (m_sve_state == SVEState::Full)
214           offset = SVE_PT_SVE_FPCR_OFFSET(sve_vq_from_vl(m_sve_header.vl));
215         else if (m_sve_state == SVEState::FPSIMD)
216           offset = SVE_PT_FPSIMD_OFFSET + (32 * 16) + 4;
217       } else {
218         // Extract SVE Z register value register number for this reg_info
219         if (reg_info->value_regs &&
220             reg_info->value_regs[0] != LLDB_INVALID_REGNUM)
221           sve_reg_num = reg_info->value_regs[0];
222         offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
223       }
224 
225       assert(offset < GetSVEBufferSize());
226       src = (uint8_t *)GetSVEBuffer() + offset;
227     }
228   } else if (IsSVE(reg)) {
229 
230     if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown)
231       return Status("SVE disabled or not supported");
232 
233     if (GetRegisterInfo().IsSVERegVG(reg)) {
234       sve_vg = GetSVERegVG();
235       src = (uint8_t *)&sve_vg;
236     } else {
237       // SVE enabled, we will read and cache SVE ptrace data
238       error = ReadAllSVE();
239       if (error.Fail())
240         return error;
241 
242       if (m_sve_state == SVEState::FPSIMD) {
243         // In FPSIMD state SVE payload mirrors legacy fpsimd struct and so
244         // just copy 16 bytes of v register to the start of z register. All
245         // other SVE register will be set to zero.
246         sve_reg_non_live.resize(reg_info->byte_size, 0);
247         src = sve_reg_non_live.data();
248 
249         if (GetRegisterInfo().IsSVEZReg(reg)) {
250           offset = CalculateSVEOffset(reg_info);
251           assert(offset < GetSVEBufferSize());
252           ::memcpy(sve_reg_non_live.data(), (uint8_t *)GetSVEBuffer() + offset,
253                    16);
254         }
255       } else {
256         offset = CalculateSVEOffset(reg_info);
257         assert(offset < GetSVEBufferSize());
258         src = (uint8_t *)GetSVEBuffer() + offset;
259       }
260     }
261   } else if (IsPAuth(reg)) {
262     error = ReadPAuthMask();
263     if (error.Fail())
264       return error;
265 
266     offset = reg_info->byte_offset - GetRegisterInfo().GetPAuthOffset();
267     assert(offset < GetPACMaskSize());
268     src = (uint8_t *)GetPACMask() + offset;
269   } else if (IsMTE(reg)) {
270     error = ReadMTEControl();
271     if (error.Fail())
272       return error;
273 
274     offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset();
275     assert(offset < GetMTEControlSize());
276     src = (uint8_t *)GetMTEControl() + offset;
277   } else
278     return Status("failed - register wasn't recognized to be a GPR or an FPR, "
279                   "write strategy unknown");
280 
281   reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size,
282                               eByteOrderLittle, error);
283 
284   return error;
285 }
286 
287 Status NativeRegisterContextLinux_arm64::WriteRegister(
288     const RegisterInfo *reg_info, const RegisterValue &reg_value) {
289   Status error;
290 
291   if (!reg_info)
292     return Status("reg_info NULL");
293 
294   const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
295 
296   if (reg == LLDB_INVALID_REGNUM)
297     return Status("no lldb regnum for %s", reg_info && reg_info->name
298                                                ? reg_info->name
299                                                : "<unknown register>");
300 
301   uint8_t *dst;
302   uint32_t offset = LLDB_INVALID_INDEX32;
303   std::vector<uint8_t> sve_reg_non_live;
304 
305   if (IsGPR(reg)) {
306     error = ReadGPR();
307     if (error.Fail())
308       return error;
309 
310     assert(reg_info->byte_offset < GetGPRSize());
311     dst = (uint8_t *)GetGPRBuffer() + reg_info->byte_offset;
312     ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
313 
314     return WriteGPR();
315   } else if (IsFPR(reg)) {
316     if (m_sve_state == SVEState::Disabled) {
317       // SVE is disabled take legacy route for FPU register access
318       error = ReadFPR();
319       if (error.Fail())
320         return error;
321 
322       offset = CalculateFprOffset(reg_info);
323       assert(offset < GetFPRSize());
324       dst = (uint8_t *)GetFPRBuffer() + offset;
325       ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
326 
327       return WriteFPR();
328     } else {
329       // SVE enabled, we will read and cache SVE ptrace data
330       error = ReadAllSVE();
331       if (error.Fail())
332         return error;
333 
334       // FPSR and FPCR will be located right after Z registers in
335       // SVEState::FPSIMD while in SVEState::Full they will be located at the
336       // end of register data after an alignment correction based on currently
337       // selected vector length.
338       uint32_t sve_reg_num = LLDB_INVALID_REGNUM;
339       if (reg == GetRegisterInfo().GetRegNumFPSR()) {
340         sve_reg_num = reg;
341         if (m_sve_state == SVEState::Full)
342           offset = SVE_PT_SVE_FPSR_OFFSET(sve_vq_from_vl(m_sve_header.vl));
343         else if (m_sve_state == SVEState::FPSIMD)
344           offset = SVE_PT_FPSIMD_OFFSET + (32 * 16);
345       } else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
346         sve_reg_num = reg;
347         if (m_sve_state == SVEState::Full)
348           offset = SVE_PT_SVE_FPCR_OFFSET(sve_vq_from_vl(m_sve_header.vl));
349         else if (m_sve_state == SVEState::FPSIMD)
350           offset = SVE_PT_FPSIMD_OFFSET + (32 * 16) + 4;
351       } else {
352         // Extract SVE Z register value register number for this reg_info
353         if (reg_info->value_regs &&
354             reg_info->value_regs[0] != LLDB_INVALID_REGNUM)
355           sve_reg_num = reg_info->value_regs[0];
356         offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
357       }
358 
359       assert(offset < GetSVEBufferSize());
360       dst = (uint8_t *)GetSVEBuffer() + offset;
361       ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
362       return WriteAllSVE();
363     }
364   } else if (IsSVE(reg)) {
365     if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown)
366       return Status("SVE disabled or not supported");
367     else {
368       // Target has SVE enabled, we will read and cache SVE ptrace data
369       error = ReadAllSVE();
370       if (error.Fail())
371         return error;
372 
373       if (GetRegisterInfo().IsSVERegVG(reg)) {
374         uint64_t vg_value = reg_value.GetAsUInt64();
375 
376         if (sve_vl_valid(vg_value * 8)) {
377           if (m_sve_header_is_valid && vg_value == GetSVERegVG())
378             return error;
379 
380           SetSVERegVG(vg_value);
381 
382           error = WriteSVEHeader();
383           if (error.Success())
384             ConfigureRegisterContext();
385 
386           if (m_sve_header_is_valid && vg_value == GetSVERegVG())
387             return error;
388         }
389 
390         return Status("SVE vector length update failed.");
391       }
392 
393       // If target supports SVE but currently in FPSIMD mode.
394       if (m_sve_state == SVEState::FPSIMD) {
395         // Here we will check if writing this SVE register enables
396         // SVEState::Full
397         bool set_sve_state_full = false;
398         const uint8_t *reg_bytes = (const uint8_t *)reg_value.GetBytes();
399         if (GetRegisterInfo().IsSVEZReg(reg)) {
400           for (uint32_t i = 16; i < reg_info->byte_size; i++) {
401             if (reg_bytes[i]) {
402               set_sve_state_full = true;
403               break;
404             }
405           }
406         } else if (GetRegisterInfo().IsSVEPReg(reg) ||
407                    reg == GetRegisterInfo().GetRegNumSVEFFR()) {
408           for (uint32_t i = 0; i < reg_info->byte_size; i++) {
409             if (reg_bytes[i]) {
410               set_sve_state_full = true;
411               break;
412             }
413           }
414         }
415 
416         if (!set_sve_state_full && GetRegisterInfo().IsSVEZReg(reg)) {
417           // We are writing a Z register which is zero beyond 16 bytes so copy
418           // first 16 bytes only as SVE payload mirrors legacy fpsimd structure
419           offset = CalculateSVEOffset(reg_info);
420           assert(offset < GetSVEBufferSize());
421           dst = (uint8_t *)GetSVEBuffer() + offset;
422           ::memcpy(dst, reg_value.GetBytes(), 16);
423 
424           return WriteAllSVE();
425         } else
426           return Status("SVE state change operation not supported");
427       } else {
428         offset = CalculateSVEOffset(reg_info);
429         assert(offset < GetSVEBufferSize());
430         dst = (uint8_t *)GetSVEBuffer() + offset;
431         ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
432         return WriteAllSVE();
433       }
434     }
435   } else if (IsMTE(reg)) {
436     error = ReadMTEControl();
437     if (error.Fail())
438       return error;
439 
440     offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset();
441     assert(offset < GetMTEControlSize());
442     dst = (uint8_t *)GetMTEControl() + offset;
443     ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
444 
445     return WriteMTEControl();
446   }
447 
448   return Status("Failed to write register value");
449 }
450 
451 Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues(
452     lldb::DataBufferSP &data_sp) {
453   Status error;
454 
455   data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
456 
457   error = ReadGPR();
458   if (error.Fail())
459     return error;
460 
461   error = ReadFPR();
462   if (error.Fail())
463     return error;
464 
465   uint8_t *dst = data_sp->GetBytes();
466   ::memcpy(dst, GetGPRBuffer(), GetGPRSize());
467   dst += GetGPRSize();
468   ::memcpy(dst, GetFPRBuffer(), GetFPRSize());
469 
470   return error;
471 }
472 
473 Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
474     const lldb::DataBufferSP &data_sp) {
475   Status error;
476 
477   if (!data_sp) {
478     error.SetErrorStringWithFormat(
479         "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided",
480         __FUNCTION__);
481     return error;
482   }
483 
484   if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
485     error.SetErrorStringWithFormat(
486         "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched "
487         "data size, expected %" PRIu64 ", actual %" PRIu64,
488         __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
489     return error;
490   }
491 
492   uint8_t *src = data_sp->GetBytes();
493   if (src == nullptr) {
494     error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s "
495                                    "DataBuffer::GetBytes() returned a null "
496                                    "pointer",
497                                    __FUNCTION__);
498     return error;
499   }
500   ::memcpy(GetGPRBuffer(), src, GetRegisterInfoInterface().GetGPRSize());
501 
502   error = WriteGPR();
503   if (error.Fail())
504     return error;
505 
506   src += GetRegisterInfoInterface().GetGPRSize();
507   ::memcpy(GetFPRBuffer(), src, GetFPRSize());
508 
509   error = WriteFPR();
510   if (error.Fail())
511     return error;
512 
513   return error;
514 }
515 
516 bool NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const {
517   if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
518       RegisterInfoPOSIX_arm64::GPRegSet)
519     return true;
520   return false;
521 }
522 
523 bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const {
524   if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
525       RegisterInfoPOSIX_arm64::FPRegSet)
526     return true;
527   return false;
528 }
529 
530 bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const {
531   return GetRegisterInfo().IsSVEReg(reg);
532 }
533 
534 bool NativeRegisterContextLinux_arm64::IsPAuth(unsigned reg) const {
535   return GetRegisterInfo().IsPAuthReg(reg);
536 }
537 
538 bool NativeRegisterContextLinux_arm64::IsMTE(unsigned reg) const {
539   return GetRegisterInfo().IsMTEReg(reg);
540 }
541 
542 llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
543   if (!m_refresh_hwdebug_info) {
544     return llvm::Error::success();
545   }
546 
547   ::pid_t tid = m_thread.GetID();
548 
549   int regset = NT_ARM_HW_WATCH;
550   struct iovec ioVec;
551   struct user_hwdebug_state dreg_state;
552   Status error;
553 
554   ioVec.iov_base = &dreg_state;
555   ioVec.iov_len = sizeof(dreg_state);
556   error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,
557                                             &ioVec, ioVec.iov_len);
558 
559   if (error.Fail())
560     return error.ToError();
561 
562   m_max_hwp_supported = dreg_state.dbg_info & 0xff;
563 
564   regset = NT_ARM_HW_BREAK;
565   error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,
566                                             &ioVec, ioVec.iov_len);
567 
568   if (error.Fail())
569     return error.ToError();
570 
571   m_max_hbp_supported = dreg_state.dbg_info & 0xff;
572   m_refresh_hwdebug_info = false;
573 
574   return llvm::Error::success();
575 }
576 
577 llvm::Error
578 NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
579   struct iovec ioVec;
580   struct user_hwdebug_state dreg_state;
581   int regset;
582 
583   memset(&dreg_state, 0, sizeof(dreg_state));
584   ioVec.iov_base = &dreg_state;
585 
586   switch (hwbType) {
587   case eDREGTypeWATCH:
588     regset = NT_ARM_HW_WATCH;
589     ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
590                     (sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported);
591 
592     for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
593       dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address;
594       dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control;
595     }
596     break;
597   case eDREGTypeBREAK:
598     regset = NT_ARM_HW_BREAK;
599     ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
600                     (sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported);
601 
602     for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
603       dreg_state.dbg_regs[i].addr = m_hbp_regs[i].address;
604       dreg_state.dbg_regs[i].ctrl = m_hbp_regs[i].control;
605     }
606     break;
607   }
608 
609   return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),
610                                            &regset, &ioVec, ioVec.iov_len)
611       .ToError();
612 }
613 
614 Status NativeRegisterContextLinux_arm64::ReadGPR() {
615   Status error;
616 
617   if (m_gpr_is_valid)
618     return error;
619 
620   struct iovec ioVec;
621   ioVec.iov_base = GetGPRBuffer();
622   ioVec.iov_len = GetGPRBufferSize();
623 
624   error = ReadRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS);
625 
626   if (error.Success())
627     m_gpr_is_valid = true;
628 
629   return error;
630 }
631 
632 Status NativeRegisterContextLinux_arm64::WriteGPR() {
633   Status error = ReadGPR();
634   if (error.Fail())
635     return error;
636 
637   struct iovec ioVec;
638   ioVec.iov_base = GetGPRBuffer();
639   ioVec.iov_len = GetGPRBufferSize();
640 
641   m_gpr_is_valid = false;
642 
643   return WriteRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS);
644 }
645 
646 Status NativeRegisterContextLinux_arm64::ReadFPR() {
647   Status error;
648 
649   if (m_fpu_is_valid)
650     return error;
651 
652   struct iovec ioVec;
653   ioVec.iov_base = GetFPRBuffer();
654   ioVec.iov_len = GetFPRSize();
655 
656   error = ReadRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
657 
658   if (error.Success())
659     m_fpu_is_valid = true;
660 
661   return error;
662 }
663 
664 Status NativeRegisterContextLinux_arm64::WriteFPR() {
665   Status error = ReadFPR();
666   if (error.Fail())
667     return error;
668 
669   struct iovec ioVec;
670   ioVec.iov_base = GetFPRBuffer();
671   ioVec.iov_len = GetFPRSize();
672 
673   m_fpu_is_valid = false;
674 
675   return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
676 }
677 
678 void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() {
679   m_gpr_is_valid = false;
680   m_fpu_is_valid = false;
681   m_sve_buffer_is_valid = false;
682   m_sve_header_is_valid = false;
683   m_pac_mask_is_valid = false;
684   m_mte_ctrl_is_valid = false;
685 
686   // Update SVE registers in case there is change in configuration.
687   ConfigureRegisterContext();
688 }
689 
690 Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
691   Status error;
692 
693   if (m_sve_header_is_valid)
694     return error;
695 
696   struct iovec ioVec;
697   ioVec.iov_base = GetSVEHeader();
698   ioVec.iov_len = GetSVEHeaderSize();
699 
700   error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE);
701 
702   if (error.Success())
703     m_sve_header_is_valid = true;
704 
705   return error;
706 }
707 
708 Status NativeRegisterContextLinux_arm64::ReadPAuthMask() {
709   Status error;
710 
711   if (m_pac_mask_is_valid)
712     return error;
713 
714   struct iovec ioVec;
715   ioVec.iov_base = GetPACMask();
716   ioVec.iov_len = GetPACMaskSize();
717 
718   error = ReadRegisterSet(&ioVec, GetPACMaskSize(), NT_ARM_PAC_MASK);
719 
720   if (error.Success())
721     m_pac_mask_is_valid = true;
722 
723   return error;
724 }
725 
726 Status NativeRegisterContextLinux_arm64::WriteSVEHeader() {
727   Status error;
728 
729   error = ReadSVEHeader();
730   if (error.Fail())
731     return error;
732 
733   struct iovec ioVec;
734   ioVec.iov_base = GetSVEHeader();
735   ioVec.iov_len = GetSVEHeaderSize();
736 
737   m_sve_buffer_is_valid = false;
738   m_sve_header_is_valid = false;
739   m_fpu_is_valid = false;
740 
741   return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE);
742 }
743 
744 Status NativeRegisterContextLinux_arm64::ReadAllSVE() {
745   Status error;
746 
747   if (m_sve_buffer_is_valid)
748     return error;
749 
750   struct iovec ioVec;
751   ioVec.iov_base = GetSVEBuffer();
752   ioVec.iov_len = GetSVEBufferSize();
753 
754   error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE);
755 
756   if (error.Success())
757     m_sve_buffer_is_valid = true;
758 
759   return error;
760 }
761 
762 Status NativeRegisterContextLinux_arm64::WriteAllSVE() {
763   Status error;
764 
765   error = ReadAllSVE();
766   if (error.Fail())
767     return error;
768 
769   struct iovec ioVec;
770 
771   ioVec.iov_base = GetSVEBuffer();
772   ioVec.iov_len = GetSVEBufferSize();
773 
774   m_sve_buffer_is_valid = false;
775   m_sve_header_is_valid = false;
776   m_fpu_is_valid = false;
777 
778   return WriteRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE);
779 }
780 
781 Status NativeRegisterContextLinux_arm64::ReadMTEControl() {
782   Status error;
783 
784   if (m_mte_ctrl_is_valid)
785     return error;
786 
787   struct iovec ioVec;
788   ioVec.iov_base = GetMTEControl();
789   ioVec.iov_len = GetMTEControlSize();
790 
791   error = ReadRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
792 
793   if (error.Success())
794     m_mte_ctrl_is_valid = true;
795 
796   return error;
797 }
798 
799 Status NativeRegisterContextLinux_arm64::WriteMTEControl() {
800   Status error;
801 
802   error = ReadMTEControl();
803   if (error.Fail())
804     return error;
805 
806   struct iovec ioVec;
807   ioVec.iov_base = GetMTEControl();
808   ioVec.iov_len = GetMTEControlSize();
809 
810   m_mte_ctrl_is_valid = false;
811 
812   return WriteRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
813 }
814 
815 void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
816   // ConfigureRegisterContext gets called from InvalidateAllRegisters
817   // on every stop and configures SVE vector length.
818   // If m_sve_state is set to SVEState::Disabled on first stop, code below will
819   // be deemed non operational for the lifetime of current process.
820   if (!m_sve_header_is_valid && m_sve_state != SVEState::Disabled) {
821     Status error = ReadSVEHeader();
822     if (error.Success()) {
823       // If SVE is enabled thread can switch between SVEState::FPSIMD and
824       // SVEState::Full on every stop.
825       if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD)
826         m_sve_state = SVEState::FPSIMD;
827       else if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE)
828         m_sve_state = SVEState::Full;
829 
830       // On every stop we configure SVE vector length by calling
831       // ConfigureVectorLength regardless of current SVEState of this thread.
832       uint32_t vq = RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64SVE;
833       if (sve_vl_valid(m_sve_header.vl))
834         vq = sve_vq_from_vl(m_sve_header.vl);
835 
836       GetRegisterInfo().ConfigureVectorLength(vq);
837       m_sve_ptrace_payload.resize(SVE_PT_SIZE(vq, SVE_PT_REGS_SVE));
838     }
839   }
840 }
841 
842 uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset(
843     const RegisterInfo *reg_info) const {
844   return reg_info->byte_offset - GetGPRSize();
845 }
846 
847 uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset(
848     const RegisterInfo *reg_info) const {
849   // Start of Z0 data is after GPRs plus 8 bytes of vg register
850   uint32_t sve_reg_offset = LLDB_INVALID_INDEX32;
851   if (m_sve_state == SVEState::FPSIMD) {
852     const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
853     sve_reg_offset =
854         SVE_PT_FPSIMD_OFFSET + (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16;
855   } else if (m_sve_state == SVEState::Full) {
856     uint32_t sve_z0_offset = GetGPRSize() + 16;
857     sve_reg_offset =
858         SVE_SIG_REGS_OFFSET + reg_info->byte_offset - sve_z0_offset;
859   }
860   return sve_reg_offset;
861 }
862 
863 void *NativeRegisterContextLinux_arm64::GetSVEBuffer() {
864   if (m_sve_state == SVEState::FPSIMD)
865     return m_sve_ptrace_payload.data() + SVE_PT_FPSIMD_OFFSET;
866 
867   return m_sve_ptrace_payload.data();
868 }
869 
870 std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters(
871     ExpeditedRegs expType) const {
872   std::vector<uint32_t> expedited_reg_nums =
873       NativeRegisterContext::GetExpeditedRegisters(expType);
874   if (m_sve_state == SVEState::FPSIMD || m_sve_state == SVEState::Full)
875     expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG());
876 
877   return expedited_reg_nums;
878 }
879 
880 #endif // defined (__arm64__) || defined (__aarch64__)
881