1 //===-- DNBArchImplARM64.h --------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM64_DNBARCHIMPLARM64_H
10 #define LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM64_DNBARCHIMPLARM64_H
12 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
14 #include <mach/thread_status.h>
18 #if !defined(ARM_SME_STATE)
19 #include "sme_thread_status.h"
22 #if defined(ARM_THREAD_STATE64_COUNT)
28 class DNBArchMachARM64
: public DNBArchProtocol
{
30 enum { kMaxNumThumbITBreakpoints
= 4 };
32 DNBArchMachARM64(MachThread
*thread
)
33 : m_thread(thread
), m_state(), m_disabled_watchpoints(),
34 m_disabled_breakpoints(), m_watchpoint_hw_index(-1),
35 m_watchpoint_did_occur(false),
36 m_watchpoint_resume_single_step_enabled(false),
37 m_saved_register_states() {
38 m_disabled_watchpoints
.resize(16);
39 m_disabled_breakpoints
.resize(16);
40 memset(&m_dbg_save
, 0, sizeof(m_dbg_save
));
43 struct WatchpointSpec
{
44 nub_addr_t aligned_start
;
45 nub_addr_t requested_start
;
46 nub_size_t aligned_size
;
47 nub_size_t requested_size
;
50 virtual ~DNBArchMachARM64() {}
52 static void Initialize();
53 static const DNBRegisterSetInfo
*GetRegisterSetInfo(nub_size_t
*num_reg_sets
);
55 bool GetRegisterValue(uint32_t set
, uint32_t reg
,
56 DNBRegisterValue
*value
) override
;
57 bool SetRegisterValue(uint32_t set
, uint32_t reg
,
58 const DNBRegisterValue
*value
) override
;
59 nub_size_t
GetRegisterContext(void *buf
, nub_size_t buf_len
) override
;
60 nub_size_t
SetRegisterContext(const void *buf
, nub_size_t buf_len
) override
;
61 uint32_t SaveRegisterState() override
;
62 bool RestoreRegisterState(uint32_t save_id
) override
;
64 kern_return_t
GetRegisterState(int set
, bool force
) override
;
65 kern_return_t
SetRegisterState(int set
) override
;
66 bool RegisterSetStateIsValid(int set
) const override
;
68 uint64_t GetPC(uint64_t failValue
) override
; // Get program counter
69 kern_return_t
SetPC(uint64_t value
) override
;
70 uint64_t GetSP(uint64_t failValue
) override
; // Get stack pointer
71 void ThreadWillResume() override
;
72 bool ThreadDidStop() override
;
73 bool NotifyException(MachException::Data
&exc
) override
;
75 static DNBArchProtocol
*Create(MachThread
*thread
);
76 static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size
);
77 static uint32_t GetCPUType();
79 uint32_t NumSupportedHardwareBreakpoints() override
;
80 uint32_t NumSupportedHardwareWatchpoints() override
;
82 uint32_t EnableHardwareBreakpoint(nub_addr_t addr
, nub_size_t size
,
83 bool also_set_on_task
) override
;
84 bool DisableHardwareBreakpoint(uint32_t hw_break_index
,
85 bool also_set_on_task
) override
;
86 std::vector
<WatchpointSpec
>
87 AlignRequestedWatchpoint(nub_addr_t requested_addr
,
88 nub_size_t requested_size
);
89 uint32_t EnableHardwareWatchpoint(nub_addr_t addr
, nub_size_t size
, bool read
,
90 bool write
, bool also_set_on_task
) override
;
91 uint32_t SetBASWatchpoint(WatchpointSpec wp
, bool read
, bool write
,
92 bool also_set_on_task
);
93 uint32_t SetMASKWatchpoint(WatchpointSpec wp
, bool read
, bool write
,
94 bool also_set_on_task
);
95 bool DisableHardwareWatchpoint(uint32_t hw_break_index
,
96 bool also_set_on_task
) override
;
97 bool DisableHardwareWatchpoint_helper(uint32_t hw_break_index
,
98 bool also_set_on_task
);
100 kern_return_t
EnableHardwareSingleStep(bool enable
);
101 static bool FixGenericRegisterNumber(uint32_t &set
, uint32_t ®
);
104 e_regSetALL
= REGISTER_SET_ALL
,
105 e_regSetGPR
, // ARM_THREAD_STATE64,
106 e_regSetVFP
, // ARM_NEON_STATE64,
107 e_regSetEXC
, // ARM_EXCEPTION_STATE64,
108 e_regSetSVE
, // ARM_SVE_Z_STATE1, ARM_SVE_Z_STATE2, ARM_SVE_P_STATE
109 e_regSetSME
, // ARM_SME_STATE, ARM_SME_ZA_STATE1..16, ARM_SME2_STATE
110 e_regSetDBG
, // ARM_DEBUG_STATE64,
115 e_regSetGPRCount
= ARM_THREAD_STATE64_COUNT
,
116 e_regSetVFPCount
= ARM_NEON_STATE64_COUNT
,
117 e_regSetEXCCount
= ARM_EXCEPTION_STATE64_COUNT
,
118 e_regSetDBGCount
= ARM_DEBUG_STATE64_COUNT
,
121 enum { Read
= 0, Write
= 1, kNumErrors
= 2 };
123 typedef arm_thread_state64_t GPR
;
124 typedef arm_neon_state64_t FPU
;
125 typedef arm_exception_state64_t EXC
;
128 uint8_t z
[32][256]; // arm_sve_z_state_t z[2]
129 uint8_t p
[16][32]; // arm_sve_p_state_t p
133 uint64_t svcr
; // arm_sme_state_t
134 uint64_t tpidr2
; // arm_sme_state_t
135 uint16_t svl_b
; // arm_sme_state_t
137 std::vector
<uint8_t> za
;
141 if (DNBArchMachARM64::CPUHasSME()) {
142 int svl
= GetSMEMaxSVL();
143 za
.resize(svl
* svl
, 0);
148 static const DNBRegisterInfo g_gpr_registers
[];
149 static const DNBRegisterInfo g_exc_registers
[];
151 static const size_t k_num_gpr_registers
;
152 static const size_t k_num_exc_registers
;
153 static const size_t k_num_all_registers
;
165 arm_debug_state64_t dbg
;
166 kern_return_t gpr_errs
[2]; // Read/Write errors
167 kern_return_t vfp_errs
[2]; // Read/Write errors
168 kern_return_t sve_errs
[2]; // Read/Write errors
169 kern_return_t sme_errs
[2]; // Read/Write errors
170 kern_return_t exc_errs
[2]; // Read/Write errors
171 kern_return_t dbg_errs
[2]; // Read/Write errors
174 for (i
= 0; i
< kNumErrors
; i
++) {
183 void InvalidateRegisterSetState(int set
) { SetError(set
, Read
, -1); }
185 void InvalidateAllRegisterStates() { SetError(e_regSetALL
, Read
, -1); }
187 kern_return_t
GetError(int set
, uint32_t err_idx
) const {
188 if (err_idx
< kNumErrors
) {
190 // When getting all errors, just OR all values together to see if
191 // we got any kind of error.
193 return gpr_errs
[err_idx
] | vfp_errs
[err_idx
] | exc_errs
[err_idx
] |
194 sve_errs
[err_idx
] | sme_errs
[err_idx
] | dbg_errs
[err_idx
];
196 return gpr_errs
[err_idx
];
198 return vfp_errs
[err_idx
];
200 return sve_errs
[err_idx
];
202 return sme_errs
[err_idx
];
204 return exc_errs
[err_idx
];
205 // case e_regSetDBG: return dbg_errs[err_idx];
212 bool SetError(int set
, uint32_t err_idx
, kern_return_t err
) {
213 if (err_idx
< kNumErrors
) {
216 gpr_errs
[err_idx
] = err
;
217 vfp_errs
[err_idx
] = err
;
218 sve_errs
[err_idx
] = err
;
219 sme_errs
[err_idx
] = err
;
220 dbg_errs
[err_idx
] = err
;
221 exc_errs
[err_idx
] = err
;
225 gpr_errs
[err_idx
] = err
;
229 vfp_errs
[err_idx
] = err
;
233 sve_errs
[err_idx
] = err
;
237 sme_errs
[err_idx
] = err
;
241 exc_errs
[err_idx
] = err
;
245 // dbg_errs[err_idx] = err;
253 bool RegsAreValid(int set
) const {
254 return GetError(set
, Read
) == KERN_SUCCESS
;
258 kern_return_t
GetGPRState(bool force
);
259 kern_return_t
GetVFPState(bool force
);
260 kern_return_t
GetSVEState(bool force
);
261 kern_return_t
GetSMEState(bool force
);
262 kern_return_t
GetEXCState(bool force
);
263 kern_return_t
GetDBGState(bool force
);
265 kern_return_t
SetGPRState();
266 kern_return_t
SetVFPState();
267 kern_return_t
SetSVEState();
268 kern_return_t
SetSMEState();
269 kern_return_t
SetEXCState();
270 kern_return_t
SetDBGState(bool also_set_on_task
);
272 // Helper functions for watchpoint implementaions.
274 typedef arm_debug_state64_t DBG
;
276 void ClearWatchpointOccurred();
277 bool HasWatchpointOccurred();
278 bool IsWatchpointEnabled(const DBG
&debug_state
, uint32_t hw_index
);
279 nub_addr_t
GetWatchpointAddressByIndex(uint32_t hw_index
);
280 nub_addr_t
GetWatchAddress(const DBG
&debug_state
, uint32_t hw_index
);
281 virtual bool ReenableHardwareWatchpoint(uint32_t hw_break_index
);
282 virtual bool ReenableHardwareWatchpoint_helper(uint32_t hw_break_index
);
283 uint32_t GetHardwareWatchpointHit(nub_addr_t
&addr
) override
;
285 class disabled_watchpoint
{
287 disabled_watchpoint() {
295 static bool CPUHasSME();
296 static bool CPUHasSME2();
297 static unsigned int GetSMEMaxSVL();
300 static DNBRegisterInfo
*get_vfp_registerinfo(size_t &num_vfp_registers
);
301 static DNBRegisterInfo
*get_sve_registerinfo(size_t &num_sve_registers
);
302 static DNBRegisterInfo
*get_sme_registerinfo(size_t &num_sme_registers
);
303 static void initialize_reg_sets();
305 MachThread
*m_thread
;
307 arm_debug_state64_t m_dbg_save
;
309 // arm64 doesn't keep the disabled watchpoint and breakpoint values in the
310 // debug register context like armv7;
311 // we need to save them aside when we disable them temporarily.
312 std::vector
<disabled_watchpoint
> m_disabled_watchpoints
;
313 std::vector
<disabled_watchpoint
> m_disabled_breakpoints
;
315 // The following member variables should be updated atomically.
316 int32_t m_watchpoint_hw_index
;
317 bool m_watchpoint_did_occur
;
318 bool m_watchpoint_resume_single_step_enabled
;
320 typedef std::map
<uint32_t, Context
> SaveRegisterStates
;
321 SaveRegisterStates m_saved_register_states
;
323 DNBArchMachARM64(const DNBArchMachARM64
&) = delete;
324 DNBArchMachARM64
&operator=(const DNBArchMachARM64
&) = delete;
327 #endif // #if defined (ARM_THREAD_STATE64_COUNT)
328 #endif // #if defined (__arm__)
329 #endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM64_DNBARCHIMPLARM64_H