[RISCV] Add RVVConstraint to SiFive custom matrix multiply instructions. (#124055)
[llvm-project.git] / lldb / source / Plugins / Process / Utility / NativeRegisterContextDBReg.cpp
blob1e0c1a5db09ca440586313ea668422434b914068
1 //===-- NativeRegisterContextDBReg.cpp ------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "NativeRegisterContextDBReg.h"
11 #include "lldb/Utility/LLDBLog.h"
12 #include "lldb/Utility/Log.h"
13 #include "lldb/Utility/RegisterValue.h"
15 using namespace lldb_private;
17 uint32_t NativeRegisterContextDBReg::NumSupportedHardwareBreakpoints() {
18 Log *log = GetLog(LLDBLog::Breakpoints);
20 // Read hardware breakpoint and watchpoint information.
21 llvm::Error error = ReadHardwareDebugInfo();
23 if (error) {
24 LLDB_LOG_ERROR(log, std::move(error),
25 "failed to read debug registers: {0}");
26 return 0;
29 LLDB_LOG(log, "{0}", m_max_hbp_supported);
30 return m_max_hbp_supported;
33 uint32_t NativeRegisterContextDBReg::SetHardwareBreakpoint(lldb::addr_t addr,
34 size_t size) {
35 Log *log = GetLog(LLDBLog::Breakpoints);
36 LLDB_LOG(log, "addr: {0:x}, size: {1:x}", addr, size);
38 // Read hardware breakpoint and watchpoint information.
39 llvm::Error error = ReadHardwareDebugInfo();
40 if (error) {
41 LLDB_LOG_ERROR(
42 log, std::move(error),
43 "unable to set breakpoint: failed to read debug registers: {0}");
44 return LLDB_INVALID_INDEX32;
47 uint32_t control_value = 0, bp_index = 0;
49 if (!ValidateBreakpoint(size, addr))
50 return LLDB_INVALID_INDEX32;
52 control_value = MakeBreakControlValue(size);
54 // Iterate over stored breakpoints and find a free bp_index
55 bp_index = LLDB_INVALID_INDEX32;
56 for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
57 if (!BreakpointIsEnabled(i))
58 bp_index = i; // Mark last free slot
59 else if (m_hbp_regs[i].address == addr)
60 return LLDB_INVALID_INDEX32; // We do not support duplicate breakpoints.
63 if (bp_index == LLDB_INVALID_INDEX32)
64 return LLDB_INVALID_INDEX32;
66 // Update breakpoint in local cache
67 m_hbp_regs[bp_index].real_addr = addr;
68 m_hbp_regs[bp_index].address = addr;
69 m_hbp_regs[bp_index].control = control_value;
71 // PTRACE call to set corresponding hardware breakpoint register.
72 error = WriteHardwareDebugRegs(eDREGTypeBREAK);
74 if (error) {
75 m_hbp_regs[bp_index].address = 0;
76 m_hbp_regs[bp_index].control &= ~m_hw_dbg_enable_bit;
78 LLDB_LOG_ERROR(
79 log, std::move(error),
80 "unable to set breakpoint: failed to write debug registers: {0}");
81 return LLDB_INVALID_INDEX32;
84 return bp_index;
87 bool NativeRegisterContextDBReg::ClearHardwareBreakpoint(uint32_t hw_idx) {
88 Log *log = GetLog(LLDBLog::Breakpoints);
89 LLDB_LOG(log, "hw_idx: {0}", hw_idx);
91 // Read hardware breakpoint and watchpoint information.
92 llvm::Error error = ReadHardwareDebugInfo();
93 if (error) {
94 LLDB_LOG_ERROR(
95 log, std::move(error),
96 "unable to clear breakpoint: failed to read debug registers: {0}");
97 return false;
100 if (hw_idx >= m_max_hbp_supported)
101 return false;
103 // Create a backup we can revert to in case of failure.
104 lldb::addr_t tempAddr = m_hbp_regs[hw_idx].address;
105 uint32_t tempControl = m_hbp_regs[hw_idx].control;
107 m_hbp_regs[hw_idx].control &= ~m_hw_dbg_enable_bit;
108 m_hbp_regs[hw_idx].address = 0;
110 // PTRACE call to clear corresponding hardware breakpoint register.
111 error = WriteHardwareDebugRegs(eDREGTypeBREAK);
113 if (error) {
114 m_hbp_regs[hw_idx].control = tempControl;
115 m_hbp_regs[hw_idx].address = tempAddr;
117 LLDB_LOG_ERROR(
118 log, std::move(error),
119 "unable to clear breakpoint: failed to write debug registers: {0}");
120 return false;
123 return true;
126 Status
127 NativeRegisterContextDBReg::GetHardwareBreakHitIndex(uint32_t &bp_index,
128 lldb::addr_t trap_addr) {
129 Log *log = GetLog(LLDBLog::Breakpoints);
131 LLDB_LOGF(log, "NativeRegisterContextDBReg::%s()", __FUNCTION__);
133 lldb::addr_t break_addr;
135 for (bp_index = 0; bp_index < m_max_hbp_supported; ++bp_index) {
136 break_addr = m_hbp_regs[bp_index].address;
138 if (BreakpointIsEnabled(bp_index) && trap_addr == break_addr) {
139 m_hbp_regs[bp_index].hit_addr = trap_addr;
140 return Status();
144 bp_index = LLDB_INVALID_INDEX32;
145 return Status();
148 Status NativeRegisterContextDBReg::ClearAllHardwareBreakpoints() {
149 Log *log = GetLog(LLDBLog::Breakpoints);
151 LLDB_LOGF(log, "NativeRegisterContextDBReg::%s()", __FUNCTION__);
153 // Read hardware breakpoint and watchpoint information.
154 llvm::Error error = ReadHardwareDebugInfo();
155 if (error)
156 return Status::FromError(std::move(error));
158 for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
159 if (!BreakpointIsEnabled(i))
160 continue;
161 // Create a backup we can revert to in case of failure.
162 lldb::addr_t tempAddr = m_hbp_regs[i].address;
163 uint32_t tempControl = m_hbp_regs[i].control;
165 // Clear watchpoints in local cache
166 m_hbp_regs[i].control &= ~m_hw_dbg_enable_bit;
167 m_hbp_regs[i].address = 0;
169 // Ptrace call to update hardware debug registers
170 error = WriteHardwareDebugRegs(eDREGTypeBREAK);
172 if (error) {
173 m_hbp_regs[i].control = tempControl;
174 m_hbp_regs[i].address = tempAddr;
176 return Status::FromError(std::move(error));
180 return Status();
183 bool NativeRegisterContextDBReg::BreakpointIsEnabled(uint32_t bp_index) {
184 return ((m_hbp_regs[bp_index].control & m_hw_dbg_enable_bit) != 0);
187 uint32_t NativeRegisterContextDBReg::NumSupportedHardwareWatchpoints() {
188 Log *log = GetLog(LLDBLog::Watchpoints);
189 llvm::Error error = ReadHardwareDebugInfo();
190 if (error) {
191 LLDB_LOG_ERROR(log, std::move(error),
192 "failed to read debug registers: {0}");
193 return 0;
196 return m_max_hwp_supported;
199 uint32_t NativeRegisterContextDBReg::SetHardwareWatchpoint(
200 lldb::addr_t addr, size_t size, uint32_t watch_flags) {
201 Log *log = GetLog(LLDBLog::Watchpoints);
202 LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size,
203 watch_flags);
205 // Read hardware breakpoint and watchpoint information.
206 llvm::Error error = ReadHardwareDebugInfo();
207 if (error) {
208 LLDB_LOG_ERROR(
209 log, std::move(error),
210 "unable to set watchpoint: failed to read debug registers: {0}");
211 return LLDB_INVALID_INDEX32;
214 uint32_t control_value = 0, wp_index = 0;
215 lldb::addr_t real_addr = addr;
216 WatchpointDetails details{size, addr};
218 auto adjusted = AdjustWatchpoint(details);
219 if (adjusted == std::nullopt)
220 return LLDB_INVALID_INDEX32;
221 size = adjusted->size;
222 addr = adjusted->addr;
224 // Check if we are setting watchpoint other than read/write/access Also
225 // update watchpoint flag to match AArch64/LoongArch write-read bit
226 // configuration.
227 switch (watch_flags) {
228 case lldb::eWatchpointKindWrite:
229 watch_flags = 2;
230 break;
231 case lldb::eWatchpointKindRead:
232 watch_flags = 1;
233 break;
234 case (lldb::eWatchpointKindRead | lldb::eWatchpointKindWrite):
235 break;
236 default:
237 return LLDB_INVALID_INDEX32;
240 control_value = MakeWatchControlValue(size, watch_flags);
242 // Iterate over stored watchpoints and find a free wp_index
243 wp_index = LLDB_INVALID_INDEX32;
244 for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
245 if (!WatchpointIsEnabled(i))
246 wp_index = i; // Mark last free slot
247 else if (m_hwp_regs[i].address == addr) {
248 return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints.
252 if (wp_index == LLDB_INVALID_INDEX32)
253 return LLDB_INVALID_INDEX32;
255 // Update watchpoint in local cache
256 m_hwp_regs[wp_index].real_addr = real_addr;
257 m_hwp_regs[wp_index].address = addr;
258 m_hwp_regs[wp_index].control = control_value;
260 // PTRACE call to set corresponding watchpoint register.
261 error = WriteHardwareDebugRegs(eDREGTypeWATCH);
263 if (error) {
264 m_hwp_regs[wp_index].address = 0;
265 m_hwp_regs[wp_index].control &= ~m_hw_dbg_enable_bit;
267 LLDB_LOG_ERROR(
268 log, std::move(error),
269 "unable to set watchpoint: failed to write debug registers: {0}");
270 return LLDB_INVALID_INDEX32;
273 return wp_index;
276 bool NativeRegisterContextDBReg::ClearHardwareWatchpoint(uint32_t wp_index) {
277 Log *log = GetLog(LLDBLog::Watchpoints);
278 LLDB_LOG(log, "wp_index: {0}", wp_index);
280 // Read hardware breakpoint and watchpoint information.
281 llvm::Error error = ReadHardwareDebugInfo();
282 if (error) {
283 LLDB_LOG_ERROR(
284 log, std::move(error),
285 "unable to set watchpoint: failed to read debug registers: {0}");
286 return LLDB_INVALID_INDEX32;
289 if (wp_index >= m_max_hwp_supported)
290 return false;
292 // Create a backup we can revert to in case of failure.
293 lldb::addr_t tempAddr = m_hwp_regs[wp_index].address;
294 uint32_t tempControl = m_hwp_regs[wp_index].control;
296 // Update watchpoint in local cache
297 m_hwp_regs[wp_index].control &= ~m_hw_dbg_enable_bit;
298 m_hwp_regs[wp_index].address = 0;
300 // Ptrace call to update hardware debug registers
301 error = WriteHardwareDebugRegs(eDREGTypeWATCH);
303 if (error) {
304 m_hwp_regs[wp_index].control = tempControl;
305 m_hwp_regs[wp_index].address = tempAddr;
307 LLDB_LOG_ERROR(
308 log, std::move(error),
309 "unable to clear watchpoint: failed to read debug registers: {0}");
310 return false;
313 return true;
316 Status NativeRegisterContextDBReg::ClearAllHardwareWatchpoints() {
317 // Read hardware breakpoint and watchpoint information.
318 llvm::Error error = ReadHardwareDebugInfo();
319 if (error)
320 return Status::FromError(std::move(error));
322 for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
323 if (!WatchpointIsEnabled(i))
324 continue;
325 // Create a backup we can revert to in case of failure.
326 lldb::addr_t tempAddr = m_hwp_regs[i].address;
327 uint32_t tempControl = m_hwp_regs[i].control;
329 // Clear watchpoints in local cache
330 m_hwp_regs[i].control = 0;
331 m_hwp_regs[i].address = 0;
333 // Ptrace call to update hardware debug registers
334 error = WriteHardwareDebugRegs(eDREGTypeWATCH);
336 if (error) {
337 m_hwp_regs[i].control = tempControl;
338 m_hwp_regs[i].address = tempAddr;
340 return Status::FromError(std::move(error));
344 return Status();
347 Status
348 NativeRegisterContextDBReg::GetWatchpointHitIndex(uint32_t &wp_index,
349 lldb::addr_t trap_addr) {
350 Log *log = GetLog(LLDBLog::Watchpoints);
351 LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr);
353 // Read hardware breakpoint and watchpoint information.
354 llvm::Error error = ReadHardwareDebugInfo();
355 if (error)
356 return Status::FromError(std::move(error));
358 // AArch64 need mask off ignored bits from watchpoint trap address.
359 trap_addr = FixWatchpointHitAddress(trap_addr);
361 uint32_t watch_size;
362 lldb::addr_t watch_addr;
364 for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) {
365 watch_size = GetWatchpointSize(wp_index);
366 watch_addr = m_hwp_regs[wp_index].address;
368 if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr &&
369 trap_addr < watch_addr + watch_size) {
370 m_hwp_regs[wp_index].hit_addr = trap_addr;
371 return Status();
375 wp_index = LLDB_INVALID_INDEX32;
376 return Status();
379 bool NativeRegisterContextDBReg::WatchpointIsEnabled(uint32_t wp_index) {
380 Log *log = GetLog(LLDBLog::Watchpoints);
381 LLDB_LOG(log, "wp_index: {0}", wp_index);
382 return ((m_hwp_regs[wp_index].control & m_hw_dbg_enable_bit) != 0);
385 lldb::addr_t
386 NativeRegisterContextDBReg::GetWatchpointAddress(uint32_t wp_index) {
387 Log *log = GetLog(LLDBLog::Watchpoints);
388 LLDB_LOG(log, "wp_index: {0}", wp_index);
390 if (wp_index >= m_max_hwp_supported)
391 return LLDB_INVALID_ADDRESS;
393 if (WatchpointIsEnabled(wp_index))
394 return m_hwp_regs[wp_index].real_addr;
395 return LLDB_INVALID_ADDRESS;
398 lldb::addr_t
399 NativeRegisterContextDBReg::GetWatchpointHitAddress(uint32_t wp_index) {
400 Log *log = GetLog(LLDBLog::Watchpoints);
401 LLDB_LOG(log, "wp_index: {0}", wp_index);
403 if (wp_index >= m_max_hwp_supported)
404 return LLDB_INVALID_ADDRESS;
406 if (WatchpointIsEnabled(wp_index))
407 return m_hwp_regs[wp_index].hit_addr;
408 return LLDB_INVALID_ADDRESS;