180814287SRaphael Isemann //===-- NativeRegisterContextLinux_arm64.cpp ------------------------------===//
21e209fccSTamas Berghammer //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61e209fccSTamas Berghammer //
71e209fccSTamas Berghammer //===----------------------------------------------------------------------===//
81e209fccSTamas Berghammer 
9068f8a7eSTamas Berghammer #if defined(__arm64__) || defined(__aarch64__)
10068f8a7eSTamas Berghammer 
11e85e6021STamas Berghammer #include "NativeRegisterContextLinux_arm.h"
121e209fccSTamas Berghammer #include "NativeRegisterContextLinux_arm64.h"
131e209fccSTamas Berghammer 
14068f8a7eSTamas Berghammer 
151e209fccSTamas Berghammer #include "lldb/Host/common/NativeProcessProtocol.h"
16da2e614fSDavid Spickett #include "lldb/Host/linux/Ptrace.h"
17666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h"
186f9e6901SZachary Turner #include "lldb/Utility/Log.h"
19d821c997SPavel Labath #include "lldb/Utility/RegisterValue.h"
2097206d57SZachary Turner #include "lldb/Utility/Status.h"
211e209fccSTamas Berghammer 
22068f8a7eSTamas Berghammer #include "Plugins/Process/Linux/NativeProcessLinux.h"
23068f8a7eSTamas Berghammer #include "Plugins/Process/Linux/Procfs.h"
24e85e6021STamas Berghammer #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
25da2e614fSDavid Spickett #include "Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h"
26567ba6c4SMuhammad Omair Javaid #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
27068f8a7eSTamas Berghammer 
28b9c1b51eSKate Stone // System includes - They have to be included after framework includes because
2905097246SAdrian Prantl // they define some macros which collide with variable names in other modules
30068f8a7eSTamas Berghammer #include <sys/socket.h>
31068f8a7eSTamas Berghammer // NT_PRSTATUS and NT_FPREGSET definition
32068f8a7eSTamas Berghammer #include <elf.h>
33567ba6c4SMuhammad Omair Javaid 
34567ba6c4SMuhammad Omair Javaid #ifndef NT_ARM_SVE
35567ba6c4SMuhammad Omair Javaid #define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension */
36567ba6c4SMuhammad Omair Javaid #endif
37068f8a7eSTamas Berghammer 
3888a5b35dSMuhammad Omair Javaid #ifndef NT_ARM_PAC_MASK
3988a5b35dSMuhammad Omair Javaid #define NT_ARM_PAC_MASK 0x406 /* Pointer authentication code masks */
4088a5b35dSMuhammad Omair Javaid #endif
4188a5b35dSMuhammad Omair Javaid 
4288a5b35dSMuhammad Omair Javaid #ifndef NT_ARM_TAGGED_ADDR_CTRL
4388a5b35dSMuhammad Omair Javaid #define NT_ARM_TAGGED_ADDR_CTRL 0x409 /* Tagged address control register */
4488a5b35dSMuhammad Omair Javaid #endif
4588a5b35dSMuhammad Omair Javaid 
4688a5b35dSMuhammad Omair Javaid #define HWCAP_PACA (1 << 30)
4788a5b35dSMuhammad Omair Javaid #define HWCAP2_MTE (1 << 18)
4888a5b35dSMuhammad Omair Javaid 
49068f8a7eSTamas Berghammer #define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize())
501e209fccSTamas Berghammer 
511e209fccSTamas Berghammer using namespace lldb;
521e209fccSTamas Berghammer using namespace lldb_private;
53db264a6dSTamas Berghammer using namespace lldb_private::process_linux;
541e209fccSTamas Berghammer 
55d37349f3SPavel Labath std::unique_ptr<NativeRegisterContextLinux>
56b9c1b51eSKate Stone NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
57d1486e65SPavel Labath     const ArchSpec &target_arch, NativeThreadLinux &native_thread) {
58b9c1b51eSKate Stone   switch (target_arch.GetMachine()) {
59e85e6021STamas Berghammer   case llvm::Triple::arm:
60a8f3ae7cSJonas Devlieghere     return std::make_unique<NativeRegisterContextLinux_arm>(target_arch,
61d37349f3SPavel Labath                                                             native_thread);
62d6d3d21cSMuhammad Omair Javaid   case llvm::Triple::aarch64: {
63d6d3d21cSMuhammad Omair Javaid     // Configure register sets supported by this AArch64 target.
64d6d3d21cSMuhammad Omair Javaid     // Read SVE header to check for SVE support.
65d6d3d21cSMuhammad Omair Javaid     struct user_sve_header sve_header;
66d6d3d21cSMuhammad Omair Javaid     struct iovec ioVec;
67d6d3d21cSMuhammad Omair Javaid     ioVec.iov_base = &sve_header;
68d6d3d21cSMuhammad Omair Javaid     ioVec.iov_len = sizeof(sve_header);
69d6d3d21cSMuhammad Omair Javaid     unsigned int regset = NT_ARM_SVE;
70d6d3d21cSMuhammad Omair Javaid 
71d6d3d21cSMuhammad Omair Javaid     Flags opt_regsets;
72d6d3d21cSMuhammad Omair Javaid     if (NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET,
73d6d3d21cSMuhammad Omair Javaid                                           native_thread.GetID(), &regset,
74d6d3d21cSMuhammad Omair Javaid                                           &ioVec, sizeof(sve_header))
75d6d3d21cSMuhammad Omair Javaid             .Success())
76d6d3d21cSMuhammad Omair Javaid       opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE);
77d6d3d21cSMuhammad Omair Javaid 
7888a5b35dSMuhammad Omair Javaid     NativeProcessLinux &process = native_thread.GetProcess();
7988a5b35dSMuhammad Omair Javaid 
8088a5b35dSMuhammad Omair Javaid     llvm::Optional<uint64_t> auxv_at_hwcap =
8188a5b35dSMuhammad Omair Javaid         process.GetAuxValue(AuxVector::AUXV_AT_HWCAP);
8288a5b35dSMuhammad Omair Javaid     if (auxv_at_hwcap && (*auxv_at_hwcap & HWCAP_PACA))
8388a5b35dSMuhammad Omair Javaid       opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskPAuth);
8488a5b35dSMuhammad Omair Javaid 
8588a5b35dSMuhammad Omair Javaid     llvm::Optional<uint64_t> auxv_at_hwcap2 =
8688a5b35dSMuhammad Omair Javaid         process.GetAuxValue(AuxVector::AUXV_AT_HWCAP2);
8788a5b35dSMuhammad Omair Javaid     if (auxv_at_hwcap2 && (*auxv_at_hwcap2 & HWCAP2_MTE))
8888a5b35dSMuhammad Omair Javaid       opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskMTE);
8988a5b35dSMuhammad Omair Javaid 
90d6d3d21cSMuhammad Omair Javaid     auto register_info_up =
91d6d3d21cSMuhammad Omair Javaid         std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets);
92d6d3d21cSMuhammad Omair Javaid     return std::make_unique<NativeRegisterContextLinux_arm64>(
93d6d3d21cSMuhammad Omair Javaid         target_arch, native_thread, std::move(register_info_up));
94d6d3d21cSMuhammad Omair Javaid   }
95e85e6021STamas Berghammer   default:
96ea1b6b17SPavel Labath     llvm_unreachable("have no register context for architecture");
97e85e6021STamas Berghammer   }
98068f8a7eSTamas Berghammer }
99068f8a7eSTamas Berghammer 
100b9c1b51eSKate Stone NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
101d6d3d21cSMuhammad Omair Javaid     const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
102d6d3d21cSMuhammad Omair Javaid     std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up)
103d6d3d21cSMuhammad Omair Javaid     : NativeRegisterContextRegisterInfo(native_thread,
104e1d4fb1eSPavel Labath                                         register_info_up.release()),
105e1d4fb1eSPavel Labath       NativeRegisterContextLinux(native_thread) {
1061e209fccSTamas Berghammer   ::memset(&m_fpr, 0, sizeof(m_fpr));
1071e209fccSTamas Berghammer   ::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64));
108ea8c25a8SOmair Javaid   ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
109771c4c9cSMichał Górny   ::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs));
110567ba6c4SMuhammad Omair Javaid   ::memset(&m_sve_header, 0, sizeof(m_sve_header));
11188a5b35dSMuhammad Omair Javaid   ::memset(&m_pac_mask, 0, sizeof(m_pac_mask));
11288a5b35dSMuhammad Omair Javaid 
11388a5b35dSMuhammad Omair Javaid   m_mte_ctrl_reg = 0;
114ea8c25a8SOmair Javaid 
115ea8c25a8SOmair Javaid   // 16 is just a maximum value, query hardware for actual watchpoint count
116ea8c25a8SOmair Javaid   m_max_hwp_supported = 16;
117ea8c25a8SOmair Javaid   m_max_hbp_supported = 16;
118567ba6c4SMuhammad Omair Javaid 
119ea8c25a8SOmair Javaid   m_refresh_hwdebug_info = true;
120b6f9d7b8SMuhammad Omair Javaid 
121b6f9d7b8SMuhammad Omair Javaid   m_gpr_is_valid = false;
122b6f9d7b8SMuhammad Omair Javaid   m_fpu_is_valid = false;
123567ba6c4SMuhammad Omair Javaid   m_sve_buffer_is_valid = false;
124567ba6c4SMuhammad Omair Javaid   m_sve_header_is_valid = false;
12588a5b35dSMuhammad Omair Javaid   m_pac_mask_is_valid = false;
12688a5b35dSMuhammad Omair Javaid   m_mte_ctrl_is_valid = false;
127567ba6c4SMuhammad Omair Javaid 
128d6d3d21cSMuhammad Omair Javaid   if (GetRegisterInfo().IsSVEEnabled())
129567ba6c4SMuhammad Omair Javaid     m_sve_state = SVEState::Unknown;
130d6d3d21cSMuhammad Omair Javaid   else
131d6d3d21cSMuhammad Omair Javaid     m_sve_state = SVEState::Disabled;
1321e209fccSTamas Berghammer }
1331e209fccSTamas Berghammer 
1347fa7b81bSMuhammad Omair Javaid RegisterInfoPOSIX_arm64 &
1357fa7b81bSMuhammad Omair Javaid NativeRegisterContextLinux_arm64::GetRegisterInfo() const {
1367fa7b81bSMuhammad Omair Javaid   return static_cast<RegisterInfoPOSIX_arm64 &>(*m_register_info_interface_up);
1377fa7b81bSMuhammad Omair Javaid }
1387fa7b81bSMuhammad Omair Javaid 
139b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount() const {
1407fa7b81bSMuhammad Omair Javaid   return GetRegisterInfo().GetRegisterSetCount();
1411e209fccSTamas Berghammer }
1421e209fccSTamas Berghammer 
143db264a6dSTamas Berghammer const RegisterSet *
144b9c1b51eSKate Stone NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index) const {
1457fa7b81bSMuhammad Omair Javaid   return GetRegisterInfo().GetRegisterSet(set_index);
1461e209fccSTamas Berghammer }
1471e209fccSTamas Berghammer 
148b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount() const {
149cec93c35STamas Berghammer   uint32_t count = 0;
1507fa7b81bSMuhammad Omair Javaid   for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
1517fa7b81bSMuhammad Omair Javaid     count += GetRegisterSet(set_index)->num_registers;
152cec93c35STamas Berghammer   return count;
153cec93c35STamas Berghammer }
154cec93c35STamas Berghammer 
15597206d57SZachary Turner Status
15697206d57SZachary Turner NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info,
15797206d57SZachary Turner                                                RegisterValue &reg_value) {
15897206d57SZachary Turner   Status error;
1591e209fccSTamas Berghammer 
160b9c1b51eSKate Stone   if (!reg_info) {
1611e209fccSTamas Berghammer     error.SetErrorString("reg_info NULL");
1621e209fccSTamas Berghammer     return error;
1631e209fccSTamas Berghammer   }
1641e209fccSTamas Berghammer 
1651e209fccSTamas Berghammer   const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
1661e209fccSTamas Berghammer 
167b6f9d7b8SMuhammad Omair Javaid   if (reg == LLDB_INVALID_REGNUM)
168b6f9d7b8SMuhammad Omair Javaid     return Status("no lldb regnum for %s", reg_info && reg_info->name
169b6f9d7b8SMuhammad Omair Javaid                                                ? reg_info->name
170b6f9d7b8SMuhammad Omair Javaid                                                : "<unknown register>");
171b6f9d7b8SMuhammad Omair Javaid 
172b6f9d7b8SMuhammad Omair Javaid   uint8_t *src;
1734283320bSMuhammad Omair Javaid   uint32_t offset = LLDB_INVALID_INDEX32;
174567ba6c4SMuhammad Omair Javaid   uint64_t sve_vg;
175567ba6c4SMuhammad Omair Javaid   std::vector<uint8_t> sve_reg_non_live;
176b6f9d7b8SMuhammad Omair Javaid 
177b6f9d7b8SMuhammad Omair Javaid   if (IsGPR(reg)) {
178b6f9d7b8SMuhammad Omair Javaid     error = ReadGPR();
179b6f9d7b8SMuhammad Omair Javaid     if (error.Fail())
180b6f9d7b8SMuhammad Omair Javaid       return error;
181b6f9d7b8SMuhammad Omair Javaid 
182b6f9d7b8SMuhammad Omair Javaid     offset = reg_info->byte_offset;
183b6f9d7b8SMuhammad Omair Javaid     assert(offset < GetGPRSize());
184b6f9d7b8SMuhammad Omair Javaid     src = (uint8_t *)GetGPRBuffer() + offset;
185b6f9d7b8SMuhammad Omair Javaid 
186b6f9d7b8SMuhammad Omair Javaid   } else if (IsFPR(reg)) {
187567ba6c4SMuhammad Omair Javaid     if (m_sve_state == SVEState::Disabled) {
188567ba6c4SMuhammad Omair Javaid       // SVE is disabled take legacy route for FPU register access
189068f8a7eSTamas Berghammer       error = ReadFPR();
190068f8a7eSTamas Berghammer       if (error.Fail())
1911e209fccSTamas Berghammer         return error;
192567ba6c4SMuhammad Omair Javaid 
193b6f9d7b8SMuhammad Omair Javaid       offset = CalculateFprOffset(reg_info);
194b6f9d7b8SMuhammad Omair Javaid       assert(offset < GetFPRSize());
195b6f9d7b8SMuhammad Omair Javaid       src = (uint8_t *)GetFPRBuffer() + offset;
196567ba6c4SMuhammad Omair Javaid     } else {
197567ba6c4SMuhammad Omair Javaid       // SVE enabled, we will read and cache SVE ptrace data
198567ba6c4SMuhammad Omair Javaid       error = ReadAllSVE();
199567ba6c4SMuhammad Omair Javaid       if (error.Fail())
200567ba6c4SMuhammad Omair Javaid         return error;
201567ba6c4SMuhammad Omair Javaid 
202567ba6c4SMuhammad Omair Javaid       // FPSR and FPCR will be located right after Z registers in
203567ba6c4SMuhammad Omair Javaid       // SVEState::FPSIMD while in SVEState::Full they will be located at the
204567ba6c4SMuhammad Omair Javaid       // end of register data after an alignment correction based on currently
205567ba6c4SMuhammad Omair Javaid       // selected vector length.
206567ba6c4SMuhammad Omair Javaid       uint32_t sve_reg_num = LLDB_INVALID_REGNUM;
207567ba6c4SMuhammad Omair Javaid       if (reg == GetRegisterInfo().GetRegNumFPSR()) {
208567ba6c4SMuhammad Omair Javaid         sve_reg_num = reg;
209567ba6c4SMuhammad Omair Javaid         if (m_sve_state == SVEState::Full)
21005915400SCaroline Tice           offset = sve::PTraceFPSROffset(sve::vq_from_vl(m_sve_header.vl));
211567ba6c4SMuhammad Omair Javaid         else if (m_sve_state == SVEState::FPSIMD)
21205915400SCaroline Tice           offset = sve::ptrace_fpsimd_offset + (32 * 16);
213567ba6c4SMuhammad Omair Javaid       } else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
214567ba6c4SMuhammad Omair Javaid         sve_reg_num = reg;
215567ba6c4SMuhammad Omair Javaid         if (m_sve_state == SVEState::Full)
21605915400SCaroline Tice           offset = sve::PTraceFPCROffset(sve::vq_from_vl(m_sve_header.vl));
217567ba6c4SMuhammad Omair Javaid         else if (m_sve_state == SVEState::FPSIMD)
21805915400SCaroline Tice           offset = sve::ptrace_fpsimd_offset + (32 * 16) + 4;
219567ba6c4SMuhammad Omair Javaid       } else {
220567ba6c4SMuhammad Omair Javaid         // Extract SVE Z register value register number for this reg_info
221567ba6c4SMuhammad Omair Javaid         if (reg_info->value_regs &&
222567ba6c4SMuhammad Omair Javaid             reg_info->value_regs[0] != LLDB_INVALID_REGNUM)
223567ba6c4SMuhammad Omair Javaid           sve_reg_num = reg_info->value_regs[0];
224567ba6c4SMuhammad Omair Javaid         offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
225567ba6c4SMuhammad Omair Javaid       }
226567ba6c4SMuhammad Omair Javaid 
227567ba6c4SMuhammad Omair Javaid       assert(offset < GetSVEBufferSize());
228567ba6c4SMuhammad Omair Javaid       src = (uint8_t *)GetSVEBuffer() + offset;
229567ba6c4SMuhammad Omair Javaid     }
230567ba6c4SMuhammad Omair Javaid   } else if (IsSVE(reg)) {
231567ba6c4SMuhammad Omair Javaid 
232567ba6c4SMuhammad Omair Javaid     if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown)
233567ba6c4SMuhammad Omair Javaid       return Status("SVE disabled or not supported");
234567ba6c4SMuhammad Omair Javaid 
235567ba6c4SMuhammad Omair Javaid     if (GetRegisterInfo().IsSVERegVG(reg)) {
236567ba6c4SMuhammad Omair Javaid       sve_vg = GetSVERegVG();
237567ba6c4SMuhammad Omair Javaid       src = (uint8_t *)&sve_vg;
238567ba6c4SMuhammad Omair Javaid     } else {
239567ba6c4SMuhammad Omair Javaid       // SVE enabled, we will read and cache SVE ptrace data
240567ba6c4SMuhammad Omair Javaid       error = ReadAllSVE();
241567ba6c4SMuhammad Omair Javaid       if (error.Fail())
242567ba6c4SMuhammad Omair Javaid         return error;
243567ba6c4SMuhammad Omair Javaid 
244567ba6c4SMuhammad Omair Javaid       if (m_sve_state == SVEState::FPSIMD) {
245567ba6c4SMuhammad Omair Javaid         // In FPSIMD state SVE payload mirrors legacy fpsimd struct and so
246567ba6c4SMuhammad Omair Javaid         // just copy 16 bytes of v register to the start of z register. All
247567ba6c4SMuhammad Omair Javaid         // other SVE register will be set to zero.
248567ba6c4SMuhammad Omair Javaid         sve_reg_non_live.resize(reg_info->byte_size, 0);
249567ba6c4SMuhammad Omair Javaid         src = sve_reg_non_live.data();
250567ba6c4SMuhammad Omair Javaid 
251567ba6c4SMuhammad Omair Javaid         if (GetRegisterInfo().IsSVEZReg(reg)) {
252567ba6c4SMuhammad Omair Javaid           offset = CalculateSVEOffset(reg_info);
253567ba6c4SMuhammad Omair Javaid           assert(offset < GetSVEBufferSize());
254567ba6c4SMuhammad Omair Javaid           ::memcpy(sve_reg_non_live.data(), (uint8_t *)GetSVEBuffer() + offset,
255567ba6c4SMuhammad Omair Javaid                    16);
256567ba6c4SMuhammad Omair Javaid         }
257567ba6c4SMuhammad Omair Javaid       } else {
258567ba6c4SMuhammad Omair Javaid         offset = CalculateSVEOffset(reg_info);
259567ba6c4SMuhammad Omair Javaid         assert(offset < GetSVEBufferSize());
260567ba6c4SMuhammad Omair Javaid         src = (uint8_t *)GetSVEBuffer() + offset;
261567ba6c4SMuhammad Omair Javaid       }
262567ba6c4SMuhammad Omair Javaid     }
26388a5b35dSMuhammad Omair Javaid   } else if (IsPAuth(reg)) {
26488a5b35dSMuhammad Omair Javaid     error = ReadPAuthMask();
26588a5b35dSMuhammad Omair Javaid     if (error.Fail())
26688a5b35dSMuhammad Omair Javaid       return error;
26788a5b35dSMuhammad Omair Javaid 
26888a5b35dSMuhammad Omair Javaid     offset = reg_info->byte_offset - GetRegisterInfo().GetPAuthOffset();
26988a5b35dSMuhammad Omair Javaid     assert(offset < GetPACMaskSize());
27088a5b35dSMuhammad Omair Javaid     src = (uint8_t *)GetPACMask() + offset;
27188a5b35dSMuhammad Omair Javaid   } else if (IsMTE(reg)) {
27288a5b35dSMuhammad Omair Javaid     error = ReadMTEControl();
27388a5b35dSMuhammad Omair Javaid     if (error.Fail())
27488a5b35dSMuhammad Omair Javaid       return error;
27588a5b35dSMuhammad Omair Javaid 
27688a5b35dSMuhammad Omair Javaid     offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset();
27788a5b35dSMuhammad Omair Javaid     assert(offset < GetMTEControlSize());
27888a5b35dSMuhammad Omair Javaid     src = (uint8_t *)GetMTEControl() + offset;
279b6f9d7b8SMuhammad Omair Javaid   } else
280b6f9d7b8SMuhammad Omair Javaid     return Status("failed - register wasn't recognized to be a GPR or an FPR, "
281b6f9d7b8SMuhammad Omair Javaid                   "write strategy unknown");
2821e209fccSTamas Berghammer 
283b9c1b51eSKate Stone   reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size,
284b9c1b51eSKate Stone                               eByteOrderLittle, error);
2851e209fccSTamas Berghammer 
2861e209fccSTamas Berghammer   return error;
2871e209fccSTamas Berghammer }
2881e209fccSTamas Berghammer 
28997206d57SZachary Turner Status NativeRegisterContextLinux_arm64::WriteRegister(
290b9c1b51eSKate Stone     const RegisterInfo *reg_info, const RegisterValue &reg_value) {
291b6f9d7b8SMuhammad Omair Javaid   Status error;
292b6f9d7b8SMuhammad Omair Javaid 
2931e209fccSTamas Berghammer   if (!reg_info)
29497206d57SZachary Turner     return Status("reg_info NULL");
2951e209fccSTamas Berghammer 
296b6f9d7b8SMuhammad Omair Javaid   const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
297b6f9d7b8SMuhammad Omair Javaid 
298b6f9d7b8SMuhammad Omair Javaid   if (reg == LLDB_INVALID_REGNUM)
29997206d57SZachary Turner     return Status("no lldb regnum for %s", reg_info && reg_info->name
300b9c1b51eSKate Stone                                                ? reg_info->name
301b9c1b51eSKate Stone                                                : "<unknown register>");
3021e209fccSTamas Berghammer 
303b6f9d7b8SMuhammad Omair Javaid   uint8_t *dst;
3044283320bSMuhammad Omair Javaid   uint32_t offset = LLDB_INVALID_INDEX32;
305567ba6c4SMuhammad Omair Javaid   std::vector<uint8_t> sve_reg_non_live;
3061e209fccSTamas Berghammer 
307b6f9d7b8SMuhammad Omair Javaid   if (IsGPR(reg)) {
308b6f9d7b8SMuhammad Omair Javaid     error = ReadGPR();
309068f8a7eSTamas Berghammer     if (error.Fail())
310068f8a7eSTamas Berghammer       return error;
3111e209fccSTamas Berghammer 
312567ba6c4SMuhammad Omair Javaid     assert(reg_info->byte_offset < GetGPRSize());
313567ba6c4SMuhammad Omair Javaid     dst = (uint8_t *)GetGPRBuffer() + reg_info->byte_offset;
314b6f9d7b8SMuhammad Omair Javaid     ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
315b6f9d7b8SMuhammad Omair Javaid 
316b6f9d7b8SMuhammad Omair Javaid     return WriteGPR();
317b6f9d7b8SMuhammad Omair Javaid   } else if (IsFPR(reg)) {
318567ba6c4SMuhammad Omair Javaid     if (m_sve_state == SVEState::Disabled) {
319567ba6c4SMuhammad Omair Javaid       // SVE is disabled take legacy route for FPU register access
320b6f9d7b8SMuhammad Omair Javaid       error = ReadFPR();
321b6f9d7b8SMuhammad Omair Javaid       if (error.Fail())
322b6f9d7b8SMuhammad Omair Javaid         return error;
323567ba6c4SMuhammad Omair Javaid 
324b6f9d7b8SMuhammad Omair Javaid       offset = CalculateFprOffset(reg_info);
325b6f9d7b8SMuhammad Omair Javaid       assert(offset < GetFPRSize());
326b6f9d7b8SMuhammad Omair Javaid       dst = (uint8_t *)GetFPRBuffer() + offset;
327b6f9d7b8SMuhammad Omair Javaid       ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
328b6f9d7b8SMuhammad Omair Javaid 
329b6f9d7b8SMuhammad Omair Javaid       return WriteFPR();
330567ba6c4SMuhammad Omair Javaid     } else {
331567ba6c4SMuhammad Omair Javaid       // SVE enabled, we will read and cache SVE ptrace data
332567ba6c4SMuhammad Omair Javaid       error = ReadAllSVE();
333567ba6c4SMuhammad Omair Javaid       if (error.Fail())
334567ba6c4SMuhammad Omair Javaid         return error;
335567ba6c4SMuhammad Omair Javaid 
336567ba6c4SMuhammad Omair Javaid       // FPSR and FPCR will be located right after Z registers in
337567ba6c4SMuhammad Omair Javaid       // SVEState::FPSIMD while in SVEState::Full they will be located at the
338567ba6c4SMuhammad Omair Javaid       // end of register data after an alignment correction based on currently
339567ba6c4SMuhammad Omair Javaid       // selected vector length.
340567ba6c4SMuhammad Omair Javaid       uint32_t sve_reg_num = LLDB_INVALID_REGNUM;
341567ba6c4SMuhammad Omair Javaid       if (reg == GetRegisterInfo().GetRegNumFPSR()) {
342567ba6c4SMuhammad Omair Javaid         sve_reg_num = reg;
343567ba6c4SMuhammad Omair Javaid         if (m_sve_state == SVEState::Full)
34405915400SCaroline Tice           offset = sve::PTraceFPSROffset(sve::vq_from_vl(m_sve_header.vl));
345567ba6c4SMuhammad Omair Javaid         else if (m_sve_state == SVEState::FPSIMD)
34605915400SCaroline Tice           offset = sve::ptrace_fpsimd_offset + (32 * 16);
347567ba6c4SMuhammad Omair Javaid       } else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
348567ba6c4SMuhammad Omair Javaid         sve_reg_num = reg;
349567ba6c4SMuhammad Omair Javaid         if (m_sve_state == SVEState::Full)
35005915400SCaroline Tice           offset = sve::PTraceFPCROffset(sve::vq_from_vl(m_sve_header.vl));
351567ba6c4SMuhammad Omair Javaid         else if (m_sve_state == SVEState::FPSIMD)
35205915400SCaroline Tice           offset = sve::ptrace_fpsimd_offset + (32 * 16) + 4;
353567ba6c4SMuhammad Omair Javaid       } else {
354567ba6c4SMuhammad Omair Javaid         // Extract SVE Z register value register number for this reg_info
355567ba6c4SMuhammad Omair Javaid         if (reg_info->value_regs &&
356567ba6c4SMuhammad Omair Javaid             reg_info->value_regs[0] != LLDB_INVALID_REGNUM)
357567ba6c4SMuhammad Omair Javaid           sve_reg_num = reg_info->value_regs[0];
358567ba6c4SMuhammad Omair Javaid         offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
359b6f9d7b8SMuhammad Omair Javaid       }
360b6f9d7b8SMuhammad Omair Javaid 
361567ba6c4SMuhammad Omair Javaid       assert(offset < GetSVEBufferSize());
362567ba6c4SMuhammad Omair Javaid       dst = (uint8_t *)GetSVEBuffer() + offset;
363567ba6c4SMuhammad Omair Javaid       ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
364567ba6c4SMuhammad Omair Javaid       return WriteAllSVE();
365567ba6c4SMuhammad Omair Javaid     }
366567ba6c4SMuhammad Omair Javaid   } else if (IsSVE(reg)) {
367567ba6c4SMuhammad Omair Javaid     if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown)
368567ba6c4SMuhammad Omair Javaid       return Status("SVE disabled or not supported");
369567ba6c4SMuhammad Omair Javaid     else {
370567ba6c4SMuhammad Omair Javaid       // Target has SVE enabled, we will read and cache SVE ptrace data
371567ba6c4SMuhammad Omair Javaid       error = ReadAllSVE();
372567ba6c4SMuhammad Omair Javaid       if (error.Fail())
373b6f9d7b8SMuhammad Omair Javaid         return error;
374567ba6c4SMuhammad Omair Javaid 
375e448ad78SMuhammad Omair Javaid       if (GetRegisterInfo().IsSVERegVG(reg)) {
376e448ad78SMuhammad Omair Javaid         uint64_t vg_value = reg_value.GetAsUInt64();
377e448ad78SMuhammad Omair Javaid 
378e448ad78SMuhammad Omair Javaid         if (sve_vl_valid(vg_value * 8)) {
379e448ad78SMuhammad Omair Javaid           if (m_sve_header_is_valid && vg_value == GetSVERegVG())
380e448ad78SMuhammad Omair Javaid             return error;
381e448ad78SMuhammad Omair Javaid 
382e448ad78SMuhammad Omair Javaid           SetSVERegVG(vg_value);
383e448ad78SMuhammad Omair Javaid 
384e448ad78SMuhammad Omair Javaid           error = WriteSVEHeader();
385e448ad78SMuhammad Omair Javaid           if (error.Success())
386e448ad78SMuhammad Omair Javaid             ConfigureRegisterContext();
387e448ad78SMuhammad Omair Javaid 
388e448ad78SMuhammad Omair Javaid           if (m_sve_header_is_valid && vg_value == GetSVERegVG())
389e448ad78SMuhammad Omair Javaid             return error;
390e448ad78SMuhammad Omair Javaid         }
391e448ad78SMuhammad Omair Javaid 
392e448ad78SMuhammad Omair Javaid         return Status("SVE vector length update failed.");
393e448ad78SMuhammad Omair Javaid       }
394e448ad78SMuhammad Omair Javaid 
395567ba6c4SMuhammad Omair Javaid       // If target supports SVE but currently in FPSIMD mode.
396567ba6c4SMuhammad Omair Javaid       if (m_sve_state == SVEState::FPSIMD) {
397567ba6c4SMuhammad Omair Javaid         // Here we will check if writing this SVE register enables
398567ba6c4SMuhammad Omair Javaid         // SVEState::Full
399567ba6c4SMuhammad Omair Javaid         bool set_sve_state_full = false;
400567ba6c4SMuhammad Omair Javaid         const uint8_t *reg_bytes = (const uint8_t *)reg_value.GetBytes();
401567ba6c4SMuhammad Omair Javaid         if (GetRegisterInfo().IsSVEZReg(reg)) {
402567ba6c4SMuhammad Omair Javaid           for (uint32_t i = 16; i < reg_info->byte_size; i++) {
403567ba6c4SMuhammad Omair Javaid             if (reg_bytes[i]) {
404567ba6c4SMuhammad Omair Javaid               set_sve_state_full = true;
405567ba6c4SMuhammad Omair Javaid               break;
406567ba6c4SMuhammad Omair Javaid             }
407567ba6c4SMuhammad Omair Javaid           }
408567ba6c4SMuhammad Omair Javaid         } else if (GetRegisterInfo().IsSVEPReg(reg) ||
409567ba6c4SMuhammad Omair Javaid                    reg == GetRegisterInfo().GetRegNumSVEFFR()) {
410567ba6c4SMuhammad Omair Javaid           for (uint32_t i = 0; i < reg_info->byte_size; i++) {
411567ba6c4SMuhammad Omair Javaid             if (reg_bytes[i]) {
412567ba6c4SMuhammad Omair Javaid               set_sve_state_full = true;
413567ba6c4SMuhammad Omair Javaid               break;
414567ba6c4SMuhammad Omair Javaid             }
415567ba6c4SMuhammad Omair Javaid           }
416567ba6c4SMuhammad Omair Javaid         }
417567ba6c4SMuhammad Omair Javaid 
418567ba6c4SMuhammad Omair Javaid         if (!set_sve_state_full && GetRegisterInfo().IsSVEZReg(reg)) {
419567ba6c4SMuhammad Omair Javaid           // We are writing a Z register which is zero beyond 16 bytes so copy
420567ba6c4SMuhammad Omair Javaid           // first 16 bytes only as SVE payload mirrors legacy fpsimd structure
421567ba6c4SMuhammad Omair Javaid           offset = CalculateSVEOffset(reg_info);
422567ba6c4SMuhammad Omair Javaid           assert(offset < GetSVEBufferSize());
423567ba6c4SMuhammad Omair Javaid           dst = (uint8_t *)GetSVEBuffer() + offset;
424567ba6c4SMuhammad Omair Javaid           ::memcpy(dst, reg_value.GetBytes(), 16);
425567ba6c4SMuhammad Omair Javaid 
426567ba6c4SMuhammad Omair Javaid           return WriteAllSVE();
427567ba6c4SMuhammad Omair Javaid         } else
428567ba6c4SMuhammad Omair Javaid           return Status("SVE state change operation not supported");
429567ba6c4SMuhammad Omair Javaid       } else {
430567ba6c4SMuhammad Omair Javaid         offset = CalculateSVEOffset(reg_info);
431567ba6c4SMuhammad Omair Javaid         assert(offset < GetSVEBufferSize());
432567ba6c4SMuhammad Omair Javaid         dst = (uint8_t *)GetSVEBuffer() + offset;
433567ba6c4SMuhammad Omair Javaid         ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
434567ba6c4SMuhammad Omair Javaid         return WriteAllSVE();
435567ba6c4SMuhammad Omair Javaid       }
436567ba6c4SMuhammad Omair Javaid     }
43788a5b35dSMuhammad Omair Javaid   } else if (IsMTE(reg)) {
43888a5b35dSMuhammad Omair Javaid     error = ReadMTEControl();
43988a5b35dSMuhammad Omair Javaid     if (error.Fail())
44088a5b35dSMuhammad Omair Javaid       return error;
44188a5b35dSMuhammad Omair Javaid 
44288a5b35dSMuhammad Omair Javaid     offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset();
44388a5b35dSMuhammad Omair Javaid     assert(offset < GetMTEControlSize());
44488a5b35dSMuhammad Omair Javaid     dst = (uint8_t *)GetMTEControl() + offset;
44588a5b35dSMuhammad Omair Javaid     ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
44688a5b35dSMuhammad Omair Javaid 
44788a5b35dSMuhammad Omair Javaid     return WriteMTEControl();
448567ba6c4SMuhammad Omair Javaid   }
449567ba6c4SMuhammad Omair Javaid 
450567ba6c4SMuhammad Omair Javaid   return Status("Failed to write register value");
4511e209fccSTamas Berghammer }
4521e209fccSTamas Berghammer 
45397206d57SZachary Turner Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues(
454b9c1b51eSKate Stone     lldb::DataBufferSP &data_sp) {
45597206d57SZachary Turner   Status error;
4561e209fccSTamas Berghammer 
457db264a6dSTamas Berghammer   data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
458567ba6c4SMuhammad Omair Javaid 
459068f8a7eSTamas Berghammer   error = ReadGPR();
460068f8a7eSTamas Berghammer   if (error.Fail())
4611e209fccSTamas Berghammer     return error;
4621e209fccSTamas Berghammer 
463068f8a7eSTamas Berghammer   error = ReadFPR();
464068f8a7eSTamas Berghammer   if (error.Fail())
4651e209fccSTamas Berghammer     return error;
466567ba6c4SMuhammad Omair Javaid 
4671e209fccSTamas Berghammer   uint8_t *dst = data_sp->GetBytes();
468b6f9d7b8SMuhammad Omair Javaid   ::memcpy(dst, GetGPRBuffer(), GetGPRSize());
4691e209fccSTamas Berghammer   dst += GetGPRSize();
470b6f9d7b8SMuhammad Omair Javaid   ::memcpy(dst, GetFPRBuffer(), GetFPRSize());
4711e209fccSTamas Berghammer 
4721e209fccSTamas Berghammer   return error;
4731e209fccSTamas Berghammer }
4741e209fccSTamas Berghammer 
47597206d57SZachary Turner Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
476b9c1b51eSKate Stone     const lldb::DataBufferSP &data_sp) {
47797206d57SZachary Turner   Status error;
4781e209fccSTamas Berghammer 
479b9c1b51eSKate Stone   if (!data_sp) {
480b9c1b51eSKate Stone     error.SetErrorStringWithFormat(
481b9c1b51eSKate Stone         "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided",
482b9c1b51eSKate Stone         __FUNCTION__);
4831e209fccSTamas Berghammer     return error;
4841e209fccSTamas Berghammer   }
4851e209fccSTamas Berghammer 
486b9c1b51eSKate Stone   if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
487b9c1b51eSKate Stone     error.SetErrorStringWithFormat(
488b9c1b51eSKate Stone         "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched "
489b9c1b51eSKate Stone         "data size, expected %" PRIu64 ", actual %" PRIu64,
490b9c1b51eSKate Stone         __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
4911e209fccSTamas Berghammer     return error;
4921e209fccSTamas Berghammer   }
4931e209fccSTamas Berghammer 
4941e209fccSTamas Berghammer   uint8_t *src = data_sp->GetBytes();
495b9c1b51eSKate Stone   if (src == nullptr) {
496b9c1b51eSKate Stone     error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s "
497b9c1b51eSKate Stone                                    "DataBuffer::GetBytes() returned a null "
498b9c1b51eSKate Stone                                    "pointer",
499b9c1b51eSKate Stone                                    __FUNCTION__);
5001e209fccSTamas Berghammer     return error;
5011e209fccSTamas Berghammer   }
502b6f9d7b8SMuhammad Omair Javaid   ::memcpy(GetGPRBuffer(), src, GetRegisterInfoInterface().GetGPRSize());
5031e209fccSTamas Berghammer 
504068f8a7eSTamas Berghammer   error = WriteGPR();
505068f8a7eSTamas Berghammer   if (error.Fail())
5061e209fccSTamas Berghammer     return error;
5071e209fccSTamas Berghammer 
5081e209fccSTamas Berghammer   src += GetRegisterInfoInterface().GetGPRSize();
509b6f9d7b8SMuhammad Omair Javaid   ::memcpy(GetFPRBuffer(), src, GetFPRSize());
5101e209fccSTamas Berghammer 
511068f8a7eSTamas Berghammer   error = WriteFPR();
5121e209fccSTamas Berghammer   if (error.Fail())
5131e209fccSTamas Berghammer     return error;
5141e209fccSTamas Berghammer 
5151e209fccSTamas Berghammer   return error;
5161e209fccSTamas Berghammer }
5171e209fccSTamas Berghammer 
518b9c1b51eSKate Stone bool NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const {
5197fa7b81bSMuhammad Omair Javaid   if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
5207fa7b81bSMuhammad Omair Javaid       RegisterInfoPOSIX_arm64::GPRegSet)
5217fa7b81bSMuhammad Omair Javaid     return true;
5227fa7b81bSMuhammad Omair Javaid   return false;
5231e209fccSTamas Berghammer }
5241e209fccSTamas Berghammer 
525b9c1b51eSKate Stone bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const {
5267fa7b81bSMuhammad Omair Javaid   if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
5277fa7b81bSMuhammad Omair Javaid       RegisterInfoPOSIX_arm64::FPRegSet)
5287fa7b81bSMuhammad Omair Javaid     return true;
5297fa7b81bSMuhammad Omair Javaid   return false;
5301e209fccSTamas Berghammer }
5311e209fccSTamas Berghammer 
532567ba6c4SMuhammad Omair Javaid bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const {
533d6d3d21cSMuhammad Omair Javaid   return GetRegisterInfo().IsSVEReg(reg);
534567ba6c4SMuhammad Omair Javaid }
535567ba6c4SMuhammad Omair Javaid 
53688a5b35dSMuhammad Omair Javaid bool NativeRegisterContextLinux_arm64::IsPAuth(unsigned reg) const {
53788a5b35dSMuhammad Omair Javaid   return GetRegisterInfo().IsPAuthReg(reg);
53888a5b35dSMuhammad Omair Javaid }
53988a5b35dSMuhammad Omair Javaid 
54088a5b35dSMuhammad Omair Javaid bool NativeRegisterContextLinux_arm64::IsMTE(unsigned reg) const {
54188a5b35dSMuhammad Omair Javaid   return GetRegisterInfo().IsMTEReg(reg);
54288a5b35dSMuhammad Omair Javaid }
54388a5b35dSMuhammad Omair Javaid 
544771c4c9cSMichał Górny llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
545b9c1b51eSKate Stone   if (!m_refresh_hwdebug_info) {
546771c4c9cSMichał Górny     return llvm::Error::success();
5471fd2a8cfSOmair Javaid   }
5481fd2a8cfSOmair Javaid 
549c7512fdcSPavel Labath   ::pid_t tid = m_thread.GetID();
550ea8c25a8SOmair Javaid 
551c7512fdcSPavel Labath   int regset = NT_ARM_HW_WATCH;
552c7512fdcSPavel Labath   struct iovec ioVec;
553c7512fdcSPavel Labath   struct user_hwdebug_state dreg_state;
55497206d57SZachary Turner   Status error;
555c7512fdcSPavel Labath 
556c7512fdcSPavel Labath   ioVec.iov_base = &dreg_state;
557c7512fdcSPavel Labath   ioVec.iov_len = sizeof(dreg_state);
558b9c1b51eSKate Stone   error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,
559b9c1b51eSKate Stone                                             &ioVec, ioVec.iov_len);
5603a56363aSOmair Javaid 
5613a56363aSOmair Javaid   if (error.Fail())
562771c4c9cSMichał Górny     return error.ToError();
5633a56363aSOmair Javaid 
5641fd2a8cfSOmair Javaid   m_max_hwp_supported = dreg_state.dbg_info & 0xff;
565c7512fdcSPavel Labath 
566c7512fdcSPavel Labath   regset = NT_ARM_HW_BREAK;
567b9c1b51eSKate Stone   error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,
568b9c1b51eSKate Stone                                             &ioVec, ioVec.iov_len);
5691fd2a8cfSOmair Javaid 
5703a56363aSOmair Javaid   if (error.Fail())
571771c4c9cSMichał Górny     return error.ToError();
5723a56363aSOmair Javaid 
5733a56363aSOmair Javaid   m_max_hbp_supported = dreg_state.dbg_info & 0xff;
5741fd2a8cfSOmair Javaid   m_refresh_hwdebug_info = false;
575c7512fdcSPavel Labath 
576771c4c9cSMichał Górny   return llvm::Error::success();
577ea8c25a8SOmair Javaid }
578068f8a7eSTamas Berghammer 
579771c4c9cSMichał Górny llvm::Error
580771c4c9cSMichał Górny NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
581c7512fdcSPavel Labath   struct iovec ioVec;
582c7512fdcSPavel Labath   struct user_hwdebug_state dreg_state;
583771c4c9cSMichał Górny   int regset;
584c7512fdcSPavel Labath 
585c7512fdcSPavel Labath   memset(&dreg_state, 0, sizeof(dreg_state));
586c7512fdcSPavel Labath   ioVec.iov_base = &dreg_state;
587c7512fdcSPavel Labath 
588771c4c9cSMichał Górny   switch (hwbType) {
589771c4c9cSMichał Górny   case eDREGTypeWATCH:
590771c4c9cSMichał Górny     regset = NT_ARM_HW_WATCH;
591b9c1b51eSKate Stone     ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
592b9c1b51eSKate Stone                     (sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported);
5931fd2a8cfSOmair Javaid 
594b9c1b51eSKate Stone     for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
5951fd2a8cfSOmair Javaid       dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address;
5961fd2a8cfSOmair Javaid       dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control;
5971fd2a8cfSOmair Javaid     }
598771c4c9cSMichał Górny     break;
599771c4c9cSMichał Górny   case eDREGTypeBREAK:
600771c4c9cSMichał Górny     regset = NT_ARM_HW_BREAK;
601b9c1b51eSKate Stone     ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
602b9c1b51eSKate Stone                     (sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported);
6031fd2a8cfSOmair Javaid 
604b9c1b51eSKate Stone     for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
605771c4c9cSMichał Górny       dreg_state.dbg_regs[i].addr = m_hbp_regs[i].address;
606771c4c9cSMichał Górny       dreg_state.dbg_regs[i].ctrl = m_hbp_regs[i].control;
6071fd2a8cfSOmair Javaid     }
608771c4c9cSMichał Górny     break;
609068f8a7eSTamas Berghammer   }
610068f8a7eSTamas Berghammer 
611b9c1b51eSKate Stone   return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),
612771c4c9cSMichał Górny                                            &regset, &ioVec, ioVec.iov_len)
613771c4c9cSMichał Górny       .ToError();
614c7512fdcSPavel Labath }
615c7512fdcSPavel Labath 
6163f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::ReadGPR() {
617b6f9d7b8SMuhammad Omair Javaid   Status error;
618b6f9d7b8SMuhammad Omair Javaid 
619567ba6c4SMuhammad Omair Javaid   if (m_gpr_is_valid)
620567ba6c4SMuhammad Omair Javaid     return error;
621b6f9d7b8SMuhammad Omair Javaid 
622567ba6c4SMuhammad Omair Javaid   struct iovec ioVec;
6233f3673eaSPavel Labath   ioVec.iov_base = GetGPRBuffer();
62426b8ea2eSMuhammad Omair Javaid   ioVec.iov_len = GetGPRBufferSize();
625b6f9d7b8SMuhammad Omair Javaid 
62626b8ea2eSMuhammad Omair Javaid   error = ReadRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS);
627b6f9d7b8SMuhammad Omair Javaid 
628b6f9d7b8SMuhammad Omair Javaid   if (error.Success())
629b6f9d7b8SMuhammad Omair Javaid     m_gpr_is_valid = true;
630b6f9d7b8SMuhammad Omair Javaid 
631b6f9d7b8SMuhammad Omair Javaid   return error;
632068f8a7eSTamas Berghammer }
633068f8a7eSTamas Berghammer 
6343f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::WriteGPR() {
635567ba6c4SMuhammad Omair Javaid   Status error = ReadGPR();
636567ba6c4SMuhammad Omair Javaid   if (error.Fail())
637567ba6c4SMuhammad Omair Javaid     return error;
638567ba6c4SMuhammad Omair Javaid 
639c7512fdcSPavel Labath   struct iovec ioVec;
6403f3673eaSPavel Labath   ioVec.iov_base = GetGPRBuffer();
64126b8ea2eSMuhammad Omair Javaid   ioVec.iov_len = GetGPRBufferSize();
642b6f9d7b8SMuhammad Omair Javaid 
643567ba6c4SMuhammad Omair Javaid   m_gpr_is_valid = false;
644567ba6c4SMuhammad Omair Javaid 
64526b8ea2eSMuhammad Omair Javaid   return WriteRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS);
646068f8a7eSTamas Berghammer }
647068f8a7eSTamas Berghammer 
6483f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::ReadFPR() {
649b6f9d7b8SMuhammad Omair Javaid   Status error;
650b6f9d7b8SMuhammad Omair Javaid 
651567ba6c4SMuhammad Omair Javaid   if (m_fpu_is_valid)
652567ba6c4SMuhammad Omair Javaid     return error;
653b6f9d7b8SMuhammad Omair Javaid 
654567ba6c4SMuhammad Omair Javaid   struct iovec ioVec;
6553f3673eaSPavel Labath   ioVec.iov_base = GetFPRBuffer();
6563f3673eaSPavel Labath   ioVec.iov_len = GetFPRSize();
657b6f9d7b8SMuhammad Omair Javaid 
658b6f9d7b8SMuhammad Omair Javaid   error = ReadRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
659b6f9d7b8SMuhammad Omair Javaid 
660b6f9d7b8SMuhammad Omair Javaid   if (error.Success())
661b6f9d7b8SMuhammad Omair Javaid     m_fpu_is_valid = true;
662b6f9d7b8SMuhammad Omair Javaid 
663b6f9d7b8SMuhammad Omair Javaid   return error;
664068f8a7eSTamas Berghammer }
665068f8a7eSTamas Berghammer 
6663f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::WriteFPR() {
667567ba6c4SMuhammad Omair Javaid   Status error = ReadFPR();
668567ba6c4SMuhammad Omair Javaid   if (error.Fail())
669567ba6c4SMuhammad Omair Javaid     return error;
670567ba6c4SMuhammad Omair Javaid 
671c7512fdcSPavel Labath   struct iovec ioVec;
6723f3673eaSPavel Labath   ioVec.iov_base = GetFPRBuffer();
6733f3673eaSPavel Labath   ioVec.iov_len = GetFPRSize();
674b6f9d7b8SMuhammad Omair Javaid 
675567ba6c4SMuhammad Omair Javaid   m_fpu_is_valid = false;
676567ba6c4SMuhammad Omair Javaid 
6773f3673eaSPavel Labath   return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
678068f8a7eSTamas Berghammer }
679068f8a7eSTamas Berghammer 
680b6f9d7b8SMuhammad Omair Javaid void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() {
681b6f9d7b8SMuhammad Omair Javaid   m_gpr_is_valid = false;
682b6f9d7b8SMuhammad Omair Javaid   m_fpu_is_valid = false;
683567ba6c4SMuhammad Omair Javaid   m_sve_buffer_is_valid = false;
684567ba6c4SMuhammad Omair Javaid   m_sve_header_is_valid = false;
68588a5b35dSMuhammad Omair Javaid   m_pac_mask_is_valid = false;
68688a5b35dSMuhammad Omair Javaid   m_mte_ctrl_is_valid = false;
687567ba6c4SMuhammad Omair Javaid 
688567ba6c4SMuhammad Omair Javaid   // Update SVE registers in case there is change in configuration.
689567ba6c4SMuhammad Omair Javaid   ConfigureRegisterContext();
690567ba6c4SMuhammad Omair Javaid }
691567ba6c4SMuhammad Omair Javaid 
692567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
693567ba6c4SMuhammad Omair Javaid   Status error;
694567ba6c4SMuhammad Omair Javaid 
695567ba6c4SMuhammad Omair Javaid   if (m_sve_header_is_valid)
696567ba6c4SMuhammad Omair Javaid     return error;
697567ba6c4SMuhammad Omair Javaid 
698567ba6c4SMuhammad Omair Javaid   struct iovec ioVec;
699567ba6c4SMuhammad Omair Javaid   ioVec.iov_base = GetSVEHeader();
700567ba6c4SMuhammad Omair Javaid   ioVec.iov_len = GetSVEHeaderSize();
701567ba6c4SMuhammad Omair Javaid 
702567ba6c4SMuhammad Omair Javaid   error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE);
703567ba6c4SMuhammad Omair Javaid 
70488a5b35dSMuhammad Omair Javaid   if (error.Success())
705567ba6c4SMuhammad Omair Javaid     m_sve_header_is_valid = true;
706567ba6c4SMuhammad Omair Javaid 
707567ba6c4SMuhammad Omair Javaid   return error;
708567ba6c4SMuhammad Omair Javaid }
709567ba6c4SMuhammad Omair Javaid 
71088a5b35dSMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::ReadPAuthMask() {
71188a5b35dSMuhammad Omair Javaid   Status error;
71288a5b35dSMuhammad Omair Javaid 
71388a5b35dSMuhammad Omair Javaid   if (m_pac_mask_is_valid)
71488a5b35dSMuhammad Omair Javaid     return error;
71588a5b35dSMuhammad Omair Javaid 
71688a5b35dSMuhammad Omair Javaid   struct iovec ioVec;
71788a5b35dSMuhammad Omair Javaid   ioVec.iov_base = GetPACMask();
71888a5b35dSMuhammad Omair Javaid   ioVec.iov_len = GetPACMaskSize();
71988a5b35dSMuhammad Omair Javaid 
72088a5b35dSMuhammad Omair Javaid   error = ReadRegisterSet(&ioVec, GetPACMaskSize(), NT_ARM_PAC_MASK);
72188a5b35dSMuhammad Omair Javaid 
72288a5b35dSMuhammad Omair Javaid   if (error.Success())
72388a5b35dSMuhammad Omair Javaid     m_pac_mask_is_valid = true;
72488a5b35dSMuhammad Omair Javaid 
72588a5b35dSMuhammad Omair Javaid   return error;
72688a5b35dSMuhammad Omair Javaid }
72788a5b35dSMuhammad Omair Javaid 
728567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::WriteSVEHeader() {
729567ba6c4SMuhammad Omair Javaid   Status error;
730567ba6c4SMuhammad Omair Javaid 
731567ba6c4SMuhammad Omair Javaid   error = ReadSVEHeader();
732567ba6c4SMuhammad Omair Javaid   if (error.Fail())
733567ba6c4SMuhammad Omair Javaid     return error;
734567ba6c4SMuhammad Omair Javaid 
735567ba6c4SMuhammad Omair Javaid   struct iovec ioVec;
736567ba6c4SMuhammad Omair Javaid   ioVec.iov_base = GetSVEHeader();
737567ba6c4SMuhammad Omair Javaid   ioVec.iov_len = GetSVEHeaderSize();
738567ba6c4SMuhammad Omair Javaid 
739567ba6c4SMuhammad Omair Javaid   m_sve_buffer_is_valid = false;
740567ba6c4SMuhammad Omair Javaid   m_sve_header_is_valid = false;
741567ba6c4SMuhammad Omair Javaid   m_fpu_is_valid = false;
742567ba6c4SMuhammad Omair Javaid 
743567ba6c4SMuhammad Omair Javaid   return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE);
744567ba6c4SMuhammad Omair Javaid }
745567ba6c4SMuhammad Omair Javaid 
746567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::ReadAllSVE() {
747567ba6c4SMuhammad Omair Javaid   Status error;
748567ba6c4SMuhammad Omair Javaid 
749567ba6c4SMuhammad Omair Javaid   if (m_sve_buffer_is_valid)
750567ba6c4SMuhammad Omair Javaid     return error;
751567ba6c4SMuhammad Omair Javaid 
752567ba6c4SMuhammad Omair Javaid   struct iovec ioVec;
753567ba6c4SMuhammad Omair Javaid   ioVec.iov_base = GetSVEBuffer();
754567ba6c4SMuhammad Omair Javaid   ioVec.iov_len = GetSVEBufferSize();
755567ba6c4SMuhammad Omair Javaid 
756567ba6c4SMuhammad Omair Javaid   error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE);
757567ba6c4SMuhammad Omair Javaid 
758567ba6c4SMuhammad Omair Javaid   if (error.Success())
759567ba6c4SMuhammad Omair Javaid     m_sve_buffer_is_valid = true;
760567ba6c4SMuhammad Omair Javaid 
761567ba6c4SMuhammad Omair Javaid   return error;
762567ba6c4SMuhammad Omair Javaid }
763567ba6c4SMuhammad Omair Javaid 
764567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::WriteAllSVE() {
765567ba6c4SMuhammad Omair Javaid   Status error;
766567ba6c4SMuhammad Omair Javaid 
767567ba6c4SMuhammad Omair Javaid   error = ReadAllSVE();
768567ba6c4SMuhammad Omair Javaid   if (error.Fail())
769567ba6c4SMuhammad Omair Javaid     return error;
770567ba6c4SMuhammad Omair Javaid 
771567ba6c4SMuhammad Omair Javaid   struct iovec ioVec;
772567ba6c4SMuhammad Omair Javaid 
773567ba6c4SMuhammad Omair Javaid   ioVec.iov_base = GetSVEBuffer();
774567ba6c4SMuhammad Omair Javaid   ioVec.iov_len = GetSVEBufferSize();
775567ba6c4SMuhammad Omair Javaid 
776567ba6c4SMuhammad Omair Javaid   m_sve_buffer_is_valid = false;
777567ba6c4SMuhammad Omair Javaid   m_sve_header_is_valid = false;
778567ba6c4SMuhammad Omair Javaid   m_fpu_is_valid = false;
779567ba6c4SMuhammad Omair Javaid 
780567ba6c4SMuhammad Omair Javaid   return WriteRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE);
781567ba6c4SMuhammad Omair Javaid }
782567ba6c4SMuhammad Omair Javaid 
78388a5b35dSMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::ReadMTEControl() {
78488a5b35dSMuhammad Omair Javaid   Status error;
78588a5b35dSMuhammad Omair Javaid 
78688a5b35dSMuhammad Omair Javaid   if (m_mte_ctrl_is_valid)
78788a5b35dSMuhammad Omair Javaid     return error;
78888a5b35dSMuhammad Omair Javaid 
78988a5b35dSMuhammad Omair Javaid   struct iovec ioVec;
79088a5b35dSMuhammad Omair Javaid   ioVec.iov_base = GetMTEControl();
79188a5b35dSMuhammad Omair Javaid   ioVec.iov_len = GetMTEControlSize();
79288a5b35dSMuhammad Omair Javaid 
79388a5b35dSMuhammad Omair Javaid   error = ReadRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
79488a5b35dSMuhammad Omair Javaid 
79588a5b35dSMuhammad Omair Javaid   if (error.Success())
79688a5b35dSMuhammad Omair Javaid     m_mte_ctrl_is_valid = true;
79788a5b35dSMuhammad Omair Javaid 
79888a5b35dSMuhammad Omair Javaid   return error;
79988a5b35dSMuhammad Omair Javaid }
80088a5b35dSMuhammad Omair Javaid 
80188a5b35dSMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::WriteMTEControl() {
80288a5b35dSMuhammad Omair Javaid   Status error;
80388a5b35dSMuhammad Omair Javaid 
80488a5b35dSMuhammad Omair Javaid   error = ReadMTEControl();
80588a5b35dSMuhammad Omair Javaid   if (error.Fail())
80688a5b35dSMuhammad Omair Javaid     return error;
80788a5b35dSMuhammad Omair Javaid 
80888a5b35dSMuhammad Omair Javaid   struct iovec ioVec;
80988a5b35dSMuhammad Omair Javaid   ioVec.iov_base = GetMTEControl();
81088a5b35dSMuhammad Omair Javaid   ioVec.iov_len = GetMTEControlSize();
81188a5b35dSMuhammad Omair Javaid 
81288a5b35dSMuhammad Omair Javaid   m_mte_ctrl_is_valid = false;
81388a5b35dSMuhammad Omair Javaid 
81488a5b35dSMuhammad Omair Javaid   return WriteRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
81588a5b35dSMuhammad Omair Javaid }
81688a5b35dSMuhammad Omair Javaid 
817567ba6c4SMuhammad Omair Javaid void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
818d6d3d21cSMuhammad Omair Javaid   // ConfigureRegisterContext gets called from InvalidateAllRegisters
819d6d3d21cSMuhammad Omair Javaid   // on every stop and configures SVE vector length.
820d6d3d21cSMuhammad Omair Javaid   // If m_sve_state is set to SVEState::Disabled on first stop, code below will
821d6d3d21cSMuhammad Omair Javaid   // be deemed non operational for the lifetime of current process.
822567ba6c4SMuhammad Omair Javaid   if (!m_sve_header_is_valid && m_sve_state != SVEState::Disabled) {
823567ba6c4SMuhammad Omair Javaid     Status error = ReadSVEHeader();
824d6d3d21cSMuhammad Omair Javaid     if (error.Success()) {
825d6d3d21cSMuhammad Omair Javaid       // If SVE is enabled thread can switch between SVEState::FPSIMD and
826d6d3d21cSMuhammad Omair Javaid       // SVEState::Full on every stop.
82705915400SCaroline Tice       if ((m_sve_header.flags & sve::ptrace_regs_mask) ==
82805915400SCaroline Tice           sve::ptrace_regs_fpsimd)
829567ba6c4SMuhammad Omair Javaid         m_sve_state = SVEState::FPSIMD;
83005915400SCaroline Tice       else if ((m_sve_header.flags & sve::ptrace_regs_mask) ==
83105915400SCaroline Tice                sve::ptrace_regs_sve)
832567ba6c4SMuhammad Omair Javaid         m_sve_state = SVEState::Full;
833567ba6c4SMuhammad Omair Javaid 
834d6d3d21cSMuhammad Omair Javaid       // On every stop we configure SVE vector length by calling
835d6d3d21cSMuhammad Omair Javaid       // ConfigureVectorLength regardless of current SVEState of this thread.
836567ba6c4SMuhammad Omair Javaid       uint32_t vq = RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64SVE;
837567ba6c4SMuhammad Omair Javaid       if (sve_vl_valid(m_sve_header.vl))
83805915400SCaroline Tice         vq = sve::vq_from_vl(m_sve_header.vl);
839d6d3d21cSMuhammad Omair Javaid 
840d6d3d21cSMuhammad Omair Javaid       GetRegisterInfo().ConfigureVectorLength(vq);
84105915400SCaroline Tice       m_sve_ptrace_payload.resize(sve::PTraceSize(vq, sve::ptrace_regs_sve));
842567ba6c4SMuhammad Omair Javaid     }
843567ba6c4SMuhammad Omair Javaid   }
844b6f9d7b8SMuhammad Omair Javaid }
845b6f9d7b8SMuhammad Omair Javaid 
846b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset(
847b9c1b51eSKate Stone     const RegisterInfo *reg_info) const {
8487fa7b81bSMuhammad Omair Javaid   return reg_info->byte_offset - GetGPRSize();
849c40e7b17STamas Berghammer }
850c40e7b17STamas Berghammer 
851567ba6c4SMuhammad Omair Javaid uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset(
852567ba6c4SMuhammad Omair Javaid     const RegisterInfo *reg_info) const {
853567ba6c4SMuhammad Omair Javaid   // Start of Z0 data is after GPRs plus 8 bytes of vg register
854567ba6c4SMuhammad Omair Javaid   uint32_t sve_reg_offset = LLDB_INVALID_INDEX32;
855567ba6c4SMuhammad Omair Javaid   if (m_sve_state == SVEState::FPSIMD) {
856567ba6c4SMuhammad Omair Javaid     const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
85705915400SCaroline Tice     sve_reg_offset = sve::ptrace_fpsimd_offset +
85805915400SCaroline Tice                      (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16;
859567ba6c4SMuhammad Omair Javaid   } else if (m_sve_state == SVEState::Full) {
860661e4040SMuhammad Omair Javaid     uint32_t sve_z0_offset = GetGPRSize() + 16;
861567ba6c4SMuhammad Omair Javaid     sve_reg_offset =
86205915400SCaroline Tice         sve::SigRegsOffset() + reg_info->byte_offset - sve_z0_offset;
863567ba6c4SMuhammad Omair Javaid   }
864567ba6c4SMuhammad Omair Javaid   return sve_reg_offset;
865567ba6c4SMuhammad Omair Javaid }
866567ba6c4SMuhammad Omair Javaid 
867567ba6c4SMuhammad Omair Javaid void *NativeRegisterContextLinux_arm64::GetSVEBuffer() {
868567ba6c4SMuhammad Omair Javaid   if (m_sve_state == SVEState::FPSIMD)
86905915400SCaroline Tice     return m_sve_ptrace_payload.data() + sve::ptrace_fpsimd_offset;
870567ba6c4SMuhammad Omair Javaid 
871567ba6c4SMuhammad Omair Javaid   return m_sve_ptrace_payload.data();
872567ba6c4SMuhammad Omair Javaid }
873567ba6c4SMuhammad Omair Javaid 
8744e8aeb97SMuhammad Omair Javaid std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters(
8754e8aeb97SMuhammad Omair Javaid     ExpeditedRegs expType) const {
8764e8aeb97SMuhammad Omair Javaid   std::vector<uint32_t> expedited_reg_nums =
8774e8aeb97SMuhammad Omair Javaid       NativeRegisterContext::GetExpeditedRegisters(expType);
8784e8aeb97SMuhammad Omair Javaid   if (m_sve_state == SVEState::FPSIMD || m_sve_state == SVEState::Full)
8794e8aeb97SMuhammad Omair Javaid     expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG());
8804e8aeb97SMuhammad Omair Javaid 
8814e8aeb97SMuhammad Omair Javaid   return expedited_reg_nums;
8824e8aeb97SMuhammad Omair Javaid }
8834e8aeb97SMuhammad Omair Javaid 
884da2e614fSDavid Spickett llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails>
885da2e614fSDavid Spickett NativeRegisterContextLinux_arm64::GetMemoryTaggingDetails(int32_t type) {
886da2e614fSDavid Spickett   if (type == MemoryTagManagerAArch64MTE::eMTE_allocation) {
887da2e614fSDavid Spickett     return MemoryTaggingDetails{std::make_unique<MemoryTagManagerAArch64MTE>(),
888da2e614fSDavid Spickett                                 PTRACE_PEEKMTETAGS, PTRACE_POKEMTETAGS};
889da2e614fSDavid Spickett   }
890da2e614fSDavid Spickett 
891da2e614fSDavid Spickett   return llvm::createStringError(llvm::inconvertibleErrorCode(),
892da2e614fSDavid Spickett                                  "Unknown AArch64 memory tag type %d", type);
893da2e614fSDavid Spickett }
894da2e614fSDavid Spickett 
895*5e6aabd4SMuhammad Omair Javaid lldb::addr_t NativeRegisterContextLinux_arm64::FixWatchpointHitAddress(
896*5e6aabd4SMuhammad Omair Javaid     lldb::addr_t hit_addr) {
897*5e6aabd4SMuhammad Omair Javaid   // Linux configures user-space virtual addresses with top byte ignored.
898*5e6aabd4SMuhammad Omair Javaid   // We set default value of mask such that top byte is masked out.
899*5e6aabd4SMuhammad Omair Javaid   lldb::addr_t mask = ~((1ULL << 56) - 1);
900*5e6aabd4SMuhammad Omair Javaid 
901*5e6aabd4SMuhammad Omair Javaid   // Try to read pointer authentication data_mask register and calculate a
902*5e6aabd4SMuhammad Omair Javaid   // consolidated data address mask after ignoring the top byte.
903*5e6aabd4SMuhammad Omair Javaid   if (ReadPAuthMask().Success())
904*5e6aabd4SMuhammad Omair Javaid     mask |= m_pac_mask.data_mask;
905*5e6aabd4SMuhammad Omair Javaid 
906*5e6aabd4SMuhammad Omair Javaid   return hit_addr & ~mask;
907*5e6aabd4SMuhammad Omair Javaid   ;
908*5e6aabd4SMuhammad Omair Javaid }
909*5e6aabd4SMuhammad Omair Javaid 
910068f8a7eSTamas Berghammer #endif // defined (__arm64__) || defined (__aarch64__)
911