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_mrc(15, 0, 0, 1, 0, 2);
194 self.execute_instruction(instruction)?;
195 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
196 let cpacr = Cpacr(self.execute_instruction_with_result(instruction)?);
197 if cpacr.cp(10) == 0 || cpacr.cp(11) == 0 {
198 return Ok(());
199 }
200
201 let instruction = build_vmrs(0, 0b0111);
203 self.execute_instruction(instruction)?;
204
205 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
207 let vmrs = self.execute_instruction_with_result(instruction)?;
208
209 self.state.fp_reg_count = match vmrs & 0b111 {
210 0b001 => 16,
211 0b010 => 32,
212 _ => 0,
213 };
214 }
215
216 Ok(())
217 }
218
219 fn execute_instruction(&mut self, instruction: u32) -> Result<Dbgdscr, ArmError> {
221 if !self.state.current_state.is_halted() {
222 return Err(ArmError::CoreNotHalted);
223 }
224
225 if !self.itr_enabled {
227 let address = Dbgdscr::get_mmio_address_from_base(self.base_address)?;
228 let mut dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
229 dbgdscr.set_itren(true);
230
231 self.memory.write_word_32(address, dbgdscr.into())?;
232
233 self.itr_enabled = true;
234 }
235
236 execute_instruction(&mut *self.memory, self.base_address, instruction)
237 }
238
239 fn execute_instruction_with_result(&mut self, instruction: u32) -> Result<u32, Error> {
241 let mut dbgdscr = self.execute_instruction(instruction)?;
243
244 let start = Instant::now();
246 while !dbgdscr.txfull_l() {
247 let address = Dbgdscr::get_mmio_address_from_base(self.base_address)?;
248 dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
249 check_and_clear_data_abort(&mut *self.memory, self.base_address, dbgdscr)?;
251 if start.elapsed() >= OPERATION_TIMEOUT {
252 return Err(Error::Timeout);
253 }
254 }
255
256 let address = Dbgdtrtx::get_mmio_address_from_base(self.base_address)?;
258 let result = self.memory.read_word_32(address)?;
259
260 Ok(result)
261 }
262
263 fn execute_instruction_with_input(
264 &mut self,
265 instruction: u32,
266 value: u32,
267 ) -> Result<(), Error> {
268 let address = Dbgdtrrx::get_mmio_address_from_base(self.base_address)?;
270 self.memory.write_word_32(address, value)?;
271
272 let address = Dbgdscr::get_mmio_address_from_base(self.base_address)?;
274 let mut dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
275
276 let start = Instant::now();
277 while !dbgdscr.rxfull_l() {
278 dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
279 check_and_clear_data_abort(&mut *self.memory, self.base_address, dbgdscr)?;
281 if start.elapsed() >= OPERATION_TIMEOUT {
282 return Err(Error::Timeout);
283 }
284 }
285
286 self.execute_instruction(instruction)?;
288
289 Ok(())
290 }
291
292 fn reset_register_cache(&mut self) {
293 self.state.register_cache = vec![None; 51];
294 }
295
296 fn writeback_registers(&mut self) -> Result<(), Error> {
298 let writeback_iter = (17u16..=48).chain(15u16..=16).chain(0u16..=14);
299
300 for i in writeback_iter {
301 if let Some((val, writeback)) = self.state.register_cache[i as usize]
302 && writeback
303 {
304 match i {
305 0..=14 => {
306 let instruction = build_mrc(14, 0, i, 0, 5, 0);
307
308 self.execute_instruction_with_input(instruction, val.try_into()?)?;
309 }
310 15 => {
311 let instruction = build_mrc(14, 0, 0, 0, 5, 0);
313
314 self.execute_instruction_with_input(instruction, val.try_into()?)?;
315
316 let instruction = build_mov(15, 0);
320 self.execute_instruction(instruction)?;
321 }
322 16 => {
323 let instruction = build_msr(0);
325 self.execute_instruction_with_input(instruction, val.try_into()?)?;
326 }
327 17..=48 => {
328 let value: u64 = val.try_into()?;
330 let low_word = value as u32;
331 let high_word = (value >> 32) as u32;
332
333 let instruction = build_mrc(14, 0, 0, 0, 5, 0);
334 self.execute_instruction_with_input(instruction, low_word)?;
335
336 let instruction = build_mrc(14, 0, 1, 0, 5, 0);
337 self.execute_instruction_with_input(instruction, high_word)?;
338
339 let instruction = build_vmov(0, 0, 1, i - 17);
341 self.execute_instruction(instruction)?;
342 }
343 _ => {
344 panic!("Logic missing for writeback of register {i}");
345 }
346 }
347 }
348 }
349
350 self.reset_register_cache();
351
352 Ok(())
353 }
354
355 fn prepare_r0_for_clobber(&mut self) -> Result<(), Error> {
357 self.prepare_for_clobber(0)
358 }
359
360 fn prepare_for_clobber(&mut self, reg: usize) -> Result<(), Error> {
362 if self.state.register_cache[reg].is_none() {
363 let val: u32 = self.read_core_reg(RegisterId(reg as u16))?.try_into()?;
365
366 self.state.register_cache[reg] = Some((val.into(), true));
368 }
369
370 Ok(())
371 }
372
373 fn set_r0(&mut self, value: u32) -> Result<(), Error> {
374 let instruction = build_mrc(14, 0, 0, 0, 5, 0);
375
376 self.execute_instruction_with_input(instruction, value)
377 }
378
379 fn set_core_status(&mut self, new_status: CoreStatus) {
380 super::update_core_status(&mut self.memory, &mut self.state.current_state, new_status);
381 }
382
383 pub(crate) fn halted_access<R>(
384 &mut self,
385 op: impl FnOnce(&mut Self) -> Result<R, Error>,
386 ) -> Result<R, Error> {
387 let was_running = !(self.state.current_state.is_halted() || self.status()?.is_halted());
388
389 if was_running {
390 self.halt(Duration::from_millis(100))?;
391 }
392
393 let result = op(self);
394
395 if was_running {
396 self.run()?
397 }
398
399 result
400 }
401
402 fn banked_access(&mut self) -> Result<BankedAccess<'_>, Error> {
406 let address = Dbgdtrtx::get_mmio_address_from_base(self.base_address)?;
407 let ap = self.memory.fully_qualified_address();
408 let is_64_bit = self.is_64_bit();
409 let interface = self.memory.get_arm_debug_interface()?;
410
411 if is_64_bit {
412 interface.write_raw_ap_register(&ap, TAR2::ADDRESS, (address >> 32) as u32)?;
413 }
414 interface.write_raw_ap_register(&ap, TAR::ADDRESS, address as u32)?;
415
416 Ok(BankedAccess {
417 interface,
418 ap,
419 dtrtx: BD0::ADDRESS,
420 itr: BD1::ADDRESS,
421 dscr: BD2::ADDRESS,
422 dtrrx: BD3::ADDRESS,
423 })
424 }
425}
426
427pub(crate) fn request_halt(
432 memory: &mut dyn ArmMemoryInterface,
433 base_address: u64,
434) -> Result<(), ArmError> {
435 let address = Dbgdrcr::get_mmio_address_from_base(base_address)?;
436 let mut value = Dbgdrcr(0);
437 value.set_hrq(true);
438
439 memory.write_word_32(address, value.into())?;
440 Ok(())
441}
442
443pub(crate) fn run(memory: &mut dyn ArmMemoryInterface, base_address: u64) -> Result<(), ArmError> {
445 let address = Dbgdrcr::get_mmio_address_from_base(base_address)?;
446 let mut value = Dbgdrcr(0);
447 value.set_rrq(true);
448
449 memory.write_word_32(address, value.into())?;
450
451 let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
453
454 let start = Instant::now();
455 loop {
456 let dbgdscr = Dbgdscr(memory.read_word_32(address)?);
457 if dbgdscr.restarted() {
458 return Ok(());
459 }
460 if start.elapsed() > OPERATION_TIMEOUT {
461 return Err(ArmError::Timeout);
462 }
463 }
464}
465
466pub(crate) fn wait_for_core_halted(
469 memory: &mut dyn ArmMemoryInterface,
470 base_address: u64,
471 timeout: Duration,
472) -> Result<(), ArmError> {
473 let start = Instant::now();
475
476 while !core_halted(memory, base_address)? {
477 if start.elapsed() >= timeout {
478 return Err(ArmError::Timeout);
479 }
480 std::thread::sleep(Duration::from_millis(1));
482 }
483
484 Ok(())
485}
486
487fn core_halted(memory: &mut dyn ArmMemoryInterface, base_address: u64) -> Result<bool, ArmError> {
489 let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
490 let dbgdscr = Dbgdscr(memory.read_word_32(address)?);
491
492 Ok(dbgdscr.halted())
493}
494
495pub(crate) fn set_hw_breakpoint(
498 memory: &mut dyn ArmMemoryInterface,
499 base_address: u64,
500 bp_unit_index: usize,
501 addr: u32,
502) -> Result<(), ArmError> {
503 let bp_value_addr = Dbgbvr::get_mmio_address_from_base(base_address)?
504 + (bp_unit_index * size_of::<u32>()) as u64;
505 let bp_control_addr = Dbgbcr::get_mmio_address_from_base(base_address)?
506 + (bp_unit_index * size_of::<u32>()) as u64;
507 let mut bp_control = Dbgbcr(0);
508
509 bp_control.set_bt(0b0000);
511 bp_control.set_hmc(true);
513 bp_control.set_pmc(0b11);
514 bp_control.set_bas(0b1111);
516 bp_control.set_e(true);
518
519 memory.write_word_32(bp_value_addr, addr)?;
520 memory.write_word_32(bp_control_addr, bp_control.into())?;
521
522 Ok(())
523}
524
525pub(crate) fn clear_hw_breakpoint(
527 memory: &mut dyn ArmMemoryInterface,
528 base_address: u64,
529 bp_unit_index: usize,
530) -> Result<(), ArmError> {
531 let bp_value_addr = Dbgbvr::get_mmio_address_from_base(base_address)?
532 + (bp_unit_index * size_of::<u32>()) as u64;
533 let bp_control_addr = Dbgbcr::get_mmio_address_from_base(base_address)?
534 + (bp_unit_index * size_of::<u32>()) as u64;
535
536 memory.write_word_32(bp_value_addr, 0)?;
537 memory.write_word_32(bp_control_addr, 0)?;
538 Ok(())
539}
540
541pub(crate) fn get_hw_breakpoint(
543 memory: &mut dyn ArmMemoryInterface,
544 base_address: u64,
545 bp_unit_index: usize,
546) -> Result<Option<u32>, ArmError> {
547 let bp_value_addr = Dbgbvr::get_mmio_address_from_base(base_address)?
548 + (bp_unit_index * size_of::<u32>()) as u64;
549 let bp_value = memory.read_word_32(bp_value_addr)?;
550
551 let bp_control_addr = Dbgbcr::get_mmio_address_from_base(base_address)?
552 + (bp_unit_index * size_of::<u32>()) as u64;
553 let bp_control = Dbgbcr(memory.read_word_32(bp_control_addr)?);
554
555 Ok(if bp_control.e() { Some(bp_value) } else { None })
556}
557
558fn check_and_clear_data_abort(
559 memory: &mut dyn ArmMemoryInterface,
560 base_address: u64,
561 dbgdscr: Dbgdscr,
562) -> Result<(), ArmError> {
563 if dbgdscr.adabort_l() || dbgdscr.sdabort_l() || dbgdscr.und_l() {
565 let address = Dbgdrcr::get_mmio_address_from_base(base_address)?;
566 let mut dbgdrcr = Dbgdrcr(0);
567 dbgdrcr.set_cse(true);
568
569 memory.write_word_32(address, dbgdrcr.into())?;
570 return Err(ArmError::Armv7a(
571 crate::architecture::arm::armv7a::Armv7aError::DataAbort,
572 ));
573 }
574 Ok(())
575}
576
577fn execute_instruction(
579 memory: &mut dyn ArmMemoryInterface,
580 base_address: u64,
581 instruction: u32,
582) -> Result<Dbgdscr, ArmError> {
583 let address = Dbgitr::get_mmio_address_from_base(base_address)?;
585 memory.write_word_32(address, instruction)?;
586
587 let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
589 let mut dbgdscr = Dbgdscr(memory.read_word_32(address)?);
590
591 let start = Instant::now();
592 while !dbgdscr.instrcoml_l() {
593 dbgdscr = Dbgdscr(memory.read_word_32(address)?);
594 check_and_clear_data_abort(memory, base_address, dbgdscr)?;
596 if start.elapsed() >= OPERATION_TIMEOUT {
597 return Err(ArmError::Timeout);
598 }
599 }
600
601 check_and_clear_data_abort(memory, base_address, dbgdscr)?;
603
604 Ok(dbgdscr)
605}
606
607fn set_instruction_input(
610 memory: &mut dyn ArmMemoryInterface,
611 base_address: u64,
612 value: u32,
613) -> Result<(), ArmError> {
614 let address = Dbgdtrrx::get_mmio_address_from_base(base_address)?;
616 memory.write_word_32(address, value)?;
617
618 let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
620 let mut dbgdscr = Dbgdscr(memory.read_word_32(address)?);
621
622 let start = Instant::now();
623 while !dbgdscr.rxfull_l() {
624 dbgdscr = Dbgdscr(memory.read_word_32(address)?);
625 check_and_clear_data_abort(memory, base_address, dbgdscr)?;
627 if start.elapsed() >= OPERATION_TIMEOUT {
628 return Err(ArmError::Timeout);
629 }
630 }
631
632 Ok(())
633}
634
635fn get_instruction_result(
638 memory: &mut dyn ArmMemoryInterface,
639 base_address: u64,
640) -> Result<u32, ArmError> {
641 let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
643 let start = Instant::now();
644 loop {
645 let dbgdscr = Dbgdscr(memory.read_word_32(address)?);
646 if dbgdscr.txfull_l() {
647 break;
648 }
649 if start.elapsed() > OPERATION_TIMEOUT {
650 return Err(ArmError::Timeout);
651 }
652 }
653
654 let address = Dbgdtrtx::get_mmio_address_from_base(base_address)?;
656 memory.read_word_32(address)
657}
658
659pub(crate) fn write_word_32(
662 memory: &mut dyn ArmMemoryInterface,
663 base_address: u64,
664 address: u32,
665 data: u32,
666) -> Result<(), ArmError> {
667 set_instruction_input(memory, base_address, address)?;
669 execute_instruction(memory, base_address, build_mrc(14, 0, 0, 0, 5, 0))?;
670
671 set_instruction_input(memory, base_address, data)?;
674 execute_instruction(memory, base_address, build_stc(14, 5, 0, 4))?;
675 Ok(())
676}
677
678pub(crate) fn read_word_32(
681 memory: &mut dyn ArmMemoryInterface,
682 base_address: u64,
683 address: u32,
684) -> Result<u32, ArmError> {
685 set_instruction_input(memory, base_address, address)?;
687 execute_instruction(memory, base_address, build_mrc(14, 0, 0, 0, 5, 0))?;
688
689 execute_instruction(memory, base_address, build_ldc(14, 5, 0, 4))?;
692 get_instruction_result(memory, base_address)
693}
694
695impl CoreInterface for Armv7a<'_> {
696 fn wait_for_core_halted(&mut self, timeout: Duration) -> Result<(), Error> {
697 wait_for_core_halted(&mut *self.memory, self.base_address, timeout).map_err(|e| e.into())
698 }
699
700 fn core_halted(&mut self) -> Result<bool, Error> {
701 core_halted(&mut *self.memory, self.base_address).map_err(|e| e.into())
702 }
703
704 fn status(&mut self) -> Result<crate::core::CoreStatus, Error> {
705 let address = Dbgdscr::get_mmio_address_from_base(self.base_address)?;
707 let dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
708
709 if dbgdscr.halted() {
710 let reason = dbgdscr.halt_reason();
711
712 self.set_core_status(CoreStatus::Halted(reason));
713
714 self.read_fp_reg_count()?;
715
716 return Ok(CoreStatus::Halted(reason));
717 }
718 if self.state.current_state.is_halted() {
720 tracing::warn!("Core is running, but we expected it to be halted");
721 }
722
723 self.set_core_status(CoreStatus::Running);
724
725 Ok(CoreStatus::Running)
726 }
727
728 fn halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
729 if !matches!(self.state.current_state, CoreStatus::Halted(_)) {
730 request_halt(&mut *self.memory, self.base_address)?;
731 self.wait_for_core_halted(timeout)?;
732
733 self.reset_register_cache();
735 }
736 let _ = self.status()?;
738
739 let pc_value = self.read_core_reg(self.program_counter().into())?;
741
742 Ok(CoreInformation {
744 pc: pc_value.try_into()?,
745 })
746 }
747
748 fn run(&mut self) -> Result<(), Error> {
749 if matches!(self.state.current_state, CoreStatus::Running) {
750 return Ok(());
751 }
752
753 self.writeback_registers()?;
755
756 if self.itr_enabled {
758 let address = Dbgdscr::get_mmio_address_from_base(self.base_address)?;
759 let mut dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
760 dbgdscr.set_itren(false);
761 self.memory.write_word_32(address, dbgdscr.into())?;
762 self.itr_enabled = false;
763 }
764
765 run(&mut *self.memory, self.base_address)?;
766
767 self.set_core_status(CoreStatus::Running);
769 let _ = self.status()?;
770
771 Ok(())
772 }
773
774 fn reset(&mut self) -> Result<(), Error> {
775 self.sequence.reset_system(
776 &mut *self.memory,
777 crate::CoreType::Armv7a,
778 Some(self.base_address),
779 )?;
780
781 self.reset_register_cache();
783
784 self.set_core_status(CoreStatus::Running);
786 let _ = self.status()?;
787
788 Ok(())
789 }
790
791 fn reset_and_halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
792 self.sequence.reset_catch_set(
793 &mut *self.memory,
794 crate::CoreType::Armv7a,
795 Some(self.base_address),
796 )?;
797 self.sequence.reset_system(
798 &mut *self.memory,
799 crate::CoreType::Armv7a,
800 Some(self.base_address),
801 )?;
802
803 if !self.core_halted()? {
804 tracing::warn!("Core not halted after reset, platform-specific setup may be required");
805 tracing::warn!("Requesting halt anyway, but system may already be initialised");
806 let address = Dbgdrcr::get_mmio_address_from_base(self.base_address)?;
807 let mut value = Dbgdrcr(0);
808 value.set_hrq(true);
809 self.memory.write_word_32(address, value.into())?;
810 }
811
812 self.sequence.reset_catch_clear(
813 &mut *self.memory,
814 crate::CoreType::Armv7a,
815 Some(self.base_address),
816 )?;
817 self.wait_for_core_halted(timeout)?;
818
819 let _ = self.status()?;
821
822 self.reset_register_cache();
824
825 let pc_value = self.read_core_reg(self.program_counter().into())?;
827
828 Ok(CoreInformation {
830 pc: pc_value.try_into()?,
831 })
832 }
833
834 fn step(&mut self) -> Result<CoreInformation, Error> {
835 let bp_unit_index = (self.available_breakpoint_units()? - 1) as usize;
837 let bp_value_addr = Dbgbvr::get_mmio_address_from_base(self.base_address)?
838 + (bp_unit_index * size_of::<u32>()) as u64;
839 let saved_bp_value = self.memory.read_word_32(bp_value_addr)?;
840
841 let bp_control_addr = Dbgbcr::get_mmio_address_from_base(self.base_address)?
842 + (bp_unit_index * size_of::<u32>()) as u64;
843 let saved_bp_control = self.memory.read_word_32(bp_control_addr)?;
844
845 let current_pc: u32 = self
847 .read_core_reg(self.program_counter().into())?
848 .try_into()?;
849 let mut bp_control = Dbgbcr(0);
850
851 bp_control.set_bt(0b0100);
853 bp_control.set_hmc(true);
855 bp_control.set_pmc(0b11);
856 bp_control.set_bas(0b1111);
858 bp_control.set_e(true);
860
861 self.memory.write_word_32(bp_value_addr, current_pc)?;
862 self.memory
863 .write_word_32(bp_control_addr, bp_control.into())?;
864
865 self.run()?;
867
868 self.wait_for_core_halted(Duration::from_millis(100))?;
870
871 self.memory.write_word_32(bp_value_addr, saved_bp_value)?;
873 self.memory
874 .write_word_32(bp_control_addr, saved_bp_control)?;
875
876 let pc_value = self.read_core_reg(self.program_counter().into())?;
878
879 Ok(CoreInformation {
881 pc: pc_value.try_into()?,
882 })
883 }
884
885 fn read_core_reg(&mut self, address: RegisterId) -> Result<RegisterValue, Error> {
886 let reg_num = address.0;
887
888 if (reg_num as usize) < self.state.register_cache.len()
890 && let Some(cached_result) = self.state.register_cache[reg_num as usize]
891 {
892 return Ok(cached_result.0);
893 }
894
895 let result: Result<RegisterValue, Error> = match reg_num {
897 0..=14 => {
898 let instruction = build_mcr(14, 0, reg_num, 0, 5, 0);
901
902 let val = self.execute_instruction_with_result(instruction)?;
903
904 Ok(val.into())
905 }
906 15 => {
907 self.prepare_r0_for_clobber()?;
909
910 let instruction = build_mov(0, 15);
912 self.execute_instruction(instruction)?;
913
914 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
916 let pra_plus_offset = self.execute_instruction_with_result(instruction)?;
917
918 Ok((pra_plus_offset - 8).into())
920 }
921 16 => {
922 self.prepare_r0_for_clobber()?;
924
925 let instruction = build_mrs(0);
927 self.execute_instruction(instruction)?;
928
929 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
931 let cpsr = self.execute_instruction_with_result(instruction)?;
932
933 Ok(cpsr.into())
934 }
935 17..=48 => {
936 self.prepare_for_clobber(0)?;
938 self.prepare_for_clobber(1)?;
939
940 let fpexc: u32 = self.read_core_reg(50.into())?.try_into()?;
942 if (fpexc & (1 << 30)) == 0 {
943 return Ok(0u32.into());
945 }
946
947 let instruction = build_vmov(1, 0, 1, reg_num - 17);
949 self.execute_instruction(instruction)?;
950
951 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
953 let mut value = self.execute_instruction_with_result(instruction)? as u64;
954
955 let instruction = build_mcr(14, 0, 1, 0, 5, 0);
957 value |= (self.execute_instruction_with_result(instruction)? as u64) << 32;
958
959 Ok(value.into())
960 }
961 49 => {
962 self.prepare_for_clobber(0)?;
964
965 let fpexc: u32 = self.read_core_reg(50.into())?.try_into()?;
967 if (fpexc & (1 << 30)) == 0 {
968 return Ok(0u32.into());
970 }
971
972 let instruction = build_vmrs(0, 1);
974 self.execute_instruction(instruction)?;
975
976 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
978 let value = self.execute_instruction_with_result(instruction)?;
979
980 Ok(value.into())
981 }
982 50 => {
983 self.prepare_for_clobber(0)?;
985
986 let instruction = build_vmrs(0, 0b1000);
988 self.execute_instruction(instruction)?;
989
990 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
991 let value = self.execute_instruction_with_result(instruction)?;
992
993 Ok(value.into())
994 }
995 _ => Err(Error::Arm(
996 Armv7aError::InvalidRegisterNumber(reg_num).into(),
997 )),
998 };
999
1000 if let Ok(value) = result {
1001 self.state.register_cache[reg_num as usize] = Some((value, false));
1002
1003 Ok(value)
1004 } else {
1005 Err(result.err().unwrap())
1006 }
1007 }
1008
1009 fn write_core_reg(&mut self, address: RegisterId, value: RegisterValue) -> Result<(), Error> {
1010 let reg_num = address.0;
1011
1012 if (reg_num as usize) >= self.state.register_cache.len() {
1013 return Err(Error::Arm(
1014 Armv7aError::InvalidRegisterNumber(reg_num).into(),
1015 ));
1016 }
1017 self.state.register_cache[reg_num as usize] = Some((value, true));
1018
1019 Ok(())
1020 }
1021
1022 fn available_breakpoint_units(&mut self) -> Result<u32, Error> {
1023 if self.num_breakpoints.is_none() {
1024 let address = Dbgdidr::get_mmio_address_from_base(self.base_address)?;
1025 let dbgdidr = Dbgdidr(self.memory.read_word_32(address)?);
1026
1027 self.num_breakpoints = Some(dbgdidr.brps() + 1);
1028 }
1029 Ok(self.num_breakpoints.unwrap())
1030 }
1031
1032 fn hw_breakpoints(&mut self) -> Result<Vec<Option<u64>>, Error> {
1034 let mut breakpoints = vec![];
1035 let num_hw_breakpoints = self.available_breakpoint_units()? as usize;
1036
1037 for bp_unit_index in 0..num_hw_breakpoints {
1038 let bp_value_addr = Dbgbvr::get_mmio_address_from_base(self.base_address)?
1039 + (bp_unit_index * size_of::<u32>()) as u64;
1040 let bp_value = self.memory.read_word_32(bp_value_addr)?;
1041
1042 let bp_control_addr = Dbgbcr::get_mmio_address_from_base(self.base_address)?
1043 + (bp_unit_index * size_of::<u32>()) as u64;
1044 let bp_control = Dbgbcr(self.memory.read_word_32(bp_control_addr)?);
1045
1046 if bp_control.e() {
1047 breakpoints.push(Some(bp_value as u64));
1048 } else {
1049 breakpoints.push(None);
1050 }
1051 }
1052 Ok(breakpoints)
1053 }
1054
1055 fn enable_breakpoints(&mut self, _state: bool) -> Result<(), Error> {
1056 Ok(())
1058 }
1059
1060 fn set_hw_breakpoint(&mut self, bp_unit_index: usize, addr: u64) -> Result<(), Error> {
1061 let addr = valid_32bit_address(addr)?;
1062 set_hw_breakpoint(&mut *self.memory, self.base_address, bp_unit_index, addr)?;
1063 Ok(())
1064 }
1065
1066 fn clear_hw_breakpoint(&mut self, bp_unit_index: usize) -> Result<(), Error> {
1067 clear_hw_breakpoint(&mut *self.memory, self.base_address, bp_unit_index)?;
1068 Ok(())
1069 }
1070
1071 fn registers(&self) -> &'static CoreRegisters {
1072 match self.state.fp_reg_count {
1073 16 => &AARCH32_WITH_FP_16_CORE_REGISTERS,
1074 32 => &AARCH32_WITH_FP_32_CORE_REGISTERS,
1075 _ => &AARCH32_CORE_REGISTERS,
1076 }
1077 }
1078
1079 fn program_counter(&self) -> &'static CoreRegister {
1080 &PC
1081 }
1082
1083 fn frame_pointer(&self) -> &'static CoreRegister {
1084 &FP
1085 }
1086
1087 fn stack_pointer(&self) -> &'static CoreRegister {
1088 &SP
1089 }
1090
1091 fn return_address(&self) -> &'static CoreRegister {
1092 &RA
1093 }
1094
1095 fn hw_breakpoints_enabled(&self) -> bool {
1096 true
1097 }
1098
1099 fn architecture(&self) -> Architecture {
1100 Architecture::Arm
1101 }
1102
1103 fn core_type(&self) -> CoreType {
1104 CoreType::Armv7a
1105 }
1106
1107 fn instruction_set(&mut self) -> Result<InstructionSet, Error> {
1108 let cpsr: u32 = self.read_core_reg(XPSR.id())?.try_into()?;
1109
1110 match (cpsr >> 5) & 1 {
1112 1 => Ok(InstructionSet::Thumb2),
1113 _ => Ok(InstructionSet::A32),
1114 }
1115 }
1116
1117 fn endianness(&mut self) -> Result<Endian, Error> {
1118 if let Some(endianness) = self.endianness {
1119 return Ok(endianness);
1120 }
1121 self.halted_access(|core| {
1122 let endianness = {
1123 let psr = TryInto::<u32>::try_into(core.read_core_reg(XPSR.id())?).unwrap();
1124 if psr & 1 << 9 == 0 {
1125 Endian::Little
1126 } else {
1127 Endian::Big
1128 }
1129 };
1130 core.endianness = Some(endianness);
1131 Ok(endianness)
1132 })
1133 }
1134
1135 fn fpu_support(&mut self) -> Result<bool, Error> {
1136 Ok(self.state.fp_reg_count != 0)
1137 }
1138
1139 fn floating_point_register_count(&mut self) -> Result<usize, Error> {
1140 Ok(self.state.fp_reg_count)
1141 }
1142
1143 #[tracing::instrument(skip(self))]
1144 fn reset_catch_set(&mut self) -> Result<(), Error> {
1145 self.halted_access(|core| {
1146 core.sequence.reset_catch_set(
1147 &mut *core.memory,
1148 CoreType::Armv7a,
1149 Some(core.base_address),
1150 )?;
1151 Ok(())
1152 })?;
1153 Ok(())
1154 }
1155
1156 #[tracing::instrument(skip(self))]
1157 fn reset_catch_clear(&mut self) -> Result<(), Error> {
1158 self.halted_access(|core| {
1160 core.sequence.reset_catch_clear(
1161 &mut *core.memory,
1162 CoreType::Armv7a,
1163 Some(core.base_address),
1164 )?;
1165 Ok(())
1166 })?;
1167 Ok(())
1168 }
1169
1170 #[tracing::instrument(skip(self))]
1171 fn debug_core_stop(&mut self) -> Result<(), Error> {
1172 if matches!(self.state.current_state, CoreStatus::Halted(_)) {
1173 self.writeback_registers()?;
1176 }
1177
1178 self.sequence
1179 .debug_core_stop(&mut *self.memory, CoreType::Armv7a)?;
1180
1181 Ok(())
1182 }
1183}
1184
1185impl MemoryInterface for Armv7a<'_> {
1186 fn supports_native_64bit_access(&mut self) -> bool {
1187 false
1188 }
1189
1190 fn read_word_64(&mut self, address: u64) -> Result<u64, Error> {
1191 self.halted_access(|core| {
1192 #[repr(align(4))]
1193 struct AlignedBytes([u8; 8]);
1194 let mut bytes = AlignedBytes([0u8; 8]);
1195 core.read(address, &mut bytes.0)?;
1196 let ret = match core.endianness()? {
1197 Endian::Little => u64::from_le_bytes(bytes.0),
1198 Endian::Big => u64::from_be_bytes(bytes.0),
1199 };
1200
1201 Ok(ret)
1202 })
1203 }
1204
1205 fn read_word_32(&mut self, address: u64) -> Result<u32, Error> {
1206 self.halted_access(|core| {
1207 let address = valid_32bit_address(address)?;
1208
1209 let instr = build_ldc(14, 5, 0, 4);
1211
1212 core.prepare_r0_for_clobber()?;
1214
1215 core.set_r0(address)?;
1217
1218 core.execute_instruction_with_result(instr)
1220 })
1221 }
1222
1223 fn read_word_16(&mut self, address: u64) -> Result<u16, Error> {
1224 self.halted_access(|core| {
1225 let mut byte_offset = address % 4;
1227 let word_start = address - byte_offset;
1228
1229 let data = core.read_word_32(word_start)?;
1231
1232 if Endian::Big == core.endianness()? {
1235 if address & 1 != 0 {
1237 return Err(Error::MemoryNotAligned(MemoryNotAlignedError {
1238 address,
1239 alignment: 2,
1240 }));
1241 }
1242 byte_offset = 2 - byte_offset;
1243 }
1244
1245 Ok((data >> (byte_offset * 8)) as u16)
1247 })
1248 }
1249
1250 fn read_word_8(&mut self, address: u64) -> Result<u8, Error> {
1251 self.halted_access(|core| {
1252 let mut byte_offset = address % 4;
1254
1255 let word_start = address - byte_offset;
1256
1257 let data = core.read_word_32(word_start)?;
1259
1260 if Endian::Big == core.endianness()? {
1263 byte_offset = 3 - byte_offset;
1264 }
1265
1266 Ok(data.to_le_bytes()[byte_offset as usize])
1268 })
1269 }
1270
1271 fn read_64(&mut self, address: u64, data: &mut [u64]) -> Result<(), Error> {
1272 self.halted_access(|core| {
1273 for (i, word) in data.iter_mut().enumerate() {
1274 *word = core.read_word_64(address + ((i as u64) * 8))?;
1275 }
1276
1277 Ok(())
1278 })
1279 }
1280
1281 fn read_32(&mut self, address: u64, data: &mut [u32]) -> Result<(), Error> {
1282 self.halted_access(|core| {
1283 let count = data.len();
1284 if count > 2 {
1285 core.prepare_r0_for_clobber()?;
1287 core.set_r0(valid_32bit_address(address)?)?;
1288
1289 let mut banked = core.banked_access()?;
1290
1291 if banked
1294 .with_dcc_fast_mode(|banked| {
1295 banked.set_itr(build_ldc(14, 5, 0, 4))?;
1297
1298 let _ = banked.dtrrx()?;
1300
1301 for word in data[0..count - 1].iter_mut() {
1306 *word = banked.dtrrx()?;
1307 }
1308 Ok(())
1309 })
1310 .is_ok()
1311 {
1312 if let Ok(last) = banked.dtrrx()
1316 && let Some(v) = data.last_mut()
1317 {
1318 *v = last;
1319 }
1320 }
1321
1322 let dscr = banked.dscr()?;
1324 check_and_clear_data_abort(&mut *core.memory, core.base_address, dscr)?;
1325 } else {
1326 for (i, word) in data.iter_mut().enumerate() {
1327 *word = core.read_word_32(address + ((i as u64) * 4))?;
1328 }
1329 }
1330
1331 Ok(())
1332 })
1333 }
1334
1335 fn read_16(&mut self, address: u64, data: &mut [u16]) -> Result<(), Error> {
1336 self.halted_access(|core| {
1337 for (i, word) in data.iter_mut().enumerate() {
1338 *word = core.read_word_16(address + ((i as u64) * 2))?;
1339 }
1340
1341 Ok(())
1342 })
1343 }
1344
1345 fn read_8(&mut self, address: u64, data: &mut [u8]) -> Result<(), Error> {
1346 self.read(address, data)
1347 }
1348
1349 fn read(&mut self, address: u64, data: &mut [u8]) -> Result<(), Error> {
1350 self.halted_access(|core| {
1351 if address.is_multiple_of(4) && data.len().is_multiple_of(4) {
1352 if let Ok((aligned_buffer, _)) =
1354 <[u32]>::mut_from_prefix_with_elems(data, data.len() / 4)
1355 {
1356 core.read_32(address, aligned_buffer)?;
1357 } else {
1358 let mut temporary_buffer = vec![0u32; data.len() / 4];
1359 core.read_32(address, &mut temporary_buffer)?;
1360 data.copy_from_slice(temporary_buffer.as_bytes());
1361 }
1362
1363 if core.endianness()? == Endian::Big {
1365 for word in data.chunks_exact_mut(4) {
1366 word.reverse();
1367 }
1368 }
1369 } else {
1370 let start_address = address & !3;
1371 let end_address = address + (data.len() as u64);
1372 let end_address = end_address + (4 - (end_address & 3));
1373 let start_extra_count = address as usize % 4;
1374 let mut buffer = vec![0u32; (end_address - start_address) as usize / 4];
1375 core.read_32(start_address, &mut buffer)?;
1376 if core.endianness()? == Endian::Big {
1377 for word in buffer.iter_mut() {
1378 *word = word.swap_bytes();
1379 }
1380 }
1381 data.copy_from_slice(
1382 &buffer.as_bytes()[start_extra_count..start_extra_count + data.len()],
1383 );
1384 }
1385 Ok(())
1386 })
1387 }
1388
1389 fn write_word_64(&mut self, address: u64, data: u64) -> Result<(), Error> {
1390 self.halted_access(|core| {
1391 let (data_low, data_high) = match core.endianness()? {
1392 Endian::Little => (data as u32, (data >> 32) as u32),
1393 Endian::Big => ((data >> 32) as u32, data as u32),
1394 };
1395
1396 core.write_32(address, &[data_low, data_high])
1397 })
1398 }
1399
1400 fn write_word_32(&mut self, address: u64, data: u32) -> Result<(), Error> {
1401 self.halted_access(|core| {
1402 let address = valid_32bit_address(address)?;
1403
1404 let instr = build_stc(14, 5, 0, 4);
1406
1407 core.prepare_r0_for_clobber()?;
1409
1410 core.set_r0(address)?;
1412
1413 core.execute_instruction_with_input(instr, data)
1415 })
1416 }
1417
1418 fn write_word_8(&mut self, address: u64, data: u8) -> Result<(), Error> {
1419 self.halted_access(|core| {
1420 let mut byte_offset = address % 4;
1422 let word_start = address - byte_offset;
1423
1424 if Endian::Big == core.endianness()? {
1427 byte_offset = 3 - byte_offset;
1428 }
1429
1430 let current_word = core.read_word_32(word_start)?;
1432 let mut word_bytes = current_word.to_le_bytes();
1433 word_bytes[byte_offset as usize] = data;
1434
1435 core.write_word_32(word_start, u32::from_le_bytes(word_bytes))
1436 })
1437 }
1438
1439 fn write_word_16(&mut self, address: u64, data: u16) -> Result<(), Error> {
1440 self.halted_access(|core| {
1441 let mut byte_offset = address % 4;
1443 let word_start = address - byte_offset;
1444
1445 if Endian::Big == core.endianness()? {
1448 if address & 1 != 0 {
1450 return Err(Error::MemoryNotAligned(MemoryNotAlignedError {
1451 address,
1452 alignment: 2,
1453 }));
1454 }
1455 byte_offset = 2 - byte_offset;
1456 }
1457
1458 let mut word = core.read_word_32(word_start)?;
1460
1461 word &= !(0xFFFFu32 << (byte_offset * 8));
1463 word |= (data as u32) << (byte_offset * 8);
1464
1465 core.write_word_32(word_start, word)
1466 })
1467 }
1468
1469 fn write_64(&mut self, address: u64, data: &[u64]) -> Result<(), Error> {
1470 self.halted_access(|core| {
1471 for (i, word) in data.iter().enumerate() {
1472 core.write_word_64(address + ((i as u64) * 8), *word)?;
1473 }
1474
1475 Ok(())
1476 })
1477 }
1478
1479 fn write_32(&mut self, address: u64, data: &[u32]) -> Result<(), Error> {
1480 self.halted_access(|core| {
1481 if data.len() > 2 {
1482 core.prepare_r0_for_clobber()?;
1484 core.set_r0(valid_32bit_address(address)?)?;
1485
1486 let mut banked = core.banked_access()?;
1487
1488 banked
1489 .with_dcc_fast_mode(|banked| {
1490 banked.set_itr(build_stc(14, 5, 0, 4))?;
1492
1493 for word in data.iter() {
1495 banked.set_dtrtx(*word)?;
1496 }
1497 Ok(())
1498 })
1499 .ok();
1500
1501 let dscr = banked.dscr()?;
1503 check_and_clear_data_abort(&mut *core.memory, core.base_address, dscr)?;
1504 } else {
1505 for (i, word) in data.iter().enumerate() {
1507 core.write_word_32(address + ((i as u64) * 4), *word)?;
1508 }
1509 }
1510
1511 Ok(())
1512 })
1513 }
1514
1515 fn write_16(&mut self, address: u64, data: &[u16]) -> Result<(), Error> {
1516 self.halted_access(|core| {
1517 for (i, word) in data.iter().enumerate() {
1518 core.write_word_16(address + ((i as u64) * 2), *word)?;
1519 }
1520
1521 Ok(())
1522 })
1523 }
1524
1525 fn write_8(&mut self, address: u64, data: &[u8]) -> Result<(), Error> {
1526 self.write(address, data)
1527 }
1528
1529 fn write(&mut self, address: u64, data: &[u8]) -> Result<(), Error> {
1530 self.halted_access(|core| {
1531 let len = data.len();
1532 let start_extra_count = ((4 - (address % 4) as usize) % 4).min(len);
1533 let end_extra_count = (len - start_extra_count) % 4;
1534 assert!(start_extra_count < 4);
1535 assert!(end_extra_count < 4);
1536
1537 if start_extra_count != 0 || end_extra_count != 0 {
1539 for (i, byte) in data.iter().enumerate() {
1540 core.write_word_8(address + (i as u64), *byte)?;
1541 }
1542 return Ok(());
1543 }
1544
1545 let mut buffer = vec![0u32; data.len() / 4];
1548 let endianness = core.endianness()?;
1549 for (bytes, value) in data.chunks_exact(4).zip(buffer.iter_mut()) {
1550 *value = match endianness {
1551 Endian::Little => u32::from_le_bytes(bytes.try_into().unwrap()),
1552 Endian::Big => u32::from_be_bytes(bytes.try_into().unwrap()),
1553 }
1554 }
1555 core.write_32(address, &buffer)?;
1556
1557 Ok(())
1558 })
1559 }
1560
1561 fn supports_8bit_transfers(&self) -> Result<bool, Error> {
1562 Ok(false)
1563 }
1564
1565 fn flush(&mut self) -> Result<(), Error> {
1566 Ok(())
1568 }
1569}
1570
1571#[cfg(test)]
1572mod test {
1573 use crate::{
1574 architecture::arm::{
1575 FullyQualifiedApAddress, communication_interface::SwdSequence,
1576 sequences::DefaultArmSequence,
1577 },
1578 probe::DebugProbeError,
1579 };
1580
1581 use super::*;
1582
1583 const TEST_BASE_ADDRESS: u64 = 0x8000_1000;
1584
1585 fn address_to_reg_num(address: u64) -> u32 {
1586 ((address - TEST_BASE_ADDRESS) / 4) as u32
1587 }
1588
1589 #[derive(Debug)]
1590 pub struct ExpectedMemoryOp {
1591 read: bool,
1592 address: u64,
1593 value: u32,
1594 }
1595
1596 pub struct MockProbe {
1597 expected_ops: Vec<ExpectedMemoryOp>,
1598 }
1599
1600 impl MockProbe {
1601 pub fn new() -> Self {
1602 MockProbe {
1603 expected_ops: vec![],
1604 }
1605 }
1606
1607 pub fn expected_read(&mut self, addr: u64, value: u32) {
1608 self.expected_ops.push(ExpectedMemoryOp {
1609 read: true,
1610 address: addr,
1611 value,
1612 });
1613 }
1614
1615 pub fn expected_write(&mut self, addr: u64, value: u32) {
1616 self.expected_ops.push(ExpectedMemoryOp {
1617 read: false,
1618 address: addr,
1619 value,
1620 });
1621 }
1622 }
1623
1624 impl MemoryInterface<ArmError> for MockProbe {
1625 fn read_8(&mut self, _address: u64, _data: &mut [u8]) -> Result<(), ArmError> {
1626 todo!()
1627 }
1628
1629 fn read_16(&mut self, _address: u64, _data: &mut [u16]) -> Result<(), ArmError> {
1630 todo!()
1631 }
1632
1633 fn read_32(&mut self, address: u64, data: &mut [u32]) -> Result<(), ArmError> {
1634 if self.expected_ops.is_empty() {
1635 panic!(
1636 "Received unexpected read_32 op: register {:#}",
1637 address_to_reg_num(address)
1638 );
1639 }
1640
1641 assert_eq!(data.len(), 1);
1642
1643 let expected_op = self.expected_ops.remove(0);
1644
1645 assert!(
1646 expected_op.read,
1647 "R/W mismatch for register: Expected {:#} Actual: {:#}",
1648 address_to_reg_num(expected_op.address),
1649 address_to_reg_num(address)
1650 );
1651 assert_eq!(
1652 expected_op.address,
1653 address,
1654 "Read from unexpected register: Expected {:#} Actual: {:#}",
1655 address_to_reg_num(expected_op.address),
1656 address_to_reg_num(address)
1657 );
1658
1659 data[0] = expected_op.value;
1660
1661 Ok(())
1662 }
1663
1664 fn read(&mut self, address: u64, data: &mut [u8]) -> Result<(), ArmError> {
1665 self.read_8(address, data)
1666 }
1667
1668 fn write_8(&mut self, _address: u64, _data: &[u8]) -> Result<(), ArmError> {
1669 todo!()
1670 }
1671
1672 fn write_16(&mut self, _address: u64, _data: &[u16]) -> Result<(), ArmError> {
1673 todo!()
1674 }
1675
1676 fn write_32(&mut self, address: u64, data: &[u32]) -> Result<(), ArmError> {
1677 if self.expected_ops.is_empty() {
1678 panic!(
1679 "Received unexpected write_32 op: register {:#}",
1680 address_to_reg_num(address)
1681 );
1682 }
1683
1684 assert_eq!(data.len(), 1);
1685
1686 let expected_op = self.expected_ops.remove(0);
1687
1688 assert!(
1689 !expected_op.read,
1690 "Read/write mismatch on register: {:#}",
1691 address_to_reg_num(address)
1692 );
1693 assert_eq!(
1694 expected_op.address,
1695 address,
1696 "Write to unexpected register: Expected {:#} Actual: {:#}",
1697 address_to_reg_num(expected_op.address),
1698 address_to_reg_num(address)
1699 );
1700
1701 assert_eq!(
1702 expected_op.value, data[0],
1703 "Write value mismatch Expected {:#X} Actual: {:#X}",
1704 expected_op.value, data[0]
1705 );
1706
1707 Ok(())
1708 }
1709
1710 fn write(&mut self, address: u64, data: &[u8]) -> Result<(), ArmError> {
1711 self.write_8(address, data)
1712 }
1713
1714 fn flush(&mut self) -> Result<(), ArmError> {
1715 todo!()
1716 }
1717
1718 fn read_64(&mut self, _address: u64, _data: &mut [u64]) -> Result<(), ArmError> {
1719 todo!()
1720 }
1721
1722 fn write_64(&mut self, _address: u64, _data: &[u64]) -> Result<(), ArmError> {
1723 todo!()
1724 }
1725
1726 fn supports_8bit_transfers(&self) -> Result<bool, ArmError> {
1727 Ok(false)
1728 }
1729
1730 fn supports_native_64bit_access(&mut self) -> bool {
1731 false
1732 }
1733 }
1734
1735 impl ArmMemoryInterface for MockProbe {
1736 fn fully_qualified_address(&self) -> FullyQualifiedApAddress {
1737 todo!()
1738 }
1739
1740 fn get_arm_debug_interface(
1741 &mut self,
1742 ) -> Result<&mut dyn crate::architecture::arm::ArmDebugInterface, DebugProbeError> {
1743 Err(DebugProbeError::NotImplemented {
1744 function_name: "get_arm_debug_interface",
1745 })
1746 }
1747
1748 fn generic_status(&mut self) -> Result<crate::architecture::arm::ap::CSW, ArmError> {
1749 Err(ArmError::Probe(DebugProbeError::NotImplemented {
1750 function_name: "generic_status",
1751 }))
1752 }
1753
1754 fn base_address(&mut self) -> Result<u64, ArmError> {
1755 todo!()
1756 }
1757 }
1758
1759 impl SwdSequence for MockProbe {
1760 fn swj_sequence(&mut self, _bit_len: u8, _bits: u64) -> Result<(), DebugProbeError> {
1761 todo!()
1762 }
1763
1764 fn swj_pins(
1765 &mut self,
1766 _pin_out: u32,
1767 _pin_select: u32,
1768 _pin_wait: u32,
1769 ) -> Result<u32, DebugProbeError> {
1770 todo!()
1771 }
1772 }
1773
1774 fn add_status_expectations(probe: &mut MockProbe, halted: bool) {
1775 let mut dbgdscr = Dbgdscr(0);
1776 dbgdscr.set_halted(halted);
1777 dbgdscr.set_restarted(true);
1778 probe.expected_read(
1779 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1780 dbgdscr.into(),
1781 );
1782 }
1783
1784 fn add_enable_itr_expectations(probe: &mut MockProbe) {
1785 let mut dbgdscr = Dbgdscr(0);
1786 dbgdscr.set_halted(true);
1787 probe.expected_read(
1788 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1789 dbgdscr.into(),
1790 );
1791 dbgdscr.set_itren(true);
1792 probe.expected_write(
1793 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1794 dbgdscr.into(),
1795 );
1796 }
1797
1798 fn add_read_reg_expectations(probe: &mut MockProbe, reg: u16, value: u32) {
1799 probe.expected_write(
1800 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1801 build_mcr(14, 0, reg, 0, 5, 0),
1802 );
1803 let mut dbgdscr = Dbgdscr(0);
1804 dbgdscr.set_instrcoml_l(true);
1805 dbgdscr.set_txfull_l(true);
1806
1807 probe.expected_read(
1808 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1809 dbgdscr.into(),
1810 );
1811 probe.expected_read(
1812 Dbgdtrtx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1813 value,
1814 );
1815 }
1816
1817 fn add_read_pc_expectations(probe: &mut MockProbe, value: u32) {
1818 let mut dbgdscr = Dbgdscr(0);
1819 dbgdscr.set_instrcoml_l(true);
1820 dbgdscr.set_txfull_l(true);
1821
1822 probe.expected_write(
1823 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1824 build_mov(0, 15),
1825 );
1826 probe.expected_read(
1827 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1828 dbgdscr.into(),
1829 );
1830 add_read_reg_expectations(probe, 0, value + 8);
1832 }
1833
1834 fn add_read_fp_count_expectations(probe: &mut MockProbe) {
1835 let mut dbgdscr = Dbgdscr(0);
1836 dbgdscr.set_instrcoml_l(true);
1837 dbgdscr.set_txfull_l(true);
1838 let mut cpacr = Cpacr(0);
1839 cpacr.set_cp(10, 0b11);
1840 cpacr.set_cp(11, 0b11);
1841
1842 probe.expected_write(
1844 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1845 build_mrc(15, 0, 0, 1, 0, 2),
1846 );
1847 probe.expected_read(
1848 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1849 dbgdscr.into(),
1850 );
1851 add_read_reg_expectations(probe, 0, cpacr.0);
1853
1854 probe.expected_write(
1856 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1857 build_vmrs(0, 0b0111),
1858 );
1859 probe.expected_read(
1860 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1861 dbgdscr.into(),
1862 );
1863 add_read_reg_expectations(probe, 0, 0b010);
1864 }
1865
1866 fn add_read_cpsr_expectations(probe: &mut MockProbe, value: u32) {
1867 let mut dbgdscr = Dbgdscr(0);
1868 dbgdscr.set_instrcoml_l(true);
1869 dbgdscr.set_txfull_l(true);
1870
1871 probe.expected_write(
1872 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1873 build_mrs(0),
1874 );
1875 probe.expected_read(
1876 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1877 dbgdscr.into(),
1878 );
1879 add_read_reg_expectations(probe, 0, value);
1880 }
1881
1882 fn add_idr_expectations(probe: &mut MockProbe, bp_count: u32) {
1883 let mut dbgdidr = Dbgdidr(0);
1884 dbgdidr.set_brps(bp_count - 1);
1885 probe.expected_read(
1886 Dbgdidr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1887 dbgdidr.into(),
1888 );
1889 }
1890
1891 fn add_set_r0_expectation(probe: &mut MockProbe, value: u32) {
1892 let mut dbgdscr = Dbgdscr(0);
1893 dbgdscr.set_instrcoml_l(true);
1894 dbgdscr.set_rxfull_l(true);
1895
1896 probe.expected_write(
1897 Dbgdtrrx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1898 value,
1899 );
1900 probe.expected_read(
1901 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1902 dbgdscr.into(),
1903 );
1904
1905 probe.expected_write(
1906 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1907 build_mrc(14, 0, 0, 0, 5, 0),
1908 );
1909 probe.expected_read(
1910 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1911 dbgdscr.into(),
1912 );
1913 }
1914
1915 fn add_read_memory_expectations(probe: &mut MockProbe, address: u64, value: u32) {
1916 add_set_r0_expectation(probe, address as u32);
1917
1918 let mut dbgdscr = Dbgdscr(0);
1919 dbgdscr.set_instrcoml_l(true);
1920 dbgdscr.set_txfull_l(true);
1921
1922 probe.expected_write(
1923 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1924 build_ldc(14, 5, 0, 4),
1925 );
1926 probe.expected_read(
1927 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1928 dbgdscr.into(),
1929 );
1930 probe.expected_read(
1931 Dbgdtrtx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1932 value,
1933 );
1934 }
1935
1936 impl Drop for MockProbe {
1937 fn drop(&mut self) {
1938 if !self.expected_ops.is_empty() {
1939 panic!("self.expected_ops is not empty: {:?}", self.expected_ops);
1940 }
1941 }
1942 }
1943
1944 #[test]
1945 fn armv7a_new() {
1946 let mut probe = MockProbe::new();
1947
1948 add_status_expectations(&mut probe, true);
1950 add_enable_itr_expectations(&mut probe);
1951 add_read_reg_expectations(&mut probe, 0, 0);
1952 add_read_fp_count_expectations(&mut probe);
1953
1954 let mock_mem = Box::new(probe) as _;
1955
1956 let _ = Armv7a::new(
1957 mock_mem,
1958 &mut CortexAState::new(),
1959 TEST_BASE_ADDRESS,
1960 DefaultArmSequence::create(),
1961 )
1962 .unwrap();
1963 }
1964
1965 #[test]
1966 fn armv7a_core_halted() {
1967 let mut probe = MockProbe::new();
1968 let mut state = CortexAState::new();
1969
1970 add_status_expectations(&mut probe, true);
1972 add_enable_itr_expectations(&mut probe);
1973 add_read_reg_expectations(&mut probe, 0, 0);
1974 add_read_fp_count_expectations(&mut probe);
1975
1976 let mut dbgdscr = Dbgdscr(0);
1977 dbgdscr.set_halted(false);
1978 probe.expected_read(
1979 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1980 dbgdscr.into(),
1981 );
1982
1983 dbgdscr.set_halted(true);
1984 probe.expected_read(
1985 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1986 dbgdscr.into(),
1987 );
1988
1989 let mock_mem = Box::new(probe) as _;
1990
1991 let mut armv7a = Armv7a::new(
1992 mock_mem,
1993 &mut state,
1994 TEST_BASE_ADDRESS,
1995 DefaultArmSequence::create(),
1996 )
1997 .unwrap();
1998
1999 assert!(!armv7a.core_halted().unwrap());
2001 assert!(armv7a.core_halted().unwrap());
2002 }
2003
2004 #[test]
2005 fn armv7a_wait_for_core_halted() {
2006 let mut probe = MockProbe::new();
2007 let mut state = CortexAState::new();
2008
2009 add_status_expectations(&mut probe, true);
2011 add_enable_itr_expectations(&mut probe);
2012 add_read_reg_expectations(&mut probe, 0, 0);
2013 add_read_fp_count_expectations(&mut probe);
2014
2015 let mut dbgdscr = Dbgdscr(0);
2016 dbgdscr.set_halted(false);
2017 probe.expected_read(
2018 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2019 dbgdscr.into(),
2020 );
2021
2022 dbgdscr.set_halted(true);
2023 probe.expected_read(
2024 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2025 dbgdscr.into(),
2026 );
2027
2028 let mock_mem = Box::new(probe) as _;
2029
2030 let mut armv7a = Armv7a::new(
2031 mock_mem,
2032 &mut state,
2033 TEST_BASE_ADDRESS,
2034 DefaultArmSequence::create(),
2035 )
2036 .unwrap();
2037
2038 armv7a
2040 .wait_for_core_halted(Duration::from_millis(100))
2041 .unwrap();
2042 }
2043
2044 #[test]
2045 fn armv7a_status_running() {
2046 let mut probe = MockProbe::new();
2047 let mut state = CortexAState::new();
2048
2049 add_status_expectations(&mut probe, true);
2051 add_enable_itr_expectations(&mut probe);
2052 add_read_reg_expectations(&mut probe, 0, 0);
2053 add_read_fp_count_expectations(&mut probe);
2054
2055 let mut dbgdscr = Dbgdscr(0);
2056 dbgdscr.set_halted(false);
2057 probe.expected_read(
2058 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2059 dbgdscr.into(),
2060 );
2061
2062 let mock_mem = Box::new(probe) as _;
2063
2064 let mut armv7a = Armv7a::new(
2065 mock_mem,
2066 &mut state,
2067 TEST_BASE_ADDRESS,
2068 DefaultArmSequence::create(),
2069 )
2070 .unwrap();
2071
2072 assert_eq!(CoreStatus::Running, armv7a.status().unwrap());
2074 }
2075
2076 #[test]
2077 fn armv7a_status_halted() {
2078 let mut probe = MockProbe::new();
2079 let mut state = CortexAState::new();
2080
2081 add_status_expectations(&mut probe, true);
2083 add_enable_itr_expectations(&mut probe);
2084 add_read_reg_expectations(&mut probe, 0, 0);
2085 add_read_fp_count_expectations(&mut probe);
2086
2087 let mut dbgdscr = Dbgdscr(0);
2088 dbgdscr.set_halted(true);
2089 probe.expected_read(
2090 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2091 dbgdscr.into(),
2092 );
2093
2094 let mock_mem = Box::new(probe) as _;
2095
2096 let mut armv7a = Armv7a::new(
2097 mock_mem,
2098 &mut state,
2099 TEST_BASE_ADDRESS,
2100 DefaultArmSequence::create(),
2101 )
2102 .unwrap();
2103
2104 assert_eq!(
2106 CoreStatus::Halted(crate::HaltReason::Request),
2107 armv7a.status().unwrap()
2108 );
2109 }
2110
2111 #[test]
2112 fn armv7a_read_core_reg_common() {
2113 const REG_VALUE: u32 = 0xABCD;
2114
2115 let mut probe = MockProbe::new();
2116 let mut state = CortexAState::new();
2117
2118 add_status_expectations(&mut probe, true);
2120 add_enable_itr_expectations(&mut probe);
2121 add_read_reg_expectations(&mut probe, 0, 0);
2122 add_read_fp_count_expectations(&mut probe);
2123
2124 add_read_reg_expectations(&mut probe, 2, REG_VALUE);
2126
2127 let mock_mem = Box::new(probe) as _;
2128
2129 let mut armv7a = Armv7a::new(
2130 mock_mem,
2131 &mut state,
2132 TEST_BASE_ADDRESS,
2133 DefaultArmSequence::create(),
2134 )
2135 .unwrap();
2136
2137 assert_eq!(
2139 RegisterValue::from(REG_VALUE),
2140 armv7a.read_core_reg(RegisterId(2)).unwrap()
2141 );
2142
2143 assert_eq!(
2145 RegisterValue::from(REG_VALUE),
2146 armv7a.read_core_reg(RegisterId(2)).unwrap()
2147 );
2148 }
2149
2150 #[test]
2151 fn armv7a_read_core_reg_pc() {
2152 const REG_VALUE: u32 = 0xABCD;
2153
2154 let mut probe = MockProbe::new();
2155 let mut state = CortexAState::new();
2156
2157 add_status_expectations(&mut probe, true);
2159 add_enable_itr_expectations(&mut probe);
2160 add_read_reg_expectations(&mut probe, 0, 0);
2161 add_read_fp_count_expectations(&mut probe);
2162
2163 add_read_pc_expectations(&mut probe, REG_VALUE);
2165
2166 let mock_mem = Box::new(probe) as _;
2167
2168 let mut armv7a = Armv7a::new(
2169 mock_mem,
2170 &mut state,
2171 TEST_BASE_ADDRESS,
2172 DefaultArmSequence::create(),
2173 )
2174 .unwrap();
2175
2176 assert_eq!(
2178 RegisterValue::from(REG_VALUE),
2179 armv7a.read_core_reg(RegisterId(15)).unwrap()
2180 );
2181
2182 assert_eq!(
2184 RegisterValue::from(REG_VALUE),
2185 armv7a.read_core_reg(RegisterId(15)).unwrap()
2186 );
2187 }
2188
2189 #[test]
2190 fn armv7a_read_core_reg_cpsr() {
2191 const REG_VALUE: u32 = 0xABCD;
2192
2193 let mut probe = MockProbe::new();
2194 let mut state = CortexAState::new();
2195
2196 add_status_expectations(&mut probe, true);
2198 add_enable_itr_expectations(&mut probe);
2199 add_read_reg_expectations(&mut probe, 0, 0);
2200 add_read_fp_count_expectations(&mut probe);
2201
2202 add_read_cpsr_expectations(&mut probe, REG_VALUE);
2204
2205 let mock_mem = Box::new(probe) as _;
2206
2207 let mut armv7a = Armv7a::new(
2208 mock_mem,
2209 &mut state,
2210 TEST_BASE_ADDRESS,
2211 DefaultArmSequence::create(),
2212 )
2213 .unwrap();
2214
2215 assert_eq!(
2217 RegisterValue::from(REG_VALUE),
2218 armv7a.read_core_reg(XPSR.id()).unwrap()
2219 );
2220
2221 assert_eq!(
2223 RegisterValue::from(REG_VALUE),
2224 armv7a.read_core_reg(XPSR.id()).unwrap()
2225 );
2226 }
2227
2228 #[test]
2229 fn armv7a_halt() {
2230 const REG_VALUE: u32 = 0xABCD;
2231
2232 let mut probe = MockProbe::new();
2233 let mut state = CortexAState::new();
2234
2235 add_status_expectations(&mut probe, false);
2237
2238 let mut dbgdrcr = Dbgdrcr(0);
2240 dbgdrcr.set_hrq(true);
2241 probe.expected_write(
2242 Dbgdrcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2243 dbgdrcr.into(),
2244 );
2245
2246 add_status_expectations(&mut probe, true);
2248
2249 add_status_expectations(&mut probe, true);
2251 add_enable_itr_expectations(&mut probe);
2252 add_read_reg_expectations(&mut probe, 0, 0);
2253 add_read_fp_count_expectations(&mut probe);
2254
2255 add_read_pc_expectations(&mut probe, REG_VALUE);
2257
2258 let mock_mem = Box::new(probe) as _;
2259
2260 let mut armv7a = Armv7a::new(
2261 mock_mem,
2262 &mut state,
2263 TEST_BASE_ADDRESS,
2264 DefaultArmSequence::create(),
2265 )
2266 .unwrap();
2267
2268 assert_eq!(
2270 REG_VALUE as u64,
2271 armv7a.halt(Duration::from_millis(100)).unwrap().pc
2272 );
2273 }
2274
2275 #[test]
2276 fn armv7a_run() {
2277 let mut probe = MockProbe::new();
2278 let mut state = CortexAState::new();
2279
2280 add_status_expectations(&mut probe, true);
2282 add_enable_itr_expectations(&mut probe);
2283 add_read_reg_expectations(&mut probe, 0, 0);
2284 add_read_fp_count_expectations(&mut probe);
2285
2286 add_set_r0_expectation(&mut probe, 0);
2288
2289 let mut dbgdscr = Dbgdscr(0);
2291 dbgdscr.set_itren(true);
2292 probe.expected_read(
2293 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2294 dbgdscr.into(),
2295 );
2296 dbgdscr.set_itren(false);
2297 probe.expected_write(
2298 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2299 dbgdscr.into(),
2300 );
2301
2302 let mut dbgdrcr = Dbgdrcr(0);
2304 dbgdrcr.set_rrq(true);
2305 probe.expected_write(
2306 Dbgdrcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2307 dbgdrcr.into(),
2308 );
2309
2310 add_status_expectations(&mut probe, false);
2312
2313 add_status_expectations(&mut probe, false);
2315
2316 let mock_mem = Box::new(probe) as _;
2317
2318 let mut armv7a = Armv7a::new(
2319 mock_mem,
2320 &mut state,
2321 TEST_BASE_ADDRESS,
2322 DefaultArmSequence::create(),
2323 )
2324 .unwrap();
2325
2326 armv7a.run().unwrap();
2327 }
2328
2329 #[test]
2330 fn armv7a_available_breakpoint_units() {
2331 const BP_COUNT: u32 = 4;
2332 let mut probe = MockProbe::new();
2333 let mut state = CortexAState::new();
2334
2335 add_status_expectations(&mut probe, true);
2337 add_enable_itr_expectations(&mut probe);
2338 add_read_reg_expectations(&mut probe, 0, 0);
2339 add_read_fp_count_expectations(&mut probe);
2340
2341 add_idr_expectations(&mut probe, BP_COUNT);
2343
2344 let mock_mem = Box::new(probe) as _;
2345
2346 let mut armv7a = Armv7a::new(
2347 mock_mem,
2348 &mut state,
2349 TEST_BASE_ADDRESS,
2350 DefaultArmSequence::create(),
2351 )
2352 .unwrap();
2353
2354 assert_eq!(BP_COUNT, armv7a.available_breakpoint_units().unwrap());
2355 }
2356
2357 #[test]
2358 fn armv7a_hw_breakpoints() {
2359 const BP_COUNT: u32 = 4;
2360 const BP1: u64 = 0x2345;
2361 const BP2: u64 = 0x8000_0000;
2362 let mut probe = MockProbe::new();
2363 let mut state = CortexAState::new();
2364
2365 add_status_expectations(&mut probe, true);
2367 add_enable_itr_expectations(&mut probe);
2368 add_read_reg_expectations(&mut probe, 0, 0);
2369 add_read_fp_count_expectations(&mut probe);
2370
2371 add_idr_expectations(&mut probe, BP_COUNT);
2373
2374 probe.expected_read(
2376 Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2377 BP1 as u32,
2378 );
2379 probe.expected_read(
2380 Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2381 1,
2382 );
2383
2384 probe.expected_read(
2385 Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + 4,
2386 BP2 as u32,
2387 );
2388 probe.expected_read(
2389 Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + 4,
2390 1,
2391 );
2392
2393 probe.expected_read(
2394 Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (2 * 4),
2395 0,
2396 );
2397 probe.expected_read(
2398 Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (2 * 4),
2399 0,
2400 );
2401
2402 probe.expected_read(
2403 Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (3 * 4),
2404 0,
2405 );
2406 probe.expected_read(
2407 Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (3 * 4),
2408 0,
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 let results = armv7a.hw_breakpoints().unwrap();
2422 assert_eq!(Some(BP1), results[0]);
2423 assert_eq!(Some(BP2), results[1]);
2424 assert_eq!(None, results[2]);
2425 assert_eq!(None, results[3]);
2426 }
2427
2428 #[test]
2429 fn armv7a_set_hw_breakpoint() {
2430 const BP_VALUE: u64 = 0x2345;
2431 let mut probe = MockProbe::new();
2432 let mut state = CortexAState::new();
2433
2434 add_status_expectations(&mut probe, true);
2436 add_enable_itr_expectations(&mut probe);
2437 add_read_reg_expectations(&mut probe, 0, 0);
2438 add_read_fp_count_expectations(&mut probe);
2439
2440 let mut dbgbcr = Dbgbcr(0);
2442 dbgbcr.set_hmc(true);
2444 dbgbcr.set_pmc(0b11);
2445 dbgbcr.set_bas(0b1111);
2447 dbgbcr.set_e(true);
2449
2450 probe.expected_write(
2451 Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2452 BP_VALUE as u32,
2453 );
2454 probe.expected_write(
2455 Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2456 dbgbcr.into(),
2457 );
2458
2459 let mock_mem = Box::new(probe) as _;
2460
2461 let mut armv7a = Armv7a::new(
2462 mock_mem,
2463 &mut state,
2464 TEST_BASE_ADDRESS,
2465 DefaultArmSequence::create(),
2466 )
2467 .unwrap();
2468
2469 armv7a.set_hw_breakpoint(0, BP_VALUE).unwrap();
2470 }
2471
2472 #[test]
2473 fn armv7a_clear_hw_breakpoint() {
2474 let mut probe = MockProbe::new();
2475 let mut state = CortexAState::new();
2476
2477 add_status_expectations(&mut probe, true);
2479 add_enable_itr_expectations(&mut probe);
2480 add_read_reg_expectations(&mut probe, 0, 0);
2481 add_read_fp_count_expectations(&mut probe);
2482
2483 probe.expected_write(
2485 Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2486 0,
2487 );
2488 probe.expected_write(
2489 Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2490 0,
2491 );
2492
2493 let mock_mem = Box::new(probe) as _;
2494
2495 let mut armv7a = Armv7a::new(
2496 mock_mem,
2497 &mut state,
2498 TEST_BASE_ADDRESS,
2499 DefaultArmSequence::create(),
2500 )
2501 .unwrap();
2502
2503 armv7a.clear_hw_breakpoint(0).unwrap();
2504 }
2505
2506 #[test]
2507 fn armv7a_read_word_32() {
2508 const MEMORY_VALUE: u32 = 0xBA5EBA11;
2509 const MEMORY_ADDRESS: u64 = 0x12345678;
2510
2511 let mut probe = MockProbe::new();
2512 let mut state = CortexAState::new();
2513
2514 add_status_expectations(&mut probe, true);
2516 add_enable_itr_expectations(&mut probe);
2517 add_read_reg_expectations(&mut probe, 0, 0);
2518 add_read_fp_count_expectations(&mut probe);
2519
2520 add_read_memory_expectations(&mut probe, MEMORY_ADDRESS, MEMORY_VALUE);
2522
2523 let mock_mem = Box::new(probe) as _;
2524
2525 let mut armv7a = Armv7a::new(
2526 mock_mem,
2527 &mut state,
2528 TEST_BASE_ADDRESS,
2529 DefaultArmSequence::create(),
2530 )
2531 .unwrap();
2532
2533 assert_eq!(MEMORY_VALUE, armv7a.read_word_32(MEMORY_ADDRESS).unwrap());
2534 }
2535
2536 fn test_read_word(value: u32, address: u64, memory_word_address: u64, endian: Endian) -> u8 {
2537 let mut probe = MockProbe::new();
2538 let mut state = CortexAState::new();
2539
2540 add_status_expectations(&mut probe, true);
2542 add_enable_itr_expectations(&mut probe);
2543 add_read_reg_expectations(&mut probe, 0, 0);
2544 add_read_fp_count_expectations(&mut probe);
2545
2546 add_read_memory_expectations(&mut probe, memory_word_address, value);
2548
2549 let cpsr = if endian == Endian::Big { 1 << 9 } else { 0 };
2551 add_read_cpsr_expectations(&mut probe, cpsr);
2552
2553 let mock_mem = Box::new(probe) as _;
2554
2555 let mut armv7a = Armv7a::new(
2556 mock_mem,
2557 &mut state,
2558 TEST_BASE_ADDRESS,
2559 DefaultArmSequence::create(),
2560 )
2561 .unwrap();
2562 armv7a.read_word_8(address).unwrap()
2563 }
2564
2565 #[test]
2566 fn armv7a_read_word_8() {
2567 const MEMORY_VALUE: u32 = 0xBA5EBB11;
2568 const MEMORY_ADDRESS: u64 = 0x12345679;
2569 const MEMORY_WORD_ADDRESS: u64 = 0x12345678;
2570
2571 assert_eq!(
2572 0xBB,
2573 test_read_word(
2574 MEMORY_VALUE,
2575 MEMORY_ADDRESS,
2576 MEMORY_WORD_ADDRESS,
2577 Endian::Little
2578 )
2579 );
2580 }
2581
2582 #[test]
2583 fn armv7a_read_word_8_be() {
2584 const MEMORY_VALUE: u32 = 0xBA5EBB11;
2585 const MEMORY_ADDRESS: u64 = 0x12345679;
2586 const MEMORY_WORD_ADDRESS: u64 = 0x12345678;
2587
2588 assert_eq!(
2589 0x5E,
2590 test_read_word(
2591 MEMORY_VALUE,
2592 MEMORY_ADDRESS,
2593 MEMORY_WORD_ADDRESS,
2594 Endian::Big
2595 )
2596 );
2597 }
2598}