omjavaid created this revision.
omjavaid added reviewers: labath, clayborg, jankratochvil, jasonmolenda.
omjavaid added a project: LLDB.
Herald added subscribers: kristof.beyls, tschuett.
Herald added a reviewer: rengolin.

This is an RFC patch for the on going effort to support SVE registers access on 
AArch64 Linux. This patch lays down the structure and major parts of the 
implementation and seeks community feedback on overall design approach more 
specifically to the generic areas of gdb-remote process, register infos and 
register context classes.

The Scalable Vector Extension (SVE)  is an optional extension introduced by the 
ARMv8.2 architecture and can be implemented by underlying hardware AArch64 
execution state. SVE has introduced  32 Z registers (Z0..Z31), 16 P register 
(P0..P15 <https://reviews.llvm.org/P15>) and an FFR register.  All these 
registers can change their size dynamically during execution. SVE register 
sizes is governed by currently set vector length in multiples of 16 bytes. Z 
register has a 16 byte default size and its size can increase in multiples of 
16 bytes upto 128 bytes. While size of P and FFR registers is equal to size of 
Z register divided by 8. Linux tracks SVE register per thread and each thread 
can have its own setting of vector length upon which its size is decided.

First part of this implementation deals with adding capability for dynamic 
size/offset update in register info description hosted by gdb-remote process 
and also on native Linux side. Also we have to make these register description 
per_thread so that they can have their own size and offset.

Also there has to be a way to exchange update size information between remote 
target and host. This is where VG (Vector Granule) pseudo register comes in, VG 
is the size of a Z register in 8 bytes (64bits) multiples. This information is 
read from PTRACE and sent back via expedited registers list. We have altered 
expedited register list to send a custom register set other than the register 
set at index 0 which is choosen by default. Once read by the host VG will help 
updated register sizes and offsets in DynamicRegisterInfos hosted by each 
gdb-remote thread.

Similarly on native size there is ConfigureRegisterContext function which will 
update register infos accordingly. Rest of code is implementation of register 
infos for SVE, some modifications to register infos to support SVE and register 
context linux ptrace access routines.

I am still working on some areas like offset sync and register data resizing. 
Looking forward to hear your feedback.


https://reviews.llvm.org/D72251

Files:
  lldb/include/lldb/Host/common/NativeRegisterContext.h
  lldb/include/lldb/Utility/RegisterValue.h
  lldb/source/Plugins/Process/Linux/LinuxPTraceDefines_arm64sve.h
  lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h
  lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
  lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
  lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
  lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
  lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
  lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h
  lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
  lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
  lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
  lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h
  lldb/source/Plugins/Process/Utility/RegisterInfos_arm64_sve.h
  lldb/source/Plugins/Process/Utility/lldb-arm64-register-enums.h
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
  lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
  lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
  lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
  lldb/source/Utility/ARM64_DWARF_Registers.h
  lldb/source/Utility/ARM64_ehframe_Registers.h
  lldb/source/Utility/RegisterValue.cpp

Index: lldb/source/Utility/RegisterValue.cpp
===================================================================
--- lldb/source/Utility/RegisterValue.cpp
+++ lldb/source/Utility/RegisterValue.cpp
@@ -810,7 +810,7 @@
       if (buffer.length != rhs.buffer.length)
         return false;
       else {
-        uint8_t length = buffer.length;
+        uint32_t length = buffer.length;
         if (length > kMaxRegisterByteSize)
           length = kMaxRegisterByteSize;
         return memcmp(buffer.bytes, rhs.buffer.bytes, length) == 0;
Index: lldb/source/Utility/ARM64_ehframe_Registers.h
===================================================================
--- lldb/source/Utility/ARM64_ehframe_Registers.h
+++ lldb/source/Utility/ARM64_ehframe_Registers.h
@@ -49,10 +49,34 @@
   lr, // aka x30
   sp, // aka x31 aka wzr
   pc, // value is 32
-  cpsr
-};
+  cpsr,
+  // 34-45 reserved
 
-enum {
+  // 64-bit SVE Vector granule pseudo register
+  vg = 46,
+
+  // VG ́8-bit SVE first fault register
+  ffr = 47,
+
+  // VG x ́8-bit SVE predicate registers
+  p0 = 48,
+  p1,
+  p2,
+  p3,
+  p4,
+  p5,
+  p6,
+  p7,
+  p8,
+  p9,
+  p10,
+  p11,
+  p12,
+  p13,
+  p14,
+  p15,
+
+  // V0-V31 (128 bit vector registers)
   v0 = 64,
   v1,
   v2,
@@ -84,7 +108,41 @@
   v28,
   v29,
   v30,
-  v31 // 95
+  v31,
+
+  // VG ́64-bit SVE vector registers
+  z0 = 96,
+  z1,
+  z2,
+  z3,
+  z4,
+  z5,
+  z6,
+  z7,
+  z8,
+  z9,
+  z10,
+  z11,
+  z12,
+  z13,
+  z14,
+  z15,
+  z16,
+  z17,
+  z18,
+  z19,
+  z20,
+  z21,
+  z22,
+  z23,
+  z24,
+  z25,
+  z26,
+  z27,
+  z28,
+  z29,
+  z30,
+  z31
 };
 }
 
Index: lldb/source/Utility/ARM64_DWARF_Registers.h
===================================================================
--- lldb/source/Utility/ARM64_DWARF_Registers.h
+++ lldb/source/Utility/ARM64_DWARF_Registers.h
@@ -51,7 +51,31 @@
   sp = x31,
   pc = 32,
   cpsr = 33,
-  // 34-63 reserved
+  // 34-45 reserved
+
+  // 64-bit SVE Vector granule pseudo register
+  vg = 46,
+
+  // VG ́8-bit SVE first fault register
+  ffr = 47,
+
+  // VG x ́8-bit SVE predicate registers
+  p0 = 48,
+  p1,
+  p2,
+  p3,
+  p4,
+  p5,
+  p6,
+  p7,
+  p8,
+  p9,
+  p10,
+  p11,
+  p12,
+  p13,
+  p14,
+  p15,
 
   // V0-V31 (128 bit vector registers)
   v0 = 64,
@@ -85,9 +109,41 @@
   v28,
   v29,
   v30,
-  v31
+  v31,
 
-  // 96-127 reserved
+  // VG ́64-bit SVE vector registers
+  z0 = 96,
+  z1,
+  z2,
+  z3,
+  z4,
+  z5,
+  z6,
+  z7,
+  z8,
+  z9,
+  z10,
+  z11,
+  z12,
+  z13,
+  z14,
+  z15,
+  z16,
+  z17,
+  z18,
+  z19,
+  z20,
+  z21,
+  z22,
+  z23,
+  z24,
+  z25,
+  z26,
+  z27,
+  z28,
+  z29,
+  z30,
+  z31
 };
 
 } // namespace arm64_dwarf
Index: lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -307,7 +307,7 @@
           !pSupported || gdb_process->m_use_g_packet_for_reading;
       bool write_all_registers_at_once = !pSupported;
       reg_ctx_sp = std::make_shared<GDBRemoteRegisterContext>(
-          *this, concrete_frame_idx, gdb_process->m_register_info,
+          *this, concrete_frame_idx, gdb_process->m_register_info_sp,
           read_all_registers_at_once, write_all_registers_at_once);
     }
   } else {
Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -251,7 +251,7 @@
                                                              // the last stop
                                                              // packet variable
   std::recursive_mutex m_last_stop_packet_mutex;
-  GDBRemoteDynamicRegisterInfo m_register_info;
+  GDBRemoteDynamicRegisterInfoSP m_register_info_sp;
   Broadcaster m_async_broadcaster;
   lldb::ListenerSP m_async_listener_sp;
   HostThread m_async_thread;
Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -258,7 +258,7 @@
                                    ListenerSP listener_sp)
     : Process(target_sp, listener_sp),
       m_debugserver_pid(LLDB_INVALID_PROCESS_ID), m_last_stop_packet_mutex(),
-      m_register_info(),
+      m_register_info_sp(nullptr),
       m_async_broadcaster(nullptr, "lldb.process.gdb-remote.async-broadcaster"),
       m_async_listener_sp(
           Listener::MakeListener("lldb.process.gdb-remote.async-listener")),
@@ -376,8 +376,8 @@
           m_breakpoint_pc_offset = breakpoint_pc_int_value->GetValue();
       }
 
-      if (m_register_info.SetRegisterInfo(*target_definition_sp,
-                                          GetTarget().GetArchitecture()) > 0) {
+      if (m_register_info_sp->SetRegisterInfo(
+              *target_definition_sp, GetTarget().GetArchitecture()) > 0) {
         return true;
       }
     }
@@ -404,10 +404,13 @@
 }
 
 void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
-  if (!force && m_register_info.GetNumRegisters() > 0)
+  if (!m_register_info_sp)
+    m_register_info_sp = std::make_shared<GDBRemoteDynamicRegisterInfo>();
+
+  if (!force && m_register_info_sp->GetNumRegisters() > 0)
     return;
 
-  m_register_info.Clear();
+  m_register_info_sp->Clear();
 
   // Check if qHostInfo specified a specific packet timeout for this
   // connection. If so then lets update our setting so the user knows what the
@@ -589,7 +592,7 @@
         if (ABISP abi_sp = ABI::FindPlugin(shared_from_this(), arch_to_use))
           abi_sp->AugmentRegisterInfo(reg_info);
 
-        m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);
+        m_register_info_sp->AddRegister(reg_info, reg_name, alt_name, set_name);
       } else {
         break; // ensure exit before reg_num is incremented
       }
@@ -598,8 +601,8 @@
     }
   }
 
-  if (m_register_info.GetNumRegisters() > 0) {
-    m_register_info.Finalize(GetTarget().GetArchitecture());
+  if (m_register_info_sp->GetNumRegisters() > 0) {
+    m_register_info_sp->Finalize(GetTarget().GetArchitecture());
     return;
   }
 
@@ -608,21 +611,21 @@
   // updated debugserver down on the devices. On the other hand, if the
   // accumulated reg_num is positive, see if we can add composite registers to
   // the existing primordial ones.
-  bool from_scratch = (m_register_info.GetNumRegisters() == 0);
+  bool from_scratch = (m_register_info_sp->GetNumRegisters() == 0);
 
   if (!target_arch.IsValid()) {
     if (arch_to_use.IsValid() &&
         (arch_to_use.GetMachine() == llvm::Triple::arm ||
          arch_to_use.GetMachine() == llvm::Triple::thumb) &&
         arch_to_use.GetTriple().getVendor() == llvm::Triple::Apple)
-      m_register_info.HardcodeARMRegisters(from_scratch);
+      m_register_info_sp->HardcodeARMRegisters(from_scratch);
   } else if (target_arch.GetMachine() == llvm::Triple::arm ||
              target_arch.GetMachine() == llvm::Triple::thumb) {
-    m_register_info.HardcodeARMRegisters(from_scratch);
+    m_register_info_sp->HardcodeARMRegisters(from_scratch);
   }
 
   // At this point, we can finalize our register info.
-  m_register_info.Finalize(GetTarget().GetArchitecture());
+  m_register_info_sp->Finalize(GetTarget().GetArchitecture());
 }
 
 Status ProcessGDBRemote::WillLaunch(lldb_private::Module *module) {
@@ -1772,6 +1775,10 @@
         gdb_thread->PrivateSetRegisterValue(pair.first, buffer_sp->GetData());
       }
 
+      static_cast<GDBRemoteRegisterContext *>(
+          gdb_thread->GetRegisterContext().get())
+          ->UpdateDynamicRegisterInfo();
+
       thread_sp->SetName(thread_name.empty() ? nullptr : thread_name.c_str());
 
       gdb_thread->SetThreadDispatchQAddr(thread_dispatch_qaddr);
