1use super::{
4 CortexAState,
5 instructions::aarch32::{
6 build_ldc, build_mcr, build_mov, build_mrc, build_mrs, build_msr, build_stc, build_vmov,
7 build_vmrs,
8 },
9 registers::{
10 aarch32::{
11 AARCH32_CORE_REGISTERS, AARCH32_WITH_FP_16_CORE_REGISTERS,
12 AARCH32_WITH_FP_32_CORE_REGISTERS,
13 },
14 cortex_m::{FP, PC, RA, SP, XPSR},
15 },
16};
17use crate::{
18 Architecture, CoreInformation, CoreInterface, CoreRegister, CoreStatus, CoreType, Endian,
19 InstructionSet, MemoryInterface,
20 architecture::arm::{
21 ArmError, DapAccess, FullyQualifiedApAddress,
22 ap::{ApRegister, BD0, BD1, BD2, BD3, TAR, TAR2},
23 core::armv7a_debug_regs::*,
24 memory::ArmMemoryInterface,
25 sequences::ArmDebugSequence,
26 },
27 core::{CoreRegisters, MemoryMappedRegister, RegisterId, RegisterValue},
28 error::Error,
29 memory::{MemoryNotAlignedError, valid_32bit_address},
30};
31use std::{
32 mem::size_of,
33 sync::Arc,
34 time::{Duration, Instant},
35};
36use zerocopy::{FromBytes, IntoBytes};
37
38const OPERATION_TIMEOUT: Duration = Duration::from_millis(250);
40
41struct BankedAccess<'a> {
43 interface: &'a mut dyn DapAccess,
46 ap: FullyQualifiedApAddress,
47 dtrtx: u64,
48 itr: u64,
49 dscr: u64,
50 dtrrx: u64,
51}
52
53impl<'a> BankedAccess<'a> {
54 fn set_dtrtx(&mut self, value: u32) -> Result<(), ArmError> {
55 self.interface
56 .write_raw_ap_register(&self.ap, self.dtrtx, value)
57 }
58
59 fn dscr(&mut self) -> Result<Dbgdscr, ArmError> {
60 self.interface
61 .read_raw_ap_register(&self.ap, self.dscr)
62 .map(Dbgdscr::from)
63 }
64
65 fn set_dscr(&mut self, value: Dbgdscr) -> Result<(), ArmError> {
66 self.interface
67 .write_raw_ap_register(&self.ap, self.dscr, value.into())
68 }
69
70 fn set_itr(&mut self, value: u32) -> Result<(), ArmError> {
71 self.interface
72 .write_raw_ap_register(&self.ap, self.itr, value)
73 }
74
75 fn dtrrx(&mut self) -> Result<u32, ArmError> {
76 self.interface.read_raw_ap_register(&self.ap, self.dtrrx)
77 }
78
79 fn with_dcc_fast_mode<R>(
89 &mut self,
90 f: impl FnOnce(&mut Self) -> Result<R, ArmError>,
91 ) -> Result<R, ArmError> {
92 let mut dscr = self.dscr()?;
94 dscr.set_extdccmode(2);
95 self.set_dscr(dscr)?;
96 let result = f(self);
97
98 let mut dscr = self.dscr()?;
100 dscr.set_extdccmode(0);
101 self.set_dscr(dscr)?;
102
103 result
104 }
105}
106
107#[derive(thiserror::Error, Debug)]
109pub enum Armv7aError {
110 #[error("Register number {0} is not valid for ARMv7-A")]
112 InvalidRegisterNumber(u16),
113
114 #[error("Core is running but operation requires it to be halted")]
116 NotHalted,
117
118 #[error("A data abort occurred")]
120 DataAbort,
121}
122
123pub struct Armv7a<'probe> {
125 memory: Box<dyn ArmMemoryInterface + 'probe>,
126
127 state: &'probe mut CortexAState,
128
129 base_address: u64,
130
131 sequence: Arc<dyn ArmDebugSequence>,
132
133 num_breakpoints: Option<u32>,
134
135 itr_enabled: bool,
136
137 endianness: Option<Endian>,
138}
139
140impl<'probe> Armv7a<'probe> {
141 pub(crate) fn new(
142 mut memory: Box<dyn ArmMemoryInterface + 'probe>,
143 state: &'probe mut CortexAState,
144 base_address: u64,
145 sequence: Arc<dyn ArmDebugSequence>,
146 ) -> Result<Self, Error> {
147 if !state.initialized() {
148 let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
150 let dbgdscr = Dbgdscr(memory.read_word_32(address)?);
151
152 tracing::debug!("State when connecting: {:x?}", dbgdscr);
153
154 let core_state = if dbgdscr.halted() {
155 let reason = dbgdscr.halt_reason();
156
157 tracing::debug!("Core was halted when connecting, reason: {:?}", reason);
158
159 CoreStatus::Halted(reason)
160 } else {
161 CoreStatus::Running
162 };
163
164 state.current_state = core_state;
165 }
166
167 let mut core = Self {
168 memory,
169 state,
170 base_address,
171 sequence,
172 num_breakpoints: None,
173 itr_enabled: false,
174 endianness: None,
175 };
176
177 if !core.state.initialized() {
178 core.reset_register_cache();
179 core.read_fp_reg_count()?;
180 core.state.initialize();
181 }
182
183 Ok(core)
184 }
185
186 fn read_fp_reg_count(&mut self) -> Result<(), Error> {
187 if self.state.fp_reg_count == 0 && matches!(self.state.current_state, CoreStatus::Halted(_))
188 {
189 self.prepare_r0_for_clobber()?;
190
191 let instruction = build_vmrs(0, 0b0111);
193 self.execute_instruction(instruction)?;
194
195 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
197 let vmrs = self.execute_instruction_with_result(instruction)?;
198
199 self.state.fp_reg_count = match vmrs & 0b111 {
200 0b001 => 16,
201 0b010 => 32,
202 _ => 0,
203 };
204 }
205
206 Ok(())
207 }
208
209 fn execute_instruction(&mut self, instruction: u32) -> Result<Dbgdscr, ArmError> {
211 if !self.state.current_state.is_halted() {
212 return Err(ArmError::CoreNotHalted);
213 }
214
215 if !self.itr_enabled {
217 let address = Dbgdscr::get_mmio_address_from_base(self.base_address)?;
218 let mut dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
219 dbgdscr.set_itren(true);
220
221 self.memory.write_word_32(address, dbgdscr.into())?;
222
223 self.itr_enabled = true;
224 }
225
226 execute_instruction(&mut *self.memory, self.base_address, instruction)
227 }
228
229 fn execute_instruction_with_result(&mut self, instruction: u32) -> Result<u32, Error> {
231 let mut dbgdscr = self.execute_instruction(instruction)?;
233
234 let start = Instant::now();
236 while !dbgdscr.txfull_l() {
237 let address = Dbgdscr::get_mmio_address_from_base(self.base_address)?;
238 dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
239 check_and_clear_data_abort(&mut *self.memory, self.base_address, dbgdscr)?;
241 if start.elapsed() >= OPERATION_TIMEOUT {
242 return Err(Error::Timeout);
243 }
244 }
245
246 let address = Dbgdtrtx::get_mmio_address_from_base(self.base_address)?;
248 let result = self.memory.read_word_32(address)?;
249
250 Ok(result)
251 }
252
253 fn execute_instruction_with_input(
254 &mut self,
255 instruction: u32,
256 value: u32,
257 ) -> Result<(), Error> {
258 let address = Dbgdtrrx::get_mmio_address_from_base(self.base_address)?;
260 self.memory.write_word_32(address, value)?;
261
262 let address = Dbgdscr::get_mmio_address_from_base(self.base_address)?;
264 let mut dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
265
266 let start = Instant::now();
267 while !dbgdscr.rxfull_l() {
268 dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
269 check_and_clear_data_abort(&mut *self.memory, self.base_address, dbgdscr)?;
271 if start.elapsed() >= OPERATION_TIMEOUT {
272 return Err(Error::Timeout);
273 }
274 }
275
276 self.execute_instruction(instruction)?;
278
279 Ok(())
280 }
281
282 fn reset_register_cache(&mut self) {
283 self.state.register_cache = vec![None; 51];
284 }
285
286 fn writeback_registers(&mut self) -> Result<(), Error> {
288 let writeback_iter = (17u16..=48).chain(15u16..=16).chain(0u16..=14);
289
290 for i in writeback_iter {
291 if let Some((val, writeback)) = self.state.register_cache[i as usize]
292 && writeback
293 {
294 match i {
295 0..=14 => {
296 let instruction = build_mrc(14, 0, i, 0, 5, 0);
297
298 self.execute_instruction_with_input(instruction, val.try_into()?)?;
299 }
300 15 => {
301 let instruction = build_mrc(14, 0, 0, 0, 5, 0);
303
304 self.execute_instruction_with_input(instruction, val.try_into()?)?;
305
306 let instruction = build_mov(15, 0);
310 self.execute_instruction(instruction)?;
311 }
312 16 => {
313 let instruction = build_msr(0);
315 self.execute_instruction_with_input(instruction, val.try_into()?)?;
316 }
317 17..=48 => {
318 let value: u64 = val.try_into()?;
320 let low_word = value as u32;
321 let high_word = (value >> 32) as u32;
322
323 let instruction = build_mrc(14, 0, 0, 0, 5, 0);
324 self.execute_instruction_with_input(instruction, low_word)?;
325
326 let instruction = build_mrc(14, 0, 1, 0, 5, 0);
327 self.execute_instruction_with_input(instruction, high_word)?;
328
329 let instruction = build_vmov(0, 0, 1, i - 17);
331 self.execute_instruction(instruction)?;
332 }
333 _ => {
334 panic!("Logic missing for writeback of register {i}");
335 }
336 }
337 }
338 }
339
340 self.reset_register_cache();
341
342 Ok(())
343 }
344
345 fn prepare_r0_for_clobber(&mut self) -> Result<(), Error> {
347 self.prepare_for_clobber(0)
348 }
349
350 fn prepare_for_clobber(&mut self, reg: usize) -> Result<(), Error> {
352 if self.state.register_cache[reg].is_none() {
353 let val: u32 = self.read_core_reg(RegisterId(reg as u16))?.try_into()?;
355
356 self.state.register_cache[reg] = Some((val.into(), true));
358 }
359
360 Ok(())
361 }
362
363 fn set_r0(&mut self, value: u32) -> Result<(), Error> {
364 let instruction = build_mrc(14, 0, 0, 0, 5, 0);
365
366 self.execute_instruction_with_input(instruction, value)
367 }
368
369 fn set_core_status(&mut self, new_status: CoreStatus) {
370 super::update_core_status(&mut self.memory, &mut self.state.current_state, new_status);
371 }
372
373 pub(crate) fn halted_access<R>(
374 &mut self,
375 op: impl FnOnce(&mut Self) -> Result<R, Error>,
376 ) -> Result<R, Error> {
377 let was_running = !(self.state.current_state.is_halted() || self.status()?.is_halted());
378
379 if was_running {
380 self.halt(Duration::from_millis(100))?;
381 }
382
383 let result = op(self);
384
385 if was_running {
386 self.run()?
387 }
388
389 result
390 }
391
392 fn banked_access(&mut self) -> Result<BankedAccess<'_>, Error> {
396 let address = Dbgdtrtx::get_mmio_address_from_base(self.base_address)?;
397 let ap = self.memory.fully_qualified_address();
398 let is_64_bit = self.is_64_bit();
399 let interface = self.memory.get_arm_debug_interface()?;
400
401 if is_64_bit {
402 interface.write_raw_ap_register(&ap, TAR2::ADDRESS, (address >> 32) as u32)?;
403 }
404 interface.write_raw_ap_register(&ap, TAR::ADDRESS, address as u32)?;
405
406 Ok(BankedAccess {
407 interface,
408 ap,
409 dtrtx: BD0::ADDRESS,
410 itr: BD1::ADDRESS,
411 dscr: BD2::ADDRESS,
412 dtrrx: BD3::ADDRESS,
413 })
414 }
415}
416
417pub(crate) fn request_halt(
422 memory: &mut dyn ArmMemoryInterface,
423 base_address: u64,
424) -> Result<(), ArmError> {
425 let address = Dbgdrcr::get_mmio_address_from_base(base_address)?;
426 let mut value = Dbgdrcr(0);
427 value.set_hrq(true);
428
429 memory.write_word_32(address, value.into())?;
430 Ok(())
431}
432
433pub(crate) fn run(memory: &mut dyn ArmMemoryInterface, base_address: u64) -> Result<(), ArmError> {
435 let address = Dbgdrcr::get_mmio_address_from_base(base_address)?;
436 let mut value = Dbgdrcr(0);
437 value.set_rrq(true);
438
439 memory.write_word_32(address, value.into())?;
440
441 let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
443
444 let start = Instant::now();
445 loop {
446 let dbgdscr = Dbgdscr(memory.read_word_32(address)?);
447 if dbgdscr.restarted() {
448 return Ok(());
449 }
450 if start.elapsed() > OPERATION_TIMEOUT {
451 return Err(ArmError::Timeout);
452 }
453 }
454}
455
456pub(crate) fn wait_for_core_halted(
459 memory: &mut dyn ArmMemoryInterface,
460 base_address: u64,
461 timeout: Duration,
462) -> Result<(), ArmError> {
463 let start = Instant::now();
465
466 while !core_halted(memory, base_address)? {
467 if start.elapsed() >= timeout {
468 return Err(ArmError::Timeout);
469 }
470 std::thread::sleep(Duration::from_millis(1));
472 }
473
474 Ok(())
475}
476
477fn core_halted(memory: &mut dyn ArmMemoryInterface, base_address: u64) -> Result<bool, ArmError> {
479 let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
480 let dbgdscr = Dbgdscr(memory.read_word_32(address)?);
481
482 Ok(dbgdscr.halted())
483}
484
485pub(crate) fn set_hw_breakpoint(
488 memory: &mut dyn ArmMemoryInterface,
489 base_address: u64,
490 bp_unit_index: usize,
491 addr: u32,
492) -> Result<(), ArmError> {
493 let bp_value_addr = Dbgbvr::get_mmio_address_from_base(base_address)?
494 + (bp_unit_index * size_of::<u32>()) as u64;
495 let bp_control_addr = Dbgbcr::get_mmio_address_from_base(base_address)?
496 + (bp_unit_index * size_of::<u32>()) as u64;
497 let mut bp_control = Dbgbcr(0);
498
499 bp_control.set_bt(0b0000);
501 bp_control.set_hmc(true);
503 bp_control.set_pmc(0b11);
504 bp_control.set_bas(0b1111);
506 bp_control.set_e(true);
508
509 memory.write_word_32(bp_value_addr, addr)?;
510 memory.write_word_32(bp_control_addr, bp_control.into())?;
511
512 Ok(())
513}
514
515pub(crate) fn clear_hw_breakpoint(
517 memory: &mut dyn ArmMemoryInterface,
518 base_address: u64,
519 bp_unit_index: usize,
520) -> Result<(), ArmError> {
521 let bp_value_addr = Dbgbvr::get_mmio_address_from_base(base_address)?
522 + (bp_unit_index * size_of::<u32>()) as u64;
523 let bp_control_addr = Dbgbcr::get_mmio_address_from_base(base_address)?
524 + (bp_unit_index * size_of::<u32>()) as u64;
525
526 memory.write_word_32(bp_value_addr, 0)?;
527 memory.write_word_32(bp_control_addr, 0)?;
528 Ok(())
529}
530
531pub(crate) fn get_hw_breakpoint(
533 memory: &mut dyn ArmMemoryInterface,
534 base_address: u64,
535 bp_unit_index: usize,
536) -> Result<Option<u32>, ArmError> {
537 let bp_value_addr = Dbgbvr::get_mmio_address_from_base(base_address)?
538 + (bp_unit_index * size_of::<u32>()) as u64;
539 let bp_value = memory.read_word_32(bp_value_addr)?;
540
541 let bp_control_addr = Dbgbcr::get_mmio_address_from_base(base_address)?
542 + (bp_unit_index * size_of::<u32>()) as u64;
543 let bp_control = Dbgbcr(memory.read_word_32(bp_control_addr)?);
544
545 Ok(if bp_control.e() { Some(bp_value) } else { None })
546}
547
548fn check_and_clear_data_abort(
549 memory: &mut dyn ArmMemoryInterface,
550 base_address: u64,
551 dbgdscr: Dbgdscr,
552) -> Result<(), ArmError> {
553 if dbgdscr.adabort_l() || dbgdscr.sdabort_l() {
555 let address = Dbgdrcr::get_mmio_address_from_base(base_address)?;
556 let mut dbgdrcr = Dbgdrcr(0);
557 dbgdrcr.set_cse(true);
558
559 memory.write_word_32(address, dbgdrcr.into())?;
560 return Err(ArmError::Armv7a(
561 crate::architecture::arm::armv7a::Armv7aError::DataAbort,
562 ));
563 }
564 Ok(())
565}
566
567fn execute_instruction(
569 memory: &mut dyn ArmMemoryInterface,
570 base_address: u64,
571 instruction: u32,
572) -> Result<Dbgdscr, ArmError> {
573 let address = Dbgitr::get_mmio_address_from_base(base_address)?;
575 memory.write_word_32(address, instruction)?;
576
577 let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
579 let mut dbgdscr = Dbgdscr(memory.read_word_32(address)?);
580
581 let start = Instant::now();
582 while !dbgdscr.instrcoml_l() {
583 dbgdscr = Dbgdscr(memory.read_word_32(address)?);
584 check_and_clear_data_abort(memory, base_address, dbgdscr)?;
586 if start.elapsed() >= OPERATION_TIMEOUT {
587 return Err(ArmError::Timeout);
588 }
589 }
590
591 check_and_clear_data_abort(memory, base_address, dbgdscr)?;
593
594 Ok(dbgdscr)
595}
596
597fn set_instruction_input(
600 memory: &mut dyn ArmMemoryInterface,
601 base_address: u64,
602 value: u32,
603) -> Result<(), ArmError> {
604 let address = Dbgdtrrx::get_mmio_address_from_base(base_address)?;
606 memory.write_word_32(address, value)?;
607
608 let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
610 let mut dbgdscr = Dbgdscr(memory.read_word_32(address)?);
611
612 let start = Instant::now();
613 while !dbgdscr.rxfull_l() {
614 dbgdscr = Dbgdscr(memory.read_word_32(address)?);
615 check_and_clear_data_abort(memory, base_address, dbgdscr)?;
617 if start.elapsed() >= OPERATION_TIMEOUT {
618 return Err(ArmError::Timeout);
619 }
620 }
621
622 Ok(())
623}
624
625fn get_instruction_result(
628 memory: &mut dyn ArmMemoryInterface,
629 base_address: u64,
630) -> Result<u32, ArmError> {
631 let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
633 let start = Instant::now();
634 loop {
635 let dbgdscr = Dbgdscr(memory.read_word_32(address)?);
636 if dbgdscr.txfull_l() {
637 break;
638 }
639 if start.elapsed() > OPERATION_TIMEOUT {
640 return Err(ArmError::Timeout);
641 }
642 }
643
644 let address = Dbgdtrtx::get_mmio_address_from_base(base_address)?;
646 memory.read_word_32(address)
647}
648
649pub(crate) fn write_word_32(
652 memory: &mut dyn ArmMemoryInterface,
653 base_address: u64,
654 address: u32,
655 data: u32,
656) -> Result<(), ArmError> {
657 set_instruction_input(memory, base_address, address)?;
659 execute_instruction(memory, base_address, build_mrc(14, 0, 0, 0, 5, 0))?;
660
661 set_instruction_input(memory, base_address, data)?;
664 execute_instruction(memory, base_address, build_stc(14, 5, 0, 4))?;
665 Ok(())
666}
667
668pub(crate) fn read_word_32(
671 memory: &mut dyn ArmMemoryInterface,
672 base_address: u64,
673 address: u32,
674) -> Result<u32, ArmError> {
675 set_instruction_input(memory, base_address, address)?;
677 execute_instruction(memory, base_address, build_mrc(14, 0, 0, 0, 5, 0))?;
678
679 execute_instruction(memory, base_address, build_ldc(14, 5, 0, 4))?;
682 get_instruction_result(memory, base_address)
683}
684
685impl CoreInterface for Armv7a<'_> {
686 fn wait_for_core_halted(&mut self, timeout: Duration) -> Result<(), Error> {
687 wait_for_core_halted(&mut *self.memory, self.base_address, timeout).map_err(|e| e.into())
688 }
689
690 fn core_halted(&mut self) -> Result<bool, Error> {
691 core_halted(&mut *self.memory, self.base_address).map_err(|e| e.into())
692 }
693
694 fn status(&mut self) -> Result<crate::core::CoreStatus, Error> {
695 let address = Dbgdscr::get_mmio_address_from_base(self.base_address)?;
697 let dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
698
699 if dbgdscr.halted() {
700 let reason = dbgdscr.halt_reason();
701
702 self.set_core_status(CoreStatus::Halted(reason));
703
704 self.read_fp_reg_count()?;
705
706 return Ok(CoreStatus::Halted(reason));
707 }
708 if self.state.current_state.is_halted() {
710 tracing::warn!("Core is running, but we expected it to be halted");
711 }
712
713 self.set_core_status(CoreStatus::Running);
714
715 Ok(CoreStatus::Running)
716 }
717
718 fn halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
719 if !matches!(self.state.current_state, CoreStatus::Halted(_)) {
720 request_halt(&mut *self.memory, self.base_address)?;
721 self.wait_for_core_halted(timeout)?;
722
723 self.reset_register_cache();
725 }
726 let _ = self.status()?;
728
729 let pc_value = self.read_core_reg(self.program_counter().into())?;
731
732 Ok(CoreInformation {
734 pc: pc_value.try_into()?,
735 })
736 }
737
738 fn run(&mut self) -> Result<(), Error> {
739 if matches!(self.state.current_state, CoreStatus::Running) {
740 return Ok(());
741 }
742
743 self.writeback_registers()?;
745
746 run(&mut *self.memory, self.base_address)?;
747
748 self.set_core_status(CoreStatus::Running);
750 let _ = self.status()?;
751
752 Ok(())
753 }
754
755 fn reset(&mut self) -> Result<(), Error> {
756 self.sequence.reset_system(
757 &mut *self.memory,
758 crate::CoreType::Armv7a,
759 Some(self.base_address),
760 )?;
761
762 self.reset_register_cache();
764
765 self.set_core_status(CoreStatus::Running);
767 let _ = self.status()?;
768
769 Ok(())
770 }
771
772 fn reset_and_halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
773 self.sequence.reset_catch_set(
774 &mut *self.memory,
775 crate::CoreType::Armv7a,
776 Some(self.base_address),
777 )?;
778 self.sequence.reset_system(
779 &mut *self.memory,
780 crate::CoreType::Armv7a,
781 Some(self.base_address),
782 )?;
783
784 let address = Dbgdrcr::get_mmio_address_from_base(self.base_address)?;
786 let mut value = Dbgdrcr(0);
787 value.set_hrq(true);
788
789 self.memory.write_word_32(address, value.into())?;
790
791 self.sequence.reset_catch_clear(
793 &mut *self.memory,
794 crate::CoreType::Armv7a,
795 Some(self.base_address),
796 )?;
797
798 self.wait_for_core_halted(timeout)?;
799
800 let _ = self.status()?;
802
803 self.reset_register_cache();
805
806 let pc_value = self.read_core_reg(self.program_counter().into())?;
808
809 Ok(CoreInformation {
811 pc: pc_value.try_into()?,
812 })
813 }
814
815 fn step(&mut self) -> Result<CoreInformation, Error> {
816 let bp_unit_index = (self.available_breakpoint_units()? - 1) as usize;
818 let bp_value_addr = Dbgbvr::get_mmio_address_from_base(self.base_address)?
819 + (bp_unit_index * size_of::<u32>()) as u64;
820 let saved_bp_value = self.memory.read_word_32(bp_value_addr)?;
821
822 let bp_control_addr = Dbgbcr::get_mmio_address_from_base(self.base_address)?
823 + (bp_unit_index * size_of::<u32>()) as u64;
824 let saved_bp_control = self.memory.read_word_32(bp_control_addr)?;
825
826 let current_pc: u32 = self
828 .read_core_reg(self.program_counter().into())?
829 .try_into()?;
830 let mut bp_control = Dbgbcr(0);
831
832 bp_control.set_bt(0b0100);
834 bp_control.set_hmc(true);
836 bp_control.set_pmc(0b11);
837 bp_control.set_bas(0b1111);
839 bp_control.set_e(true);
841
842 self.memory.write_word_32(bp_value_addr, current_pc)?;
843 self.memory
844 .write_word_32(bp_control_addr, bp_control.into())?;
845
846 self.run()?;
848
849 self.wait_for_core_halted(Duration::from_millis(100))?;
851
852 self.memory.write_word_32(bp_value_addr, saved_bp_value)?;
854 self.memory
855 .write_word_32(bp_control_addr, saved_bp_control)?;
856
857 let pc_value = self.read_core_reg(self.program_counter().into())?;
859
860 Ok(CoreInformation {
862 pc: pc_value.try_into()?,
863 })
864 }
865
866 fn read_core_reg(&mut self, address: RegisterId) -> Result<RegisterValue, Error> {
867 let reg_num = address.0;
868
869 if (reg_num as usize) < self.state.register_cache.len()
871 && let Some(cached_result) = self.state.register_cache[reg_num as usize]
872 {
873 return Ok(cached_result.0);
874 }
875
876 let result: Result<RegisterValue, Error> = match reg_num {
878 0..=14 => {
879 let instruction = build_mcr(14, 0, reg_num, 0, 5, 0);
882
883 let val = self.execute_instruction_with_result(instruction)?;
884
885 Ok(val.into())
886 }
887 15 => {
888 self.prepare_r0_for_clobber()?;
890
891 let instruction = build_mov(0, 15);
893 self.execute_instruction(instruction)?;
894
895 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
897 let pra_plus_offset = self.execute_instruction_with_result(instruction)?;
898
899 Ok((pra_plus_offset - 8).into())
901 }
902 16 => {
903 self.prepare_r0_for_clobber()?;
905
906 let instruction = build_mrs(0);
908 self.execute_instruction(instruction)?;
909
910 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
912 let cpsr = self.execute_instruction_with_result(instruction)?;
913
914 Ok(cpsr.into())
915 }
916 17..=48 => {
917 self.prepare_for_clobber(0)?;
919 self.prepare_for_clobber(1)?;
920
921 let fpexc: u32 = self.read_core_reg(50.into())?.try_into()?;
923 if (fpexc & (1 << 30)) == 0 {
924 return Ok(0u32.into());
926 }
927
928 let instruction = build_vmov(1, 0, 1, reg_num - 17);
930 self.execute_instruction(instruction)?;
931
932 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
934 let mut value = self.execute_instruction_with_result(instruction)? as u64;
935
936 let instruction = build_mcr(14, 0, 1, 0, 5, 0);
938 value |= (self.execute_instruction_with_result(instruction)? as u64) << 32;
939
940 Ok(value.into())
941 }
942 49 => {
943 self.prepare_for_clobber(0)?;
945
946 let fpexc: u32 = self.read_core_reg(50.into())?.try_into()?;
948 if (fpexc & (1 << 30)) == 0 {
949 return Ok(0u32.into());
951 }
952
953 let instruction = build_vmrs(0, 1);
955 self.execute_instruction(instruction)?;
956
957 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
959 let value = self.execute_instruction_with_result(instruction)?;
960
961 Ok(value.into())
962 }
963 50 => {
964 self.prepare_for_clobber(0)?;
966
967 let instruction = build_vmrs(0, 0b1000);
969 self.execute_instruction(instruction)?;
970
971 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
972 let value = self.execute_instruction_with_result(instruction)?;
973
974 Ok(value.into())
975 }
976 _ => Err(Error::Arm(
977 Armv7aError::InvalidRegisterNumber(reg_num).into(),
978 )),
979 };
980
981 if let Ok(value) = result {
982 self.state.register_cache[reg_num as usize] = Some((value, false));
983
984 Ok(value)
985 } else {
986 Err(result.err().unwrap())
987 }
988 }
989
990 fn write_core_reg(&mut self, address: RegisterId, value: RegisterValue) -> Result<(), Error> {
991 let reg_num = address.0;
992
993 if (reg_num as usize) >= self.state.register_cache.len() {
994 return Err(Error::Arm(
995 Armv7aError::InvalidRegisterNumber(reg_num).into(),
996 ));
997 }
998 self.state.register_cache[reg_num as usize] = Some((value, true));
999
1000 Ok(())
1001 }
1002
1003 fn available_breakpoint_units(&mut self) -> Result<u32, Error> {
1004 if self.num_breakpoints.is_none() {
1005 let address = Dbgdidr::get_mmio_address_from_base(self.base_address)?;
1006 let dbgdidr = Dbgdidr(self.memory.read_word_32(address)?);
1007
1008 self.num_breakpoints = Some(dbgdidr.brps() + 1);
1009 }
1010 Ok(self.num_breakpoints.unwrap())
1011 }
1012
1013 fn hw_breakpoints(&mut self) -> Result<Vec<Option<u64>>, Error> {
1015 let mut breakpoints = vec![];
1016 let num_hw_breakpoints = self.available_breakpoint_units()? as usize;
1017
1018 for bp_unit_index in 0..num_hw_breakpoints {
1019 let bp_value_addr = Dbgbvr::get_mmio_address_from_base(self.base_address)?
1020 + (bp_unit_index * size_of::<u32>()) as u64;
1021 let bp_value = self.memory.read_word_32(bp_value_addr)?;
1022
1023 let bp_control_addr = Dbgbcr::get_mmio_address_from_base(self.base_address)?
1024 + (bp_unit_index * size_of::<u32>()) as u64;
1025 let bp_control = Dbgbcr(self.memory.read_word_32(bp_control_addr)?);
1026
1027 if bp_control.e() {
1028 breakpoints.push(Some(bp_value as u64));
1029 } else {
1030 breakpoints.push(None);
1031 }
1032 }
1033 Ok(breakpoints)
1034 }
1035
1036 fn enable_breakpoints(&mut self, _state: bool) -> Result<(), Error> {
1037 Ok(())
1039 }
1040
1041 fn set_hw_breakpoint(&mut self, bp_unit_index: usize, addr: u64) -> Result<(), Error> {
1042 let addr = valid_32bit_address(addr)?;
1043 set_hw_breakpoint(&mut *self.memory, self.base_address, bp_unit_index, addr)?;
1044 Ok(())
1045 }
1046
1047 fn clear_hw_breakpoint(&mut self, bp_unit_index: usize) -> Result<(), Error> {
1048 clear_hw_breakpoint(&mut *self.memory, self.base_address, bp_unit_index)?;
1049 Ok(())
1050 }
1051
1052 fn registers(&self) -> &'static CoreRegisters {
1053 match self.state.fp_reg_count {
1054 16 => &AARCH32_WITH_FP_16_CORE_REGISTERS,
1055 32 => &AARCH32_WITH_FP_32_CORE_REGISTERS,
1056 _ => &AARCH32_CORE_REGISTERS,
1057 }
1058 }
1059
1060 fn program_counter(&self) -> &'static CoreRegister {
1061 &PC
1062 }
1063
1064 fn frame_pointer(&self) -> &'static CoreRegister {
1065 &FP
1066 }
1067
1068 fn stack_pointer(&self) -> &'static CoreRegister {
1069 &SP
1070 }
1071
1072 fn return_address(&self) -> &'static CoreRegister {
1073 &RA
1074 }
1075
1076 fn hw_breakpoints_enabled(&self) -> bool {
1077 true
1078 }
1079
1080 fn architecture(&self) -> Architecture {
1081 Architecture::Arm
1082 }
1083
1084 fn core_type(&self) -> CoreType {
1085 CoreType::Armv7a
1086 }
1087
1088 fn instruction_set(&mut self) -> Result<InstructionSet, Error> {
1089 let cpsr: u32 = self.read_core_reg(XPSR.id())?.try_into()?;
1090
1091 match (cpsr >> 5) & 1 {
1093 1 => Ok(InstructionSet::Thumb2),
1094 _ => Ok(InstructionSet::A32),
1095 }
1096 }
1097
1098 fn endianness(&mut self) -> Result<Endian, Error> {
1099 if let Some(endianness) = self.endianness {
1100 return Ok(endianness);
1101 }
1102 self.halted_access(|core| {
1103 let endianness = {
1104 let psr = TryInto::<u32>::try_into(core.read_core_reg(XPSR.id())?).unwrap();
1105 if psr & 1 << 9 == 0 {
1106 Endian::Little
1107 } else {
1108 Endian::Big
1109 }
1110 };
1111 core.endianness = Some(endianness);
1112 Ok(endianness)
1113 })
1114 }
1115
1116 fn fpu_support(&mut self) -> Result<bool, Error> {
1117 Ok(self.state.fp_reg_count != 0)
1118 }
1119
1120 fn floating_point_register_count(&mut self) -> Result<usize, Error> {
1121 Ok(self.state.fp_reg_count)
1122 }
1123
1124 #[tracing::instrument(skip(self))]
1125 fn reset_catch_set(&mut self) -> Result<(), Error> {
1126 self.halted_access(|core| {
1127 core.sequence.reset_catch_set(
1128 &mut *core.memory,
1129 CoreType::Armv7a,
1130 Some(core.base_address),
1131 )?;
1132 Ok(())
1133 })?;
1134 Ok(())
1135 }
1136
1137 #[tracing::instrument(skip(self))]
1138 fn reset_catch_clear(&mut self) -> Result<(), Error> {
1139 self.halted_access(|core| {
1141 core.sequence.reset_catch_clear(
1142 &mut *core.memory,
1143 CoreType::Armv7a,
1144 Some(core.base_address),
1145 )?;
1146 Ok(())
1147 })?;
1148 Ok(())
1149 }
1150
1151 #[tracing::instrument(skip(self))]
1152 fn debug_core_stop(&mut self) -> Result<(), Error> {
1153 if matches!(self.state.current_state, CoreStatus::Halted(_)) {
1154 self.writeback_registers()?;
1157 }
1158
1159 self.sequence
1160 .debug_core_stop(&mut *self.memory, CoreType::Armv7a)?;
1161
1162 Ok(())
1163 }
1164}
1165
1166impl MemoryInterface for Armv7a<'_> {
1167 fn supports_native_64bit_access(&mut self) -> bool {
1168 false
1169 }
1170
1171 fn read_word_64(&mut self, address: u64) -> Result<u64, Error> {
1172 self.halted_access(|core| {
1173 #[repr(align(4))]
1174 struct AlignedBytes([u8; 8]);
1175 let mut bytes = AlignedBytes([0u8; 8]);
1176 core.read(address, &mut bytes.0)?;
1177 let ret = match core.endianness()? {
1178 Endian::Little => u64::from_le_bytes(bytes.0),
1179 Endian::Big => u64::from_be_bytes(bytes.0),
1180 };
1181
1182 Ok(ret)
1183 })
1184 }
1185
1186 fn read_word_32(&mut self, address: u64) -> Result<u32, Error> {
1187 self.halted_access(|core| {
1188 let address = valid_32bit_address(address)?;
1189
1190 let instr = build_ldc(14, 5, 0, 4);
1192
1193 core.prepare_r0_for_clobber()?;
1195
1196 core.set_r0(address)?;
1198
1199 core.execute_instruction_with_result(instr)
1201 })
1202 }
1203
1204 fn read_word_16(&mut self, address: u64) -> Result<u16, Error> {
1205 self.halted_access(|core| {
1206 let mut byte_offset = address % 4;
1208 let word_start = address - byte_offset;
1209
1210 let data = core.read_word_32(word_start)?;
1212
1213 if Endian::Big == core.endianness()? {
1216 if address & 1 != 0 {
1218 return Err(Error::MemoryNotAligned(MemoryNotAlignedError {
1219 address,
1220 alignment: 2,
1221 }));
1222 }
1223 byte_offset = 2 - byte_offset;
1224 }
1225
1226 Ok((data >> (byte_offset * 8)) as u16)
1228 })
1229 }
1230
1231 fn read_word_8(&mut self, address: u64) -> Result<u8, Error> {
1232 self.halted_access(|core| {
1233 let mut byte_offset = address % 4;
1235
1236 let word_start = address - byte_offset;
1237
1238 let data = core.read_word_32(word_start)?;
1240
1241 if Endian::Big == core.endianness()? {
1244 byte_offset = 3 - byte_offset;
1245 }
1246
1247 Ok(data.to_le_bytes()[byte_offset as usize])
1249 })
1250 }
1251
1252 fn read_64(&mut self, address: u64, data: &mut [u64]) -> Result<(), Error> {
1253 self.halted_access(|core| {
1254 for (i, word) in data.iter_mut().enumerate() {
1255 *word = core.read_word_64(address + ((i as u64) * 8))?;
1256 }
1257
1258 Ok(())
1259 })
1260 }
1261
1262 fn read_32(&mut self, address: u64, data: &mut [u32]) -> Result<(), Error> {
1263 self.halted_access(|core| {
1264 let count = data.len();
1265 if count > 2 {
1266 core.prepare_r0_for_clobber()?;
1268 core.set_r0(valid_32bit_address(address)?)?;
1269
1270 let mut banked = core.banked_access()?;
1271
1272 if banked
1275 .with_dcc_fast_mode(|banked| {
1276 banked.set_itr(build_ldc(14, 5, 0, 4))?;
1278
1279 let _ = banked.dtrrx()?;
1281
1282 for word in data[0..count - 1].iter_mut() {
1287 *word = banked.dtrrx()?;
1288 }
1289 Ok(())
1290 })
1291 .is_ok()
1292 {
1293 if let Ok(last) = banked.dtrrx()
1297 && let Some(v) = data.last_mut()
1298 {
1299 *v = last;
1300 }
1301 }
1302
1303 let dscr = banked.dscr()?;
1305 check_and_clear_data_abort(&mut *core.memory, core.base_address, dscr)?;
1306 } else {
1307 for (i, word) in data.iter_mut().enumerate() {
1308 *word = core.read_word_32(address + ((i as u64) * 4))?;
1309 }
1310 }
1311
1312 Ok(())
1313 })
1314 }
1315
1316 fn read_16(&mut self, address: u64, data: &mut [u16]) -> Result<(), Error> {
1317 self.halted_access(|core| {
1318 for (i, word) in data.iter_mut().enumerate() {
1319 *word = core.read_word_16(address + ((i as u64) * 2))?;
1320 }
1321
1322 Ok(())
1323 })
1324 }
1325
1326 fn read_8(&mut self, address: u64, data: &mut [u8]) -> Result<(), Error> {
1327 self.read(address, data)
1328 }
1329
1330 fn read(&mut self, address: u64, data: &mut [u8]) -> Result<(), Error> {
1331 self.halted_access(|core| {
1332 if address.is_multiple_of(4) && data.len().is_multiple_of(4) {
1333 if let Ok((aligned_buffer, _)) =
1335 <[u32]>::mut_from_prefix_with_elems(data, data.len() / 4)
1336 {
1337 core.read_32(address, aligned_buffer)?;
1338 } else {
1339 let mut temporary_buffer = vec![0u32; data.len() / 4];
1340 core.read_32(address, &mut temporary_buffer)?;
1341 data.copy_from_slice(temporary_buffer.as_bytes());
1342 }
1343
1344 if core.endianness()? == Endian::Big {
1346 for word in data.chunks_exact_mut(4) {
1347 word.reverse();
1348 }
1349 }
1350 } else {
1351 let start_address = address & !3;
1352 let end_address = address + (data.len() as u64);
1353 let end_address = end_address + (4 - (end_address & 3));
1354 let start_extra_count = address as usize % 4;
1355 let mut buffer = vec![0u32; (end_address - start_address) as usize / 4];
1356 core.read_32(start_address, &mut buffer)?;
1357 if core.endianness()? == Endian::Big {
1358 for word in buffer.iter_mut() {
1359 *word = word.swap_bytes();
1360 }
1361 }
1362 data.copy_from_slice(
1363 &buffer.as_bytes()[start_extra_count..start_extra_count + data.len()],
1364 );
1365 }
1366 Ok(())
1367 })
1368 }
1369
1370 fn write_word_64(&mut self, address: u64, data: u64) -> Result<(), Error> {
1371 self.halted_access(|core| {
1372 let (data_low, data_high) = match core.endianness()? {
1373 Endian::Little => (data as u32, (data >> 32) as u32),
1374 Endian::Big => ((data >> 32) as u32, data as u32),
1375 };
1376
1377 core.write_32(address, &[data_low, data_high])
1378 })
1379 }
1380
1381 fn write_word_32(&mut self, address: u64, data: u32) -> Result<(), Error> {
1382 self.halted_access(|core| {
1383 let address = valid_32bit_address(address)?;
1384
1385 let instr = build_stc(14, 5, 0, 4);
1387
1388 core.prepare_r0_for_clobber()?;
1390
1391 core.set_r0(address)?;
1393
1394 core.execute_instruction_with_input(instr, data)
1396 })
1397 }
1398
1399 fn write_word_8(&mut self, address: u64, data: u8) -> Result<(), Error> {
1400 self.halted_access(|core| {
1401 let mut byte_offset = address % 4;
1403 let word_start = address - byte_offset;
1404
1405 if Endian::Big == core.endianness()? {
1408 byte_offset = 3 - byte_offset;
1409 }
1410
1411 let current_word = core.read_word_32(word_start)?;
1413 let mut word_bytes = current_word.to_le_bytes();
1414 word_bytes[byte_offset as usize] = data;
1415
1416 core.write_word_32(word_start, u32::from_le_bytes(word_bytes))
1417 })
1418 }
1419
1420 fn write_word_16(&mut self, address: u64, data: u16) -> Result<(), Error> {
1421 self.halted_access(|core| {
1422 let mut byte_offset = address % 4;
1424 let word_start = address - byte_offset;
1425
1426 if Endian::Big == core.endianness()? {
1429 if address & 1 != 0 {
1431 return Err(Error::MemoryNotAligned(MemoryNotAlignedError {
1432 address,
1433 alignment: 2,
1434 }));
1435 }
1436 byte_offset = 2 - byte_offset;
1437 }
1438
1439 let mut word = core.read_word_32(word_start)?;
1441
1442 word &= !(0xFFFFu32 << (byte_offset * 8));
1444 word |= (data as u32) << (byte_offset * 8);
1445
1446 core.write_word_32(word_start, word)
1447 })
1448 }
1449
1450 fn write_64(&mut self, address: u64, data: &[u64]) -> Result<(), Error> {
1451 self.halted_access(|core| {
1452 for (i, word) in data.iter().enumerate() {
1453 core.write_word_64(address + ((i as u64) * 8), *word)?;
1454 }
1455
1456 Ok(())
1457 })
1458 }
1459
1460 fn write_32(&mut self, address: u64, data: &[u32]) -> Result<(), Error> {
1461 self.halted_access(|core| {
1462 if data.len() > 2 {
1463 core.prepare_r0_for_clobber()?;
1465 core.set_r0(valid_32bit_address(address)?)?;
1466
1467 let mut banked = core.banked_access()?;
1468
1469 banked
1470 .with_dcc_fast_mode(|banked| {
1471 banked.set_itr(build_stc(14, 5, 0, 4))?;
1473
1474 for word in data.iter() {
1476 banked.set_dtrtx(*word)?;
1477 }
1478 Ok(())
1479 })
1480 .ok();
1481
1482 let dscr = banked.dscr()?;
1484 check_and_clear_data_abort(&mut *core.memory, core.base_address, dscr)?;
1485 } else {
1486 for (i, word) in data.iter().enumerate() {
1488 core.write_word_32(address + ((i as u64) * 4), *word)?;
1489 }
1490 }
1491
1492 Ok(())
1493 })
1494 }
1495
1496 fn write_16(&mut self, address: u64, data: &[u16]) -> Result<(), Error> {
1497 self.halted_access(|core| {
1498 for (i, word) in data.iter().enumerate() {
1499 core.write_word_16(address + ((i as u64) * 2), *word)?;
1500 }
1501
1502 Ok(())
1503 })
1504 }
1505
1506 fn write_8(&mut self, address: u64, data: &[u8]) -> Result<(), Error> {
1507 self.write(address, data)
1508 }
1509
1510 fn write(&mut self, address: u64, data: &[u8]) -> Result<(), Error> {
1511 self.halted_access(|core| {
1512 let len = data.len();
1513 let start_extra_count = ((4 - (address % 4) as usize) % 4).min(len);
1514 let end_extra_count = (len - start_extra_count) % 4;
1515 assert!(start_extra_count < 4);
1516 assert!(end_extra_count < 4);
1517
1518 if start_extra_count != 0 || end_extra_count != 0 {
1520 for (i, byte) in data.iter().enumerate() {
1521 core.write_word_8(address + (i as u64), *byte)?;
1522 }
1523 return Ok(());
1524 }
1525
1526 let mut buffer = vec![0u32; data.len() / 4];
1529 let endianness = core.endianness()?;
1530 for (bytes, value) in data.chunks_exact(4).zip(buffer.iter_mut()) {
1531 *value = match endianness {
1532 Endian::Little => u32::from_le_bytes(bytes.try_into().unwrap()),
1533 Endian::Big => u32::from_be_bytes(bytes.try_into().unwrap()),
1534 }
1535 }
1536 core.write_32(address, &buffer)?;
1537
1538 Ok(())
1539 })
1540 }
1541
1542 fn supports_8bit_transfers(&self) -> Result<bool, Error> {
1543 Ok(false)
1544 }
1545
1546 fn flush(&mut self) -> Result<(), Error> {
1547 Ok(())
1549 }
1550}
1551
1552#[cfg(test)]
1553mod test {
1554 use crate::{
1555 architecture::arm::{
1556 FullyQualifiedApAddress, communication_interface::SwdSequence,
1557 sequences::DefaultArmSequence,
1558 },
1559 probe::DebugProbeError,
1560 };
1561
1562 use super::*;
1563
1564 const TEST_BASE_ADDRESS: u64 = 0x8000_1000;
1565
1566 fn address_to_reg_num(address: u64) -> u32 {
1567 ((address - TEST_BASE_ADDRESS) / 4) as u32
1568 }
1569
1570 #[derive(Debug)]
1571 pub struct ExpectedMemoryOp {
1572 read: bool,
1573 address: u64,
1574 value: u32,
1575 }
1576
1577 pub struct MockProbe {
1578 expected_ops: Vec<ExpectedMemoryOp>,
1579 }
1580
1581 impl MockProbe {
1582 pub fn new() -> Self {
1583 MockProbe {
1584 expected_ops: vec![],
1585 }
1586 }
1587
1588 pub fn expected_read(&mut self, addr: u64, value: u32) {
1589 self.expected_ops.push(ExpectedMemoryOp {
1590 read: true,
1591 address: addr,
1592 value,
1593 });
1594 }
1595
1596 pub fn expected_write(&mut self, addr: u64, value: u32) {
1597 self.expected_ops.push(ExpectedMemoryOp {
1598 read: false,
1599 address: addr,
1600 value,
1601 });
1602 }
1603 }
1604
1605 impl MemoryInterface<ArmError> for MockProbe {
1606 fn read_8(&mut self, _address: u64, _data: &mut [u8]) -> Result<(), ArmError> {
1607 todo!()
1608 }
1609
1610 fn read_16(&mut self, _address: u64, _data: &mut [u16]) -> Result<(), ArmError> {
1611 todo!()
1612 }
1613
1614 fn read_32(&mut self, address: u64, data: &mut [u32]) -> Result<(), ArmError> {
1615 if self.expected_ops.is_empty() {
1616 panic!(
1617 "Received unexpected read_32 op: register {:#}",
1618 address_to_reg_num(address)
1619 );
1620 }
1621
1622 assert_eq!(data.len(), 1);
1623
1624 let expected_op = self.expected_ops.remove(0);
1625
1626 assert!(
1627 expected_op.read,
1628 "R/W mismatch for register: Expected {:#} Actual: {:#}",
1629 address_to_reg_num(expected_op.address),
1630 address_to_reg_num(address)
1631 );
1632 assert_eq!(
1633 expected_op.address,
1634 address,
1635 "Read from unexpected register: Expected {:#} Actual: {:#}",
1636 address_to_reg_num(expected_op.address),
1637 address_to_reg_num(address)
1638 );
1639
1640 data[0] = expected_op.value;
1641
1642 Ok(())
1643 }
1644
1645 fn read(&mut self, address: u64, data: &mut [u8]) -> Result<(), ArmError> {
1646 self.read_8(address, data)
1647 }
1648
1649 fn write_8(&mut self, _address: u64, _data: &[u8]) -> Result<(), ArmError> {
1650 todo!()
1651 }
1652
1653 fn write_16(&mut self, _address: u64, _data: &[u16]) -> Result<(), ArmError> {
1654 todo!()
1655 }
1656
1657 fn write_32(&mut self, address: u64, data: &[u32]) -> Result<(), ArmError> {
1658 if self.expected_ops.is_empty() {
1659 panic!(
1660 "Received unexpected write_32 op: register {:#}",
1661 address_to_reg_num(address)
1662 );
1663 }
1664
1665 assert_eq!(data.len(), 1);
1666
1667 let expected_op = self.expected_ops.remove(0);
1668
1669 assert!(
1670 !expected_op.read,
1671 "Read/write mismatch on register: {:#}",
1672 address_to_reg_num(address)
1673 );
1674 assert_eq!(
1675 expected_op.address,
1676 address,
1677 "Write to unexpected register: Expected {:#} Actual: {:#}",
1678 address_to_reg_num(expected_op.address),
1679 address_to_reg_num(address)
1680 );
1681
1682 assert_eq!(
1683 expected_op.value, data[0],
1684 "Write value mismatch Expected {:#X} Actual: {:#X}",
1685 expected_op.value, data[0]
1686 );
1687
1688 Ok(())
1689 }
1690
1691 fn write(&mut self, address: u64, data: &[u8]) -> Result<(), ArmError> {
1692 self.write_8(address, data)
1693 }
1694
1695 fn flush(&mut self) -> Result<(), ArmError> {
1696 todo!()
1697 }
1698
1699 fn read_64(&mut self, _address: u64, _data: &mut [u64]) -> Result<(), ArmError> {
1700 todo!()
1701 }
1702
1703 fn write_64(&mut self, _address: u64, _data: &[u64]) -> Result<(), ArmError> {
1704 todo!()
1705 }
1706
1707 fn supports_8bit_transfers(&self) -> Result<bool, ArmError> {
1708 Ok(false)
1709 }
1710
1711 fn supports_native_64bit_access(&mut self) -> bool {
1712 false
1713 }
1714 }
1715
1716 impl ArmMemoryInterface for MockProbe {
1717 fn fully_qualified_address(&self) -> FullyQualifiedApAddress {
1718 todo!()
1719 }
1720
1721 fn get_arm_debug_interface(
1722 &mut self,
1723 ) -> Result<&mut dyn crate::architecture::arm::ArmDebugInterface, DebugProbeError> {
1724 Err(DebugProbeError::NotImplemented {
1725 function_name: "get_arm_debug_interface",
1726 })
1727 }
1728
1729 fn generic_status(&mut self) -> Result<crate::architecture::arm::ap::CSW, ArmError> {
1730 Err(ArmError::Probe(DebugProbeError::NotImplemented {
1731 function_name: "generic_status",
1732 }))
1733 }
1734
1735 fn base_address(&mut self) -> Result<u64, ArmError> {
1736 todo!()
1737 }
1738 }
1739
1740 impl SwdSequence for MockProbe {
1741 fn swj_sequence(&mut self, _bit_len: u8, _bits: u64) -> Result<(), DebugProbeError> {
1742 todo!()
1743 }
1744
1745 fn swj_pins(
1746 &mut self,
1747 _pin_out: u32,
1748 _pin_select: u32,
1749 _pin_wait: u32,
1750 ) -> Result<u32, DebugProbeError> {
1751 todo!()
1752 }
1753 }
1754
1755 fn add_status_expectations(probe: &mut MockProbe, halted: bool) {
1756 let mut dbgdscr = Dbgdscr(0);
1757 dbgdscr.set_halted(halted);
1758 dbgdscr.set_restarted(true);
1759 probe.expected_read(
1760 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1761 dbgdscr.into(),
1762 );
1763 }
1764
1765 fn add_enable_itr_expectations(probe: &mut MockProbe) {
1766 let mut dbgdscr = Dbgdscr(0);
1767 dbgdscr.set_halted(true);
1768 probe.expected_read(
1769 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1770 dbgdscr.into(),
1771 );
1772 dbgdscr.set_itren(true);
1773 probe.expected_write(
1774 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1775 dbgdscr.into(),
1776 );
1777 }
1778
1779 fn add_read_reg_expectations(probe: &mut MockProbe, reg: u16, value: u32) {
1780 probe.expected_write(
1781 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1782 build_mcr(14, 0, reg, 0, 5, 0),
1783 );
1784 let mut dbgdscr = Dbgdscr(0);
1785 dbgdscr.set_instrcoml_l(true);
1786 dbgdscr.set_txfull_l(true);
1787
1788 probe.expected_read(
1789 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1790 dbgdscr.into(),
1791 );
1792 probe.expected_read(
1793 Dbgdtrtx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1794 value,
1795 );
1796 }
1797
1798 fn add_read_pc_expectations(probe: &mut MockProbe, value: u32) {
1799 let mut dbgdscr = Dbgdscr(0);
1800 dbgdscr.set_instrcoml_l(true);
1801 dbgdscr.set_txfull_l(true);
1802
1803 probe.expected_write(
1804 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1805 build_mov(0, 15),
1806 );
1807 probe.expected_read(
1808 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1809 dbgdscr.into(),
1810 );
1811 add_read_reg_expectations(probe, 0, value + 8);
1813 }
1814
1815 fn add_read_fp_count_expectations(probe: &mut MockProbe) {
1816 let mut dbgdscr = Dbgdscr(0);
1817 dbgdscr.set_instrcoml_l(true);
1818 dbgdscr.set_txfull_l(true);
1819
1820 probe.expected_write(
1821 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1822 build_vmrs(0, 0b0111),
1823 );
1824 probe.expected_read(
1825 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1826 dbgdscr.into(),
1827 );
1828 add_read_reg_expectations(probe, 0, 0b010);
1829 }
1830
1831 fn add_read_cpsr_expectations(probe: &mut MockProbe, value: u32) {
1832 let mut dbgdscr = Dbgdscr(0);
1833 dbgdscr.set_instrcoml_l(true);
1834 dbgdscr.set_txfull_l(true);
1835
1836 probe.expected_write(
1837 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1838 build_mrs(0),
1839 );
1840 probe.expected_read(
1841 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1842 dbgdscr.into(),
1843 );
1844 add_read_reg_expectations(probe, 0, value);
1845 }
1846
1847 fn add_idr_expectations(probe: &mut MockProbe, bp_count: u32) {
1848 let mut dbgdidr = Dbgdidr(0);
1849 dbgdidr.set_brps(bp_count - 1);
1850 probe.expected_read(
1851 Dbgdidr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1852 dbgdidr.into(),
1853 );
1854 }
1855
1856 fn add_set_r0_expectation(probe: &mut MockProbe, value: u32) {
1857 let mut dbgdscr = Dbgdscr(0);
1858 dbgdscr.set_instrcoml_l(true);
1859 dbgdscr.set_rxfull_l(true);
1860
1861 probe.expected_write(
1862 Dbgdtrrx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1863 value,
1864 );
1865 probe.expected_read(
1866 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1867 dbgdscr.into(),
1868 );
1869
1870 probe.expected_write(
1871 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1872 build_mrc(14, 0, 0, 0, 5, 0),
1873 );
1874 probe.expected_read(
1875 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1876 dbgdscr.into(),
1877 );
1878 }
1879
1880 fn add_read_memory_expectations(probe: &mut MockProbe, address: u64, value: u32) {
1881 add_set_r0_expectation(probe, address as u32);
1882
1883 let mut dbgdscr = Dbgdscr(0);
1884 dbgdscr.set_instrcoml_l(true);
1885 dbgdscr.set_txfull_l(true);
1886
1887 probe.expected_write(
1888 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1889 build_ldc(14, 5, 0, 4),
1890 );
1891 probe.expected_read(
1892 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1893 dbgdscr.into(),
1894 );
1895 probe.expected_read(
1896 Dbgdtrtx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1897 value,
1898 );
1899 }
1900
1901 impl Drop for MockProbe {
1902 fn drop(&mut self) {
1903 if !self.expected_ops.is_empty() {
1904 panic!("self.expected_ops is not empty: {:?}", self.expected_ops);
1905 }
1906 }
1907 }
1908
1909 #[test]
1910 fn armv7a_new() {
1911 let mut probe = MockProbe::new();
1912
1913 add_status_expectations(&mut probe, true);
1915 add_enable_itr_expectations(&mut probe);
1916 add_read_reg_expectations(&mut probe, 0, 0);
1917 add_read_fp_count_expectations(&mut probe);
1918
1919 let mock_mem = Box::new(probe) as _;
1920
1921 let _ = Armv7a::new(
1922 mock_mem,
1923 &mut CortexAState::new(),
1924 TEST_BASE_ADDRESS,
1925 DefaultArmSequence::create(),
1926 )
1927 .unwrap();
1928 }
1929
1930 #[test]
1931 fn armv7a_core_halted() {
1932 let mut probe = MockProbe::new();
1933 let mut state = CortexAState::new();
1934
1935 add_status_expectations(&mut probe, true);
1937 add_enable_itr_expectations(&mut probe);
1938 add_read_reg_expectations(&mut probe, 0, 0);
1939 add_read_fp_count_expectations(&mut probe);
1940
1941 let mut dbgdscr = Dbgdscr(0);
1942 dbgdscr.set_halted(false);
1943 probe.expected_read(
1944 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1945 dbgdscr.into(),
1946 );
1947
1948 dbgdscr.set_halted(true);
1949 probe.expected_read(
1950 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1951 dbgdscr.into(),
1952 );
1953
1954 let mock_mem = Box::new(probe) as _;
1955
1956 let mut armv7a = Armv7a::new(
1957 mock_mem,
1958 &mut state,
1959 TEST_BASE_ADDRESS,
1960 DefaultArmSequence::create(),
1961 )
1962 .unwrap();
1963
1964 assert!(!armv7a.core_halted().unwrap());
1966 assert!(armv7a.core_halted().unwrap());
1967 }
1968
1969 #[test]
1970 fn armv7a_wait_for_core_halted() {
1971 let mut probe = MockProbe::new();
1972 let mut state = CortexAState::new();
1973
1974 add_status_expectations(&mut probe, true);
1976 add_enable_itr_expectations(&mut probe);
1977 add_read_reg_expectations(&mut probe, 0, 0);
1978 add_read_fp_count_expectations(&mut probe);
1979
1980 let mut dbgdscr = Dbgdscr(0);
1981 dbgdscr.set_halted(false);
1982 probe.expected_read(
1983 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1984 dbgdscr.into(),
1985 );
1986
1987 dbgdscr.set_halted(true);
1988 probe.expected_read(
1989 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1990 dbgdscr.into(),
1991 );
1992
1993 let mock_mem = Box::new(probe) as _;
1994
1995 let mut armv7a = Armv7a::new(
1996 mock_mem,
1997 &mut state,
1998 TEST_BASE_ADDRESS,
1999 DefaultArmSequence::create(),
2000 )
2001 .unwrap();
2002
2003 armv7a
2005 .wait_for_core_halted(Duration::from_millis(100))
2006 .unwrap();
2007 }
2008
2009 #[test]
2010 fn armv7a_status_running() {
2011 let mut probe = MockProbe::new();
2012 let mut state = CortexAState::new();
2013
2014 add_status_expectations(&mut probe, true);
2016 add_enable_itr_expectations(&mut probe);
2017 add_read_reg_expectations(&mut probe, 0, 0);
2018 add_read_fp_count_expectations(&mut probe);
2019
2020 let mut dbgdscr = Dbgdscr(0);
2021 dbgdscr.set_halted(false);
2022 probe.expected_read(
2023 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2024 dbgdscr.into(),
2025 );
2026
2027 let mock_mem = Box::new(probe) as _;
2028
2029 let mut armv7a = Armv7a::new(
2030 mock_mem,
2031 &mut state,
2032 TEST_BASE_ADDRESS,
2033 DefaultArmSequence::create(),
2034 )
2035 .unwrap();
2036
2037 assert_eq!(CoreStatus::Running, armv7a.status().unwrap());
2039 }
2040
2041 #[test]
2042 fn armv7a_status_halted() {
2043 let mut probe = MockProbe::new();
2044 let mut state = CortexAState::new();
2045
2046 add_status_expectations(&mut probe, true);
2048 add_enable_itr_expectations(&mut probe);
2049 add_read_reg_expectations(&mut probe, 0, 0);
2050 add_read_fp_count_expectations(&mut probe);
2051
2052 let mut dbgdscr = Dbgdscr(0);
2053 dbgdscr.set_halted(true);
2054 probe.expected_read(
2055 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2056 dbgdscr.into(),
2057 );
2058
2059 let mock_mem = Box::new(probe) as _;
2060
2061 let mut armv7a = Armv7a::new(
2062 mock_mem,
2063 &mut state,
2064 TEST_BASE_ADDRESS,
2065 DefaultArmSequence::create(),
2066 )
2067 .unwrap();
2068
2069 assert_eq!(
2071 CoreStatus::Halted(crate::HaltReason::Request),
2072 armv7a.status().unwrap()
2073 );
2074 }
2075
2076 #[test]
2077 fn armv7a_read_core_reg_common() {
2078 const REG_VALUE: u32 = 0xABCD;
2079
2080 let mut probe = MockProbe::new();
2081 let mut state = CortexAState::new();
2082
2083 add_status_expectations(&mut probe, true);
2085 add_enable_itr_expectations(&mut probe);
2086 add_read_reg_expectations(&mut probe, 0, 0);
2087 add_read_fp_count_expectations(&mut probe);
2088
2089 add_read_reg_expectations(&mut probe, 2, REG_VALUE);
2091
2092 let mock_mem = Box::new(probe) as _;
2093
2094 let mut armv7a = Armv7a::new(
2095 mock_mem,
2096 &mut state,
2097 TEST_BASE_ADDRESS,
2098 DefaultArmSequence::create(),
2099 )
2100 .unwrap();
2101
2102 assert_eq!(
2104 RegisterValue::from(REG_VALUE),
2105 armv7a.read_core_reg(RegisterId(2)).unwrap()
2106 );
2107
2108 assert_eq!(
2110 RegisterValue::from(REG_VALUE),
2111 armv7a.read_core_reg(RegisterId(2)).unwrap()
2112 );
2113 }
2114
2115 #[test]
2116 fn armv7a_read_core_reg_pc() {
2117 const REG_VALUE: u32 = 0xABCD;
2118
2119 let mut probe = MockProbe::new();
2120 let mut state = CortexAState::new();
2121
2122 add_status_expectations(&mut probe, true);
2124 add_enable_itr_expectations(&mut probe);
2125 add_read_reg_expectations(&mut probe, 0, 0);
2126 add_read_fp_count_expectations(&mut probe);
2127
2128 add_read_pc_expectations(&mut probe, REG_VALUE);
2130
2131 let mock_mem = Box::new(probe) as _;
2132
2133 let mut armv7a = Armv7a::new(
2134 mock_mem,
2135 &mut state,
2136 TEST_BASE_ADDRESS,
2137 DefaultArmSequence::create(),
2138 )
2139 .unwrap();
2140
2141 assert_eq!(
2143 RegisterValue::from(REG_VALUE),
2144 armv7a.read_core_reg(RegisterId(15)).unwrap()
2145 );
2146
2147 assert_eq!(
2149 RegisterValue::from(REG_VALUE),
2150 armv7a.read_core_reg(RegisterId(15)).unwrap()
2151 );
2152 }
2153
2154 #[test]
2155 fn armv7a_read_core_reg_cpsr() {
2156 const REG_VALUE: u32 = 0xABCD;
2157
2158 let mut probe = MockProbe::new();
2159 let mut state = CortexAState::new();
2160
2161 add_status_expectations(&mut probe, true);
2163 add_enable_itr_expectations(&mut probe);
2164 add_read_reg_expectations(&mut probe, 0, 0);
2165 add_read_fp_count_expectations(&mut probe);
2166
2167 add_read_cpsr_expectations(&mut probe, REG_VALUE);
2169
2170 let mock_mem = Box::new(probe) as _;
2171
2172 let mut armv7a = Armv7a::new(
2173 mock_mem,
2174 &mut state,
2175 TEST_BASE_ADDRESS,
2176 DefaultArmSequence::create(),
2177 )
2178 .unwrap();
2179
2180 assert_eq!(
2182 RegisterValue::from(REG_VALUE),
2183 armv7a.read_core_reg(XPSR.id()).unwrap()
2184 );
2185
2186 assert_eq!(
2188 RegisterValue::from(REG_VALUE),
2189 armv7a.read_core_reg(XPSR.id()).unwrap()
2190 );
2191 }
2192
2193 #[test]
2194 fn armv7a_halt() {
2195 const REG_VALUE: u32 = 0xABCD;
2196
2197 let mut probe = MockProbe::new();
2198 let mut state = CortexAState::new();
2199
2200 add_status_expectations(&mut probe, false);
2202
2203 let mut dbgdrcr = Dbgdrcr(0);
2205 dbgdrcr.set_hrq(true);
2206 probe.expected_write(
2207 Dbgdrcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2208 dbgdrcr.into(),
2209 );
2210
2211 add_status_expectations(&mut probe, true);
2213
2214 add_status_expectations(&mut probe, true);
2216 add_enable_itr_expectations(&mut probe);
2217 add_read_reg_expectations(&mut probe, 0, 0);
2218 add_read_fp_count_expectations(&mut probe);
2219
2220 add_read_pc_expectations(&mut probe, REG_VALUE);
2222
2223 let mock_mem = Box::new(probe) as _;
2224
2225 let mut armv7a = Armv7a::new(
2226 mock_mem,
2227 &mut state,
2228 TEST_BASE_ADDRESS,
2229 DefaultArmSequence::create(),
2230 )
2231 .unwrap();
2232
2233 assert_eq!(
2235 REG_VALUE as u64,
2236 armv7a.halt(Duration::from_millis(100)).unwrap().pc
2237 );
2238 }
2239
2240 #[test]
2241 fn armv7a_run() {
2242 let mut probe = MockProbe::new();
2243 let mut state = CortexAState::new();
2244
2245 add_status_expectations(&mut probe, true);
2247 add_enable_itr_expectations(&mut probe);
2248 add_read_reg_expectations(&mut probe, 0, 0);
2249 add_read_fp_count_expectations(&mut probe);
2250
2251 add_set_r0_expectation(&mut probe, 0);
2253
2254 let mut dbgdrcr = Dbgdrcr(0);
2256 dbgdrcr.set_rrq(true);
2257 probe.expected_write(
2258 Dbgdrcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2259 dbgdrcr.into(),
2260 );
2261
2262 add_status_expectations(&mut probe, false);
2264
2265 add_status_expectations(&mut probe, false);
2267
2268 let mock_mem = Box::new(probe) as _;
2269
2270 let mut armv7a = Armv7a::new(
2271 mock_mem,
2272 &mut state,
2273 TEST_BASE_ADDRESS,
2274 DefaultArmSequence::create(),
2275 )
2276 .unwrap();
2277
2278 armv7a.run().unwrap();
2279 }
2280
2281 #[test]
2282 fn armv7a_available_breakpoint_units() {
2283 const BP_COUNT: u32 = 4;
2284 let mut probe = MockProbe::new();
2285 let mut state = CortexAState::new();
2286
2287 add_status_expectations(&mut probe, true);
2289 add_enable_itr_expectations(&mut probe);
2290 add_read_reg_expectations(&mut probe, 0, 0);
2291 add_read_fp_count_expectations(&mut probe);
2292
2293 add_idr_expectations(&mut probe, BP_COUNT);
2295
2296 let mock_mem = Box::new(probe) as _;
2297
2298 let mut armv7a = Armv7a::new(
2299 mock_mem,
2300 &mut state,
2301 TEST_BASE_ADDRESS,
2302 DefaultArmSequence::create(),
2303 )
2304 .unwrap();
2305
2306 assert_eq!(BP_COUNT, armv7a.available_breakpoint_units().unwrap());
2307 }
2308
2309 #[test]
2310 fn armv7a_hw_breakpoints() {
2311 const BP_COUNT: u32 = 4;
2312 const BP1: u64 = 0x2345;
2313 const BP2: u64 = 0x8000_0000;
2314 let mut probe = MockProbe::new();
2315 let mut state = CortexAState::new();
2316
2317 add_status_expectations(&mut probe, true);
2319 add_enable_itr_expectations(&mut probe);
2320 add_read_reg_expectations(&mut probe, 0, 0);
2321 add_read_fp_count_expectations(&mut probe);
2322
2323 add_idr_expectations(&mut probe, BP_COUNT);
2325
2326 probe.expected_read(
2328 Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2329 BP1 as u32,
2330 );
2331 probe.expected_read(
2332 Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2333 1,
2334 );
2335
2336 probe.expected_read(
2337 Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + 4,
2338 BP2 as u32,
2339 );
2340 probe.expected_read(
2341 Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + 4,
2342 1,
2343 );
2344
2345 probe.expected_read(
2346 Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (2 * 4),
2347 0,
2348 );
2349 probe.expected_read(
2350 Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (2 * 4),
2351 0,
2352 );
2353
2354 probe.expected_read(
2355 Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (3 * 4),
2356 0,
2357 );
2358 probe.expected_read(
2359 Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (3 * 4),
2360 0,
2361 );
2362
2363 let mock_mem = Box::new(probe) as _;
2364
2365 let mut armv7a = Armv7a::new(
2366 mock_mem,
2367 &mut state,
2368 TEST_BASE_ADDRESS,
2369 DefaultArmSequence::create(),
2370 )
2371 .unwrap();
2372
2373 let results = armv7a.hw_breakpoints().unwrap();
2374 assert_eq!(Some(BP1), results[0]);
2375 assert_eq!(Some(BP2), results[1]);
2376 assert_eq!(None, results[2]);
2377 assert_eq!(None, results[3]);
2378 }
2379
2380 #[test]
2381 fn armv7a_set_hw_breakpoint() {
2382 const BP_VALUE: u64 = 0x2345;
2383 let mut probe = MockProbe::new();
2384 let mut state = CortexAState::new();
2385
2386 add_status_expectations(&mut probe, true);
2388 add_enable_itr_expectations(&mut probe);
2389 add_read_reg_expectations(&mut probe, 0, 0);
2390 add_read_fp_count_expectations(&mut probe);
2391
2392 let mut dbgbcr = Dbgbcr(0);
2394 dbgbcr.set_hmc(true);
2396 dbgbcr.set_pmc(0b11);
2397 dbgbcr.set_bas(0b1111);
2399 dbgbcr.set_e(true);
2401
2402 probe.expected_write(
2403 Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2404 BP_VALUE as u32,
2405 );
2406 probe.expected_write(
2407 Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2408 dbgbcr.into(),
2409 );
2410
2411 let mock_mem = Box::new(probe) as _;
2412
2413 let mut armv7a = Armv7a::new(
2414 mock_mem,
2415 &mut state,
2416 TEST_BASE_ADDRESS,
2417 DefaultArmSequence::create(),
2418 )
2419 .unwrap();
2420
2421 armv7a.set_hw_breakpoint(0, BP_VALUE).unwrap();
2422 }
2423
2424 #[test]
2425 fn armv7a_clear_hw_breakpoint() {
2426 let mut probe = MockProbe::new();
2427 let mut state = CortexAState::new();
2428
2429 add_status_expectations(&mut probe, true);
2431 add_enable_itr_expectations(&mut probe);
2432 add_read_reg_expectations(&mut probe, 0, 0);
2433 add_read_fp_count_expectations(&mut probe);
2434
2435 probe.expected_write(
2437 Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2438 0,
2439 );
2440 probe.expected_write(
2441 Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2442 0,
2443 );
2444
2445 let mock_mem = Box::new(probe) as _;
2446
2447 let mut armv7a = Armv7a::new(
2448 mock_mem,
2449 &mut state,
2450 TEST_BASE_ADDRESS,
2451 DefaultArmSequence::create(),
2452 )
2453 .unwrap();
2454
2455 armv7a.clear_hw_breakpoint(0).unwrap();
2456 }
2457
2458 #[test]
2459 fn armv7a_read_word_32() {
2460 const MEMORY_VALUE: u32 = 0xBA5EBA11;
2461 const MEMORY_ADDRESS: u64 = 0x12345678;
2462
2463 let mut probe = MockProbe::new();
2464 let mut state = CortexAState::new();
2465
2466 add_status_expectations(&mut probe, true);
2468 add_enable_itr_expectations(&mut probe);
2469 add_read_reg_expectations(&mut probe, 0, 0);
2470 add_read_fp_count_expectations(&mut probe);
2471
2472 add_read_memory_expectations(&mut probe, MEMORY_ADDRESS, MEMORY_VALUE);
2474
2475 let mock_mem = Box::new(probe) as _;
2476
2477 let mut armv7a = Armv7a::new(
2478 mock_mem,
2479 &mut state,
2480 TEST_BASE_ADDRESS,
2481 DefaultArmSequence::create(),
2482 )
2483 .unwrap();
2484
2485 assert_eq!(MEMORY_VALUE, armv7a.read_word_32(MEMORY_ADDRESS).unwrap());
2486 }
2487
2488 fn test_read_word(value: u32, address: u64, memory_word_address: u64, endian: Endian) -> u8 {
2489 let mut probe = MockProbe::new();
2490 let mut state = CortexAState::new();
2491
2492 add_status_expectations(&mut probe, true);
2494 add_enable_itr_expectations(&mut probe);
2495 add_read_reg_expectations(&mut probe, 0, 0);
2496 add_read_fp_count_expectations(&mut probe);
2497
2498 add_read_memory_expectations(&mut probe, memory_word_address, value);
2500
2501 let cpsr = if endian == Endian::Big { 1 << 9 } else { 0 };
2503 add_read_cpsr_expectations(&mut probe, cpsr);
2504
2505 let mock_mem = Box::new(probe) as _;
2506
2507 let mut armv7a = Armv7a::new(
2508 mock_mem,
2509 &mut state,
2510 TEST_BASE_ADDRESS,
2511 DefaultArmSequence::create(),
2512 )
2513 .unwrap();
2514 armv7a.read_word_8(address).unwrap()
2515 }
2516
2517 #[test]
2518 fn armv7a_read_word_8() {
2519 const MEMORY_VALUE: u32 = 0xBA5EBB11;
2520 const MEMORY_ADDRESS: u64 = 0x12345679;
2521 const MEMORY_WORD_ADDRESS: u64 = 0x12345678;
2522
2523 assert_eq!(
2524 0xBB,
2525 test_read_word(
2526 MEMORY_VALUE,
2527 MEMORY_ADDRESS,
2528 MEMORY_WORD_ADDRESS,
2529 Endian::Little
2530 )
2531 );
2532 }
2533
2534 #[test]
2535 fn armv7a_read_word_8_be() {
2536 const MEMORY_VALUE: u32 = 0xBA5EBB11;
2537 const MEMORY_ADDRESS: u64 = 0x12345679;
2538 const MEMORY_WORD_ADDRESS: u64 = 0x12345678;
2539
2540 assert_eq!(
2541 0x5E,
2542 test_read_word(
2543 MEMORY_VALUE,
2544 MEMORY_ADDRESS,
2545 MEMORY_WORD_ADDRESS,
2546 Endian::Big
2547 )
2548 );
2549 }
2550}