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