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