@@ -4579,7 +4586,7 @@
       // ABI is also potentially incorrect.
       ABISP abi_to_use_sp = ABI::FindPlugin(shared_from_this(), arch_to_use);
       for (auto &feature_node : feature_nodes) {
-        ParseRegisters(feature_node, target_info, this->m_register_info,
+        ParseRegisters(feature_node, target_info, *this->m_register_info_sp,
                        abi_to_use_sp, cur_reg_num, reg_offset);
       }
 
@@ -4608,9 +4615,9 @@
   uint32_t cur_reg_num = 0;
   uint32_t reg_offset = 0;
   if (GetGDBServerRegisterInfoXMLAndProcess (arch_to_use, "target.xml", cur_reg_num, reg_offset))
-    this->m_register_info.Finalize(arch_to_use);
+    this->m_register_info_sp->Finalize(arch_to_use);
 
-  return m_register_info.GetNumRegisters() > 0;
+  return m_register_info_sp->GetNumRegisters() > 0;
 }
 
 llvm::Expected<LoadedModuleInfoList> ProcessGDBRemote::GetLoadedModuleList() {
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -27,6 +27,10 @@
 
 class ThreadGDBRemote;
 class ProcessGDBRemote;
+class GDBRemoteDynamicRegisterInfo;
+
+typedef std::shared_ptr<GDBRemoteDynamicRegisterInfo>
+    GDBRemoteDynamicRegisterInfoSP;
 
 class GDBRemoteDynamicRegisterInfo : public DynamicRegisterInfo {
 public:
@@ -35,12 +39,16 @@
   ~GDBRemoteDynamicRegisterInfo() override = default;
 
   void HardcodeARMRegisters(bool from_scratch);
+
+  bool UpdateARM64SVERegistersInfos(uint64_t vg);
+
+  void CloneFrom(GDBRemoteDynamicRegisterInfoSP process_reginfo);
 };
 
 class GDBRemoteRegisterContext : public RegisterContext {
 public:
   GDBRemoteRegisterContext(ThreadGDBRemote &thread, uint32_t concrete_frame_idx,
-                           GDBRemoteDynamicRegisterInfo &reg_info,
+                           GDBRemoteDynamicRegisterInfoSP reg_info,
                            bool read_all_at_once, bool write_all_at_once);
 
   ~GDBRemoteRegisterContext() override;
@@ -73,9 +81,13 @@
   uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
                                                uint32_t num) override;
 
+  bool UpdateDynamicRegisterInfo();
+
 protected:
   friend class ThreadGDBRemote;
 
+  void SetThreadRegisterInfo(GDBRemoteDynamicRegisterInfoSP process_reginfo);
+
   bool ReadRegisterBytes(const RegisterInfo *reg_info, DataExtractor &data);
 
   bool WriteRegisterBytes(const RegisterInfo *reg_info, DataExtractor &data,
@@ -110,7 +122,7 @@
       m_reg_valid[reg] = valid;
   }
 
-  GDBRemoteDynamicRegisterInfo &m_reg_info;
+  GDBRemoteDynamicRegisterInfoSP m_reg_info_sp;
   std::vector<bool> m_reg_valid;
   DataExtractor m_reg_data;
   bool m_read_all_at_once;
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -31,19 +31,23 @@
 // GDBRemoteRegisterContext constructor
 GDBRemoteRegisterContext::GDBRemoteRegisterContext(
     ThreadGDBRemote &thread, uint32_t concrete_frame_idx,
-    GDBRemoteDynamicRegisterInfo &reg_info, bool read_all_at_once,
+    GDBRemoteDynamicRegisterInfoSP reg_info, bool read_all_at_once,
     bool write_all_at_once)
-    : RegisterContext(thread, concrete_frame_idx), m_reg_info(reg_info),
-      m_reg_valid(), m_reg_data(), m_read_all_at_once(read_all_at_once),
+    : RegisterContext(thread, concrete_frame_idx), m_reg_valid(), m_reg_data(),
+      m_read_all_at_once(read_all_at_once),
       m_write_all_at_once(write_all_at_once) {
   // Resize our vector of bools to contain one bool for every register. We will
   // use these boolean values to know when a register value is valid in
   // m_reg_data.
-  m_reg_valid.resize(reg_info.GetNumRegisters());
+  m_reg_valid.resize(reg_info->GetNumRegisters());
+
+  // At this point we can clone reg_info for architectures supporting
+  // run-time update to register sizes and offsets..
+  SetThreadRegisterInfo(reg_info);
 
   // Make a heap based buffer that is big enough to store all registers
   DataBufferSP reg_data_sp(
-      new DataBufferHeap(reg_info.GetRegisterDataByteSize(), 0));
+      new DataBufferHeap(reg_info->GetRegisterDataByteSize(), 0));
   m_reg_data.SetData(reg_data_sp);
   m_reg_data.SetByteOrder(thread.GetProcess()->GetByteOrder());
 }
@@ -51,6 +55,16 @@
 // Destructor
 GDBRemoteRegisterContext::~GDBRemoteRegisterContext() {}
 
+void GDBRemoteRegisterContext::SetThreadRegisterInfo(
+    GDBRemoteDynamicRegisterInfoSP process_reginfo) {
+  if (!process_reginfo->IsPerThreadRegInfo())
+    m_reg_info_sp = process_reginfo;
+  else {
+    m_reg_info_sp = std::make_shared<GDBRemoteDynamicRegisterInfo>();
+    m_reg_info_sp->CloneFrom(process_reginfo);
+  }
+}
+
 void GDBRemoteRegisterContext::InvalidateAllRegisters() {
   SetAllRegisterValid(false);
 }
