1use super::{
4 CortexARState,
5 instructions::aarch32::{
6 build_ldc, build_mcr, build_mov, build_mrc, build_mrs, build_mrs_spsr, build_msr,
7 build_stc, build_vmov, 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 HaltReason, InstructionSet, MemoryInterface,
20 architecture::arm::{
21 ArmError, DapAccess, FullyQualifiedApAddress,
22 ap::{ApRegister, BD0, BD1, BD2, BD3, TAR, TAR2},
23 core::armv7ar_debug_regs::*,
24 memory::ArmMemoryInterface,
25 sequences::ArmDebugSequence,
26 },
27 core::{
28 BreakpointCause, CoreRegisters, MemoryMappedRegister, RegisterId, RegisterValue,
29 VectorCatchCondition,
30 },
31 error::Error,
32 memory::{MemoryNotAlignedError, valid_32bit_address},
33 semihosting::{SemihostingCommand, decode_semihosting_syscall},
34};
35use std::{
36 mem::size_of,
37 sync::Arc,
38 time::{Duration, Instant},
39};
40use zerocopy::{FromBytes, IntoBytes};
41
42const OPERATION_TIMEOUT: Duration = Duration::from_millis(250);
44
45struct BankedAccess<'a> {
47 interface: &'a mut dyn DapAccess,
50 ap: FullyQualifiedApAddress,
51 dtrtx: u64,
52 itr: u64,
53 dscr: u64,
54 dtrrx: u64,
55}
56
57impl<'a> BankedAccess<'a> {
58 #[expect(dead_code)]
59 fn set_dtrrx(&mut self, value: u32) -> Result<(), ArmError> {
60 self.interface
61 .write_raw_ap_register(&self.ap, self.dtrrx, value)
62 }
63
64 fn set_dtrrx_repeated(&mut self, values: &[u32]) -> Result<(), ArmError> {
65 self.interface
66 .write_raw_ap_register_repeated(&self.ap, self.dtrrx, values)
67 }
68
69 fn dscr(&mut self) -> Result<Dbgdscr, ArmError> {
70 self.interface
71 .read_raw_ap_register(&self.ap, self.dscr)
72 .map(Dbgdscr::from)
73 }
74
75 fn set_dscr(&mut self, value: Dbgdscr) -> Result<(), ArmError> {
76 self.interface
77 .write_raw_ap_register(&self.ap, self.dscr, value.into())
78 }
79
80 fn set_itr(&mut self, value: u32) -> Result<(), ArmError> {
81 self.interface
82 .write_raw_ap_register(&self.ap, self.itr, value)
83 }
84
85 fn dtrtx(&mut self) -> Result<u32, ArmError> {
86 self.interface.read_raw_ap_register(&self.ap, self.dtrtx)
87 }
88
89 fn dtrtx_repeated(&mut self, buf: &mut [u32]) -> Result<(), ArmError> {
90 self.interface
91 .read_raw_ap_register_repeated(&self.ap, self.dtrtx, buf)?;
92 Ok(())
93 }
94
95 fn with_dcc_fast_mode<R>(
105 &mut self,
106 f: impl FnOnce(&mut Self) -> Result<R, ArmError>,
107 ) -> Result<R, ArmError> {
108 let mut dscr = self.dscr()?;
110 dscr.set_extdccmode(2);
111 self.set_dscr(dscr)?;
112 let result = f(self);
113
114 let mut dscr = self.dscr()?;
116 dscr.set_extdccmode(0);
117 self.set_dscr(dscr)?;
118
119 result
120 }
121}
122
123#[derive(thiserror::Error, Debug)]
125pub enum Armv7arError {
126 #[error("Register number {0} is not valid for ARMv7-A")]
128 InvalidRegisterNumber(u16),
129
130 #[error("Core is running but operation requires it to be halted")]
132 NotHalted,
133
134 #[error("A data abort occurred")]
136 DataAbort,
137}
138
139pub struct Armv7ar<'probe> {
141 memory: Box<dyn ArmMemoryInterface + 'probe>,
142
143 state: &'probe mut CortexARState,
144
145 base_address: u64,
146
147 sequence: Arc<dyn ArmDebugSequence>,
148
149 num_breakpoints: Option<u32>,
150
151 itr_enabled: bool,
152
153 endianness: Option<Endian>,
154
155 core_type: CoreType,
156}
157
158impl<'probe> Armv7ar<'probe> {
159 pub(crate) fn new(
160 mut memory: Box<dyn ArmMemoryInterface + 'probe>,
161 state: &'probe mut CortexARState,
162 base_address: u64,
163 sequence: Arc<dyn ArmDebugSequence>,
164 core_type: CoreType,
165 ) -> Result<Self, Error> {
166 if !state.initialized() {
167 let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
169 let dbgdscr = Dbgdscr(memory.read_word_32(address)?);
170
171 tracing::debug!("State when connecting: {:x?}", dbgdscr);
172
173 let core_state = if dbgdscr.halted() {
174 let reason = dbgdscr.halt_reason();
175
176 tracing::debug!("Core was halted when connecting, reason: {:?}", reason);
177
178 CoreStatus::Halted(reason)
179 } else {
180 CoreStatus::Running
181 };
182
183 state.current_state = core_state;
184 }
185
186 let mut core = Self {
187 memory,
188 state,
189 base_address,
190 sequence,
191 num_breakpoints: None,
192 itr_enabled: false,
193 endianness: None,
194 core_type,
195 };
196
197 if !core.state.initialized() {
198 core.reset_register_cache();
199 core.read_fp_reg_count()?;
200 core.state.initialize();
201 }
202
203 Ok(core)
204 }
205
206 fn read_fp_reg_count(&mut self) -> Result<(), Error> {
207 if self.state.fp_reg_count == 0 && matches!(self.state.current_state, CoreStatus::Halted(_))
208 {
209 self.prepare_r0_for_clobber()?;
210
211 let instruction = build_mrc(15, 0, 0, 1, 0, 2);
214 self.execute_instruction(instruction)?;
215 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
216 let cpacr = Cpacr(self.execute_instruction_with_result(instruction)?);
217 if cpacr.cp(10) == 0 || cpacr.cp(11) == 0 {
218 return Ok(());
219 }
220
221 let instruction = build_vmrs(0, 0b0111);
223 self.execute_instruction(instruction)?;
224
225 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
227 let vmrs = self.execute_instruction_with_result(instruction)?;
228
229 self.state.fp_reg_count = match vmrs & 0b111 {
230 0b001 => 16,
231 0b010 => 32,
232 _ => 0,
233 };
234 }
235
236 Ok(())
237 }
238
239 fn execute_instruction(&mut self, instruction: u32) -> Result<Dbgdscr, ArmError> {
241 if !self.state.current_state.is_halted() {
242 return Err(ArmError::CoreNotHalted);
243 }
244
245 if !self.itr_enabled {
247 let address = Dbgdscr::get_mmio_address_from_base(self.base_address)?;
248 let mut dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
249 dbgdscr.set_itren(true);
250
251 self.memory.write_word_32(address, dbgdscr.into())?;
252
253 self.itr_enabled = true;
254 }
255
256 execute_instruction(&mut *self.memory, self.base_address, instruction)
257 }
258
259 fn execute_instruction_with_result(&mut self, instruction: u32) -> Result<u32, Error> {
261 let mut dbgdscr = self.execute_instruction(instruction)?;
263
264 let start = Instant::now();
266 while !dbgdscr.txfull_l() {
267 let address = Dbgdscr::get_mmio_address_from_base(self.base_address)?;
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 let address = Dbgdtrtx::get_mmio_address_from_base(self.base_address)?;
278 let result = self.memory.read_word_32(address)?;
279
280 Ok(result)
281 }
282
283 fn execute_instruction_with_input(
284 &mut self,
285 instruction: u32,
286 value: u32,
287 ) -> Result<(), Error> {
288 let address = Dbgdtrrx::get_mmio_address_from_base(self.base_address)?;
290 self.memory.write_word_32(address, value)?;
291
292 let address = Dbgdscr::get_mmio_address_from_base(self.base_address)?;
294 let mut dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
295
296 let start = Instant::now();
297 while !dbgdscr.rxfull_l() {
298 dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
299 check_and_clear_data_abort(&mut *self.memory, self.base_address, dbgdscr)?;
301 if start.elapsed() >= OPERATION_TIMEOUT {
302 return Err(Error::Timeout);
303 }
304 }
305
306 self.execute_instruction(instruction)?;
308
309 Ok(())
310 }
311
312 fn reset_register_cache(&mut self) {
313 self.state.register_cache = vec![None; 51];
314 }
315
316 fn writeback_registers(&mut self) -> Result<(), Error> {
318 let writeback_iter = (17u16..=48).chain(15u16..=16).chain(0u16..=14);
319
320 for i in writeback_iter {
321 if let Some((val, writeback)) = self.state.register_cache[i as usize]
322 && writeback
323 {
324 match i {
325 0..=14 => {
326 let instruction = build_mrc(14, 0, i, 0, 5, 0);
327
328 self.execute_instruction_with_input(instruction, val.try_into()?)?;
329 }
330 15 => {
331 let instruction = build_mrc(14, 0, 0, 0, 5, 0);
333
334 self.execute_instruction_with_input(instruction, val.try_into()?)?;
335
336 let instruction = build_mov(15, 0);
340 self.execute_instruction(instruction)?;
341 }
342 16 => {
343 let instruction = build_msr(0);
345 self.execute_instruction_with_input(instruction, val.try_into()?)?;
346 }
347 17..=48 => {
348 let value: u64 = val.try_into()?;
350 let low_word = value as u32;
351 let high_word = (value >> 32) as u32;
352
353 let instruction = build_mrc(14, 0, 0, 0, 5, 0);
354 self.execute_instruction_with_input(instruction, low_word)?;
355
356 let instruction = build_mrc(14, 0, 1, 0, 5, 0);
357 self.execute_instruction_with_input(instruction, high_word)?;
358
359 let instruction = build_vmov(0, 0, 1, i - 17);
361 self.execute_instruction(instruction)?;
362 }
363 _ => {
364 panic!("Logic missing for writeback of register {i}");
365 }
366 }
367 }
368 }
369
370 self.reset_register_cache();
371
372 Ok(())
373 }
374
375 fn prepare_r0_for_clobber(&mut self) -> Result<(), Error> {
377 self.prepare_for_clobber(0)
378 }
379
380 fn prepare_for_clobber(&mut self, reg: usize) -> Result<(), Error> {
382 if self.state.register_cache[reg].is_none() {
383 let val: u32 = self.read_core_reg(RegisterId(reg as u16))?.try_into()?;
385
386 self.state.register_cache[reg] = Some((val.into(), true));
388 }
389
390 Ok(())
391 }
392
393 fn set_r0(&mut self, value: u32) -> Result<(), Error> {
394 let instruction = build_mrc(14, 0, 0, 0, 5, 0);
395
396 self.execute_instruction_with_input(instruction, value)
397 }
398
399 fn set_core_status(&mut self, new_status: CoreStatus) {
400 super::update_core_status(&mut self.memory, &mut self.state.current_state, new_status);
401 }
402
403 pub(crate) fn halted_access<R>(
404 &mut self,
405 op: impl FnOnce(&mut Self) -> Result<R, Error>,
406 ) -> Result<R, Error> {
407 let was_running = !(self.state.current_state.is_halted() || self.status()?.is_halted());
408
409 if was_running {
410 self.halt(Duration::from_millis(100))?;
411 }
412
413 let result = op(self);
414
415 if was_running {
416 self.run()?
417 }
418
419 result
420 }
421
422 fn banked_access(&mut self) -> Result<BankedAccess<'_>, Error> {
426 let address = Dbgdtrrx::get_mmio_address_from_base(self.base_address)?;
427 let ap = self.memory.fully_qualified_address();
428 let is_64_bit = self.is_64_bit();
429 let interface = self.memory.get_arm_debug_interface()?;
430
431 if is_64_bit {
432 interface.write_raw_ap_register(&ap, TAR2::ADDRESS, (address >> 32) as u32)?;
433 }
434 interface.write_raw_ap_register(&ap, TAR::ADDRESS, address as u32)?;
435
436 Ok(BankedAccess {
437 interface,
438 ap,
439 dtrrx: BD0::ADDRESS,
440 itr: BD1::ADDRESS,
441 dscr: BD2::ADDRESS,
442 dtrtx: BD3::ADDRESS,
443 })
444 }
445}
446
447pub(crate) fn request_halt(
452 memory: &mut dyn ArmMemoryInterface,
453 base_address: u64,
454) -> Result<(), ArmError> {
455 let address = Dbgdrcr::get_mmio_address_from_base(base_address)?;
456 let mut value = Dbgdrcr(0);
457 value.set_hrq(true);
458
459 memory.write_word_32(address, value.into())?;
460 Ok(())
461}
462
463pub(crate) fn run(memory: &mut dyn ArmMemoryInterface, base_address: u64) -> Result<(), ArmError> {
465 let address = Dbgdrcr::get_mmio_address_from_base(base_address)?;
466 let mut value = Dbgdrcr(0);
467 value.set_rrq(true);
468
469 memory.write_word_32(address, value.into())?;
470
471 let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
473
474 let start = Instant::now();
475 loop {
476 let dbgdscr = Dbgdscr(memory.read_word_32(address)?);
477 if dbgdscr.restarted() {
478 return Ok(());
479 }
480 if start.elapsed() > OPERATION_TIMEOUT {
481 return Err(ArmError::Timeout);
482 }
483 }
484}
485
486pub(crate) fn wait_for_core_halted(
489 memory: &mut dyn ArmMemoryInterface,
490 base_address: u64,
491 timeout: Duration,
492) -> Result<(), ArmError> {
493 let start = Instant::now();
495
496 while !core_halted(memory, base_address)? {
497 if start.elapsed() >= timeout {
498 return Err(ArmError::Timeout);
499 }
500 std::thread::sleep(Duration::from_millis(1));
502 }
503
504 Ok(())
505}
506
507pub(crate) fn core_halted(
509 memory: &mut dyn ArmMemoryInterface,
510 base_address: u64,
511) -> Result<bool, ArmError> {
512 let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
513 let dbgdscr = Dbgdscr(memory.read_word_32(address)?);
514
515 Ok(dbgdscr.halted())
516}
517
518pub(crate) fn set_hw_breakpoint(
521 memory: &mut dyn ArmMemoryInterface,
522 base_address: u64,
523 bp_unit_index: usize,
524 addr: u32,
525) -> Result<(), ArmError> {
526 let bp_value_addr = Dbgbvr::get_mmio_address_from_base(base_address)?
527 + (bp_unit_index * size_of::<u32>()) as u64;
528 let bp_control_addr = Dbgbcr::get_mmio_address_from_base(base_address)?
529 + (bp_unit_index * size_of::<u32>()) as u64;
530 let mut bp_control = Dbgbcr(0);
531
532 bp_control.set_bt(0b0000);
534 bp_control.set_hmc(true);
536 bp_control.set_pmc(0b11);
537 bp_control.set_bas(0b1111);
539 bp_control.set_e(true);
541
542 memory.write_word_32(bp_value_addr, addr)?;
543 memory.write_word_32(bp_control_addr, bp_control.into())?;
544
545 Ok(())
546}
547
548pub(crate) fn clear_hw_breakpoint(
550 memory: &mut dyn ArmMemoryInterface,
551 base_address: u64,
552 bp_unit_index: usize,
553) -> Result<(), ArmError> {
554 let bp_value_addr = Dbgbvr::get_mmio_address_from_base(base_address)?
555 + (bp_unit_index * size_of::<u32>()) as u64;
556 let bp_control_addr = Dbgbcr::get_mmio_address_from_base(base_address)?
557 + (bp_unit_index * size_of::<u32>()) as u64;
558
559 memory.write_word_32(bp_value_addr, 0)?;
560 memory.write_word_32(bp_control_addr, 0)?;
561 Ok(())
562}
563
564pub(crate) fn get_hw_breakpoint(
566 memory: &mut dyn ArmMemoryInterface,
567 base_address: u64,
568 bp_unit_index: usize,
569) -> Result<Option<u32>, ArmError> {
570 let bp_value_addr = Dbgbvr::get_mmio_address_from_base(base_address)?
571 + (bp_unit_index * size_of::<u32>()) as u64;
572 let bp_value = memory.read_word_32(bp_value_addr)?;
573
574 let bp_control_addr = Dbgbcr::get_mmio_address_from_base(base_address)?
575 + (bp_unit_index * size_of::<u32>()) as u64;
576 let bp_control = Dbgbcr(memory.read_word_32(bp_control_addr)?);
577
578 Ok(if bp_control.e() { Some(bp_value) } else { None })
579}
580
581fn check_and_clear_data_abort(
582 memory: &mut dyn ArmMemoryInterface,
583 base_address: u64,
584 dbgdscr: Dbgdscr,
585) -> Result<(), ArmError> {
586 if dbgdscr.adabort_l() || dbgdscr.sdabort_l() || dbgdscr.und_l() {
588 let address = Dbgdrcr::get_mmio_address_from_base(base_address)?;
589 let mut dbgdrcr = Dbgdrcr(0);
590 dbgdrcr.set_cse(true);
591
592 memory.write_word_32(address, dbgdrcr.into())?;
593 return Err(ArmError::Armv7ar(
594 crate::architecture::arm::armv7ar::Armv7arError::DataAbort,
595 ));
596 }
597 Ok(())
598}
599
600fn execute_instruction(
602 memory: &mut dyn ArmMemoryInterface,
603 base_address: u64,
604 instruction: u32,
605) -> Result<Dbgdscr, ArmError> {
606 let address = Dbgitr::get_mmio_address_from_base(base_address)?;
608 memory.write_word_32(address, instruction)?;
609
610 let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
612 let mut dbgdscr = Dbgdscr(memory.read_word_32(address)?);
613
614 let start = Instant::now();
615 while !dbgdscr.instrcoml_l() {
616 dbgdscr = Dbgdscr(memory.read_word_32(address)?);
617 check_and_clear_data_abort(memory, base_address, dbgdscr)?;
619 if start.elapsed() >= OPERATION_TIMEOUT {
620 return Err(ArmError::Timeout);
621 }
622 }
623
624 check_and_clear_data_abort(memory, base_address, dbgdscr)?;
626
627 Ok(dbgdscr)
628}
629
630fn set_instruction_input(
633 memory: &mut dyn ArmMemoryInterface,
634 base_address: u64,
635 value: u32,
636) -> Result<(), ArmError> {
637 let address = Dbgdtrrx::get_mmio_address_from_base(base_address)?;
639 memory.write_word_32(address, value)?;
640
641 let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
643 let mut dbgdscr = Dbgdscr(memory.read_word_32(address)?);
644
645 let start = Instant::now();
646 while !dbgdscr.rxfull_l() {
647 dbgdscr = Dbgdscr(memory.read_word_32(address)?);
648 check_and_clear_data_abort(memory, base_address, dbgdscr)?;
650 if start.elapsed() >= OPERATION_TIMEOUT {
651 return Err(ArmError::Timeout);
652 }
653 }
654
655 Ok(())
656}
657
658fn get_instruction_result(
661 memory: &mut dyn ArmMemoryInterface,
662 base_address: u64,
663) -> Result<u32, ArmError> {
664 let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
666 let start = Instant::now();
667 loop {
668 let dbgdscr = Dbgdscr(memory.read_word_32(address)?);
669 if dbgdscr.txfull_l() {
670 break;
671 }
672 if start.elapsed() > OPERATION_TIMEOUT {
673 return Err(ArmError::Timeout);
674 }
675 }
676
677 let address = Dbgdtrtx::get_mmio_address_from_base(base_address)?;
679 memory.read_word_32(address)
680}
681
682pub(crate) fn write_word_32(
685 memory: &mut dyn ArmMemoryInterface,
686 base_address: u64,
687 address: u32,
688 data: u32,
689) -> Result<(), ArmError> {
690 set_instruction_input(memory, base_address, address)?;
692 execute_instruction(memory, base_address, build_mrc(14, 0, 0, 0, 5, 0))?;
693
694 set_instruction_input(memory, base_address, data)?;
697 execute_instruction(memory, base_address, build_stc(14, 5, 0, 4))?;
698 Ok(())
699}
700
701pub(crate) fn read_word_32(
704 memory: &mut dyn ArmMemoryInterface,
705 base_address: u64,
706 address: u32,
707) -> Result<u32, ArmError> {
708 set_instruction_input(memory, base_address, address)?;
710 execute_instruction(memory, base_address, build_mrc(14, 0, 0, 0, 5, 0))?;
711
712 execute_instruction(memory, base_address, build_ldc(14, 5, 0, 4))?;
715 get_instruction_result(memory, base_address)
716}
717
718impl CoreInterface for Armv7ar<'_> {
719 fn wait_for_core_halted(&mut self, timeout: Duration) -> Result<(), Error> {
720 wait_for_core_halted(&mut *self.memory, self.base_address, timeout).map_err(|e| e.into())
721 }
722
723 fn core_halted(&mut self) -> Result<bool, Error> {
724 core_halted(&mut *self.memory, self.base_address).map_err(|e| e.into())
725 }
726
727 fn status(&mut self) -> Result<crate::core::CoreStatus, Error> {
728 let address = Dbgdscr::get_mmio_address_from_base(self.base_address)?;
730 let dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
731
732 if dbgdscr.halted() {
733 let mut reason = dbgdscr.halt_reason();
734
735 self.set_core_status(CoreStatus::Halted(reason));
737
738 self.read_fp_reg_count()?;
739
740 if let HaltReason::Exception = reason {
742 let lr: u32 = self.read_core_reg(RegisterId(14))?.try_into()?;
743
744 self.state.semihosting_command =
745 check_for_semihosting(self.state.semihosting_command.take(), self, lr)?;
746 if let Some(command) = self.state.semihosting_command {
747 reason = HaltReason::Breakpoint(BreakpointCause::Semihosting(command));
748 self.set_core_status(CoreStatus::Halted(reason));
749 }
750 }
751
752 return Ok(CoreStatus::Halted(reason));
753 }
754 if self.state.current_state.is_halted() {
756 tracing::warn!("Core is running, but we expected it to be halted");
757 }
758
759 self.set_core_status(CoreStatus::Running);
760
761 Ok(CoreStatus::Running)
762 }
763
764 fn halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
765 if !matches!(self.state.current_state, CoreStatus::Halted(_)) {
766 request_halt(&mut *self.memory, self.base_address)?;
767 self.wait_for_core_halted(timeout)?;
768
769 self.reset_register_cache();
771 }
772 let _ = self.status()?;
774
775 let pc_value = self.read_core_reg(self.program_counter().into())?;
777
778 Ok(CoreInformation {
780 pc: pc_value.try_into()?,
781 })
782 }
783
784 fn run(&mut self) -> Result<(), Error> {
785 if matches!(self.state.current_state, CoreStatus::Running) {
786 return Ok(());
787 }
788
789 if self.state.semihosting_command.is_some() {
790 let lr: u32 = self.read_core_reg(RegisterId(14))?.try_into()?;
798
799 self.prepare_for_clobber(0)?;
801
802 let mrs_spsr = build_mrs_spsr(0);
804 self.execute_instruction(mrs_spsr)?;
805
806 let msr_cpsr = build_msr(0);
808 self.execute_instruction(msr_cpsr)?;
809
810 self.write_core_reg(self.program_counter().into(), lr.into())?;
812
813 tracing::debug!(
814 "Semihosting resume: restoring CPSR from SPSR, setting PC to LR={:#x}",
815 lr
816 );
817 }
818
819 self.state.semihosting_command = None;
821
822 self.writeback_registers()?;
824
825 if self.itr_enabled {
827 let address = Dbgdscr::get_mmio_address_from_base(self.base_address)?;
828 let mut dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
829 dbgdscr.set_itren(false);
830 self.memory.write_word_32(address, dbgdscr.into())?;
831 self.itr_enabled = false;
832 }
833
834 run(&mut *self.memory, self.base_address)?;
835
836 self.set_core_status(CoreStatus::Running);
838 let _ = self.status()?;
839
840 Ok(())
841 }
842
843 fn reset(&mut self) -> Result<(), Error> {
844 self.sequence.reset_system(
845 &mut *self.memory,
846 crate::CoreType::Armv7a,
847 Some(self.base_address),
848 )?;
849
850 self.reset_register_cache();
852
853 self.set_core_status(CoreStatus::Running);
855 let _ = self.status()?;
856
857 Ok(())
858 }
859
860 fn reset_and_halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
861 self.sequence.reset_catch_set(
862 &mut *self.memory,
863 crate::CoreType::Armv7a,
864 Some(self.base_address),
865 )?;
866 self.sequence.reset_system(
867 &mut *self.memory,
868 crate::CoreType::Armv7a,
869 Some(self.base_address),
870 )?;
871
872 if !self.core_halted()? {
873 tracing::warn!("Core not halted after reset, platform-specific setup may be required");
874 tracing::warn!("Requesting halt anyway, but system may already be initialised");
875 let address = Dbgdrcr::get_mmio_address_from_base(self.base_address)?;
876 let mut value = Dbgdrcr(0);
877 value.set_hrq(true);
878 self.memory.write_word_32(address, value.into())?;
879 }
880
881 self.sequence.reset_catch_clear(
882 &mut *self.memory,
883 crate::CoreType::Armv7a,
884 Some(self.base_address),
885 )?;
886 self.wait_for_core_halted(timeout)?;
887
888 self.reset_register_cache();
889
890 self.state.semihosting_command = None;
892
893 let _ = self.status()?;
894
895 let pc_value = self.read_core_reg(self.program_counter().into())?;
897
898 Ok(CoreInformation {
900 pc: pc_value.try_into()?,
901 })
902 }
903
904 fn step(&mut self) -> Result<CoreInformation, Error> {
905 let bp_unit_index = (self.available_breakpoint_units()? - 1) as usize;
907 let bp_value_addr = Dbgbvr::get_mmio_address_from_base(self.base_address)?
908 + (bp_unit_index * size_of::<u32>()) as u64;
909 let saved_bp_value = self.memory.read_word_32(bp_value_addr)?;
910
911 let bp_control_addr = Dbgbcr::get_mmio_address_from_base(self.base_address)?
912 + (bp_unit_index * size_of::<u32>()) as u64;
913 let saved_bp_control = self.memory.read_word_32(bp_control_addr)?;
914
915 let current_pc: u32 = self
917 .read_core_reg(self.program_counter().into())?
918 .try_into()?;
919 let mut bp_control = Dbgbcr(0);
920
921 bp_control.set_bt(0b0100);
923 bp_control.set_hmc(true);
925 bp_control.set_pmc(0b11);
926 bp_control.set_bas(0b1111);
928 bp_control.set_e(true);
930
931 self.memory.write_word_32(bp_value_addr, current_pc)?;
932 self.memory
933 .write_word_32(bp_control_addr, bp_control.into())?;
934
935 self.run()?;
937
938 self.wait_for_core_halted(Duration::from_millis(100))?;
940
941 self.memory.write_word_32(bp_value_addr, saved_bp_value)?;
943 self.memory
944 .write_word_32(bp_control_addr, saved_bp_control)?;
945
946 let pc_value = self.read_core_reg(self.program_counter().into())?;
948
949 Ok(CoreInformation {
951 pc: pc_value.try_into()?,
952 })
953 }
954
955 fn read_core_reg(&mut self, address: RegisterId) -> Result<RegisterValue, Error> {
956 let reg_num = address.0;
957
958 if (reg_num as usize) < self.state.register_cache.len()
960 && let Some(cached_result) = self.state.register_cache[reg_num as usize]
961 {
962 return Ok(cached_result.0);
963 }
964
965 let result: Result<RegisterValue, Error> = match reg_num {
967 0..=14 => {
968 let instruction = build_mcr(14, 0, reg_num, 0, 5, 0);
971
972 let val = self.execute_instruction_with_result(instruction)?;
973
974 Ok(val.into())
975 }
976 15 => {
977 self.prepare_r0_for_clobber()?;
979
980 let instruction = build_mov(0, 15);
982 self.execute_instruction(instruction)?;
983
984 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
986 let pra_plus_offset = self.execute_instruction_with_result(instruction)?;
987
988 Ok((pra_plus_offset - 8).into())
990 }
991 16 => {
992 self.prepare_r0_for_clobber()?;
994
995 let instruction = build_mrs(0);
997 self.execute_instruction(instruction)?;
998
999 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
1001 let cpsr = self.execute_instruction_with_result(instruction)?;
1002
1003 Ok(cpsr.into())
1004 }
1005 17..=48 => {
1006 self.prepare_for_clobber(0)?;
1008 self.prepare_for_clobber(1)?;
1009
1010 let fpexc: u32 = self.read_core_reg(50.into())?.try_into()?;
1012 if (fpexc & (1 << 30)) == 0 {
1013 return Ok(0u32.into());
1015 }
1016
1017 let instruction = build_vmov(1, 0, 1, reg_num - 17);
1019 self.execute_instruction(instruction)?;
1020
1021 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
1023 let mut value = self.execute_instruction_with_result(instruction)? as u64;
1024
1025 let instruction = build_mcr(14, 0, 1, 0, 5, 0);
1027 value |= (self.execute_instruction_with_result(instruction)? as u64) << 32;
1028
1029 Ok(value.into())
1030 }
1031 49 => {
1032 self.prepare_for_clobber(0)?;
1034
1035 let fpexc: u32 = self.read_core_reg(50.into())?.try_into()?;
1037 if (fpexc & (1 << 30)) == 0 {
1038 return Ok(0u32.into());
1040 }
1041
1042 let instruction = build_vmrs(0, 1);
1044 self.execute_instruction(instruction)?;
1045
1046 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
1048 let value = self.execute_instruction_with_result(instruction)?;
1049
1050 Ok(value.into())
1051 }
1052 50 => {
1053 self.prepare_for_clobber(0)?;
1055
1056 let instruction = build_vmrs(0, 0b1000);
1058 self.execute_instruction(instruction)?;
1059
1060 let instruction = build_mcr(14, 0, 0, 0, 5, 0);
1061 let value = self.execute_instruction_with_result(instruction)?;
1062
1063 Ok(value.into())
1064 }
1065 _ => Err(Error::Arm(
1066 Armv7arError::InvalidRegisterNumber(reg_num).into(),
1067 )),
1068 };
1069
1070 if let Ok(value) = result {
1071 self.state.register_cache[reg_num as usize] = Some((value, false));
1072
1073 Ok(value)
1074 } else {
1075 Err(result.err().unwrap())
1076 }
1077 }
1078
1079 fn write_core_reg(&mut self, address: RegisterId, value: RegisterValue) -> Result<(), Error> {
1080 let reg_num = address.0;
1081
1082 if (reg_num as usize) >= self.state.register_cache.len() {
1083 return Err(Error::Arm(
1084 Armv7arError::InvalidRegisterNumber(reg_num).into(),
1085 ));
1086 }
1087 self.state.register_cache[reg_num as usize] = Some((value, true));
1088
1089 Ok(())
1090 }
1091
1092 fn available_breakpoint_units(&mut self) -> Result<u32, Error> {
1093 if self.num_breakpoints.is_none() {
1094 let address = Dbgdidr::get_mmio_address_from_base(self.base_address)?;
1095 let dbgdidr = Dbgdidr(self.memory.read_word_32(address)?);
1096
1097 self.num_breakpoints = Some(dbgdidr.brps() + 1);
1098 }
1099 Ok(self.num_breakpoints.unwrap())
1100 }
1101
1102 fn hw_breakpoints(&mut self) -> Result<Vec<Option<u64>>, Error> {
1104 let mut breakpoints = vec![];
1105 let num_hw_breakpoints = self.available_breakpoint_units()? as usize;
1106
1107 for bp_unit_index in 0..num_hw_breakpoints {
1108 let bp_value_addr = Dbgbvr::get_mmio_address_from_base(self.base_address)?
1109 + (bp_unit_index * size_of::<u32>()) as u64;
1110 let bp_value = self.memory.read_word_32(bp_value_addr)?;
1111
1112 let bp_control_addr = Dbgbcr::get_mmio_address_from_base(self.base_address)?
1113 + (bp_unit_index * size_of::<u32>()) as u64;
1114 let bp_control = Dbgbcr(self.memory.read_word_32(bp_control_addr)?);
1115
1116 if bp_control.e() {
1117 breakpoints.push(Some(bp_value as u64));
1118 } else {
1119 breakpoints.push(None);
1120 }
1121 }
1122 Ok(breakpoints)
1123 }
1124
1125 fn enable_breakpoints(&mut self, _state: bool) -> Result<(), Error> {
1126 Ok(())
1128 }
1129
1130 fn set_hw_breakpoint(&mut self, bp_unit_index: usize, addr: u64) -> Result<(), Error> {
1131 let addr = valid_32bit_address(addr)?;
1132 set_hw_breakpoint(&mut *self.memory, self.base_address, bp_unit_index, addr)?;
1133 Ok(())
1134 }
1135
1136 fn clear_hw_breakpoint(&mut self, bp_unit_index: usize) -> Result<(), Error> {
1137 clear_hw_breakpoint(&mut *self.memory, self.base_address, bp_unit_index)?;
1138 Ok(())
1139 }
1140
1141 fn registers(&self) -> &'static CoreRegisters {
1142 match self.state.fp_reg_count {
1143 16 => &AARCH32_WITH_FP_16_CORE_REGISTERS,
1144 32 => &AARCH32_WITH_FP_32_CORE_REGISTERS,
1145 _ => &AARCH32_CORE_REGISTERS,
1146 }
1147 }
1148
1149 fn program_counter(&self) -> &'static CoreRegister {
1150 &PC
1151 }
1152
1153 fn frame_pointer(&self) -> &'static CoreRegister {
1154 &FP
1155 }
1156
1157 fn stack_pointer(&self) -> &'static CoreRegister {
1158 &SP
1159 }
1160
1161 fn return_address(&self) -> &'static CoreRegister {
1162 &RA
1163 }
1164
1165 fn hw_breakpoints_enabled(&self) -> bool {
1166 true
1167 }
1168
1169 fn architecture(&self) -> Architecture {
1170 Architecture::Arm
1171 }
1172
1173 fn core_type(&self) -> CoreType {
1174 self.core_type
1175 }
1176
1177 fn instruction_set(&mut self) -> Result<InstructionSet, Error> {
1178 let cpsr: u32 = self.read_core_reg(XPSR.id())?.try_into()?;
1179
1180 match (cpsr >> 5) & 1 {
1182 1 => Ok(InstructionSet::Thumb2),
1183 _ => Ok(InstructionSet::A32),
1184 }
1185 }
1186
1187 fn endianness(&mut self) -> Result<Endian, Error> {
1188 if let Some(endianness) = self.endianness {
1189 return Ok(endianness);
1190 }
1191 self.halted_access(|core| {
1192 let endianness = {
1193 let psr = TryInto::<u32>::try_into(core.read_core_reg(XPSR.id())?).unwrap();
1194 if psr & 1 << 9 == 0 {
1195 Endian::Little
1196 } else {
1197 Endian::Big
1198 }
1199 };
1200 core.endianness = Some(endianness);
1201 Ok(endianness)
1202 })
1203 }
1204
1205 fn fpu_support(&mut self) -> Result<bool, Error> {
1206 Ok(self.state.fp_reg_count != 0)
1207 }
1208
1209 fn floating_point_register_count(&mut self) -> Result<usize, Error> {
1210 Ok(self.state.fp_reg_count)
1211 }
1212
1213 #[tracing::instrument(skip(self))]
1214 fn reset_catch_set(&mut self) -> Result<(), Error> {
1215 self.halted_access(|core| {
1216 core.sequence.reset_catch_set(
1217 &mut *core.memory,
1218 CoreType::Armv7a,
1219 Some(core.base_address),
1220 )?;
1221 Ok(())
1222 })?;
1223 Ok(())
1224 }
1225
1226 #[tracing::instrument(skip(self))]
1227 fn reset_catch_clear(&mut self) -> Result<(), Error> {
1228 self.halted_access(|core| {
1230 core.sequence.reset_catch_clear(
1231 &mut *core.memory,
1232 CoreType::Armv7a,
1233 Some(core.base_address),
1234 )?;
1235 Ok(())
1236 })?;
1237 Ok(())
1238 }
1239
1240 #[tracing::instrument(skip(self))]
1241 fn debug_core_stop(&mut self) -> Result<(), Error> {
1242 if matches!(self.state.current_state, CoreStatus::Halted(_)) {
1243 self.writeback_registers()?;
1246 }
1247
1248 self.sequence
1249 .debug_core_stop(&mut *self.memory, CoreType::Armv7a)?;
1250
1251 Ok(())
1252 }
1253
1254 fn enable_vector_catch(&mut self, condition: VectorCatchCondition) -> Result<(), Error> {
1255 let address = Dbgvcr::get_mmio_address_from_base(self.base_address)?;
1256 let mut dbgvcr = Dbgvcr(self.memory.read_word_32(address)?);
1257
1258 match condition {
1259 VectorCatchCondition::CoreReset => dbgvcr.set_r(true),
1260 VectorCatchCondition::Svc => dbgvcr.set_ss(true),
1261 VectorCatchCondition::Hlt => dbgvcr.set_su(true),
1262 _ => {
1264 return Err(Error::NotImplemented(
1265 "vector catch condition Hardfault/SecureFault",
1266 ));
1267 }
1268 }
1269
1270 self.memory.write_word_32(address, dbgvcr.into())?;
1271 Ok(())
1272 }
1273
1274 fn disable_vector_catch(&mut self, condition: VectorCatchCondition) -> Result<(), Error> {
1275 let address = Dbgvcr::get_mmio_address_from_base(self.base_address)?;
1276 let mut dbgvcr = Dbgvcr(self.memory.read_word_32(address)?);
1277
1278 match condition {
1279 VectorCatchCondition::CoreReset => dbgvcr.set_r(false),
1280 VectorCatchCondition::Svc => dbgvcr.set_ss(false),
1281 VectorCatchCondition::Hlt => dbgvcr.set_su(false),
1282 _ => {
1284 return Err(Error::NotImplemented(
1285 "vector catch condition Hardfault/SecureFault",
1286 ));
1287 }
1288 }
1289
1290 self.memory.write_word_32(address, dbgvcr.into())?;
1291 Ok(())
1292 }
1293}
1294
1295impl MemoryInterface for Armv7ar<'_> {
1296 fn supports_native_64bit_access(&mut self) -> bool {
1297 false
1298 }
1299
1300 fn read_word_64(&mut self, address: u64) -> Result<u64, Error> {
1301 self.halted_access(|core| {
1302 #[repr(align(4))]
1303 struct AlignedBytes([u8; 8]);
1304 let mut bytes = AlignedBytes([0u8; 8]);
1305 core.read(address, &mut bytes.0)?;
1306 let ret = match core.endianness()? {
1307 Endian::Little => u64::from_le_bytes(bytes.0),
1308 Endian::Big => u64::from_be_bytes(bytes.0),
1309 };
1310
1311 Ok(ret)
1312 })
1313 }
1314
1315 fn read_word_32(&mut self, address: u64) -> Result<u32, Error> {
1316 self.halted_access(|core| {
1317 let address = valid_32bit_address(address)?;
1318
1319 let instr = build_ldc(14, 5, 0, 4);
1321
1322 core.prepare_r0_for_clobber()?;
1324
1325 core.set_r0(address)?;
1327
1328 core.execute_instruction_with_result(instr)
1330 })
1331 }
1332
1333 fn read_word_16(&mut self, address: u64) -> Result<u16, Error> {
1334 self.halted_access(|core| {
1335 let mut byte_offset = address % 4;
1337 let word_start = address - byte_offset;
1338
1339 let data = core.read_word_32(word_start)?;
1341
1342 if Endian::Big == core.endianness()? {
1345 if address & 1 != 0 {
1347 return Err(Error::MemoryNotAligned(MemoryNotAlignedError {
1348 address,
1349 alignment: 2,
1350 }));
1351 }
1352 byte_offset = 2 - byte_offset;
1353 }
1354
1355 Ok((data >> (byte_offset * 8)) as u16)
1357 })
1358 }
1359
1360 fn read_word_8(&mut self, address: u64) -> Result<u8, Error> {
1361 self.halted_access(|core| {
1362 let mut byte_offset = address % 4;
1364
1365 let word_start = address - byte_offset;
1366
1367 let data = core.read_word_32(word_start)?;
1369
1370 if Endian::Big == core.endianness()? {
1373 byte_offset = 3 - byte_offset;
1374 }
1375
1376 Ok(data.to_le_bytes()[byte_offset as usize])
1378 })
1379 }
1380
1381 fn read_64(&mut self, address: u64, data: &mut [u64]) -> Result<(), Error> {
1382 self.halted_access(|core| {
1383 for (i, word) in data.iter_mut().enumerate() {
1384 *word = core.read_word_64(address + ((i as u64) * 8))?;
1385 }
1386
1387 Ok(())
1388 })
1389 }
1390
1391 fn read_32(&mut self, address: u64, data: &mut [u32]) -> Result<(), Error> {
1392 self.halted_access(|core| {
1393 let count = data.len();
1394 if count > 2 {
1395 core.prepare_r0_for_clobber()?;
1397 core.set_r0(valid_32bit_address(address)?)?;
1398
1399 let mut banked = core.banked_access()?;
1400
1401 if banked
1404 .with_dcc_fast_mode(|banked| {
1405 banked.set_itr(build_ldc(14, 5, 0, 4))?;
1407
1408 let _ = banked.dtrtx()?;
1410
1411 banked.dtrtx_repeated(&mut data[0..count - 1])?;
1416 Ok(())
1417 })
1418 .is_ok()
1419 {
1420 if let Ok(last) = banked.dtrtx()
1424 && let Some(v) = data.last_mut()
1425 {
1426 *v = last;
1427 }
1428 }
1429
1430 let dscr = banked.dscr()?;
1432 check_and_clear_data_abort(&mut *core.memory, core.base_address, dscr)?;
1433 } else {
1434 for (i, word) in data.iter_mut().enumerate() {
1435 *word = core.read_word_32(address + ((i as u64) * 4))?;
1436 }
1437 }
1438
1439 Ok(())
1440 })
1441 }
1442
1443 fn read_16(&mut self, address: u64, data: &mut [u16]) -> Result<(), Error> {
1444 self.halted_access(|core| {
1445 for (i, word) in data.iter_mut().enumerate() {
1446 *word = core.read_word_16(address + ((i as u64) * 2))?;
1447 }
1448
1449 Ok(())
1450 })
1451 }
1452
1453 fn read_8(&mut self, address: u64, data: &mut [u8]) -> Result<(), Error> {
1454 self.read(address, data)
1455 }
1456
1457 fn read(&mut self, address: u64, data: &mut [u8]) -> Result<(), Error> {
1458 self.halted_access(|core| {
1459 if address.is_multiple_of(4) && data.len().is_multiple_of(4) {
1460 if let Ok((aligned_buffer, _)) =
1462 <[u32]>::mut_from_prefix_with_elems(data, data.len() / 4)
1463 {
1464 core.read_32(address, aligned_buffer)?;
1465 } else {
1466 let mut temporary_buffer = vec![0u32; data.len() / 4];
1467 core.read_32(address, &mut temporary_buffer)?;
1468 data.copy_from_slice(temporary_buffer.as_bytes());
1469 }
1470
1471 if core.endianness()? == Endian::Big {
1473 for word in data.chunks_exact_mut(4) {
1474 word.reverse();
1475 }
1476 }
1477 } else {
1478 let start_address = address & !3;
1479 let end_address = address + (data.len() as u64);
1480 let end_address = end_address + (4 - (end_address & 3));
1481 let start_extra_count = address as usize % 4;
1482 let mut buffer = vec![0u32; (end_address - start_address) as usize / 4];
1483 core.read_32(start_address, &mut buffer)?;
1484 if core.endianness()? == Endian::Big {
1485 for word in buffer.iter_mut() {
1486 *word = word.swap_bytes();
1487 }
1488 }
1489 data.copy_from_slice(
1490 &buffer.as_bytes()[start_extra_count..start_extra_count + data.len()],
1491 );
1492 }
1493 Ok(())
1494 })
1495 }
1496
1497 fn write_word_64(&mut self, address: u64, data: u64) -> Result<(), Error> {
1498 self.halted_access(|core| {
1499 let (data_low, data_high) = match core.endianness()? {
1500 Endian::Little => (data as u32, (data >> 32) as u32),
1501 Endian::Big => ((data >> 32) as u32, data as u32),
1502 };
1503
1504 core.write_32(address, &[data_low, data_high])
1505 })
1506 }
1507
1508 fn write_word_32(&mut self, address: u64, data: u32) -> Result<(), Error> {
1509 self.halted_access(|core| {
1510 let address = valid_32bit_address(address)?;
1511
1512 let instr = build_stc(14, 5, 0, 4);
1514
1515 core.prepare_r0_for_clobber()?;
1517
1518 core.set_r0(address)?;
1520
1521 core.execute_instruction_with_input(instr, data)
1523 })
1524 }
1525
1526 fn write_word_8(&mut self, address: u64, data: u8) -> Result<(), Error> {
1527 self.halted_access(|core| {
1528 let mut byte_offset = address % 4;
1530 let word_start = address - byte_offset;
1531
1532 if Endian::Big == core.endianness()? {
1535 byte_offset = 3 - byte_offset;
1536 }
1537
1538 let current_word = core.read_word_32(word_start)?;
1540 let mut word_bytes = current_word.to_le_bytes();
1541 word_bytes[byte_offset as usize] = data;
1542
1543 core.write_word_32(word_start, u32::from_le_bytes(word_bytes))
1544 })
1545 }
1546
1547 fn write_word_16(&mut self, address: u64, data: u16) -> Result<(), Error> {
1548 self.halted_access(|core| {
1549 let mut byte_offset = address % 4;
1551 let word_start = address - byte_offset;
1552
1553 if Endian::Big == core.endianness()? {
1556 if address & 1 != 0 {
1558 return Err(Error::MemoryNotAligned(MemoryNotAlignedError {
1559 address,
1560 alignment: 2,
1561 }));
1562 }
1563 byte_offset = 2 - byte_offset;
1564 }
1565
1566 let mut word = core.read_word_32(word_start)?;
1568
1569 word &= !(0xFFFFu32 << (byte_offset * 8));
1571 word |= (data as u32) << (byte_offset * 8);
1572
1573 core.write_word_32(word_start, word)
1574 })
1575 }
1576
1577 fn write_64(&mut self, address: u64, data: &[u64]) -> Result<(), Error> {
1578 self.halted_access(|core| {
1579 for (i, word) in data.iter().enumerate() {
1580 core.write_word_64(address + ((i as u64) * 8), *word)?;
1581 }
1582
1583 Ok(())
1584 })
1585 }
1586
1587 fn write_32(&mut self, address: u64, data: &[u32]) -> Result<(), Error> {
1588 self.halted_access(|core| {
1589 if data.len() > 2 {
1590 core.prepare_r0_for_clobber()?;
1592 core.set_r0(valid_32bit_address(address)?)?;
1593
1594 let mut banked = core.banked_access()?;
1595
1596 banked
1597 .with_dcc_fast_mode(|banked| {
1598 banked.set_itr(build_stc(14, 5, 0, 4))?;
1600
1601 banked.set_dtrrx_repeated(data)?;
1603 Ok(())
1604 })
1605 .ok();
1606
1607 let dscr = banked.dscr()?;
1609 check_and_clear_data_abort(&mut *core.memory, core.base_address, dscr)?;
1610 } else {
1611 for (i, word) in data.iter().enumerate() {
1613 core.write_word_32(address + ((i as u64) * 4), *word)?;
1614 }
1615 }
1616
1617 Ok(())
1618 })
1619 }
1620
1621 fn write_16(&mut self, address: u64, data: &[u16]) -> Result<(), Error> {
1622 self.halted_access(|core| {
1623 for (i, word) in data.iter().enumerate() {
1624 core.write_word_16(address + ((i as u64) * 2), *word)?;
1625 }
1626
1627 Ok(())
1628 })
1629 }
1630
1631 fn write_8(&mut self, address: u64, data: &[u8]) -> Result<(), Error> {
1632 self.write(address, data)
1633 }
1634
1635 fn write(&mut self, address: u64, data: &[u8]) -> Result<(), Error> {
1636 self.halted_access(|core| {
1637 let len = data.len();
1638 let start_extra_count = ((4 - (address % 4) as usize) % 4).min(len);
1639 let end_extra_count = (len - start_extra_count) % 4;
1640 assert!(start_extra_count < 4);
1641 assert!(end_extra_count < 4);
1642
1643 if start_extra_count != 0 || end_extra_count != 0 {
1645 for (i, byte) in data.iter().enumerate() {
1646 core.write_word_8(address + (i as u64), *byte)?;
1647 }
1648 return Ok(());
1649 }
1650
1651 let mut buffer = vec![0u32; data.len() / 4];
1654 let endianness = core.endianness()?;
1655 for (bytes, value) in data.chunks_exact(4).zip(buffer.iter_mut()) {
1656 *value = match endianness {
1657 Endian::Little => u32::from_le_bytes(bytes.try_into().unwrap()),
1658 Endian::Big => u32::from_be_bytes(bytes.try_into().unwrap()),
1659 }
1660 }
1661 core.write_32(address, &buffer)?;
1662
1663 Ok(())
1664 })
1665 }
1666
1667 fn supports_8bit_transfers(&self) -> Result<bool, Error> {
1668 Ok(false)
1669 }
1670
1671 fn flush(&mut self) -> Result<(), Error> {
1672 Ok(())
1674 }
1675}
1676
1677pub(crate) fn check_for_semihosting(
1686 cached_command: Option<SemihostingCommand>,
1687 core: &mut dyn CoreInterface,
1688 lr: u32,
1689) -> Result<Option<SemihostingCommand>, Error> {
1690 if let Some(command) = cached_command {
1692 return Ok(Some(command));
1693 }
1694
1695 let pc: u32 = core.read_core_reg(core.program_counter().id)?.try_into()?;
1702
1703 const UNDEF_VECTOR_OFFSET: u32 = 0x04;
1704 const SVC_VECTOR_OFFSET: u32 = 0x08;
1705 const VECTOR_TABLE_MASK: u32 = 32 - 1;
1706
1707 let vector_offset = pc & VECTOR_TABLE_MASK;
1708
1709 if vector_offset != UNDEF_VECTOR_OFFSET && vector_offset != SVC_VECTOR_OFFSET {
1712 tracing::debug!(
1713 "Vector catch at PC={:#x} (offset {:#x}), not SVC/UNDEF vector, not semihosting",
1714 pc,
1715 vector_offset
1716 );
1717 return Ok(None);
1718 }
1719
1720 const ARM_SEMIHOSTING_SVC: [u8; 4] = 0xEF123456_u32.to_le_bytes();
1728 const THUMB_SEMIHOSTING_SVC: [u8; 2] = 0xDFAB_u16.to_le_bytes();
1729 const ARM_SEMIHOSTING_HLT: [u8; 4] = 0xE10F0070_u32.to_le_bytes();
1730 const THUMB_SEMIHOSTING_HLT: [u8; 2] = 0xBABC_u16.to_le_bytes();
1731
1732 let instruction_address = lr.wrapping_sub(4);
1734 let mut instruction = [0u8; 4];
1735 core.read_8(instruction_address as u64, &mut instruction)?;
1736
1737 let (is_semihosting, mechanism) = match vector_offset {
1738 SVC_VECTOR_OFFSET => {
1739 let is_arm = instruction == ARM_SEMIHOSTING_SVC;
1740 let is_thumb = instruction[2..] == THUMB_SEMIHOSTING_SVC;
1741 (is_arm || is_thumb, "SVC")
1742 }
1743 UNDEF_VECTOR_OFFSET => {
1744 let is_arm = instruction == ARM_SEMIHOSTING_HLT;
1745 let is_thumb = instruction[2..] == THUMB_SEMIHOSTING_HLT;
1746 (is_arm || is_thumb, "HLT")
1747 }
1748 _ => unreachable!(), };
1750
1751 if !is_semihosting {
1752 return Ok(None);
1753 }
1754
1755 tracing::debug!(
1756 "{} instruction check: LR={:#x}, bytes at {:#x} = {:#010x}, match={}",
1757 mechanism,
1758 lr,
1759 instruction_address,
1760 u32::from_le_bytes(instruction),
1761 is_semihosting
1762 );
1763
1764 let command = decode_semihosting_syscall(core)?;
1765 tracing::debug!(
1766 "Semihosting {} detected at PC={:#x}: {:?}",
1767 mechanism,
1768 pc,
1769 command
1770 );
1771 Ok(Some(command))
1772}
1773
1774#[cfg(test)]
1775mod test {
1776 use crate::{
1777 architecture::arm::{
1778 FullyQualifiedApAddress, communication_interface::SwdSequence,
1779 sequences::DefaultArmSequence,
1780 },
1781 probe::DebugProbeError,
1782 };
1783
1784 use super::*;
1785
1786 const TEST_BASE_ADDRESS: u64 = 0x8000_1000;
1787
1788 fn address_to_reg_num(address: u64) -> u32 {
1789 ((address - TEST_BASE_ADDRESS) / 4) as u32
1790 }
1791
1792 #[derive(Debug)]
1793 pub struct ExpectedMemoryOp {
1794 read: bool,
1795 address: u64,
1796 value: u32,
1797 }
1798
1799 pub struct MockProbe {
1800 expected_ops: Vec<ExpectedMemoryOp>,
1801 }
1802
1803 impl MockProbe {
1804 pub fn new() -> Self {
1805 MockProbe {
1806 expected_ops: vec![],
1807 }
1808 }
1809
1810 pub fn expected_read(&mut self, addr: u64, value: u32) {
1811 self.expected_ops.push(ExpectedMemoryOp {
1812 read: true,
1813 address: addr,
1814 value,
1815 });
1816 }
1817
1818 pub fn expected_write(&mut self, addr: u64, value: u32) {
1819 self.expected_ops.push(ExpectedMemoryOp {
1820 read: false,
1821 address: addr,
1822 value,
1823 });
1824 }
1825 }
1826
1827 impl MemoryInterface<ArmError> for MockProbe {
1828 fn read_8(&mut self, _address: u64, _data: &mut [u8]) -> Result<(), ArmError> {
1829 todo!()
1830 }
1831
1832 fn read_16(&mut self, _address: u64, _data: &mut [u16]) -> Result<(), ArmError> {
1833 todo!()
1834 }
1835
1836 fn read_32(&mut self, address: u64, data: &mut [u32]) -> Result<(), ArmError> {
1837 if self.expected_ops.is_empty() {
1838 panic!(
1839 "Received unexpected read_32 op: register {:#}",
1840 address_to_reg_num(address)
1841 );
1842 }
1843
1844 assert_eq!(data.len(), 1);
1845
1846 let expected_op = self.expected_ops.remove(0);
1847
1848 assert!(
1849 expected_op.read,
1850 "R/W mismatch for register: Expected {:#} Actual: {:#}",
1851 address_to_reg_num(expected_op.address),
1852 address_to_reg_num(address)
1853 );
1854 assert_eq!(
1855 expected_op.address,
1856 address,
1857 "Read from unexpected register: Expected {:#} Actual: {:#}",
1858 address_to_reg_num(expected_op.address),
1859 address_to_reg_num(address)
1860 );
1861
1862 data[0] = expected_op.value;
1863
1864 Ok(())
1865 }
1866
1867 fn read(&mut self, address: u64, data: &mut [u8]) -> Result<(), ArmError> {
1868 self.read_8(address, data)
1869 }
1870
1871 fn write_8(&mut self, _address: u64, _data: &[u8]) -> Result<(), ArmError> {
1872 todo!()
1873 }
1874
1875 fn write_16(&mut self, _address: u64, _data: &[u16]) -> Result<(), ArmError> {
1876 todo!()
1877 }
1878
1879 fn write_32(&mut self, address: u64, data: &[u32]) -> Result<(), ArmError> {
1880 if self.expected_ops.is_empty() {
1881 panic!(
1882 "Received unexpected write_32 op: register {:#}",
1883 address_to_reg_num(address)
1884 );
1885 }
1886
1887 assert_eq!(data.len(), 1);
1888
1889 let expected_op = self.expected_ops.remove(0);
1890
1891 assert!(
1892 !expected_op.read,
1893 "Read/write mismatch on register: {:#}",
1894 address_to_reg_num(address)
1895 );
1896 assert_eq!(
1897 expected_op.address,
1898 address,
1899 "Write to unexpected register: Expected {:#} Actual: {:#}",
1900 address_to_reg_num(expected_op.address),
1901 address_to_reg_num(address)
1902 );
1903
1904 assert_eq!(
1905 expected_op.value, data[0],
1906 "Write value mismatch Expected {:#X} Actual: {:#X}",
1907 expected_op.value, data[0]
1908 );
1909
1910 Ok(())
1911 }
1912
1913 fn write(&mut self, address: u64, data: &[u8]) -> Result<(), ArmError> {
1914 self.write_8(address, data)
1915 }
1916
1917 fn flush(&mut self) -> Result<(), ArmError> {
1918 todo!()
1919 }
1920
1921 fn read_64(&mut self, _address: u64, _data: &mut [u64]) -> Result<(), ArmError> {
1922 todo!()
1923 }
1924
1925 fn write_64(&mut self, _address: u64, _data: &[u64]) -> Result<(), ArmError> {
1926 todo!()
1927 }
1928
1929 fn supports_8bit_transfers(&self) -> Result<bool, ArmError> {
1930 Ok(false)
1931 }
1932
1933 fn supports_native_64bit_access(&mut self) -> bool {
1934 false
1935 }
1936 }
1937
1938 impl ArmMemoryInterface for MockProbe {
1939 fn fully_qualified_address(&self) -> FullyQualifiedApAddress {
1940 todo!()
1941 }
1942
1943 fn get_arm_debug_interface(
1944 &mut self,
1945 ) -> Result<&mut dyn crate::architecture::arm::ArmDebugInterface, DebugProbeError> {
1946 Err(DebugProbeError::NotImplemented {
1947 function_name: "get_arm_debug_interface",
1948 })
1949 }
1950
1951 fn generic_status(&mut self) -> Result<crate::architecture::arm::ap::CSW, ArmError> {
1952 Err(ArmError::Probe(DebugProbeError::NotImplemented {
1953 function_name: "generic_status",
1954 }))
1955 }
1956
1957 fn base_address(&mut self) -> Result<u64, ArmError> {
1958 todo!()
1959 }
1960 }
1961
1962 impl SwdSequence for MockProbe {
1963 fn swj_sequence(&mut self, _bit_len: u8, _bits: u64) -> Result<(), DebugProbeError> {
1964 todo!()
1965 }
1966
1967 fn swj_pins(
1968 &mut self,
1969 _pin_out: u32,
1970 _pin_select: u32,
1971 _pin_wait: u32,
1972 ) -> Result<u32, DebugProbeError> {
1973 todo!()
1974 }
1975 }
1976
1977 fn add_status_expectations(probe: &mut MockProbe, halted: bool) {
1978 let mut dbgdscr = Dbgdscr(0);
1979 dbgdscr.set_halted(halted);
1980 dbgdscr.set_restarted(true);
1981 probe.expected_read(
1982 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1983 dbgdscr.into(),
1984 );
1985 }
1986
1987 fn add_enable_itr_expectations(probe: &mut MockProbe) {
1988 let mut dbgdscr = Dbgdscr(0);
1989 dbgdscr.set_halted(true);
1990 probe.expected_read(
1991 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1992 dbgdscr.into(),
1993 );
1994 dbgdscr.set_itren(true);
1995 probe.expected_write(
1996 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1997 dbgdscr.into(),
1998 );
1999 }
2000
2001 fn add_read_reg_expectations(probe: &mut MockProbe, reg: u16, value: u32) {
2002 probe.expected_write(
2003 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2004 build_mcr(14, 0, reg, 0, 5, 0),
2005 );
2006 let mut dbgdscr = Dbgdscr(0);
2007 dbgdscr.set_instrcoml_l(true);
2008 dbgdscr.set_txfull_l(true);
2009
2010 probe.expected_read(
2011 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2012 dbgdscr.into(),
2013 );
2014 probe.expected_read(
2015 Dbgdtrtx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2016 value,
2017 );
2018 }
2019
2020 fn add_read_pc_expectations(probe: &mut MockProbe, value: u32) {
2021 let mut dbgdscr = Dbgdscr(0);
2022 dbgdscr.set_instrcoml_l(true);
2023 dbgdscr.set_txfull_l(true);
2024
2025 probe.expected_write(
2026 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2027 build_mov(0, 15),
2028 );
2029 probe.expected_read(
2030 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2031 dbgdscr.into(),
2032 );
2033 add_read_reg_expectations(probe, 0, value + 8);
2035 }
2036
2037 fn add_read_fp_count_expectations(probe: &mut MockProbe) {
2038 let mut dbgdscr = Dbgdscr(0);
2039 dbgdscr.set_instrcoml_l(true);
2040 dbgdscr.set_txfull_l(true);
2041 let mut cpacr = Cpacr(0);
2042 cpacr.set_cp(10, 0b11);
2043 cpacr.set_cp(11, 0b11);
2044
2045 probe.expected_write(
2047 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2048 build_mrc(15, 0, 0, 1, 0, 2),
2049 );
2050 probe.expected_read(
2051 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2052 dbgdscr.into(),
2053 );
2054 add_read_reg_expectations(probe, 0, cpacr.0);
2056
2057 probe.expected_write(
2059 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2060 build_vmrs(0, 0b0111),
2061 );
2062 probe.expected_read(
2063 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2064 dbgdscr.into(),
2065 );
2066 add_read_reg_expectations(probe, 0, 0b010);
2067 }
2068
2069 fn add_read_cpsr_expectations(probe: &mut MockProbe, value: u32) {
2070 let mut dbgdscr = Dbgdscr(0);
2071 dbgdscr.set_instrcoml_l(true);
2072 dbgdscr.set_txfull_l(true);
2073
2074 probe.expected_write(
2075 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2076 build_mrs(0),
2077 );
2078 probe.expected_read(
2079 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2080 dbgdscr.into(),
2081 );
2082 add_read_reg_expectations(probe, 0, value);
2083 }
2084
2085 fn add_idr_expectations(probe: &mut MockProbe, bp_count: u32) {
2086 let mut dbgdidr = Dbgdidr(0);
2087 dbgdidr.set_brps(bp_count - 1);
2088 probe.expected_read(
2089 Dbgdidr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2090 dbgdidr.into(),
2091 );
2092 }
2093
2094 fn add_set_r0_expectation(probe: &mut MockProbe, value: u32) {
2095 let mut dbgdscr = Dbgdscr(0);
2096 dbgdscr.set_instrcoml_l(true);
2097 dbgdscr.set_rxfull_l(true);
2098
2099 probe.expected_write(
2100 Dbgdtrrx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2101 value,
2102 );
2103 probe.expected_read(
2104 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2105 dbgdscr.into(),
2106 );
2107
2108 probe.expected_write(
2109 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2110 build_mrc(14, 0, 0, 0, 5, 0),
2111 );
2112 probe.expected_read(
2113 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2114 dbgdscr.into(),
2115 );
2116 }
2117
2118 fn add_read_memory_expectations(probe: &mut MockProbe, address: u64, value: u32) {
2119 add_set_r0_expectation(probe, address as u32);
2120
2121 let mut dbgdscr = Dbgdscr(0);
2122 dbgdscr.set_instrcoml_l(true);
2123 dbgdscr.set_txfull_l(true);
2124
2125 probe.expected_write(
2126 Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2127 build_ldc(14, 5, 0, 4),
2128 );
2129 probe.expected_read(
2130 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2131 dbgdscr.into(),
2132 );
2133 probe.expected_read(
2134 Dbgdtrtx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2135 value,
2136 );
2137 }
2138
2139 impl Drop for MockProbe {
2140 fn drop(&mut self) {
2141 if !self.expected_ops.is_empty() {
2142 panic!("self.expected_ops is not empty: {:?}", self.expected_ops);
2143 }
2144 }
2145 }
2146
2147 #[test]
2148 fn armv7a_new() {
2149 let mut probe = MockProbe::new();
2150
2151 add_status_expectations(&mut probe, true);
2153 add_enable_itr_expectations(&mut probe);
2154 add_read_reg_expectations(&mut probe, 0, 0);
2155 add_read_fp_count_expectations(&mut probe);
2156
2157 let mock_mem = Box::new(probe) as _;
2158
2159 let _ = Armv7ar::new(
2160 mock_mem,
2161 &mut CortexARState::new(),
2162 TEST_BASE_ADDRESS,
2163 DefaultArmSequence::create(),
2164 CoreType::Armv7a,
2165 )
2166 .unwrap();
2167 }
2168
2169 #[test]
2170 fn armv7a_core_halted() {
2171 let mut probe = MockProbe::new();
2172 let mut state = CortexARState::new();
2173
2174 add_status_expectations(&mut probe, true);
2176 add_enable_itr_expectations(&mut probe);
2177 add_read_reg_expectations(&mut probe, 0, 0);
2178 add_read_fp_count_expectations(&mut probe);
2179
2180 let mut dbgdscr = Dbgdscr(0);
2181 dbgdscr.set_halted(false);
2182 probe.expected_read(
2183 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2184 dbgdscr.into(),
2185 );
2186
2187 dbgdscr.set_halted(true);
2188 probe.expected_read(
2189 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2190 dbgdscr.into(),
2191 );
2192
2193 let mock_mem = Box::new(probe) as _;
2194
2195 let mut armv7ar = Armv7ar::new(
2196 mock_mem,
2197 &mut state,
2198 TEST_BASE_ADDRESS,
2199 DefaultArmSequence::create(),
2200 CoreType::Armv7a,
2201 )
2202 .unwrap();
2203
2204 assert!(!armv7ar.core_halted().unwrap());
2206 assert!(armv7ar.core_halted().unwrap());
2207 }
2208
2209 #[test]
2210 fn armv7a_wait_for_core_halted() {
2211 let mut probe = MockProbe::new();
2212 let mut state = CortexARState::new();
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 let mut dbgdscr = Dbgdscr(0);
2221 dbgdscr.set_halted(false);
2222 probe.expected_read(
2223 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2224 dbgdscr.into(),
2225 );
2226
2227 dbgdscr.set_halted(true);
2228 probe.expected_read(
2229 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2230 dbgdscr.into(),
2231 );
2232
2233 let mock_mem = Box::new(probe) as _;
2234
2235 let mut armv7ar = Armv7ar::new(
2236 mock_mem,
2237 &mut state,
2238 TEST_BASE_ADDRESS,
2239 DefaultArmSequence::create(),
2240 CoreType::Armv7a,
2241 )
2242 .unwrap();
2243
2244 armv7ar
2246 .wait_for_core_halted(Duration::from_millis(100))
2247 .unwrap();
2248 }
2249
2250 #[test]
2251 fn armv7a_status_running() {
2252 let mut probe = MockProbe::new();
2253 let mut state = CortexARState::new();
2254
2255 add_status_expectations(&mut probe, true);
2257 add_enable_itr_expectations(&mut probe);
2258 add_read_reg_expectations(&mut probe, 0, 0);
2259 add_read_fp_count_expectations(&mut probe);
2260
2261 let mut dbgdscr = Dbgdscr(0);
2262 dbgdscr.set_halted(false);
2263 probe.expected_read(
2264 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2265 dbgdscr.into(),
2266 );
2267
2268 let mock_mem = Box::new(probe) as _;
2269
2270 let mut armv7ar = Armv7ar::new(
2271 mock_mem,
2272 &mut state,
2273 TEST_BASE_ADDRESS,
2274 DefaultArmSequence::create(),
2275 CoreType::Armv7a,
2276 )
2277 .unwrap();
2278
2279 assert_eq!(CoreStatus::Running, armv7ar.status().unwrap());
2281 }
2282
2283 #[test]
2284 fn armv7a_status_halted() {
2285 let mut probe = MockProbe::new();
2286 let mut state = CortexARState::new();
2287
2288 add_status_expectations(&mut probe, true);
2290 add_enable_itr_expectations(&mut probe);
2291 add_read_reg_expectations(&mut probe, 0, 0);
2292 add_read_fp_count_expectations(&mut probe);
2293
2294 let mut dbgdscr = Dbgdscr(0);
2295 dbgdscr.set_halted(true);
2296 probe.expected_read(
2297 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2298 dbgdscr.into(),
2299 );
2300
2301 let mock_mem = Box::new(probe) as _;
2302
2303 let mut armv7ar = Armv7ar::new(
2304 mock_mem,
2305 &mut state,
2306 TEST_BASE_ADDRESS,
2307 DefaultArmSequence::create(),
2308 CoreType::Armv7a,
2309 )
2310 .unwrap();
2311
2312 assert_eq!(
2314 CoreStatus::Halted(crate::HaltReason::Request),
2315 armv7ar.status().unwrap()
2316 );
2317 }
2318
2319 #[test]
2320 fn armv7a_read_core_reg_common() {
2321 const REG_VALUE: u32 = 0xABCD;
2322
2323 let mut probe = MockProbe::new();
2324 let mut state = CortexARState::new();
2325
2326 add_status_expectations(&mut probe, true);
2328 add_enable_itr_expectations(&mut probe);
2329 add_read_reg_expectations(&mut probe, 0, 0);
2330 add_read_fp_count_expectations(&mut probe);
2331
2332 add_read_reg_expectations(&mut probe, 2, REG_VALUE);
2334
2335 let mock_mem = Box::new(probe) as _;
2336
2337 let mut armv7ar = Armv7ar::new(
2338 mock_mem,
2339 &mut state,
2340 TEST_BASE_ADDRESS,
2341 DefaultArmSequence::create(),
2342 CoreType::Armv7a,
2343 )
2344 .unwrap();
2345
2346 assert_eq!(
2348 RegisterValue::from(REG_VALUE),
2349 armv7ar.read_core_reg(RegisterId(2)).unwrap()
2350 );
2351
2352 assert_eq!(
2354 RegisterValue::from(REG_VALUE),
2355 armv7ar.read_core_reg(RegisterId(2)).unwrap()
2356 );
2357 }
2358
2359 #[test]
2360 fn armv7a_read_core_reg_pc() {
2361 const REG_VALUE: u32 = 0xABCD;
2362
2363 let mut probe = MockProbe::new();
2364 let mut state = CortexARState::new();
2365
2366 add_status_expectations(&mut probe, true);
2368 add_enable_itr_expectations(&mut probe);
2369 add_read_reg_expectations(&mut probe, 0, 0);
2370 add_read_fp_count_expectations(&mut probe);
2371
2372 add_read_pc_expectations(&mut probe, REG_VALUE);
2374
2375 let mock_mem = Box::new(probe) as _;
2376
2377 let mut armv7ar = Armv7ar::new(
2378 mock_mem,
2379 &mut state,
2380 TEST_BASE_ADDRESS,
2381 DefaultArmSequence::create(),
2382 CoreType::Armv7a,
2383 )
2384 .unwrap();
2385
2386 assert_eq!(
2388 RegisterValue::from(REG_VALUE),
2389 armv7ar.read_core_reg(RegisterId(15)).unwrap()
2390 );
2391
2392 assert_eq!(
2394 RegisterValue::from(REG_VALUE),
2395 armv7ar.read_core_reg(RegisterId(15)).unwrap()
2396 );
2397 }
2398
2399 #[test]
2400 fn armv7a_read_core_reg_cpsr() {
2401 const REG_VALUE: u32 = 0xABCD;
2402
2403 let mut probe = MockProbe::new();
2404 let mut state = CortexARState::new();
2405
2406 add_status_expectations(&mut probe, true);
2408 add_enable_itr_expectations(&mut probe);
2409 add_read_reg_expectations(&mut probe, 0, 0);
2410 add_read_fp_count_expectations(&mut probe);
2411
2412 add_read_cpsr_expectations(&mut probe, REG_VALUE);
2414
2415 let mock_mem = Box::new(probe) as _;
2416
2417 let mut armv7ar = Armv7ar::new(
2418 mock_mem,
2419 &mut state,
2420 TEST_BASE_ADDRESS,
2421 DefaultArmSequence::create(),
2422 CoreType::Armv7a,
2423 )
2424 .unwrap();
2425
2426 assert_eq!(
2428 RegisterValue::from(REG_VALUE),
2429 armv7ar.read_core_reg(XPSR.id()).unwrap()
2430 );
2431
2432 assert_eq!(
2434 RegisterValue::from(REG_VALUE),
2435 armv7ar.read_core_reg(XPSR.id()).unwrap()
2436 );
2437 }
2438
2439 #[test]
2440 fn armv7a_halt() {
2441 const REG_VALUE: u32 = 0xABCD;
2442
2443 let mut probe = MockProbe::new();
2444 let mut state = CortexARState::new();
2445
2446 add_status_expectations(&mut probe, false);
2448
2449 let mut dbgdrcr = Dbgdrcr(0);
2451 dbgdrcr.set_hrq(true);
2452 probe.expected_write(
2453 Dbgdrcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2454 dbgdrcr.into(),
2455 );
2456
2457 add_status_expectations(&mut probe, true);
2459
2460 add_status_expectations(&mut probe, true);
2462 add_enable_itr_expectations(&mut probe);
2463 add_read_reg_expectations(&mut probe, 0, 0);
2464 add_read_fp_count_expectations(&mut probe);
2465
2466 add_read_pc_expectations(&mut probe, REG_VALUE);
2468
2469 let mock_mem = Box::new(probe) as _;
2470
2471 let mut armv7ar = Armv7ar::new(
2472 mock_mem,
2473 &mut state,
2474 TEST_BASE_ADDRESS,
2475 DefaultArmSequence::create(),
2476 CoreType::Armv7a,
2477 )
2478 .unwrap();
2479
2480 assert_eq!(
2482 REG_VALUE as u64,
2483 armv7ar.halt(Duration::from_millis(100)).unwrap().pc
2484 );
2485 }
2486
2487 #[test]
2488 fn armv7a_run() {
2489 let mut probe = MockProbe::new();
2490 let mut state = CortexARState::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_set_r0_expectation(&mut probe, 0);
2500
2501 let mut dbgdscr = Dbgdscr(0);
2503 dbgdscr.set_itren(true);
2504 probe.expected_read(
2505 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2506 dbgdscr.into(),
2507 );
2508 dbgdscr.set_itren(false);
2509 probe.expected_write(
2510 Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2511 dbgdscr.into(),
2512 );
2513
2514 let mut dbgdrcr = Dbgdrcr(0);
2516 dbgdrcr.set_rrq(true);
2517 probe.expected_write(
2518 Dbgdrcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2519 dbgdrcr.into(),
2520 );
2521
2522 add_status_expectations(&mut probe, false);
2524
2525 add_status_expectations(&mut probe, false);
2527
2528 let mock_mem = Box::new(probe) as _;
2529
2530 let mut armv7ar = Armv7ar::new(
2531 mock_mem,
2532 &mut state,
2533 TEST_BASE_ADDRESS,
2534 DefaultArmSequence::create(),
2535 CoreType::Armv7a,
2536 )
2537 .unwrap();
2538
2539 armv7ar.run().unwrap();
2540 }
2541
2542 #[test]
2543 fn armv7a_available_breakpoint_units() {
2544 const BP_COUNT: u32 = 4;
2545 let mut probe = MockProbe::new();
2546 let mut state = CortexARState::new();
2547
2548 add_status_expectations(&mut probe, true);
2550 add_enable_itr_expectations(&mut probe);
2551 add_read_reg_expectations(&mut probe, 0, 0);
2552 add_read_fp_count_expectations(&mut probe);
2553
2554 add_idr_expectations(&mut probe, BP_COUNT);
2556
2557 let mock_mem = Box::new(probe) as _;
2558
2559 let mut armv7ar = Armv7ar::new(
2560 mock_mem,
2561 &mut state,
2562 TEST_BASE_ADDRESS,
2563 DefaultArmSequence::create(),
2564 CoreType::Armv7a,
2565 )
2566 .unwrap();
2567
2568 assert_eq!(BP_COUNT, armv7ar.available_breakpoint_units().unwrap());
2569 }
2570
2571 #[test]
2572 fn armv7a_hw_breakpoints() {
2573 const BP_COUNT: u32 = 4;
2574 const BP1: u64 = 0x2345;
2575 const BP2: u64 = 0x8000_0000;
2576 let mut probe = MockProbe::new();
2577 let mut state = CortexARState::new();
2578
2579 add_status_expectations(&mut probe, true);
2581 add_enable_itr_expectations(&mut probe);
2582 add_read_reg_expectations(&mut probe, 0, 0);
2583 add_read_fp_count_expectations(&mut probe);
2584
2585 add_idr_expectations(&mut probe, BP_COUNT);
2587
2588 probe.expected_read(
2590 Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2591 BP1 as u32,
2592 );
2593 probe.expected_read(
2594 Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2595 1,
2596 );
2597
2598 probe.expected_read(
2599 Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + 4,
2600 BP2 as u32,
2601 );
2602 probe.expected_read(
2603 Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + 4,
2604 1,
2605 );
2606
2607 probe.expected_read(
2608 Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (2 * 4),
2609 0,
2610 );
2611 probe.expected_read(
2612 Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (2 * 4),
2613 0,
2614 );
2615
2616 probe.expected_read(
2617 Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (3 * 4),
2618 0,
2619 );
2620 probe.expected_read(
2621 Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (3 * 4),
2622 0,
2623 );
2624
2625 let mock_mem = Box::new(probe) as _;
2626
2627 let mut armv7ar = Armv7ar::new(
2628 mock_mem,
2629 &mut state,
2630 TEST_BASE_ADDRESS,
2631 DefaultArmSequence::create(),
2632 CoreType::Armv7a,
2633 )
2634 .unwrap();
2635
2636 let results = armv7ar.hw_breakpoints().unwrap();
2637 assert_eq!(Some(BP1), results[0]);
2638 assert_eq!(Some(BP2), results[1]);
2639 assert_eq!(None, results[2]);
2640 assert_eq!(None, results[3]);
2641 }
2642
2643 #[test]
2644 fn armv7a_set_hw_breakpoint() {
2645 const BP_VALUE: u64 = 0x2345;
2646 let mut probe = MockProbe::new();
2647 let mut state = CortexARState::new();
2648
2649 add_status_expectations(&mut probe, true);
2651 add_enable_itr_expectations(&mut probe);
2652 add_read_reg_expectations(&mut probe, 0, 0);
2653 add_read_fp_count_expectations(&mut probe);
2654
2655 let mut dbgbcr = Dbgbcr(0);
2657 dbgbcr.set_hmc(true);
2659 dbgbcr.set_pmc(0b11);
2660 dbgbcr.set_bas(0b1111);
2662 dbgbcr.set_e(true);
2664
2665 probe.expected_write(
2666 Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2667 BP_VALUE as u32,
2668 );
2669 probe.expected_write(
2670 Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2671 dbgbcr.into(),
2672 );
2673
2674 let mock_mem = Box::new(probe) as _;
2675
2676 let mut armv7ar = Armv7ar::new(
2677 mock_mem,
2678 &mut state,
2679 TEST_BASE_ADDRESS,
2680 DefaultArmSequence::create(),
2681 CoreType::Armv7a,
2682 )
2683 .unwrap();
2684
2685 armv7ar.set_hw_breakpoint(0, BP_VALUE).unwrap();
2686 }
2687
2688 #[test]
2689 fn armv7a_clear_hw_breakpoint() {
2690 let mut probe = MockProbe::new();
2691 let mut state = CortexARState::new();
2692
2693 add_status_expectations(&mut probe, true);
2695 add_enable_itr_expectations(&mut probe);
2696 add_read_reg_expectations(&mut probe, 0, 0);
2697 add_read_fp_count_expectations(&mut probe);
2698
2699 probe.expected_write(
2701 Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2702 0,
2703 );
2704 probe.expected_write(
2705 Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2706 0,
2707 );
2708
2709 let mock_mem = Box::new(probe) as _;
2710
2711 let mut armv7ar = Armv7ar::new(
2712 mock_mem,
2713 &mut state,
2714 TEST_BASE_ADDRESS,
2715 DefaultArmSequence::create(),
2716 CoreType::Armv7a,
2717 )
2718 .unwrap();
2719
2720 armv7ar.clear_hw_breakpoint(0).unwrap();
2721 }
2722
2723 #[test]
2724 fn armv7a_read_word_32() {
2725 const MEMORY_VALUE: u32 = 0xBA5EBA11;
2726 const MEMORY_ADDRESS: u64 = 0x12345678;
2727
2728 let mut probe = MockProbe::new();
2729 let mut state = CortexARState::new();
2730
2731 add_status_expectations(&mut probe, true);
2733 add_enable_itr_expectations(&mut probe);
2734 add_read_reg_expectations(&mut probe, 0, 0);
2735 add_read_fp_count_expectations(&mut probe);
2736
2737 add_read_memory_expectations(&mut probe, MEMORY_ADDRESS, MEMORY_VALUE);
2739
2740 let mock_mem = Box::new(probe) as _;
2741
2742 let mut armv7ar = Armv7ar::new(
2743 mock_mem,
2744 &mut state,
2745 TEST_BASE_ADDRESS,
2746 DefaultArmSequence::create(),
2747 CoreType::Armv7a,
2748 )
2749 .unwrap();
2750
2751 assert_eq!(MEMORY_VALUE, armv7ar.read_word_32(MEMORY_ADDRESS).unwrap());
2752 }
2753
2754 fn test_read_word(value: u32, address: u64, memory_word_address: u64, endian: Endian) -> u8 {
2755 let mut probe = MockProbe::new();
2756 let mut state = CortexARState::new();
2757
2758 add_status_expectations(&mut probe, true);
2760 add_enable_itr_expectations(&mut probe);
2761 add_read_reg_expectations(&mut probe, 0, 0);
2762 add_read_fp_count_expectations(&mut probe);
2763
2764 add_read_memory_expectations(&mut probe, memory_word_address, value);
2766
2767 let cpsr = if endian == Endian::Big { 1 << 9 } else { 0 };
2769 add_read_cpsr_expectations(&mut probe, cpsr);
2770
2771 let mock_mem = Box::new(probe) as _;
2772
2773 let mut armv7ar = Armv7ar::new(
2774 mock_mem,
2775 &mut state,
2776 TEST_BASE_ADDRESS,
2777 DefaultArmSequence::create(),
2778 CoreType::Armv7a,
2779 )
2780 .unwrap();
2781 armv7ar.read_word_8(address).unwrap()
2782 }
2783
2784 #[test]
2785 fn armv7a_read_word_8() {
2786 const MEMORY_VALUE: u32 = 0xBA5EBB11;
2787 const MEMORY_ADDRESS: u64 = 0x12345679;
2788 const MEMORY_WORD_ADDRESS: u64 = 0x12345678;
2789
2790 assert_eq!(
2791 0xBB,
2792 test_read_word(
2793 MEMORY_VALUE,
2794 MEMORY_ADDRESS,
2795 MEMORY_WORD_ADDRESS,
2796 Endian::Little
2797 )
2798 );
2799 }
2800
2801 #[test]
2802 fn armv7a_read_word_8_be() {
2803 const MEMORY_VALUE: u32 = 0xBA5EBB11;
2804 const MEMORY_ADDRESS: u64 = 0x12345679;
2805 const MEMORY_WORD_ADDRESS: u64 = 0x12345678;
2806
2807 assert_eq!(
2808 0x5E,
2809 test_read_word(
2810 MEMORY_VALUE,
2811 MEMORY_ADDRESS,
2812 MEMORY_WORD_ADDRESS,
2813 Endian::Big
2814 )
2815 );
2816 }
2817}