1pub fn debugger_connected() -> bool {
5 cfg_if::cfg_if! {
6 if #[cfg(xtensa)] {
7 xtensa_lx::is_debugger_attached()
8 } else if #[cfg(all(riscv, soc_has_assist_debug))] {
9 crate::peripherals::ASSIST_DEBUG::regs()
10 .cpu(0)
11 .debug_mode()
12 .read()
13 .debug_module_active()
14 .bit_is_set()
15 } else {
16 false
17 }
18 }
19}
20
21pub unsafe fn set_stack_watchpoint(addr: usize) {
30 assert!(addr.is_multiple_of(4));
31
32 if cfg!(stack_guard_monitoring_with_debugger_connected)
33 || !crate::debugger::debugger_connected()
34 {
35 cfg_if::cfg_if! {
36 if #[cfg(xtensa)] {
37 let addr = addr & !0b11;
38 let dbreakc = 0b1111100 | (1 << 31); unsafe {
41 core::arch::asm!(
42 "
43 wsr {addr}, 144 // 144 = dbreaka0
44 wsr {dbreakc}, 160 // 160 = dbreakc0
45 ",
46 addr = in(reg) addr,
47 dbreakc = in(reg) dbreakc,
48 );
49 }
50 } else {
51 unsafe { set_watchpoint(0, addr, 4); }
52 }
53 }
54 }
55}
56
57#[cfg(riscv)]
58pub(crate) static DEBUGGER_LOCK: esp_sync::RawMutex = esp_sync::RawMutex::new();
59
60#[cfg(riscv)]
61const NAPOT_MATCH: u8 = 1;
62
63#[cfg(riscv)]
64bitfield::bitfield! {
65 #[derive(Clone, Copy, Default)]
67 pub(crate) struct Tdata1(u32);
68
69 pub bool, load, set_load: 0;
72
73 pub bool, store, set_store: 1;
76
77 pub bool, execute, set_execute: 2;
80
81 pub bool, u, set_u: 3;
83
84 pub bool, m, set_m: 6;
86
87 pub u8, _match, set_match: 10, 7;
95
96 pub u8, action, set_action: 15, 12;
102
103 pub bool, hit, set_hit: 20;
105
106 pub bool, dmode, set_dmode: 27;
111}
112
113#[cfg(riscv)]
114bitfield::bitfield! {
115 #[derive(Clone, Copy, Default)]
117 pub(crate) struct Tcontrol(u32);
118
119 pub bool, mte, set_mte: 3;
121
122 pub bool, mpte, set_mpte: 7;
124
125}
126
127#[cfg(riscv)]
128pub(crate) struct WatchPoint {
129 tdata1: u32,
130 tdata2: u32,
131}
132
133#[cfg(riscv)]
135pub(crate) unsafe fn clear_watchpoint(id: u8) -> WatchPoint {
136 assert!(id < 4);
137
138 let mut tdata1 = 0;
140 let mut tdata2 = 0;
141
142 DEBUGGER_LOCK.lock(|| unsafe {
143 core::arch::asm!(
144 "
145 csrw 0x7a0, {id} // tselect
146 csrrw {tdata1}, 0x7a1, {tdata2} // tdata1
147 csrr {tdata2}, 0x7a2 // tdata2
148 ", id = in(reg) id,
149 tdata1 = inout(reg) tdata1,
150 tdata2 = out(reg) tdata2,
151 );
152 });
153
154 WatchPoint { tdata1, tdata2 }
155}
156
157#[cfg(riscv)]
159pub(crate) unsafe fn restore_watchpoint(id: u8, watchpoint: WatchPoint) {
160 DEBUGGER_LOCK.lock(|| unsafe {
161 core::arch::asm!(
162 "
163 csrw 0x7a0, {id} // tselect
164 csrw 0x7a1, {tdata1} // tdata1
165 csrw 0x7a2, {tdata2} // tdata2
166 ", id = in(reg) id,
167 tdata1 = in(reg) watchpoint.tdata1,
168 tdata2 = in(reg) watchpoint.tdata2,
169 );
170 });
171}
172
173#[cfg(all(riscv, feature = "exception-handler"))]
175pub(crate) unsafe fn watchpoint_hit(id: u8) -> bool {
176 assert!(id < 4);
177 let mut tdata = Tdata1::default();
178
179 DEBUGGER_LOCK.lock(|| unsafe {
180 core::arch::asm!(
181 "
182 csrw 0x7a0, {id} // tselect
183 csrr {tdata}, 0x7a1 // tdata1
184 ", id = in(reg) id,
185 tdata = out(reg) tdata.0,
186 );
187 });
188
189 tdata.hit()
190}
191
192#[cfg(riscv)]
194pub(crate) unsafe fn set_watchpoint(id: u8, addr: usize, len: usize) {
195 assert!(id < 4);
196 assert!(len.is_power_of_two());
197 assert!(addr.is_multiple_of(len));
198
199 let z = len.trailing_zeros();
200 let mask = {
201 let mut mask: usize = 0;
202 for i in 0..z {
203 mask |= 1 << i;
204 }
205 mask
206 };
207
208 let napot_encoding = { mask & !(1 << (z - 1)) };
209 let addr = (addr & !mask) | napot_encoding;
210
211 let mut tdata = Tdata1::default();
212 tdata.set_m(true);
213 tdata.set_store(true);
214 tdata.set_match(NAPOT_MATCH);
215 let tdata: u32 = tdata.0;
216
217 let mut tcontrol = Tcontrol::default();
218 tcontrol.set_mte(true);
219 let tcontrol: u32 = tcontrol.0;
220
221 DEBUGGER_LOCK.lock(|| unsafe {
222 core::arch::asm!(
223 "
224 csrw 0x7a0, {id} // tselect
225 csrw 0x7a5, {tcontrol} // tcontrol
226 csrw 0x7a1, {tdata} // tdata1
227 csrw 0x7a2, {addr} // tdata2
228 ", id = in(reg) id,
229 addr = in(reg) addr,
230 tdata = in(reg) tdata,
231 tcontrol = in(reg) tcontrol,
232 );
233 });
234}