@@ -62,12 +76,12 @@
 }
 
 size_t GDBRemoteRegisterContext::GetRegisterCount() {
-  return m_reg_info.GetNumRegisters();
+  return m_reg_info_sp->GetNumRegisters();
 }
 
 const RegisterInfo *
 GDBRemoteRegisterContext::GetRegisterInfoAtIndex(size_t reg) {
-  RegisterInfo *reg_info = m_reg_info.GetRegisterInfoAtIndex(reg);
+  RegisterInfo *reg_info = m_reg_info_sp->GetRegisterInfoAtIndex(reg);
 
   if (reg_info && reg_info->dynamic_size_dwarf_expr_bytes) {
     const ArchSpec &arch = m_thread.GetProcess()->GetTarget().GetArchitecture();
@@ -78,11 +92,11 @@
 }
 
 size_t GDBRemoteRegisterContext::GetRegisterSetCount() {
-  return m_reg_info.GetNumRegisterSets();
+  return m_reg_info_sp->GetNumRegisterSets();
 }
 
 const RegisterSet *GDBRemoteRegisterContext::GetRegisterSet(size_t reg_set) {
-  return m_reg_info.GetRegisterSet(reg_set);
+  return m_reg_info_sp->GetRegisterSet(reg_set);
 }
 
 bool GDBRemoteRegisterContext::ReadRegister(const RegisterInfo *reg_info,
@@ -209,9 +223,10 @@
           SetAllRegisterValid(true);
           return true;
         } else if (buffer_sp->GetByteSize() > 0) {
-          const int regcount = m_reg_info.GetNumRegisters();
+          const int regcount = m_reg_info_sp->GetNumRegisters();
           for (int i = 0; i < regcount; i++) {
-            struct RegisterInfo *reginfo = m_reg_info.GetRegisterInfoAtIndex(i);
+            struct RegisterInfo *reginfo =
+                m_reg_info_sp->GetRegisterInfoAtIndex(i);
             if (reginfo->byte_offset + reginfo->byte_size 
                    <= buffer_sp->GetByteSize()) {
               m_reg_valid[i] = true;
@@ -506,7 +521,7 @@
       // m_reg_data buffer
     }
     data_sp = std::make_shared<DataBufferHeap>(
-        m_reg_data.GetDataStart(), m_reg_info.GetRegisterDataByteSize());
+        m_reg_data.GetDataStart(), m_reg_info_sp->GetRegisterDataByteSize());
     return true;
   } else {
 
@@ -708,7 +723,53 @@
 
 uint32_t GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber(
     lldb::RegisterKind kind, uint32_t num) {
-  return m_reg_info.ConvertRegisterKindToRegisterNumber(kind, num);
+  return m_reg_info_sp->ConvertRegisterKindToRegisterNumber(kind, num);
+}
+
+bool GDBRemoteRegisterContext::UpdateDynamicRegisterInfo(void) {
+  if (!m_reg_info_sp || !m_reg_info_sp->IsPerThreadRegInfo())
+    return false;
+
+  const ArchSpec &arch = m_thread.GetProcess()->GetTarget().GetArchitecture();
+  if (arch.IsValid() && (arch.GetMachine() == llvm::Triple::aarch64)) {
+    uint8_t arm64_sve_vg_dwarf_regnum = 46;
+    uint32_t reg = ConvertRegisterKindToRegisterNumber(
+        eRegisterKindDWARF, arm64_sve_vg_dwarf_regnum);
+    uint64_t fail_value = LLDB_INVALID_ADDRESS;
+    uint64_t vg = ReadRegisterAsUnsigned(reg, fail_value);
+
+    if (vg != fail_value && vg <= 32) {
+      return m_reg_info_sp->UpdateARM64SVERegistersInfos(vg);
+    }
+  }
+  return false;
+}
+
+bool GDBRemoteDynamicRegisterInfo::UpdateARM64SVERegistersInfos(uint64_t vg) {
+  for (auto &reg : m_regs) {
+    if (reg.name[0] == 'z')
+      reg.byte_size = vg * 8;
+    else if (reg.name[0] == 'p')
+      reg.byte_size = vg;
+    else if (strcmp(reg.name, "ffr") == 0)
+      reg.byte_size = vg;
+  }
+  return true;
+}
+
+void GDBRemoteDynamicRegisterInfo::CloneFrom(
+    GDBRemoteDynamicRegisterInfoSP proc_reginfo) {
+  m_regs = proc_reginfo->m_regs;
+  m_sets = proc_reginfo->m_sets;
+  m_set_reg_nums = proc_reginfo->m_set_reg_nums;
+  m_set_names = proc_reginfo->m_set_names;
+  m_value_regs_map = proc_reginfo->m_value_regs_map;
+  m_invalidate_regs_map = proc_reginfo->m_invalidate_regs_map;
+  m_dynamic_reg_size_map = proc_reginfo->m_dynamic_reg_size_map;
+  m_reg_data_byte_size = proc_reginfo->m_reg_data_byte_size;
+
+  m_finalized = proc_reginfo->m_finalized;
+  m_per_thread_reginfo = proc_reginfo->m_per_thread_reginfo;
 }
 
 void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) {
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -713,11 +713,17 @@
 
   // Grab the register context.
   NativeRegisterContext& reg_ctx = thread->GetRegisterContext();
-  // Expedite all registers in the first register set (i.e. should be GPRs)
-  // that are not contained in other registers.
-  const RegisterSet *reg_set_p;
-  if (reg_ctx.GetRegisterSetCount() > 0 &&
-      ((reg_set_p = reg_ctx.GetRegisterSet(0)) != nullptr)) {
+  const RegisterSet *reg_set_p = reg_ctx.GetExpeditedRegisterSet();
+
+  if (reg_set_p == nullptr) {
+    // Architecture does not specify an expedited register set.
+    // Expedite all registers in the first register set (i.e. should be GPRs)
+    // that are not contained in other registers.
+    if (reg_ctx.GetRegisterSetCount() > 0)
+      reg_set_p = reg_ctx.GetRegisterSet(0);
+  }
+
+  if (reg_set_p != nullptr) {
     LLDB_LOGF(log,
               "GDBRemoteCommunicationServerLLGS::%s expediting registers "
               "from set '%s' (registers set count: %zu)",
Index: lldb/source/Plugins/Process/Utility/lldb-arm64-register-enums.h
===================================================================
--- lldb/source/Plugins/Process/Utility/lldb-arm64-register-enums.h
+++ lldb/source/Plugins/Process/Utility/lldb-arm64-register-enums.h
@@ -255,9 +255,68 @@
   dbg_wcr14_arm64,
   dbg_wcr15_arm64,
 
+  k_first_sve_arm64,
+  sve_vg_arm64 = k_first_sve_arm64,
+  sve_z0_arm64,
+  sve_z1_arm64,
+  sve_z2_arm64,
+  sve_z3_arm64,
+  sve_z4_arm64,
+  sve_z5_arm64,
+  sve_z6_arm64,
+  sve_z7_arm64,
+  sve_z8_arm64,
+  sve_z9_arm64,
+  sve_z10_arm64,
+  sve_z11_arm64,
+  sve_z12_arm64,
+  sve_z13_arm64,
+  sve_z14_arm64,
+  sve_z15_arm64,
+  sve_z16_arm64,
+  sve_z17_arm64,
+  sve_z18_arm64,
+  sve_z19_arm64,
+  sve_z20_arm64,
+  sve_z21_arm64,
+  sve_z22_arm64,
+  sve_z23_arm64,
+  sve_z24_arm64,
+  sve_z25_arm64,
+  sve_z26_arm64,
+  sve_z27_arm64,
+  sve_z28_arm64,
+  sve_z29_arm64,
+  sve_z30_arm64,
+  sve_z31_arm64,
+
+  sve_p0_arm64,
+  sve_p1_arm64,
+  sve_p2_arm64,
+  sve_p3_arm64,
+  sve_p4_arm64,
+  sve_p5_arm64,
+  sve_p6_arm64,
+  sve_p7_arm64,
+  sve_p8_arm64,
+  sve_p9_arm64,
+  sve_p10_arm64,
+  sve_p11_arm64,
+  sve_p12_arm64,
+  sve_p13_arm64,
+  sve_p14_arm64,
+  sve_p15_arm64,
+
+  sve_ffr_arm64,
+  k_last_sve_arm64 = sve_ffr_arm64,
+
   k_num_registers_arm64,
+  k_num_wgpr_registers_arm64 = gpr_w28_arm64 - gpr_w0_arm64 + 1,
   k_num_gpr_registers_arm64 = k_last_gpr_arm64 - k_first_gpr_arm64 + 1,
-  k_num_fpr_registers_arm64 = k_last_fpr_arm64 - k_first_fpr_arm64 + 1
+  k_num_fpr_registers_arm64 = k_last_fpr_arm64 - k_first_fpr_arm64 + 1,
+  k_num_sve_registers_arm64 = k_last_sve_arm64 - k_first_sve_arm64 + 1,
+  k_num_expedited_registers_arm64_sve =
+      k_num_gpr_registers_arm64 - k_num_wgpr_registers_arm64 + 1
 };
 }
 
Index: lldb/source/Plugins/Process/Utility/RegisterInfos_arm64_sve.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/Utility/RegisterInfos_arm64_sve.h
@@ -0,0 +1,519 @@
+//===-- RegisterInfos_arm64_sve.h -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifdef DECLARE_REGISTER_INFOS_ARM64_SVE_STRUCT
+
+#ifndef SVE_ZREG_OFFSET
+#error SVE_ZREG_OFFSET must be defined before including this header file
+#endif
+
+#ifndef SVE_PREG_OFFSET
+#error SVE_PREG_OFFSET must be defined before including this header file
+#endif
+
+#ifndef SVE_OFFSET_VG
+#error SVE_OFFSET_VG must be defined before including this header file
+#endif
+
+static uint32_t g_contained_z0[] = {sve_z0, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z1[] = {sve_z1, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z2[] = {sve_z2, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z3[] = {sve_z3, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z4[] = {sve_z4, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z5[] = {sve_z5, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z6[] = {sve_z6, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z7[] = {sve_z7, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z8[] = {sve_z8, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z9[] = {sve_z9, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z10[] = {sve_z10, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z11[] = {sve_z11, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z12[] = {sve_z12, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z13[] = {sve_z13, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z14[] = {sve_z14, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z15[] = {sve_z15, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z16[] = {sve_z16, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z17[] = {sve_z17, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z18[] = {sve_z18, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z19[] = {sve_z19, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z20[] = {sve_z20, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z21[] = {sve_z21, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z22[] = {sve_z22, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z23[] = {sve_z23, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z24[] = {sve_z24, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z25[] = {sve_z25, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z26[] = {sve_z26, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z27[] = {sve_z27, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z28[] = {sve_z28, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z29[] = {sve_z29, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z30[] = {sve_z30, LLDB_INVALID_REGNUM};
+static uint32_t g_contained_z31[] = {sve_z31, LLDB_INVALID_REGNUM};
+
+static uint32_t g_sve_v0_invalidates[] = {sve_z0, fpu_d0, fpu_s0,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v1_invalidates[] = {sve_z1, fpu_d1, fpu_s1,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v2_invalidates[] = {sve_z2, fpu_d2, fpu_s2,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v3_invalidates[] = {sve_z3, fpu_d3, fpu_s3,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v4_invalidates[] = {sve_z4, fpu_d4, fpu_s4,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v5_invalidates[] = {sve_z5, fpu_d5, fpu_s5,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v6_invalidates[] = {sve_z6, fpu_d6, fpu_s6,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v7_invalidates[] = {sve_z7, fpu_d7, fpu_s7,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v8_invalidates[] = {sve_z8, fpu_d8, fpu_s8,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v9_invalidates[] = {sve_z9, fpu_d9, fpu_s9,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v10_invalidates[] = {sve_z10, fpu_d10, fpu_s10,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v11_invalidates[] = {sve_z11, fpu_d11, fpu_s11,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v12_invalidates[] = {sve_z12, fpu_d12, fpu_s12,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v13_invalidates[] = {sve_z13, fpu_d13, fpu_s13,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v14_invalidates[] = {sve_z14, fpu_d14, fpu_s14,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v15_invalidates[] = {sve_z15, fpu_d15, fpu_s15,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v16_invalidates[] = {sve_z16, fpu_d16, fpu_s16,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v17_invalidates[] = {sve_z17, fpu_d17, fpu_s17,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v18_invalidates[] = {sve_z18, fpu_d18, fpu_s18,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v19_invalidates[] = {sve_z19, fpu_d19, fpu_s19,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v20_invalidates[] = {sve_z20, fpu_d20, fpu_s20,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v21_invalidates[] = {sve_z21, fpu_d21, fpu_s21,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v22_invalidates[] = {sve_z22, fpu_d22, fpu_s22,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v23_invalidates[] = {sve_z23, fpu_d23, fpu_s23,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v24_invalidates[] = {sve_z24, fpu_d24, fpu_s24,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v25_invalidates[] = {sve_z25, fpu_d25, fpu_s25,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v26_invalidates[] = {sve_z26, fpu_d26, fpu_s26,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v27_invalidates[] = {sve_z27, fpu_d27, fpu_s27,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v28_invalidates[] = {sve_z28, fpu_d28, fpu_s28,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v29_invalidates[] = {sve_z29, fpu_d29, fpu_s29,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v30_invalidates[] = {sve_z30, fpu_d30, fpu_s30,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_v31_invalidates[] = {sve_z31, fpu_d31, fpu_s31,
+                                           LLDB_INVALID_REGNUM};
+
+static uint32_t g_sve_z0_invalidates[] = {fpu_v0, fpu_d0, fpu_s0,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z1_invalidates[] = {fpu_v1, fpu_d1, fpu_s1,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z2_invalidates[] = {fpu_v2, fpu_d2, fpu_s2,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z3_invalidates[] = {fpu_v3, fpu_d3, fpu_s3,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z4_invalidates[] = {fpu_v4, fpu_d4, fpu_s4,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z5_invalidates[] = {fpu_v5, fpu_d5, fpu_s5,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z6_invalidates[] = {fpu_v6, fpu_d6, fpu_s6,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z7_invalidates[] = {fpu_v7, fpu_d7, fpu_s7,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z8_invalidates[] = {fpu_v8, fpu_d8, fpu_s8,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z9_invalidates[] = {fpu_v9, fpu_d9, fpu_s9,
+                                          LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z10_invalidates[] = {fpu_v10, fpu_d10, fpu_s10,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z11_invalidates[] = {fpu_v11, fpu_d11, fpu_s11,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z12_invalidates[] = {fpu_v12, fpu_d12, fpu_s12,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z13_invalidates[] = {fpu_v13, fpu_d13, fpu_s13,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z14_invalidates[] = {fpu_v14, fpu_d14, fpu_s14,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z15_invalidates[] = {fpu_v15, fpu_d15, fpu_s15,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z16_invalidates[] = {fpu_v16, fpu_d16, fpu_s16,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z17_invalidates[] = {fpu_v17, fpu_d17, fpu_s17,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z18_invalidates[] = {fpu_v18, fpu_d18, fpu_s18,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z19_invalidates[] = {fpu_v19, fpu_d19, fpu_s19,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z20_invalidates[] = {fpu_v20, fpu_d20, fpu_s20,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z21_invalidates[] = {fpu_v21, fpu_d21, fpu_s21,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z22_invalidates[] = {fpu_v22, fpu_d22, fpu_s22,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z23_invalidates[] = {fpu_v23, fpu_d23, fpu_s23,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z24_invalidates[] = {fpu_v24, fpu_d24, fpu_s24,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z25_invalidates[] = {fpu_v25, fpu_d25, fpu_s25,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z26_invalidates[] = {fpu_v26, fpu_d26, fpu_s26,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z27_invalidates[] = {fpu_v27, fpu_d27, fpu_s27,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z28_invalidates[] = {fpu_v28, fpu_d28, fpu_s28,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z29_invalidates[] = {fpu_v29, fpu_d29, fpu_s29,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z30_invalidates[] = {fpu_v30, fpu_d30, fpu_s30,
+                                           LLDB_INVALID_REGNUM};
+static uint32_t g_sve_z31_invalidates[] = {fpu_v31, fpu_d31, fpu_s31,
+                                           LLDB_INVALID_REGNUM};
+
+#define VG_OFFSET_NAME(reg) SVE_OFFSET_VG
+
+#define SVE_REG_KIND(reg) MISC_KIND_GENERIC(reg, sve, LLDB_INVALID_REGNUM)
+#define MISC_VG_KIND(lldb_kind) MISC_KIND_GENERIC(vg, sve, LLDB_INVALID_REGNUM)
+
+// Defines sve pseudo vector (V) register with 16-byte size
+#define DEFINE_VREG_SVE(vreg, zreg)                                            \
+  {                                                                            \
+    #vreg, nullptr, 16, SVE_ZREG_OFFSET(sve_##zreg - sve_z0),                  \
+        lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, VREG_KIND(vreg),    \
+        g_contained_##zreg, g_sve_##vreg##_invalidates, nullptr, 0             \
+  }
+
+// Defines a Z vector register with 16-byte default size
+#define DEFINE_ZREG(reg)                                                       \
+  {                                                                            \
+    #reg, nullptr, SVE_ZREG_SIZE, SVE_ZREG_OFFSET(sve_##reg - sve_z0),         \
+        lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, SVE_REG_KIND(reg),  \
+        nullptr, g_sve_##reg##_invalidates, nullptr, 0                         \
+  }
+
+// Defines a P vector register with 2-byte default size
+#define DEFINE_PREG(reg)                                                       \
+  {                                                                            \
+    #reg, nullptr, SVE_PREG_SIZE, SVE_PREG_OFFSET(sve_##reg - sve_p0),         \
+        lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, SVE_REG_KIND(reg),  \
+        nullptr, nullptr, nullptr, 0                                           \
+  }
+
+static lldb_private::RegisterInfo g_register_infos_arm64_sve_le[] = {
+    // DEFINE_GPR64(name, GENERIC KIND)
+    DEFINE_GPR64(x0, nullptr, LLDB_REGNUM_GENERIC_ARG1, g_x0_invalidates),
+    DEFINE_GPR64(x1, nullptr, LLDB_REGNUM_GENERIC_ARG2, g_x1_invalidates),
+    DEFINE_GPR64(x2, nullptr, LLDB_REGNUM_GENERIC_ARG3, g_x2_invalidates),
+    DEFINE_GPR64(x3, nullptr, LLDB_REGNUM_GENERIC_ARG4, g_x3_invalidates),
+    DEFINE_GPR64(x4, nullptr, LLDB_REGNUM_GENERIC_ARG5, g_x4_invalidates),
+    DEFINE_GPR64(x5, nullptr, LLDB_REGNUM_GENERIC_ARG6, g_x5_invalidates),
+    DEFINE_GPR64(x6, nullptr, LLDB_REGNUM_GENERIC_ARG7, g_x6_invalidates),
+    DEFINE_GPR64(x7, nullptr, LLDB_REGNUM_GENERIC_ARG8, g_x7_invalidates),
+    DEFINE_GPR64(x8, nullptr, LLDB_INVALID_REGNUM, g_x8_invalidates),
+    DEFINE_GPR64(x9, nullptr, LLDB_INVALID_REGNUM, g_x9_invalidates),
+    DEFINE_GPR64(x10, nullptr, LLDB_INVALID_REGNUM, g_x10_invalidates),
+    DEFINE_GPR64(x11, nullptr, LLDB_INVALID_REGNUM, g_x11_invalidates),
+    DEFINE_GPR64(x12, nullptr, LLDB_INVALID_REGNUM, g_x12_invalidates),
+    DEFINE_GPR64(x13, nullptr, LLDB_INVALID_REGNUM, g_x13_invalidates),
+    DEFINE_GPR64(x14, nullptr, LLDB_INVALID_REGNUM, g_x14_invalidates),
+    DEFINE_GPR64(x15, nullptr, LLDB_INVALID_REGNUM, g_x15_invalidates),
+    DEFINE_GPR64(x16, nullptr, LLDB_INVALID_REGNUM, g_x16_invalidates),
+    DEFINE_GPR64(x17, nullptr, LLDB_INVALID_REGNUM, g_x17_invalidates),
+    DEFINE_GPR64(x18, nullptr, LLDB_INVALID_REGNUM, g_x18_invalidates),
+    DEFINE_GPR64(x19, nullptr, LLDB_INVALID_REGNUM, g_x19_invalidates),
+    DEFINE_GPR64(x20, nullptr, LLDB_INVALID_REGNUM, g_x20_invalidates),
+    DEFINE_GPR64(x21, nullptr, LLDB_INVALID_REGNUM, g_x21_invalidates),
+    DEFINE_GPR64(x22, nullptr, LLDB_INVALID_REGNUM, g_x22_invalidates),
+    DEFINE_GPR64(x23, nullptr, LLDB_INVALID_REGNUM, g_x23_invalidates),
+    DEFINE_GPR64(x24, nullptr, LLDB_INVALID_REGNUM, g_x24_invalidates),
+    DEFINE_GPR64(x25, nullptr, LLDB_INVALID_REGNUM, g_x25_invalidates),
+    DEFINE_GPR64(x26, nullptr, LLDB_INVALID_REGNUM, g_x26_invalidates),
+    DEFINE_GPR64(x27, nullptr, LLDB_INVALID_REGNUM, g_x27_invalidates),
+    DEFINE_GPR64(x28, nullptr, LLDB_INVALID_REGNUM, g_x28_invalidates),
+    // DEFINE_GPR64(name, GENERIC KIND)
+    DEFINE_GPR64(fp, STRINGIZE(x29), LLDB_REGNUM_GENERIC_FP, nullptr),
+    DEFINE_GPR64(lr, STRINGIZE(x30), LLDB_REGNUM_GENERIC_RA, nullptr),
+    DEFINE_GPR64(sp, STRINGIZE(x31), LLDB_REGNUM_GENERIC_SP, nullptr),
+    DEFINE_GPR64(pc, nullptr, LLDB_REGNUM_GENERIC_PC, nullptr),
+
+    // DEFINE_MISC_REGS(name, size, TYPE, lldb kind)
+    DEFINE_MISC_REGS(cpsr, 4, CPSR, gpr_cpsr),
+
+    // DEFINE_GPR32(name, parent name)
+    DEFINE_GPR32(w0, x0),
+    DEFINE_GPR32(w1, x1),
+    DEFINE_GPR32(w2, x2),
+    DEFINE_GPR32(w3, x3),
+    DEFINE_GPR32(w4, x4),
+    DEFINE_GPR32(w5, x5),
+    DEFINE_GPR32(w6, x6),
+    DEFINE_GPR32(w7, x7),
+    DEFINE_GPR32(w8, x8),
+    DEFINE_GPR32(w9, x9),
+    DEFINE_GPR32(w10, x10),
+    DEFINE_GPR32(w11, x11),
+    DEFINE_GPR32(w12, x12),
+    DEFINE_GPR32(w13, x13),
+    DEFINE_GPR32(w14, x14),
+    DEFINE_GPR32(w15, x15),
+    DEFINE_GPR32(w16, x16),
+    DEFINE_GPR32(w17, x17),
+    DEFINE_GPR32(w18, x18),
+    DEFINE_GPR32(w19, x19),
+    DEFINE_GPR32(w20, x20),
+    DEFINE_GPR32(w21, x21),
+    DEFINE_GPR32(w22, x22),
+    DEFINE_GPR32(w23, x23),
+    DEFINE_GPR32(w24, x24),
+    DEFINE_GPR32(w25, x25),
+    DEFINE_GPR32(w26, x26),
+    DEFINE_GPR32(w27, x27),
+    DEFINE_GPR32(w28, x28),
+
+    // DEFINE_VREG_SVE(v register, z register)
+    DEFINE_VREG_SVE(v0, z0),
+    DEFINE_VREG_SVE(v1, z1),
+    DEFINE_VREG_SVE(v2, z2),
+    DEFINE_VREG_SVE(v3, z3),
+    DEFINE_VREG_SVE(v4, z4),
+    DEFINE_VREG_SVE(v5, z5),
+    DEFINE_VREG_SVE(v6, z6),
+    DEFINE_VREG_SVE(v7, z7),
+    DEFINE_VREG_SVE(v8, z8),
+    DEFINE_VREG_SVE(v9, z9),
+    DEFINE_VREG_SVE(v10, z10),
+    DEFINE_VREG_SVE(v11, z11),
+    DEFINE_VREG_SVE(v12, z12),
+    DEFINE_VREG_SVE(v13, z13),
+    DEFINE_VREG_SVE(v14, z14),
+    DEFINE_VREG_SVE(v15, z15),
+    DEFINE_VREG_SVE(v16, z16),
+    DEFINE_VREG_SVE(v17, z17),
+    DEFINE_VREG_SVE(v18, z18),
+    DEFINE_VREG_SVE(v19, z19),
+    DEFINE_VREG_SVE(v20, z20),
+    DEFINE_VREG_SVE(v21, z21),
+    DEFINE_VREG_SVE(v22, z22),
+    DEFINE_VREG_SVE(v23, z23),
+    DEFINE_VREG_SVE(v24, z24),
+    DEFINE_VREG_SVE(v25, z25),
+    DEFINE_VREG_SVE(v26, z26),
+    DEFINE_VREG_SVE(v27, z27),
+    DEFINE_VREG_SVE(v28, z28),
+    DEFINE_VREG_SVE(v29, z29),
+    DEFINE_VREG_SVE(v30, z30),
+    DEFINE_VREG_SVE(v31, z31),
+
+    // DEFINE_FPU_PSEUDO(name, size, ENDIAN OFFSET, parent register)
+    DEFINE_FPU_PSEUDO(s0, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v0),
+    DEFINE_FPU_PSEUDO(s1, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v1),
+    DEFINE_FPU_PSEUDO(s2, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v2),
+    DEFINE_FPU_PSEUDO(s3, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v3),
+    DEFINE_FPU_PSEUDO(s4, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v4),
+    DEFINE_FPU_PSEUDO(s5, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v5),
+    DEFINE_FPU_PSEUDO(s6, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v6),
+    DEFINE_FPU_PSEUDO(s7, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v7),
+    DEFINE_FPU_PSEUDO(s8, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v8),
+    DEFINE_FPU_PSEUDO(s9, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v9),
+    DEFINE_FPU_PSEUDO(s10, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v10),
+    DEFINE_FPU_PSEUDO(s11, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v11),
+    DEFINE_FPU_PSEUDO(s12, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v12),
+    DEFINE_FPU_PSEUDO(s13, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v13),
+    DEFINE_FPU_PSEUDO(s14, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v14),
+    DEFINE_FPU_PSEUDO(s15, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v15),
+    DEFINE_FPU_PSEUDO(s16, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v16),
+    DEFINE_FPU_PSEUDO(s17, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v17),
+    DEFINE_FPU_PSEUDO(s18, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v18),
+    DEFINE_FPU_PSEUDO(s19, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v19),
+    DEFINE_FPU_PSEUDO(s20, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v20),
+    DEFINE_FPU_PSEUDO(s21, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v21),
+    DEFINE_FPU_PSEUDO(s22, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v22),
+    DEFINE_FPU_PSEUDO(s23, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v23),
+    DEFINE_FPU_PSEUDO(s24, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v24),
+    DEFINE_FPU_PSEUDO(s25, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v25),
+    DEFINE_FPU_PSEUDO(s26, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v26),
+    DEFINE_FPU_PSEUDO(s27, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v27),
+    DEFINE_FPU_PSEUDO(s28, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v28),
+    DEFINE_FPU_PSEUDO(s29, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v29),
+    DEFINE_FPU_PSEUDO(s30, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v30),
+    DEFINE_FPU_PSEUDO(s31, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v31),
+
+    DEFINE_FPU_PSEUDO(d0, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v0),
+    DEFINE_FPU_PSEUDO(d1, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v1),
+    DEFINE_FPU_PSEUDO(d2, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v2),
+    DEFINE_FPU_PSEUDO(d3, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v3),
+    DEFINE_FPU_PSEUDO(d4, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v4),
+    DEFINE_FPU_PSEUDO(d5, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v5),
+    DEFINE_FPU_PSEUDO(d6, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v6),
+    DEFINE_FPU_PSEUDO(d7, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v7),
+    DEFINE_FPU_PSEUDO(d8, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v8),
+    DEFINE_FPU_PSEUDO(d9, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v9),
+    DEFINE_FPU_PSEUDO(d10, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v10),
+    DEFINE_FPU_PSEUDO(d11, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v11),
+    DEFINE_FPU_PSEUDO(d12, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v12),
+    DEFINE_FPU_PSEUDO(d13, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v13),
+    DEFINE_FPU_PSEUDO(d14, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v14),
+    DEFINE_FPU_PSEUDO(d15, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v15),
+    DEFINE_FPU_PSEUDO(d16, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v16),
+    DEFINE_FPU_PSEUDO(d17, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v17),
+    DEFINE_FPU_PSEUDO(d18, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v18),
+    DEFINE_FPU_PSEUDO(d19, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v19),
+    DEFINE_FPU_PSEUDO(d20, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v20),
+    DEFINE_FPU_PSEUDO(d21, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v21),
+    DEFINE_FPU_PSEUDO(d22, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v22),
+    DEFINE_FPU_PSEUDO(d23, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v23),
+    DEFINE_FPU_PSEUDO(d24, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v24),
+    DEFINE_FPU_PSEUDO(d25, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v25),
+    DEFINE_FPU_PSEUDO(d26, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v26),
+    DEFINE_FPU_PSEUDO(d27, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v27),
+    DEFINE_FPU_PSEUDO(d28, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v28),
+    DEFINE_FPU_PSEUDO(d29, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v29),
+    DEFINE_FPU_PSEUDO(d30, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v30),
+    DEFINE_FPU_PSEUDO(d31, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v31),
+
+    // DEFINE_MISC_REGS(name, size, TYPE, lldb kind)
+    DEFINE_MISC_REGS(fpsr, 4, FPU, fpu_fpsr),
+    DEFINE_MISC_REGS(fpcr, 4, FPU, fpu_fpcr),
+    DEFINE_MISC_REGS(far, 8, EXC, exc_far),
+    DEFINE_MISC_REGS(esr, 4, EXC, exc_esr),
+    DEFINE_MISC_REGS(exception, 4, EXC, exc_exception),
+
+    {DEFINE_DBG(bvr, 0)},
+    {DEFINE_DBG(bvr, 1)},
+    {DEFINE_DBG(bvr, 2)},
+    {DEFINE_DBG(bvr, 3)},
+    {DEFINE_DBG(bvr, 4)},
+    {DEFINE_DBG(bvr, 5)},
+    {DEFINE_DBG(bvr, 6)},
+    {DEFINE_DBG(bvr, 7)},
+    {DEFINE_DBG(bvr, 8)},
+    {DEFINE_DBG(bvr, 9)},
+    {DEFINE_DBG(bvr, 10)},
+    {DEFINE_DBG(bvr, 11)},
+    {DEFINE_DBG(bvr, 12)},
+    {DEFINE_DBG(bvr, 13)},
+    {DEFINE_DBG(bvr, 14)},
+    {DEFINE_DBG(bvr, 15)},
+
+    {DEFINE_DBG(bcr, 0)},
+    {DEFINE_DBG(bcr, 1)},
+    {DEFINE_DBG(bcr, 2)},
+    {DEFINE_DBG(bcr, 3)},
+    {DEFINE_DBG(bcr, 4)},
+    {DEFINE_DBG(bcr, 5)},
+    {DEFINE_DBG(bcr, 6)},
+    {DEFINE_DBG(bcr, 7)},
+    {DEFINE_DBG(bcr, 8)},
+    {DEFINE_DBG(bcr, 9)},
+    {DEFINE_DBG(bcr, 10)},
+    {DEFINE_DBG(bcr, 11)},
+    {DEFINE_DBG(bcr, 12)},
+    {DEFINE_DBG(bcr, 13)},
+    {DEFINE_DBG(bcr, 14)},
+    {DEFINE_DBG(bcr, 15)},
+
+    {DEFINE_DBG(wvr, 0)},
+    {DEFINE_DBG(wvr, 1)},
+    {DEFINE_DBG(wvr, 2)},
+    {DEFINE_DBG(wvr, 3)},
+    {DEFINE_DBG(wvr, 4)},
+    {DEFINE_DBG(wvr, 5)},
+    {DEFINE_DBG(wvr, 6)},
+    {DEFINE_DBG(wvr, 7)},
+    {DEFINE_DBG(wvr, 8)},
+    {DEFINE_DBG(wvr, 9)},
+    {DEFINE_DBG(wvr, 10)},
+    {DEFINE_DBG(wvr, 11)},
+    {DEFINE_DBG(wvr, 12)},
+    {DEFINE_DBG(wvr, 13)},
+    {DEFINE_DBG(wvr, 14)},
+    {DEFINE_DBG(wvr, 15)},
+
+    {DEFINE_DBG(wcr, 0)},
+    {DEFINE_DBG(wcr, 1)},
+    {DEFINE_DBG(wcr, 2)},
+    {DEFINE_DBG(wcr, 3)},
+    {DEFINE_DBG(wcr, 4)},
+    {DEFINE_DBG(wcr, 5)},
+    {DEFINE_DBG(wcr, 6)},
+    {DEFINE_DBG(wcr, 7)},
+    {DEFINE_DBG(wcr, 8)},
+    {DEFINE_DBG(wcr, 9)},
+    {DEFINE_DBG(wcr, 10)},
+    {DEFINE_DBG(wcr, 11)},
+    {DEFINE_DBG(wcr, 12)},
+    {DEFINE_DBG(wcr, 13)},
+    {DEFINE_DBG(wcr, 14)},
+    {DEFINE_DBG(wcr, 15)},
+
+    DEFINE_MISC_REGS(vg, 8, VG, sve_vg),
+
+    // DEFINE_ZREG(name)
+    DEFINE_ZREG(z0),
+    DEFINE_ZREG(z1),
+    DEFINE_ZREG(z2),
+    DEFINE_ZREG(z3),
+    DEFINE_ZREG(z4),
+    DEFINE_ZREG(z5),
+    DEFINE_ZREG(z6),
+    DEFINE_ZREG(z7),
+    DEFINE_ZREG(z8),
+    DEFINE_ZREG(z9),
+    DEFINE_ZREG(z10),
+    DEFINE_ZREG(z11),
+    DEFINE_ZREG(z12),
+    DEFINE_ZREG(z13),
+    DEFINE_ZREG(z14),
+    DEFINE_ZREG(z15),
+    DEFINE_ZREG(z16),
+    DEFINE_ZREG(z17),
+    DEFINE_ZREG(z18),
+    DEFINE_ZREG(z19),
+    DEFINE_ZREG(z20),
+    DEFINE_ZREG(z21),
+    DEFINE_ZREG(z22),
+    DEFINE_ZREG(z23),
+    DEFINE_ZREG(z24),
+    DEFINE_ZREG(z25),
+    DEFINE_ZREG(z26),
+    DEFINE_ZREG(z27),
+    DEFINE_ZREG(z28),
+    DEFINE_ZREG(z29),
+    DEFINE_ZREG(z30),
+    DEFINE_ZREG(z31),
+
+    // DEFINE_PREG(name)
+    DEFINE_PREG(p0),
+    DEFINE_PREG(p1),
+    DEFINE_PREG(p2),
+    DEFINE_PREG(p3),
+    DEFINE_PREG(p4),
+    DEFINE_PREG(p5),
+    DEFINE_PREG(p6),
+    DEFINE_PREG(p7),
+    DEFINE_PREG(p8),
+    DEFINE_PREG(p9),
+    DEFINE_PREG(p10),
+    DEFINE_PREG(p11),
+    DEFINE_PREG(p12),
+    DEFINE_PREG(p13),
+    DEFINE_PREG(p14),
+    DEFINE_PREG(p15),
+
+    // DEFINE FFR
+    DEFINE_PREG(ffr)};
+
+#endif // DECLARE_REGISTER_INFOS_ARM64_SVE_STRUCT
Index: lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h
===================================================================
--- lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h
+++ lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h
@@ -294,9 +294,98 @@
   dbg_wcr14,
   dbg_wcr15,
 
+#ifdef DECLARE_REGISTER_INFOS_ARM64_SVE_STRUCT
+  sve_fpsr = fpu_fpsr,
+  sve_fpcr = fpu_fpcr,
+
+  sve_vg = dbg_wcr15 + 1,
+
+  sve_z0,
+  sve_z1,
+  sve_z2,
+  sve_z3,
+  sve_z4,
+  sve_z5,
+  sve_z6,
+  sve_z7,
+  sve_z8,
+  sve_z9,
+  sve_z10,
+  sve_z11,
+  sve_z12,
+  sve_z13,
+  sve_z14,
+  sve_z15,
+  sve_z16,
+  sve_z17,
+  sve_z18,
+  sve_z19,
+  sve_z20,
+  sve_z21,
+  sve_z22,
+  sve_z23,
+  sve_z24,
+  sve_z25,
+  sve_z26,
+  sve_z27,
+  sve_z28,
+  sve_z29,
+  sve_z30,
+  sve_z31,
+
+  sve_p0,
+  sve_p1,
+  sve_p2,
+  sve_p3,
+  sve_p4,
+  sve_p5,
+  sve_p6,
+  sve_p7,
+  sve_p8,
+  sve_p9,
+  sve_p10,
+  sve_p11,
+  sve_p12,
+  sve_p13,
+  sve_p14,
+  sve_p15,
+
+  sve_ffr,
+
+#endif
   k_num_registers
 };
 
+static uint32_t g_x0_invalidates[] = {gpr_w0, LLDB_INVALID_REGNUM};
+static uint32_t g_x1_invalidates[] = {gpr_w1, LLDB_INVALID_REGNUM};
+static uint32_t g_x2_invalidates[] = {gpr_w2, LLDB_INVALID_REGNUM};
+static uint32_t g_x3_invalidates[] = {gpr_w3, LLDB_INVALID_REGNUM};
+static uint32_t g_x4_invalidates[] = {gpr_w4, LLDB_INVALID_REGNUM};
+static uint32_t g_x5_invalidates[] = {gpr_w5, LLDB_INVALID_REGNUM};
+static uint32_t g_x6_invalidates[] = {gpr_w6, LLDB_INVALID_REGNUM};
+static uint32_t g_x7_invalidates[] = {gpr_w7, LLDB_INVALID_REGNUM};
+static uint32_t g_x8_invalidates[] = {gpr_w8, LLDB_INVALID_REGNUM};
+static uint32_t g_x9_invalidates[] = {gpr_w9, LLDB_INVALID_REGNUM};
+static uint32_t g_x10_invalidates[] = {gpr_w10, LLDB_INVALID_REGNUM};
+static uint32_t g_x11_invalidates[] = {gpr_w11, LLDB_INVALID_REGNUM};
+static uint32_t g_x12_invalidates[] = {gpr_w12, LLDB_INVALID_REGNUM};
+static uint32_t g_x13_invalidates[] = {gpr_w13, LLDB_INVALID_REGNUM};
+static uint32_t g_x14_invalidates[] = {gpr_w14, LLDB_INVALID_REGNUM};
+static uint32_t g_x15_invalidates[] = {gpr_w15, LLDB_INVALID_REGNUM};
+static uint32_t g_x16_invalidates[] = {gpr_w16, LLDB_INVALID_REGNUM};
+static uint32_t g_x17_invalidates[] = {gpr_w17, LLDB_INVALID_REGNUM};
+static uint32_t g_x18_invalidates[] = {gpr_w18, LLDB_INVALID_REGNUM};
+static uint32_t g_x19_invalidates[] = {gpr_w19, LLDB_INVALID_REGNUM};
+static uint32_t g_x20_invalidates[] = {gpr_w20, LLDB_INVALID_REGNUM};
+static uint32_t g_x21_invalidates[] = {gpr_w21, LLDB_INVALID_REGNUM};
+static uint32_t g_x22_invalidates[] = {gpr_w22, LLDB_INVALID_REGNUM};
+static uint32_t g_x23_invalidates[] = {gpr_w23, LLDB_INVALID_REGNUM};
+static uint32_t g_x24_invalidates[] = {gpr_w24, LLDB_INVALID_REGNUM};
+static uint32_t g_x25_invalidates[] = {gpr_w25, LLDB_INVALID_REGNUM};
+static uint32_t g_x26_invalidates[] = {gpr_w26, LLDB_INVALID_REGNUM};
+static uint32_t g_x27_invalidates[] = {gpr_w27, LLDB_INVALID_REGNUM};
+static uint32_t g_x28_invalidates[] = {gpr_w28, LLDB_INVALID_REGNUM};
+
 static uint32_t g_contained_x0[] = {gpr_x0, LLDB_INVALID_REGNUM};
 static uint32_t g_contained_x1[] = {gpr_x1, LLDB_INVALID_REGNUM};
 static uint32_t g_contained_x2[] = {gpr_x2, LLDB_INVALID_REGNUM};
@@ -456,6 +545,38 @@
 static uint32_t g_d30_invalidates[] = {fpu_v30, fpu_s30, LLDB_INVALID_REGNUM};
 static uint32_t g_d31_invalidates[] = {fpu_v31, fpu_s31, LLDB_INVALID_REGNUM};
 
+static uint32_t g_v0_invalidates[] = {fpu_d0, fpu_s0, LLDB_INVALID_REGNUM};
+static uint32_t g_v1_invalidates[] = {fpu_d1, fpu_s1, LLDB_INVALID_REGNUM};
+static uint32_t g_v2_invalidates[] = {fpu_d2, fpu_s2, LLDB_INVALID_REGNUM};
+static uint32_t g_v3_invalidates[] = {fpu_d3, fpu_s3, LLDB_INVALID_REGNUM};
+static uint32_t g_v4_invalidates[] = {fpu_d4, fpu_s4, LLDB_INVALID_REGNUM};
+static uint32_t g_v5_invalidates[] = {fpu_d5, fpu_s5, LLDB_INVALID_REGNUM};
+static uint32_t g_v6_invalidates[] = {fpu_d6, fpu_s6, LLDB_INVALID_REGNUM};
+static uint32_t g_v7_invalidates[] = {fpu_d7, fpu_s7, LLDB_INVALID_REGNUM};
+static uint32_t g_v8_invalidates[] = {fpu_d8, fpu_s8, LLDB_INVALID_REGNUM};
+static uint32_t g_v9_invalidates[] = {fpu_d9, fpu_s9, LLDB_INVALID_REGNUM};
+static uint32_t g_v10_invalidates[] = {fpu_d10, fpu_s10, LLDB_INVALID_REGNUM};
+static uint32_t g_v11_invalidates[] = {fpu_d11, fpu_s11, LLDB_INVALID_REGNUM};
+static uint32_t g_v12_invalidates[] = {fpu_d12, fpu_s12, LLDB_INVALID_REGNUM};
+static uint32_t g_v13_invalidates[] = {fpu_d13, fpu_s13, LLDB_INVALID_REGNUM};
+static uint32_t g_v14_invalidates[] = {fpu_d14, fpu_s14, LLDB_INVALID_REGNUM};
+static uint32_t g_v15_invalidates[] = {fpu_d15, fpu_s15, LLDB_INVALID_REGNUM};
+static uint32_t g_v16_invalidates[] = {fpu_d16, fpu_s16, LLDB_INVALID_REGNUM};
+static uint32_t g_v17_invalidates[] = {fpu_d17, fpu_s17, LLDB_INVALID_REGNUM};
+static uint32_t g_v18_invalidates[] = {fpu_d18, fpu_s18, LLDB_INVALID_REGNUM};
+static uint32_t g_v19_invalidates[] = {fpu_d19, fpu_s19, LLDB_INVALID_REGNUM};
+static uint32_t g_v20_invalidates[] = {fpu_d20, fpu_s20, LLDB_INVALID_REGNUM};
+static uint32_t g_v21_invalidates[] = {fpu_d21, fpu_s21, LLDB_INVALID_REGNUM};
+static uint32_t g_v22_invalidates[] = {fpu_d22, fpu_s22, LLDB_INVALID_REGNUM};
+static uint32_t g_v23_invalidates[] = {fpu_d23, fpu_s23, LLDB_INVALID_REGNUM};
+static uint32_t g_v24_invalidates[] = {fpu_d24, fpu_s24, LLDB_INVALID_REGNUM};
+static uint32_t g_v25_invalidates[] = {fpu_d25, fpu_s25, LLDB_INVALID_REGNUM};
+static uint32_t g_v26_invalidates[] = {fpu_d26, fpu_s26, LLDB_INVALID_REGNUM};
+static uint32_t g_v27_invalidates[] = {fpu_d27, fpu_s27, LLDB_INVALID_REGNUM};
+static uint32_t g_v28_invalidates[] = {fpu_d28, fpu_s28, LLDB_INVALID_REGNUM};
+static uint32_t g_v29_invalidates[] = {fpu_d29, fpu_s29, LLDB_INVALID_REGNUM};
+static uint32_t g_v30_invalidates[] = {fpu_d30, fpu_s30, LLDB_INVALID_REGNUM};
+static uint32_t g_v31_invalidates[] = {fpu_d31, fpu_s31, LLDB_INVALID_REGNUM};
 // Generates register kinds array for 64-bit general purpose registers
 #define GPR64_KIND(reg, generic_kind)                                          \
   {                                                                            \
@@ -470,38 +591,29 @@
         LLDB_INVALID_REGNUM, lldb_kind                                         \
   }
 
-// Generates register kinds array for vector registers
-#define VREG_KIND(reg)                                                         \
+// Generates register kinds array with dwarf, ehframe, generic and lldb kind
+#define MISC_KIND_GENERIC(reg, type, generic_kind)                             \
   {                                                                            \
-    LLDB_INVALID_REGNUM, arm64_dwarf::reg, LLDB_INVALID_REGNUM,                \
-        LLDB_INVALID_REGNUM, fpu_##reg                                         \
+    arm64_ehframe::reg, arm64_dwarf::reg, generic_kind, LLDB_INVALID_REGNUM,   \
+        type##_##reg                                                           \
   }
 
 // Generates register kinds array for cpsr
-#define CPSR_KIND(lldb_kind)                                                   \
-  {                                                                            \
-    arm64_ehframe::cpsr, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS,         \
-        LLDB_INVALID_REGNUM, lldb_kind                                         \
-  }
+#define MISC_CPSR_KIND(lldb_kind)                                              \
+  MISC_KIND_GENERIC(cpsr, gpr, LLDB_REGNUM_GENERIC_FLAGS)
+#define CPSR_OFFSET_NAME(reg) GPR_OFFSET_NAME(reg)
 
 #define MISC_GPR_KIND(lldb_kind) CPSR_KIND(lldb_kind)
 #define MISC_FPU_KIND(lldb_kind) MISC_KIND(lldb_kind)
 #define MISC_EXC_KIND(lldb_kind) MISC_KIND(lldb_kind)
+#define VREG_KIND(vreg) MISC_KIND_GENERIC(vreg, fpu, LLDB_INVALID_REGNUM)
 
 // Defines a 64-bit general purpose register
-#define DEFINE_GPR64(reg, generic_kind)                                        \
+#define DEFINE_GPR64(reg, alt_name, generic_kind, invalidate_list)             \
   {                                                                            \
-    #reg, nullptr, 8, GPR_OFFSET(gpr_##reg), lldb::eEncodingUint,              \
-        lldb::eFormatHex, GPR64_KIND(reg, generic_kind), nullptr, nullptr,     \
-        nullptr, 0                                                             \
-  }
-
-// Defines a 64-bit general purpose register
-#define DEFINE_GPR64_ALT(reg, alt, generic_kind)                               \
-  {                                                                            \
-    #reg, #alt, 8, GPR_OFFSET(gpr_##reg), lldb::eEncodingUint,                 \
-        lldb::eFormatHex, GPR64_KIND(reg, generic_kind), nullptr, nullptr,     \
-        nullptr, 0                                                             \
+    #reg, alt_name, 8, GPR_OFFSET(gpr_##reg), lldb::eEncodingUint,             \
+        lldb::eFormatHex, GPR64_KIND(reg, generic_kind), nullptr,              \
+        invalidate_list, nullptr, 0                                            \
   }
 
 // Defines a 32-bit general purpose pseudo register
@@ -517,8 +629,8 @@
 #define DEFINE_VREG(reg)                                                       \
   {                                                                            \
     #reg, nullptr, 16, FPU_OFFSET(fpu_##reg - fpu_v0), lldb::eEncodingVector,  \
-        lldb::eFormatVectorOfUInt8, VREG_KIND(reg), nullptr, nullptr, nullptr, \
-        0                                                                      \
+        lldb::eFormatVectorOfUInt8, VREG_KIND(reg), nullptr,                   \
+        g_##reg##_invalidates, nullptr, 0                                      \
   }
 
 // Defines S and D pseudo registers mapping over correspondig vector register
@@ -537,45 +649,48 @@
         nullptr, 0                                                             \
   }
 
+#define STRINGIZE2(x) #x
+#define STRINGIZE(x) STRINGIZE2(x)
+
 static lldb_private::RegisterInfo g_register_infos_arm64_le[] = {
     // DEFINE_GPR64(name, GENERIC KIND)
-    DEFINE_GPR64(x0, LLDB_REGNUM_GENERIC_ARG1),
-    DEFINE_GPR64(x1, LLDB_REGNUM_GENERIC_ARG2),
-    DEFINE_GPR64(x2, LLDB_REGNUM_GENERIC_ARG3),
-    DEFINE_GPR64(x3, LLDB_REGNUM_GENERIC_ARG4),
-    DEFINE_GPR64(x4, LLDB_REGNUM_GENERIC_ARG5),
-    DEFINE_GPR64(x5, LLDB_REGNUM_GENERIC_ARG6),
-    DEFINE_GPR64(x6, LLDB_REGNUM_GENERIC_ARG7),
-    DEFINE_GPR64(x7, LLDB_REGNUM_GENERIC_ARG8),
-    DEFINE_GPR64(x8, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x9, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x10, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x11, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x12, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x13, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x14, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x15, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x16, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x17, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x18, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x19, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x20, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x21, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x22, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x23, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x24, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x25, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x26, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x27, LLDB_INVALID_REGNUM),
-    DEFINE_GPR64(x28, LLDB_INVALID_REGNUM),
+    DEFINE_GPR64(x0, nullptr, LLDB_REGNUM_GENERIC_ARG1, g_x0_invalidates),
+    DEFINE_GPR64(x1, nullptr, LLDB_REGNUM_GENERIC_ARG2, g_x1_invalidates),
+    DEFINE_GPR64(x2, nullptr, LLDB_REGNUM_GENERIC_ARG3, g_x2_invalidates),
+    DEFINE_GPR64(x3, nullptr, LLDB_REGNUM_GENERIC_ARG4, g_x3_invalidates),
+    DEFINE_GPR64(x4, nullptr, LLDB_REGNUM_GENERIC_ARG5, g_x4_invalidates),
+    DEFINE_GPR64(x5, nullptr, LLDB_REGNUM_GENERIC_ARG6, g_x5_invalidates),
+    DEFINE_GPR64(x6, nullptr, LLDB_REGNUM_GENERIC_ARG7, g_x6_invalidates),
+    DEFINE_GPR64(x7, nullptr, LLDB_REGNUM_GENERIC_ARG8, g_x7_invalidates),
+    DEFINE_GPR64(x8, nullptr, LLDB_INVALID_REGNUM, g_x8_invalidates),
+    DEFINE_GPR64(x9, nullptr, LLDB_INVALID_REGNUM, g_x9_invalidates),
+    DEFINE_GPR64(x10, nullptr, LLDB_INVALID_REGNUM, g_x10_invalidates),
+    DEFINE_GPR64(x11, nullptr, LLDB_INVALID_REGNUM, g_x11_invalidates),
+    DEFINE_GPR64(x12, nullptr, LLDB_INVALID_REGNUM, g_x12_invalidates),
+    DEFINE_GPR64(x13, nullptr, LLDB_INVALID_REGNUM, g_x13_invalidates),
+    DEFINE_GPR64(x14, nullptr, LLDB_INVALID_REGNUM, g_x14_invalidates),
+    DEFINE_GPR64(x15, nullptr, LLDB_INVALID_REGNUM, g_x15_invalidates),
+    DEFINE_GPR64(x16, nullptr, LLDB_INVALID_REGNUM, g_x16_invalidates),
+    DEFINE_GPR64(x17, nullptr, LLDB_INVALID_REGNUM, g_x17_invalidates),
+    DEFINE_GPR64(x18, nullptr, LLDB_INVALID_REGNUM, g_x18_invalidates),
+    DEFINE_GPR64(x19, nullptr, LLDB_INVALID_REGNUM, g_x19_invalidates),
+    DEFINE_GPR64(x20, nullptr, LLDB_INVALID_REGNUM, g_x20_invalidates),
+    DEFINE_GPR64(x21, nullptr, LLDB_INVALID_REGNUM, g_x21_invalidates),
+    DEFINE_GPR64(x22, nullptr, LLDB_INVALID_REGNUM, g_x22_invalidates),
+    DEFINE_GPR64(x23, nullptr, LLDB_INVALID_REGNUM, g_x23_invalidates),
+    DEFINE_GPR64(x24, nullptr, LLDB_INVALID_REGNUM, g_x24_invalidates),
+    DEFINE_GPR64(x25, nullptr, LLDB_INVALID_REGNUM, g_x25_invalidates),
+    DEFINE_GPR64(x26, nullptr, LLDB_INVALID_REGNUM, g_x26_invalidates),
+    DEFINE_GPR64(x27, nullptr, LLDB_INVALID_REGNUM, g_x27_invalidates),
+    DEFINE_GPR64(x28, nullptr, LLDB_INVALID_REGNUM, g_x28_invalidates),
     // DEFINE_GPR64(name, GENERIC KIND)
-    DEFINE_GPR64_ALT(fp, x29, LLDB_REGNUM_GENERIC_FP),
-    DEFINE_GPR64_ALT(lr, x30, LLDB_REGNUM_GENERIC_RA),
-    DEFINE_GPR64_ALT(sp, x31, LLDB_REGNUM_GENERIC_SP),
-    DEFINE_GPR64(pc, LLDB_REGNUM_GENERIC_PC),
+    DEFINE_GPR64(fp, STRINGIZE(x29), LLDB_REGNUM_GENERIC_FP, nullptr),
+    DEFINE_GPR64(lr, STRINGIZE(x30), LLDB_REGNUM_GENERIC_RA, nullptr),
+    DEFINE_GPR64(sp, STRINGIZE(x31), LLDB_REGNUM_GENERIC_SP, nullptr),
+    DEFINE_GPR64(pc, nullptr, LLDB_REGNUM_GENERIC_PC, nullptr),
 
     // DEFINE_MISC_REGS(name, size, TYPE, lldb kind)
-    DEFINE_MISC_REGS(cpsr, 4, GPR, gpr_cpsr),
+    DEFINE_MISC_REGS(cpsr, 4, CPSR, gpr_cpsr),
 
     // DEFINE_GPR32(name, parent name)
     DEFINE_GPR32(w0, x0),
Index: lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
===================================================================
--- lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
+++ lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
@@ -13,6 +13,13 @@
 #include "lldb/Target/RegisterContext.h"
 #include "lldb/lldb-private.h"
 
+// AArch64 Register set FP/SIMD feature configuration
+enum {
+  eRegisterInfoModeAArch64,
+  eRegisterInfoModeAArch64SVE,
+  eRegisterInfoModeAArch64SVEMax = 256
+};
+
 class RegisterInfoPOSIX_arm64 : public lldb_private::RegisterInfoInterface {
 public:
   // based on RegisterContextDarwin_arm64.h
@@ -61,7 +68,13 @@
 
   uint32_t GetRegisterCount() const override;
 
+  uint32_t SetRegisterInfoMode(uint32_t mode) override;
+
+  uint32_t GetRegisterInfoMode() const override;
+
 private:
+  uint32_t m_reg_info_mode = UINT32_MAX;
+  std::vector<lldb_private::RegisterInfo> d_register_infos;
   const lldb_private::RegisterInfo *m_register_info_p;
   uint32_t m_register_info_count;
 };
Index: lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
===================================================================
--- lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
+++ lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
@@ -25,6 +25,37 @@
   (LLVM_EXTENSION offsetof(RegisterInfoPOSIX_arm64::FPU, reg) +                \
    sizeof(RegisterInfoPOSIX_arm64::GPR))
 
+// This information is based on AArch64 with SVE architecture reference.
+// Some parts are based on SVE implementation by Linux Ptrace interface.
+
+// AArch64 with SVE has 32 Z and 16 P vector registers. There is also an FFR
+// (First Fault) register and a VG (Vector Granule) pseudo register.
+#define SVE_NUM_ZREGS 32
+#define SVE_NUM_PREGS 16
+
+// SVE 16-byte quad word is the basic unit of expansion in vector length.
+#define SVE_QUAD_WORD_BYTES 16
+
+// Vector length is the multiplier which decides the no of quad words,
+// (multiples of 128-bits or 16-bytes) present in a Z register.
+// Vector length is decided during execution and can change at runtime.
+// We assume a default vector length of 1 for initializing register infos.
+#define SVE_VECTOR_LENGTH_DEFAULT 1
+
+#define SVE_ZREG_SIZE (SVE_VECTOR_LENGTH_DEFAULT * SVE_QUAD_WORD_BYTES)
+#define SVE_PREG_SIZE (SVE_ZREG_SIZE / 8)
+
+// Linux defines a 16-byte header at the start of its SVE data payload.
+// This header contains information about currently enabled SVE configuration.
+// We declare a 16-byte header as the start of SVE data for sanity purpose.
+// This will be updated once register context reads actual SVE configuration.
+#define SVE_LINUX_USER_HEADER 16
+#define SVE_OFFSET_VG 0
+#define SVE_ZREGS_OFFSET SVE_LINUX_USER_HEADER
+#define SVE_ZREG_OFFSET(idx) (SVE_ZREGS_OFFSET + (SVE_ZREG_SIZE * (idx)))
+#define SVE_PREGS_OFFSET (SVE_ZREGS_OFFSET + (SVE_ZREG_SIZE * SVE_NUM_ZREGS))
+#define SVE_PREG_OFFSET(idx) (SVE_PREGS_OFFSET + (SVE_PREG_SIZE * (idx)))
+
 #define EXC_OFFSET_NAME(reg)                                                   \
   (LLVM_EXTENSION offsetof(RegisterInfoPOSIX_arm64::EXC, reg) +                \
    sizeof(RegisterInfoPOSIX_arm64::GPR) +                                      \
@@ -50,8 +81,11 @@
 
 // Include RegisterInfos_arm64 to declare our g_register_infos_arm64 structure.
 #define DECLARE_REGISTER_INFOS_ARM64_STRUCT
+#define DECLARE_REGISTER_INFOS_ARM64_SVE_STRUCT
 #include "RegisterInfos_arm64.h"
+#include "RegisterInfos_arm64_sve.h"
 #undef DECLARE_REGISTER_INFOS_ARM64_STRUCT
+#undef DECLARE_REGISTER_INFOS_ARM64_SVE_STRUCT
 
 static const lldb_private::RegisterInfo *
 GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) {
@@ -96,3 +130,54 @@
 uint32_t RegisterInfoPOSIX_arm64::GetRegisterCount() const {
   return m_register_info_count;
 }
+
+uint32_t RegisterInfoPOSIX_arm64::SetRegisterInfoMode(uint32_t mode) {
+  // Register info mode denotes SVE vector length in context of AArch64.
+  // Register info mode once set to zero permanently selects default static
+  // AArch64 register info and cannot be changed to SVE. Also if an invalid
+  // or previously set vector length is passed to this function then it will
+  // exit immediately with previously set vector length.
+  if (m_reg_info_mode == eRegisterInfoModeAArch64 || m_reg_info_mode == mode ||
+      mode > eRegisterInfoModeAArch64SVEMax)
+    return m_reg_info_mode;
+
+  // If this is first valid call to SetRegisterInfoMode, select SVE if needed.
+  if (m_reg_info_mode == UINT32_MAX) {
+    // SelectAArch64 without SVE and return with eRegisterInfoModeAArch64
+    if (mode == eRegisterInfoModeAArch64) {
+      m_reg_info_mode = eRegisterInfoModeAArch64;
+      return m_reg_info_mode;
+    }
+
+    m_register_info_count =
+        static_cast<uint32_t>(sizeof(g_register_infos_arm64_sve_le) /
+                              sizeof(g_register_infos_arm64_sve_le[0]));
+    d_register_infos = std::vector<lldb_private::RegisterInfo>(
+        g_register_infos_arm64_sve_le,
+        g_register_infos_arm64_sve_le + m_register_info_count);
+    m_register_info_p = &d_register_infos[0];
+  }
+
+  m_reg_info_mode = mode;
+
+  // Update Z registers size and offset
+  uint32_t offset = 0;
+  for (uint32_t it = sve_z0; it <= sve_z31; it++) {
+    d_register_infos[it].byte_size = mode * SVE_QUAD_WORD_BYTES;
+    d_register_infos[it].byte_offset = offset;
+    offset += d_register_infos[it].byte_size;
+  }
+
+  // Update P registers and FFR size and offset
+  for (uint32_t it = sve_p0; it <= sve_ffr; it++) {
+    d_register_infos[it].byte_size = mode * SVE_QUAD_WORD_BYTES / 8;
+    d_register_infos[it].byte_offset = offset;
+    offset += d_register_infos[it].byte_size;
+  }
+
+  return m_reg_info_mode;
+}
+
+uint32_t RegisterInfoPOSIX_arm64::GetRegisterInfoMode() const {
+  return m_reg_info_mode;
+}
Index: lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
===================================================================
--- lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
+++ lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
@@ -61,6 +61,10 @@
     return nullptr;
   }
 
+  virtual uint32_t SetRegisterInfoMode(uint32_t mode) { return 0; }
+
+  virtual uint32_t GetRegisterInfoMode() const { return 0; }
+
 public:
   // FIXME make private.
   lldb_private::ArchSpec m_target_arch;
Index: lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h
===================================================================
--- lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h
+++ lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h
@@ -33,6 +33,10 @@
 
   const RegisterInfoInterface &GetRegisterInfoInterface() const;
 
+  uint32_t SetRegisterInfoMode(uint32_t mode) {
+    return m_register_info_interface_up->SetRegisterInfoMode(mode);
+  }
+
 private:
   std::unique_ptr<RegisterInfoInterface> m_register_info_interface_up;
 };
Index: lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
===================================================================
--- lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
+++ lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
@@ -63,6 +63,8 @@
 
   void Clear();
 
+  bool IsPerThreadRegInfo();
+
 protected:
   // Classes that inherit from DynamicRegisterInfo can see and modify these
   typedef std::vector<lldb_private::RegisterInfo> reg_collection;
@@ -89,5 +91,6 @@
   size_t m_reg_data_byte_size = 0u; // The number of bytes required to store
                                     // all registers
   bool m_finalized = false;
+  bool m_per_thread_reginfo = false;
 };
 #endif // lldb_DynamicRegisterInfo_h_
Index: lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
===================================================================
--- lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
+++ lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -533,6 +533,17 @@
     }
   }
 
+  // Create per thread reginfo to support AArch64 SVE dynamic register sizes.
+  if (arch.GetMachine() == llvm::Triple::aarch64 ||
+      arch.GetMachine() == llvm::Triple::aarch64_be) {
+    for (const auto &reg : m_regs) {
+      if (strcmp(reg.name, "vg") == 0) {
+        m_per_thread_reginfo = true;
+        break;
+      }
+    }
+  }
+
   if (!generic_regs_specified) {
     switch (arch.GetMachine()) {
     case llvm::Triple::aarch64:
@@ -682,9 +693,12 @@
   m_invalidate_regs_map.clear();
   m_dynamic_reg_size_map.clear();
   m_reg_data_byte_size = 0;
+  m_per_thread_reginfo = false;
   m_finalized = false;
 }
 
+bool DynamicRegisterInfo::IsPerThreadRegInfo() { return m_per_thread_reginfo; }
+
 void DynamicRegisterInfo::Dump() const {
   StreamFile s(stdout, false);
   const size_t num_regs = m_regs.size();
Index: lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
===================================================================
--- lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
+++ lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
@@ -39,6 +39,9 @@
                      std::string &description) override;
 
   NativeRegisterContextLinux &GetRegisterContext() override {
+    if (m_reg_context_up && IsStopped(nullptr))
+      m_reg_context_up->ConfigureRegisterContext();
+
     return *m_reg_context_up;
   }
 
Index: lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
===================================================================
--- lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -14,11 +14,25 @@
 #include "Plugins/Process/Linux/NativeRegisterContextLinux.h"
 #include "Plugins/Process/Utility/lldb-arm64-register-enums.h"
 
+#include <asm/ptrace.h>
+
+#ifndef SVE_PT_REGS_SVE
+#define INCLUDE_LINUX_PTRACE_DEFINITIONS_FOR_SVE_ARM64
+#include "Plugins/Process/Linux/LinuxPTraceDefines_arm64sve.h"
+#endif
+
 namespace lldb_private {
 namespace process_linux {
 
 class NativeProcessLinux;
 
+enum class SVE_STATE {
+  SVE_STATE_UNKNOWN,
+  SVE_STATE_DISABLED,
+  SVE_STATE_FPSIMD,
+  SVE_STATE_FULL
+};
+
 class NativeRegisterContextLinux_arm64 : public NativeRegisterContextLinux {
 public:
   NativeRegisterContextLinux_arm64(const ArchSpec &target_arch,
@@ -42,6 +56,10 @@
 
   void InvalidateAllRegisters() override;
 
+  void ConfigureRegisterContext() override;
+
+  const RegisterSet *GetExpeditedRegisterSet() const override;
+
   // Hardware breakpoints/watchpoint management functions
 
   uint32_t NumSupportedHardwareBreakpoints() override;
@@ -88,17 +106,34 @@
 
   Status WriteFPR() override;
 
+  Status ReadAllSVE();
+
+  Status WriteAllSVE();
+
+  Status ReadSVEHeader();
+
+  Status WriteSVEHeader();
+
   void *GetGPRBuffer() override { return &m_gpr_arm64; }
 
   void *GetFPRBuffer() override { return &m_fpr; }
 
   size_t GetFPRSize() override { return sizeof(m_fpr); }
 
+  void *GetSVEBuffer() { return m_sve_data.get(); }
+
+  void *GetSVEHeader() { return &m_sve_header; }
+
+  size_t GetSVEHeaderSize() { return sizeof(m_sve_header); }
+
+  size_t GetSVEBufferSize();
+
 private:
   struct RegInfo {
     uint32_t num_registers;
     uint32_t num_gpr_registers;
     uint32_t num_fpr_registers;
+    uint32_t num_sve_registers;
 
     uint32_t last_gpr;
     uint32_t first_fpr;
@@ -107,6 +142,9 @@
     uint32_t first_fpr_v;
     uint32_t last_fpr_v;
 
+    uint32_t first_sve;
+    uint32_t last_sve;
+
     uint32_t gpr_flags;
   };
 
@@ -129,13 +167,24 @@
     uint64_t pstate;
   };
 
+  typedef std::unique_ptr<uint8_t[]> SVE_DATA;
+
   bool m_gpr_is_valid;
   bool m_fpu_is_valid;
+  bool m_sve_data_is_valid;
+
+  bool m_sve_header_is_valid;
 
   GPR m_gpr_arm64; // 64-bit general purpose registers.
+
   RegInfo m_reg_info;
   FPU m_fpr; // floating-point registers including extended register sets.
 
+  struct user_sve_header m_sve_header;
+  SVE_DATA m_sve_data;
+
+  mutable SVE_STATE m_sve_state;
+
   // Debug register info for hardware breakpoints and watchpoints management.
   struct DREG {
     lldb::addr_t address;  // Breakpoint/watchpoint address value.
@@ -157,11 +206,17 @@
 
   bool IsFPR(unsigned reg) const;
 
+  bool IsSVE(unsigned reg) const;
+
+  bool IsVG(unsigned reg) const;
+
   Status ReadHardwareDebugInfo();
 
   Status WriteHardwareDebugRegs(int hwbType);
 
   uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const;
+
+  uint32_t CalculateSVEOffset(const RegisterInfo *reg_info) const;
 };
 
 } // namespace process_linux
Index: lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
===================================================================
--- lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -28,8 +28,10 @@
 #include <sys/socket.h>
 // NT_PRSTATUS and NT_FPREGSET definition
 #include <elf.h>
-// user_hwdebug_state definition
-#include <asm/ptrace.h>
+
+#ifndef NT_ARM_SVE
+#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension */
+#endif
 
 #define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize())
 
@@ -95,17 +97,65 @@
                1) == k_num_fpr_registers_arm64,
               "g_fpu_regnums_arm64 has wrong number of register infos");
 
+// ARM64 SVE registers.
+static const uint32_t g_sve_regnums_arm64[] = {
+    sve_vg_arm64,
+
+    sve_z0_arm64,       sve_z1_arm64,  sve_z2_arm64,  sve_z3_arm64,
+    sve_z4_arm64,       sve_z5_arm64,  sve_z6_arm64,  sve_z7_arm64,
+    sve_z8_arm64,       sve_z9_arm64,  sve_z10_arm64, sve_z11_arm64,
+    sve_z12_arm64,      sve_z13_arm64, sve_z14_arm64, sve_z15_arm64,
+    sve_z16_arm64,      sve_z17_arm64, sve_z18_arm64, sve_z19_arm64,
+    sve_z20_arm64,      sve_z21_arm64, sve_z22_arm64, sve_z23_arm64,
+    sve_z24_arm64,      sve_z25_arm64, sve_z26_arm64, sve_z27_arm64,
+    sve_z28_arm64,      sve_z29_arm64, sve_z30_arm64, sve_z31_arm64,
+
+    sve_p0_arm64,       sve_p1_arm64,  sve_p2_arm64,  sve_p3_arm64,
+    sve_p4_arm64,       sve_p5_arm64,  sve_p6_arm64,  sve_p7_arm64,
+    sve_p8_arm64,       sve_p9_arm64,  sve_p10_arm64, sve_p11_arm64,
+    sve_p12_arm64,      sve_p13_arm64, sve_p14_arm64, sve_p15_arm64,
+
+    sve_ffr_arm64,
+    LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert(((sizeof g_sve_regnums_arm64 / sizeof g_sve_regnums_arm64[0]) -
+               1) == k_num_sve_registers_arm64,
+              "g_sve_regnums_arm64 has wrong number of register infos");
+
 namespace {
 // Number of register sets provided by this context.
-enum { k_num_register_sets = 2 };
+enum { k_num_register_sets = 3 };
 }
 
+// ARM64 general purpose registers.
+static const uint32_t g_expedited_regnums_arm64_sve[] = {
+    gpr_x0_arm64,  gpr_x1_arm64,   gpr_x2_arm64,  gpr_x3_arm64,
+    gpr_x4_arm64,  gpr_x5_arm64,   gpr_x6_arm64,  gpr_x7_arm64,
+    gpr_x8_arm64,  gpr_x9_arm64,   gpr_x10_arm64, gpr_x11_arm64,
+    gpr_x12_arm64, gpr_x13_arm64,  gpr_x14_arm64, gpr_x15_arm64,
+    gpr_x16_arm64, gpr_x17_arm64,  gpr_x18_arm64, gpr_x19_arm64,
+    gpr_x20_arm64, gpr_x21_arm64,  gpr_x22_arm64, gpr_x23_arm64,
+    gpr_x24_arm64, gpr_x25_arm64,  gpr_x26_arm64, gpr_x27_arm64,
+    gpr_x28_arm64, gpr_fp_arm64,   gpr_lr_arm64,  gpr_sp_arm64,
+    gpr_pc_arm64,  gpr_cpsr_arm64, sve_vg_arm64,  LLDB_INVALID_REGNUM};
+static_assert(
+    ((sizeof g_expedited_regnums_arm64_sve /
+      sizeof g_expedited_regnums_arm64_sve[0]) -
+     1) == k_num_expedited_registers_arm64_sve,
+    "g_expedited_regnums_arm64_sve has wrong number of register infos");
+
 // Register sets for ARM64.
 static const RegisterSet g_reg_sets_arm64[k_num_register_sets] = {
     {"General Purpose Registers", "gpr", k_num_gpr_registers_arm64,
      g_gpr_regnums_arm64},
     {"Floating Point Registers", "fpu", k_num_fpr_registers_arm64,
-     g_fpu_regnums_arm64}};
+     g_fpu_regnums_arm64},
+    {"SVE Registers", "sve", k_num_sve_registers_arm64, g_sve_regnums_arm64}};
+
+// AArch64 SVE expedited registers set
+static const RegisterSet g_expedited_reg_sets_arm64_sve = {
+    "General Purpose Registers", "expedited",
+    k_num_expedited_registers_arm64_sve, g_expedited_regnums_arm64_sve};
 
 std::unique_ptr<NativeRegisterContextLinux>
 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
@@ -131,12 +181,15 @@
     m_reg_info.num_registers = k_num_registers_arm64;
     m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64;
     m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64;
+    m_reg_info.num_sve_registers = k_num_sve_registers_arm64;
     m_reg_info.last_gpr = k_last_gpr_arm64;
     m_reg_info.first_fpr = k_first_fpr_arm64;
     m_reg_info.last_fpr = k_last_fpr_arm64;
     m_reg_info.first_fpr_v = fpu_v0_arm64;
     m_reg_info.last_fpr_v = fpu_v31_arm64;
     m_reg_info.gpr_flags = gpr_cpsr_arm64;
+    m_reg_info.first_sve = sve_vg_arm64;
+    m_reg_info.last_sve = sve_ffr_arm64;
     break;
   default:
     llvm_unreachable("Unhandled target architecture.");
@@ -155,15 +208,26 @@
 
   m_gpr_is_valid = false;
   m_fpu_is_valid = false;
+  m_sve_data_is_valid = false;
+
+  m_sve_header_is_valid = false;
+
+  // SVE is not enabled until we query user_sve_header
+  m_sve_state = SVE_STATE::SVE_STATE_UNKNOWN;
 }
 
 uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount() const {
-  return k_num_register_sets;
+  if (m_sve_state == SVE_STATE::SVE_STATE_FPSIMD ||
+      m_sve_state == SVE_STATE::SVE_STATE_FULL)
+
+    return k_num_register_sets;
+  else
+    return k_num_register_sets - 1;
 }
 
 const RegisterSet *
 NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index) const {
-  if (set_index < k_num_register_sets)
+  if (set_index < GetRegisterSetCount())
     return &g_reg_sets_arm64[set_index];
 
   return nullptr;
@@ -171,7 +235,7 @@
 
 uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount() const {
   uint32_t count = 0;
-  for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index)
+  for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
     count += g_reg_sets_arm64[set_index].num_registers;
   return count;
 }
@@ -217,6 +281,26 @@
     offset = CalculateFprOffset(reg_info);
     assert(offset < GetFPRSize());
     src = (uint8_t *)GetFPRBuffer() + offset;
+  } else if (IsVG(reg)) {
+    if (!m_sve_header_is_valid) {
+
+      error = ReadSVEHeader();
+      if (error.Fail())
+        return error;
+    }
+    offset = CalculateSVEOffset(reg_info);
+    assert(offset < GetSVEHeaderSize());
+    src = (uint8_t *)GetSVEHeader() + offset;
+  } else if (IsSVE(reg)) {
+    if (!m_sve_data_is_valid) {
+
+      error = ReadAllSVE();
+      if (error.Fail())
+        return error;
+    }
+    offset = CalculateSVEOffset(reg_info);
+    assert(offset < GetSVEBufferSize());
+    src = (uint8_t *)GetSVEBuffer() + offset;
   } else
     return Status("failed - register wasn't recognized to be a GPR or an FPR, "
                   "write strategy unknown");
@@ -265,12 +349,34 @@
         return error;
     }
     offset = CalculateFprOffset(reg_info);
+    assert(offset < GetSVEHeaderSize());
+    dst = (uint8_t *)GetSVEHeader() + offset;
+
+    ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
+
+    return WriteFPR();
+  } else if (IsVG(reg)) {
+
+    offset = CalculateSVEOffset(reg_info);
     assert(offset < GetFPRSize());
     dst = (uint8_t *)GetFPRBuffer() + offset;
 
     ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
 
-    return WriteFPR();
+    return WriteSVEHeader();
+  } else if (IsSVE(reg)) {
+    if (!m_fpu_is_valid) {
+      error = ReadFPR();
+      if (error.Fail())
+        return error;
+    }
+    offset = CalculateSVEOffset(reg_info);
+    assert(offset < GetSVEBufferSize());
+    dst = (uint8_t *)GetSVEBuffer() + offset;
+
+    ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
+
+    return WriteAllSVE();
   }
 
   return error;
@@ -351,6 +457,14 @@
   return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
 }
 
+bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const {
+  return (m_reg_info.first_sve <= reg && reg <= m_reg_info.last_sve);
+}
+
+bool NativeRegisterContextLinux_arm64::IsVG(unsigned reg) const {
+  return (m_reg_info.first_fpr == reg);
+}
+
 uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareBreakpoints() {
   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
 
@@ -893,15 +1007,120 @@
   return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
 }
 
+Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
+  Status error;
+
+  struct iovec ioVec;
+
+  ioVec.iov_base = GetSVEHeader();
+  ioVec.iov_len = GetSVEHeaderSize();
+
+  error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE);
+
+  if (error.Success()) {
+    if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD)
+      m_sve_state = SVE_STATE::SVE_STATE_FPSIMD;
+    else if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE)
+      m_sve_state = SVE_STATE::SVE_STATE_FULL;
+  } else
+    m_sve_state = SVE_STATE::SVE_STATE_DISABLED;
+
+  m_sve_header_is_valid = true;
+
+  return error;
+}
+
+Status NativeRegisterContextLinux_arm64::WriteSVEHeader() {
+  Status error;
+
+  error = ReadSVEHeader();
+
+  if (ReadSVEHeader().Fail())
+    return error;
+
+  struct iovec ioVec;
+
+  ioVec.iov_base = GetSVEHeader();
+  ioVec.iov_len = GetSVEHeaderSize();
+
+  return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE);
+}
+
+Status NativeRegisterContextLinux_arm64::ReadAllSVE() {
+  Status error;
+
+  struct iovec ioVec;
+
+  ioVec.iov_base = GetSVEBuffer();
+  ioVec.iov_len = GetSVEBufferSize();
+
+  error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE);
+
+  if (error.Success())
+    m_sve_data_is_valid = true;
+
+  return error;
+}
+
+Status NativeRegisterContextLinux_arm64::WriteAllSVE() {
+  Status error;
+
+  m_sve_header_is_valid = false;
+  m_sve_data_is_valid = false;
+
+  error = ReadSVEHeader();
+
+  if (ReadSVEHeader().Fail())
+    return error;
+
+  struct iovec ioVec;
+
+  ioVec.iov_base = GetSVEHeader();
+  ioVec.iov_len = GetSVEHeaderSize();
+
+  return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE);
+}
+
 void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() {
   m_gpr_is_valid = false;
   m_fpu_is_valid = false;
+  m_sve_data_is_valid = false;
+  m_sve_header_is_valid = false;
 }
 
+void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
+  bool set_mode = false;
+  if (m_sve_state == SVE_STATE::SVE_STATE_UNKNOWN)
+    set_mode = true;
+
+  if (!m_sve_header_is_valid && m_sve_state != SVE_STATE::SVE_STATE_DISABLED)
+    ReadSVEHeader();
+
+  if (set_mode && m_sve_state != SVE_STATE::SVE_STATE_DISABLED)
+    SetRegisterInfoMode(eRegisterInfoModeAArch64SVE);
+}
+
+size_t NativeRegisterContextLinux_arm64::GetSVEBufferSize() { return 0; }
+
 uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset(
     const RegisterInfo *reg_info) const {
   return reg_info->byte_offset -
          GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset;
 }
 
+uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset(
+    const RegisterInfo *reg_info) const {
+  return reg_info->byte_offset -
+         GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset;
+}
+
+const RegisterSet *
+NativeRegisterContextLinux_arm64::GetExpeditedRegisterSet() const {
+  if (m_sve_state == SVE_STATE::SVE_STATE_FPSIMD ||
+      m_sve_state == SVE_STATE::SVE_STATE_FULL)
+    return &g_expedited_reg_sets_arm64_sve;
+  else
+    return &g_reg_sets_arm64[0];
+}
+
 #endif // defined (__arm64__) || defined (__aarch64__)
Index: lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h
===================================================================
--- lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h
+++ lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h
@@ -31,6 +31,9 @@
   // Invalidates cached values in register context data structures
   virtual void InvalidateAllRegisters(){}
 
+  // Configures register context based on target capabilities
+  virtual void ConfigureRegisterContext() {}
+
 protected:
   lldb::ByteOrder GetByteOrder() const;
 
Index: lldb/source/Plugins/Process/Linux/LinuxPTraceDefines_arm64sve.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/Linux/LinuxPTraceDefines_arm64sve.h
@@ -0,0 +1,155 @@
+//===-- LinuxPtraceDefs_arm64.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// This file provides Linux specific defines to enable compilation with SVE
+// ptrace support. These defines may later be removed once they get defined
+// in Procfs.h and Ptrace.h.
+
+// References in Linux kernel source:
+// 1) Documentation/arm64/sve.txt
+// 2) arch/arm64/include/uapi/asm/ptrace.h
+// 3) arch/arm64/include/uapi/asm/sve_context.h
+#ifdef INCLUDE_LINUX_PTRACE_DEFINITIONS_FOR_SVE_ARM64
+
+#ifndef lldb_LinuxPtraceDefs_arm64_h
+#define lldb_LinuxPtraceDefs_arm64_h
+
+#include <asm/types.h>
+
+/* SVE/FP/SIMD state (NT_ARM_SVE) */
+
+struct user_sve_header {
+  __u32 size;     /* total meaningful regset content in bytes */
+  __u32 max_size; /* maxmium possible size for this thread */
+  __u16 vl;       /* current vector length */
+  __u16 max_vl;   /* maximum possible vector length */
+  __u16 flags;
+  __u16 __reserved;
+};
+
+/* Definitions for user_sve_header.flags: */
+#define SVE_PT_REGS_MASK (1 << 0)
+
+#define SVE_PT_REGS_FPSIMD 0
+#define SVE_PT_REGS_SVE SVE_PT_REGS_MASK
+
+/*
+ * Common SVE_PT_* flags:
+ * These must be kept in sync with prctl interface in <linux/ptrace.h>
+ */
+#define SVE_PT_VL_INHERIT (PR_SVE_VL_INHERIT >> 16)
+#define SVE_PT_VL_ONEXEC (PR_SVE_SET_VL_ONEXEC >> 16)
+
+/*
+ * The remainder of the SVE state follows struct user_sve_header.  The
+ * total size of the SVE state (including header) depends on the
+ * metadata in the header:  SVE_PT_SIZE(vq, flags) gives the total size
+ * of the state in bytes, including the header.
+ *
+ * Refer to <asm/sigcontext.h> for details of how to pass the correct
+ * "vq" argument to these macros.
+ */
+
+/* Offset from the start of struct user_sve_header to the register data */
+#define SVE_PT_REGS_OFFSET                                                     \
+  ((sizeof(struct sve_context) + (SVE_VQ_BYTES - 1)) / SVE_VQ_BYTES *          \
+   SVE_VQ_BYTES)
+
+/*
+ * The register data content and layout depends on the value of the
+ * flags field.
+ */
+
+/*
+ * (flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD case:
+ *
+ * The payload starts at offset SVE_PT_FPSIMD_OFFSET, and is of type
+ * struct user_fpsimd_state.  Additional data might be appended in the
+ * future: use SVE_PT_FPSIMD_SIZE(vq, flags) to compute the total size.
+ * SVE_PT_FPSIMD_SIZE(vq, flags) will never be less than
+ * sizeof(struct user_fpsimd_state).
+ */
+
+#define SVE_PT_FPSIMD_OFFSET SVE_PT_REGS_OFFSET
+
+#define SVE_PT_FPSIMD_SIZE(vq, flags) (sizeof(struct user_fpsimd_state))
+
+/*
+ * (flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE case:
+ *
+ * The payload starts at offset SVE_PT_SVE_OFFSET, and is of size
+ * SVE_PT_SVE_SIZE(vq, flags).
+ *
+ * Additional macros describe the contents and layout of the payload.
+ * For each, SVE_PT_SVE_x_OFFSET(args) is the start offset relative to
+ * the start of struct user_sve_header, and SVE_PT_SVE_x_SIZE(args) is
+ * the size in bytes:
+ *
+ *	x	type				description
+ *	-	----				-----------
+ *	ZREGS		\
+ *	ZREG		|
+ *	PREGS		| refer to <asm/sigcontext.h>
+ *	PREG		|
+ *	FFR		/
+ *
+ *	FPSR	uint32_t			FPSR
+ *	FPCR	uint32_t			FPCR
+ *
+ * Additional data might be appended in the future.
+ */
+
+#define SVE_PT_SVE_ZREG_SIZE(vq) SVE_SIG_ZREG_SIZE(vq)
+#define SVE_PT_SVE_PREG_SIZE(vq) SVE_SIG_PREG_SIZE(vq)
+#define SVE_PT_SVE_FFR_SIZE(vq) SVE_SIG_FFR_SIZE(vq)
+#define SVE_PT_SVE_FPSR_SIZE sizeof(__u32)
+#define SVE_PT_SVE_FPCR_SIZE sizeof(__u32)
+
+#define __SVE_SIG_TO_PT(offset)                                                \
+  ((offset)-SVE_SIG_REGS_OFFSET + SVE_PT_REGS_OFFSET)
+
+#define SVE_PT_SVE_OFFSET SVE_PT_REGS_OFFSET
+
+#define SVE_PT_SVE_ZREGS_OFFSET __SVE_SIG_TO_PT(SVE_SIG_ZREGS_OFFSET)
+#define SVE_PT_SVE_ZREG_OFFSET(vq, n)                                          \
+  __SVE_SIG_TO_PT(SVE_SIG_ZREG_OFFSET(vq, n))
+#define SVE_PT_SVE_ZREGS_SIZE(vq)                                              \
+  (SVE_PT_SVE_ZREG_OFFSET(vq, SVE_NUM_ZREGS) - SVE_PT_SVE_ZREGS_OFFSET)
+
+#define SVE_PT_SVE_PREGS_OFFSET(vq) __SVE_SIG_TO_PT(SVE_SIG_PREGS_OFFSET(vq))
+#define SVE_PT_SVE_PREG_OFFSET(vq, n)                                          \
+  __SVE_SIG_TO_PT(SVE_SIG_PREG_OFFSET(vq, n))
+#define SVE_PT_SVE_PREGS_SIZE(vq)                                              \
+  (SVE_PT_SVE_PREG_OFFSET(vq, SVE_NUM_PREGS) - SVE_PT_SVE_PREGS_OFFSET(vq))
+
+#define SVE_PT_SVE_FFR_OFFSET(vq) __SVE_SIG_TO_PT(SVE_SIG_FFR_OFFSET(vq))
+
+#define SVE_PT_SVE_FPSR_OFFSET(vq)                                             \
+  ((SVE_PT_SVE_FFR_OFFSET(vq) + SVE_PT_SVE_FFR_SIZE(vq) +                      \
+    (SVE_VQ_BYTES - 1)) /                                                      \
+   SVE_VQ_BYTES * SVE_VQ_BYTES)
+#define SVE_PT_SVE_FPCR_OFFSET(vq)                                             \
+  (SVE_PT_SVE_FPSR_OFFSET(vq) + SVE_PT_SVE_FPSR_SIZE)
+
+/*
+ * Any future extension appended after FPCR must be aligned to the next
+ * 128-bit boundary.
+ */
+
+#define SVE_PT_SVE_SIZE(vq, flags)                                             \
+  ((SVE_PT_SVE_FPCR_OFFSET(vq) + SVE_PT_SVE_FPCR_SIZE - SVE_PT_SVE_OFFSET +    \
+    (SVE_VQ_BYTES - 1)) /                                                      \
+   SVE_VQ_BYTES * SVE_VQ_BYTES)
+
+#define SVE_PT_SIZE(vq, flags)                                                 \
+  (((flags)&SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE                               \
+       ? SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, flags)                        \
+       : SVE_PT_FPSIMD_OFFSET + SVE_PT_FPSIMD_SIZE(vq, flags))
+
+#endif
+#endif
Index: lldb/include/lldb/Utility/RegisterValue.h
===================================================================
--- lldb/include/lldb/Utility/RegisterValue.h
+++ lldb/include/lldb/Utility/RegisterValue.h
@@ -26,7 +26,7 @@
 
 class RegisterValue {
 public:
-  enum { kMaxRegisterByteSize = 64u };
+  enum { kMaxRegisterByteSize = 256u };
 
   enum Type {
     eTypeInvalid,
@@ -261,7 +261,7 @@
   struct {
     uint8_t bytes[kMaxRegisterByteSize]; // This must be big enough to hold any
                                          // register for any supported target.
-    uint8_t length;
+    uint32_t length;
     lldb::ByteOrder byte_order;
   } buffer;
 };
Index: lldb/include/lldb/Host/common/NativeRegisterContext.h
===================================================================
--- lldb/include/lldb/Host/common/NativeRegisterContext.h
+++ lldb/include/lldb/Host/common/NativeRegisterContext.h
@@ -114,6 +114,10 @@
 
   virtual NativeThreadProtocol &GetThread() { return m_thread; }
 
+  virtual const RegisterSet *GetExpeditedRegisterSet() const {
+    return nullptr;
+  };
+
   const RegisterInfo *GetRegisterInfoByName(llvm::StringRef reg_name,
                                             uint32_t start_idx = 0);
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
  • [Lldb-commits] [PAT... Muhammad Omair Javaid via Phabricator via lldb-commits

Reply via email to