probe_rs/architecture/arm/core/
armv8a.rs

1//! Register types and the core interface for armv8-a
2
3use super::{
4    CortexAState,
5    instructions::{
6        aarch64,
7        thumb2::{build_ldr, build_mcr, build_mrc, build_str, build_vmov, build_vmrs},
8    },
9    registers::{aarch32::AARCH32_WITH_FP_32_CORE_REGISTERS, aarch64::AARCH64_CORE_REGISTERS},
10};
11use crate::{
12    Architecture, CoreInformation, CoreInterface, CoreRegister, CoreStatus, CoreType,
13    InstructionSet, MemoryInterface,
14    architecture::arm::{
15        ArmError, core::armv8a_debug_regs::*, memory::ArmMemoryInterface,
16        sequences::ArmDebugSequence,
17    },
18    core::{
19        CoreRegisters, RegisterId, RegisterValue, memory_mapped_registers::MemoryMappedRegister,
20    },
21    error::Error,
22    memory::{MemoryNotAlignedError, valid_32bit_address},
23};
24use std::{
25    sync::Arc,
26    time::{Duration, Instant},
27};
28
29const OPERATION_TIMEOUT: Duration = Duration::from_millis(250);
30
31/// Errors for the ARMv8-A state machine
32#[derive(thiserror::Error, Debug)]
33pub enum Armv8aError {
34    /// Invalid register number
35    #[error("Register number {0} is not valid for ARMv8-A in {1}-bit mode")]
36    InvalidRegisterNumber(u16, u16),
37
38    /// Not halted
39    #[error("Core is running but operation requires it to be halted")]
40    NotHalted,
41
42    /// Data Abort occurred
43    #[error("A data abort occurred")]
44    DataAbort,
45}
46
47/// When in 32-bit mode the two words have to be placed in swapped
48fn prep_instr_for_itr_32(instruction: u32) -> u32 {
49    ((instruction & 0xFFFF) << 16) | ((instruction & 0xFFFF_0000) >> 16)
50}
51
52/// Interface for interacting with an ARMv8-A core
53pub struct Armv8a<'probe> {
54    memory: Box<dyn ArmMemoryInterface + 'probe>,
55
56    state: &'probe mut CortexAState,
57
58    base_address: u64,
59
60    cti_address: u64,
61
62    sequence: Arc<dyn ArmDebugSequence>,
63
64    num_breakpoints: Option<u32>,
65}
66
67impl<'probe> Armv8a<'probe> {
68    pub(crate) fn new(
69        mut memory: Box<dyn ArmMemoryInterface + 'probe>,
70        state: &'probe mut CortexAState,
71        base_address: u64,
72        cti_address: u64,
73        sequence: Arc<dyn ArmDebugSequence>,
74    ) -> Result<Self, Error> {
75        if !state.initialized() {
76            // determine current state
77            let address = Edscr::get_mmio_address_from_base(base_address)?;
78            let edscr = Edscr(memory.read_word_32(address)?);
79
80            tracing::debug!("State when connecting: {:x?}", edscr);
81
82            let core_state = if edscr.halted() {
83                let reason = edscr.halt_reason();
84
85                tracing::debug!("Core was halted when connecting, reason: {:?}", reason);
86
87                CoreStatus::Halted(reason)
88            } else {
89                CoreStatus::Running
90            };
91
92            state.current_state = core_state;
93            state.is_64_bit = edscr.currently_64_bit();
94            // Always 32 FP regs for v8-a
95            state.fp_reg_count = 32;
96        }
97
98        let mut core = Self {
99            memory,
100            state,
101            base_address,
102            cti_address,
103            sequence,
104            num_breakpoints: None,
105        };
106
107        if !core.state.initialized() {
108            core.reset_register_cache();
109            core.state.initialize();
110        }
111
112        Ok(core)
113    }
114
115    /// Execute an instruction
116    fn execute_instruction(&mut self, instruction: u32) -> Result<Edscr, Error> {
117        if !self.state.current_state.is_halted() {
118            return Err(Error::Arm(Armv8aError::NotHalted.into()));
119        }
120
121        let mut final_instruction = instruction;
122
123        if !self.state.is_64_bit {
124            // ITR 32-bit instruction encoding requires swapping the half words
125            final_instruction = prep_instr_for_itr_32(instruction)
126        }
127
128        // Run instruction
129        let address = Editr::get_mmio_address_from_base(self.base_address)?;
130        self.memory.write_word_32(address, final_instruction)?;
131
132        // Wait for completion
133        let address = Edscr::get_mmio_address_from_base(self.base_address)?;
134        let mut edscr = Edscr(self.memory.read_word_32(address)?);
135
136        let start = Instant::now();
137        while !edscr.ite() {
138            if start.elapsed() > OPERATION_TIMEOUT {
139                return Err(Error::Arm(ArmError::Timeout));
140            }
141            edscr = Edscr(self.memory.read_word_32(address)?);
142        }
143
144        // Check if we had any aborts, if so clear them and fail
145        if edscr.err() || edscr.a() {
146            let address = Edrcr::get_mmio_address_from_base(self.base_address)?;
147            let mut edrcr = Edrcr(0);
148            edrcr.set_cse(true);
149
150            self.memory.write_word_32(address, edrcr.into())?;
151
152            return Err(Error::Arm(Armv8aError::DataAbort.into()));
153        }
154
155        Ok(edscr)
156    }
157
158    /// Execute an instruction on the CPU and return the result
159    fn execute_instruction_with_result_32(&mut self, instruction: u32) -> Result<u32, Error> {
160        // Run instruction
161        let mut edscr = self.execute_instruction(instruction)?;
162
163        // Wait for TXfull
164        let start = Instant::now();
165        while !edscr.txfull() {
166            if start.elapsed() > OPERATION_TIMEOUT {
167                return Err(Error::Timeout);
168            }
169            let address = Edscr::get_mmio_address_from_base(self.base_address)?;
170            edscr = Edscr(self.memory.read_word_32(address)?);
171        }
172
173        // Read result
174        let address = Dbgdtrtx::get_mmio_address_from_base(self.base_address)?;
175        let result = self.memory.read_word_32(address)?;
176
177        Ok(result)
178    }
179
180    /// Execute an instruction on the CPU and return the result
181    fn execute_instruction_with_result_64(&mut self, instruction: u32) -> Result<u64, Error> {
182        // Run instruction
183        let mut edscr = self.execute_instruction(instruction)?;
184
185        // Wait for TXfull
186        let start = Instant::now();
187        while !edscr.txfull() {
188            if start.elapsed() > OPERATION_TIMEOUT {
189                return Err(Error::Timeout);
190            }
191            let address = Edscr::get_mmio_address_from_base(self.base_address)?;
192            edscr = Edscr(self.memory.read_word_32(address)?);
193        }
194
195        // Read result
196        let address = Dbgdtrrx::get_mmio_address_from_base(self.base_address)?;
197        let mut result: u64 = (self.memory.read_word_32(address)? as u64) << 32;
198
199        let address = Dbgdtrtx::get_mmio_address_from_base(self.base_address)?;
200        result |= self.memory.read_word_32(address)? as u64;
201
202        Ok(result)
203    }
204
205    fn execute_instruction_with_input_32(
206        &mut self,
207        instruction: u32,
208        value: u32,
209    ) -> Result<(), Error> {
210        // Move value
211        let address = Dbgdtrrx::get_mmio_address_from_base(self.base_address)?;
212        self.memory.write_word_32(address, value)?;
213
214        // Wait for RXfull
215        let address = Edscr::get_mmio_address_from_base(self.base_address)?;
216        let mut edscr = Edscr(self.memory.read_word_32(address)?);
217
218        let start = Instant::now();
219        while !edscr.rxfull() {
220            if start.elapsed() > OPERATION_TIMEOUT {
221                return Err(Error::Timeout);
222            }
223            edscr = Edscr(self.memory.read_word_32(address)?);
224        }
225
226        // Run instruction
227        self.execute_instruction(instruction)?;
228
229        Ok(())
230    }
231
232    fn execute_instruction_with_input_64(
233        &mut self,
234        instruction: u32,
235        value: u64,
236    ) -> Result<(), Error> {
237        // Move value
238        let high_word = (value >> 32) as u32;
239        let low_word = (value & 0xFFFF_FFFF) as u32;
240
241        let address = Dbgdtrtx::get_mmio_address_from_base(self.base_address)?;
242        self.memory.write_word_32(address, high_word)?;
243
244        let address = Dbgdtrrx::get_mmio_address_from_base(self.base_address)?;
245        self.memory.write_word_32(address, low_word)?;
246
247        // Wait for RXfull
248        let address = Edscr::get_mmio_address_from_base(self.base_address)?;
249        let mut edscr = Edscr(self.memory.read_word_32(address)?);
250
251        let start = Instant::now();
252        while !edscr.rxfull() {
253            if start.elapsed() > OPERATION_TIMEOUT {
254                return Err(Error::Timeout);
255            }
256            edscr = Edscr(self.memory.read_word_32(address)?);
257        }
258
259        // Run instruction
260        self.execute_instruction(instruction)?;
261
262        Ok(())
263    }
264
265    fn reset_register_cache(&mut self) {
266        if self.state.is_64_bit {
267            // 31 general purpose regs, SP, PC, PSR, 31 FP registers, FPSR, FPCR
268            // Numbers match what GDB defines for aarch64
269            self.state.register_cache = vec![None; 68];
270        } else {
271            // 16 general purpose regs, CPSR, 32 FP registers, FPSR
272            self.state.register_cache = vec![None; 50];
273        }
274    }
275
276    fn writeback_registers_aarch32(&mut self) -> Result<(), Error> {
277        // Update SP, PC, CPSR first since they clobber the GP registers
278        let writeback_iter = (15u16..=16).chain(17u16..=48).chain(0u16..=14);
279
280        for i in writeback_iter {
281            if let Some((val, writeback)) = self.state.register_cache[i as usize]
282                && writeback
283            {
284                match i {
285                    0..=14 => {
286                        let instruction = build_mrc(14, 0, i, 0, 5, 0);
287
288                        self.execute_instruction_with_input_32(instruction, val.try_into()?)?;
289                    }
290                    15 => {
291                        // Move val to r0
292                        let instruction = build_mrc(14, 0, 0, 0, 5, 0);
293
294                        self.execute_instruction_with_input_32(instruction, val.try_into()?)?;
295
296                        // Arm A-profile Architecture Registers
297                        //   AArch32 Registers
298                        //     DLR, Debug Link Register
299                        //
300                        // In Debug state, holds the address to restart from.
301                        //
302                        // https://developer.arm.com/documentation/ddi0601/2025-03/AArch32-Registers/DLR--Debug-Link-Register
303                        let instruction = build_mcr(15, 3, 0, 4, 5, 1);
304                        self.execute_instruction(instruction)?;
305                    }
306                    17..=48 => {
307                        // Move value to r0, r1
308                        let value: u64 = val.try_into()?;
309                        let low_word = value as u32;
310                        let high_word = (value >> 32) as u32;
311
312                        let instruction = build_mrc(14, 0, 0, 0, 5, 0);
313                        self.execute_instruction_with_input_32(instruction, low_word)?;
314
315                        let instruction = build_mrc(14, 0, 1, 0, 5, 0);
316                        self.execute_instruction_with_input_32(instruction, high_word)?;
317
318                        // VMOV
319                        let instruction = build_vmov(0, 0, 1, i - 17);
320                        self.execute_instruction(instruction)?;
321                    }
322                    _ => {
323                        panic!("Logic missing for writeback of register {i}");
324                    }
325                }
326            }
327        }
328
329        Ok(())
330    }
331
332    fn writeback_registers_aarch64(&mut self) -> Result<(), Error> {
333        // Update SP, PC, CPSR, FP first since they clobber the GP registers
334        let writeback_iter = (31u16..=33).chain(34u16..=65).chain(0u16..=30);
335
336        for i in writeback_iter {
337            if let Some((val, writeback)) = self.state.register_cache[i as usize]
338                && writeback
339            {
340                match i {
341                    0..=30 => {
342                        self.set_reg_value(i, val.try_into()?)?;
343                    }
344                    31 => {
345                        // Move val to r0
346                        self.set_reg_value(0, val.try_into()?)?;
347
348                        // MSR SP_EL0, X0
349                        let instruction = aarch64::build_msr(3, 0, 4, 1, 0, 0);
350                        self.execute_instruction(instruction)?;
351                    }
352                    32 => {
353                        // Move val to r0
354                        self.set_reg_value(0, val.try_into()?)?;
355
356                        // MSR DLR_EL0, X0
357                        let instruction = aarch64::build_msr(3, 3, 4, 5, 1, 0);
358                        self.execute_instruction(instruction)?;
359                    }
360                    34..=65 => {
361                        let val: u128 = val.try_into()?;
362
363                        // Move lower word to r0
364                        self.set_reg_value(0, val as u64)?;
365
366                        // INS v<x>.d[0], x0
367                        let instruction = aarch64::build_ins_gp_to_fp(i - 34, 0, 0);
368                        self.execute_instruction(instruction)?;
369
370                        // Move upper word to r0
371                        self.set_reg_value(0, (val >> 64) as u64)?;
372
373                        // INS v<x>.d[0], x0
374                        let instruction = aarch64::build_ins_gp_to_fp(i - 34, 0, 1);
375                        self.execute_instruction(instruction)?;
376                    }
377                    _ => {
378                        panic!("Logic missing for writeback of register {i}");
379                    }
380                }
381            }
382        }
383
384        Ok(())
385    }
386
387    /// Sync any updated registers back to the core
388    fn writeback_registers(&mut self) -> Result<(), Error> {
389        if self.state.is_64_bit {
390            self.writeback_registers_aarch64()?;
391        } else {
392            self.writeback_registers_aarch32()?;
393        }
394
395        self.reset_register_cache();
396
397        Ok(())
398    }
399
400    /// Save register if needed before it gets clobbered by instruction execution
401    fn prepare_for_clobber(&mut self, reg: u16) -> Result<(), Error> {
402        if let Some(val) = &mut self.state.register_cache[reg as usize] {
403            // Mark reg as needing writeback
404            val.1 = true;
405        } else {
406            // cache reg since we're going to clobber it
407            let val = self.read_core_reg(RegisterId(reg))?;
408
409            // Mark reg as needing writeback
410            self.state.register_cache[reg as usize] = Some((val, true));
411        }
412
413        Ok(())
414    }
415
416    fn set_reg_value(&mut self, reg: u16, value: u64) -> Result<(), Error> {
417        if self.state.is_64_bit {
418            // MRS DBGDTR_EL0, X<n>
419            let instruction = aarch64::build_mrs(2, 3, 0, 4, 0, reg);
420
421            self.execute_instruction_with_input_64(instruction, value)
422        } else {
423            let value = valid_32bit_address(value)?;
424
425            let instruction = build_mrc(14, 0, reg, 0, 5, 0);
426
427            self.execute_instruction_with_input_32(instruction, value)
428        }
429    }
430
431    fn ack_cti_halt(&mut self) -> Result<(), Error> {
432        let mut ack = CtiIntack(0);
433        ack.set_ack(0, 1);
434
435        let address = CtiIntack::get_mmio_address_from_base(self.cti_address)?;
436        self.memory.write_word_32(address, ack.into())?;
437
438        let start = Instant::now();
439        loop {
440            let address = CtiTrigoutstatus::get_mmio_address_from_base(self.cti_address)?;
441            let trig_status = CtiTrigoutstatus(self.memory.read_word_32(address)?);
442
443            if trig_status.status(0) == 0 {
444                break;
445            }
446            if start.elapsed() > OPERATION_TIMEOUT {
447                return Err(Error::Timeout);
448            }
449        }
450
451        Ok(())
452    }
453
454    fn read_core_reg_32(&mut self, reg_num: u16) -> Result<RegisterValue, Error> {
455        // Generate instruction to extract register
456        match reg_num {
457            0..=14 => {
458                // r0-r14, valid
459                // MCR p14, 0, <Rd>, c0, c5, 0 ; Write DBGDTRTXint Register
460                let instruction = build_mcr(14, 0, reg_num, 0, 5, 0);
461
462                let reg_value = self.execute_instruction_with_result_32(instruction)?;
463
464                Ok(reg_value.into())
465            }
466            15 => {
467                // PC, must access via r0
468                self.prepare_for_clobber(0)?;
469
470                // MRC p15, 3, r0, c4, c5, 1 ; Read DLR to r0
471                let instruction = build_mrc(15, 3, 0, 4, 5, 1);
472                self.execute_instruction(instruction)?;
473
474                // Read from r0
475                let instruction = build_mcr(14, 0, 0, 0, 5, 0);
476                let pc = self.execute_instruction_with_result_32(instruction)?;
477
478                Ok(pc.into())
479            }
480            16 => {
481                // CPSR, must access via r0
482                self.prepare_for_clobber(0)?;
483
484                // MRC c15, 3, r0, c4, c5, 0
485                let instruction = build_mrc(15, 3, 0, 4, 5, 0);
486                self.execute_instruction(instruction)?;
487
488                // Read from r0
489                let instruction = build_mcr(14, 0, 0, 0, 5, 0);
490                let cpsr = self.execute_instruction_with_result_32(instruction)?;
491
492                Ok(cpsr.into())
493            }
494            17..=48 => {
495                // Access via r0, r1
496                self.prepare_for_clobber(0)?;
497                self.prepare_for_clobber(1)?;
498
499                // VMOV r0, r1, <reg>
500                let instruction = build_vmov(1, 0, 1, reg_num - 17);
501                self.execute_instruction(instruction)?;
502
503                // Read from r0
504                let instruction = build_mcr(14, 0, 0, 0, 5, 0);
505                let mut value = self.execute_instruction_with_result_32(instruction)? as u64;
506
507                // Read from r1
508                let instruction = build_mcr(14, 0, 1, 0, 5, 0);
509                value |= (self.execute_instruction_with_result_32(instruction)? as u64) << 32;
510
511                Ok(value.into())
512            }
513            49 => {
514                // Access via r0
515                self.prepare_for_clobber(0)?;
516
517                // VMRS r0, FPSCR
518                let instruction = build_vmrs(0, 1);
519                self.execute_instruction(instruction)?;
520
521                // Read from r0
522                let instruction = build_mcr(14, 0, 0, 0, 5, 0);
523                let value = self.execute_instruction_with_result_32(instruction)?;
524
525                Ok(value.into())
526            }
527            _ => Err(Error::Arm(
528                Armv8aError::InvalidRegisterNumber(reg_num, 32).into(),
529            )),
530        }
531    }
532
533    fn read_core_reg_64(&mut self, reg_num: u16) -> Result<RegisterValue, Error> {
534        match reg_num {
535            0..=30 => {
536                // GP register
537
538                // MSR DBGDTR_EL0, X<n>
539                let instruction = aarch64::build_msr(2, 3, 0, 4, 0, reg_num);
540
541                let reg_value = self.execute_instruction_with_result_64(instruction)?;
542
543                Ok(reg_value.into())
544            }
545            31 => {
546                // SP
547                self.prepare_for_clobber(0)?;
548
549                // MRS X0, SP_EL0
550                let instruction = aarch64::build_mrs(3, 0, 4, 1, 0, 0);
551                self.execute_instruction(instruction)?;
552
553                // Read from x0
554                let instruction = aarch64::build_msr(2, 3, 0, 4, 0, 0);
555                let sp = self.execute_instruction_with_result_64(instruction)?;
556
557                Ok(sp.into())
558            }
559            32 => {
560                // PC, must access via x0
561                self.prepare_for_clobber(0)?;
562
563                // MRS X0, DLR_EL0
564                let instruction = aarch64::build_mrs(3, 3, 4, 5, 1, 0);
565                self.execute_instruction(instruction)?;
566
567                // Read from x0
568                let instruction = aarch64::build_msr(2, 3, 0, 4, 0, 0);
569                let pc = self.execute_instruction_with_result_64(instruction)?;
570
571                Ok(pc.into())
572            }
573            33 => {
574                // PSR
575                self.prepare_for_clobber(0)?;
576
577                // MRS X0, DSPSR_EL0
578                let instruction = aarch64::build_mrs(3, 3, 4, 5, 0, 0);
579                self.execute_instruction(instruction)?;
580
581                // Read from x0
582                let instruction = aarch64::build_msr(2, 3, 0, 4, 0, 0);
583                let psr: u32 = self.execute_instruction_with_result_64(instruction)? as u32;
584
585                Ok(psr.into())
586            }
587            34..=65 => {
588                // v0-v31
589                self.prepare_for_clobber(0)?;
590
591                // MOV x0, v<x>.d[0]
592                let instruction = aarch64::build_ins_fp_to_gp(0, reg_num - 34, 0);
593                self.execute_instruction(instruction)?;
594
595                // Read from x0
596                let instruction = aarch64::build_msr(2, 3, 0, 4, 0, 0);
597                let mut value: u128 = self.execute_instruction_with_result_64(instruction)? as u128;
598
599                // MOV x0, v<x>.d[1]
600                let instruction = aarch64::build_ins_fp_to_gp(0, reg_num - 34, 1);
601                self.execute_instruction(instruction)?;
602
603                // Read from x0
604                let instruction = aarch64::build_msr(2, 3, 0, 4, 0, 0);
605                value |= (self.execute_instruction_with_result_64(instruction)? as u128) << 64;
606
607                Ok(value.into())
608            }
609            66 => {
610                // FPSR
611                self.prepare_for_clobber(0)?;
612
613                // MRS X0, FPSR
614                let instruction = aarch64::build_mrs(3, 3, 4, 4, 1, 0);
615                self.execute_instruction(instruction)?;
616
617                // Read from x0
618                let instruction = aarch64::build_msr(2, 3, 0, 4, 0, 0);
619                let fpsr: u32 = self.execute_instruction_with_result_64(instruction)? as u32;
620
621                Ok(fpsr.into())
622            }
623            67 => {
624                // FPCR
625                self.prepare_for_clobber(0)?;
626
627                // MRS X0, FPCR
628                let instruction = aarch64::build_mrs(3, 3, 4, 4, 0, 0);
629                self.execute_instruction(instruction)?;
630
631                // Read from x0
632                let instruction = aarch64::build_msr(2, 3, 0, 4, 0, 0);
633                let fpcr: u32 = self.execute_instruction_with_result_64(instruction)? as u32;
634
635                Ok(fpcr.into())
636            }
637            _ => Err(Error::Arm(
638                Armv8aError::InvalidRegisterNumber(reg_num, 64).into(),
639            )),
640        }
641    }
642
643    fn with_core_halted<F, R>(&mut self, f: F) -> Result<R, Error>
644    where
645        F: FnOnce(&mut Self) -> Result<R, Error>,
646    {
647        // save halt status
648        let original_halt_status = self.state.current_state.is_halted();
649        if !original_halt_status {
650            self.halt(Duration::from_millis(100))?;
651        }
652
653        let result = f(self);
654
655        // restore halt status
656        if !original_halt_status {
657            self.run()?;
658        }
659        result
660    }
661
662    /// This function enables EDSCR.MA=1, which allows direct memory access via debug instructions.
663    /// With EDSCR.MA=1, any write to DBGDTRRX / read to DBGDTRTX break the x0,x1 registers
664    fn with_memory_access_mode<F, R>(&mut self, f: F) -> Result<R, Error>
665    where
666        F: FnOnce(&mut Self) -> Result<R, Error>,
667    {
668        // enable memory access(MA) mode
669        self.set_memory_access_mode(true)?;
670
671        let result = f(self);
672
673        // disable memory access(MA) mode
674        self.set_memory_access_mode(false)?;
675
676        result
677    }
678
679    fn read_cpu_memory_aarch32_32(&mut self, address: u64) -> Result<u32, Error> {
680        let address = valid_32bit_address(address)?;
681
682        self.with_core_halted(|armv8a| {
683            // Save r0, r1
684            armv8a.prepare_for_clobber(0)?;
685            armv8a.prepare_for_clobber(1)?;
686
687            // Load r0 with the address to read from
688            armv8a.set_reg_value(0, address.into())?;
689
690            // Read data to r1 - LDR r1, [r0], #4
691            let instruction = build_ldr(1, 0, 4);
692
693            armv8a.execute_instruction(instruction)?;
694
695            // Move from r1 to transfer buffer - MCR p14, 0, r1, c0, c5, 0
696            let instruction = build_mcr(14, 0, 1, 0, 5, 0);
697            armv8a.execute_instruction_with_result_32(instruction)
698        })
699    }
700
701    fn read_cpu_memory_aarch64_bytes(
702        &mut self,
703        address: u64,
704        data: &mut [u8],
705    ) -> Result<(), Error> {
706        self.with_core_halted(|armv8a| {
707            // Save x0, x1
708            armv8a.prepare_for_clobber(0)?;
709            armv8a.prepare_for_clobber(1)?;
710
711            // Load x0 with the address to read from
712            armv8a.set_reg_value(0, address)?;
713
714            for d in data {
715                // Read data to w1 - LDRB w1, [x0], #1
716                let instruction = aarch64::build_ldrb(1, 0, 1);
717
718                armv8a.execute_instruction(instruction)?;
719
720                // MSR DBGDTRTX_EL0, X1
721                let instruction = aarch64::build_msr(2, 3, 0, 5, 0, 1);
722                *d = armv8a.execute_instruction_with_result_32(instruction)? as u8;
723            }
724
725            Ok(())
726        })
727    }
728
729    fn read_cpu_memory_aarch64_32(&mut self, address: u64) -> Result<u32, Error> {
730        self.with_core_halted(|armv8a| {
731            // Save x0, x1
732            armv8a.prepare_for_clobber(0)?;
733            armv8a.prepare_for_clobber(1)?;
734
735            // Load x0 with the address to read from
736            armv8a.set_reg_value(0, address)?;
737
738            // Read data to w1 - LDR w1, [x0], #4
739            let instruction = aarch64::build_ldrw(1, 0, 4);
740
741            armv8a.execute_instruction(instruction)?;
742
743            // MSR DBGDTRTX_EL0, X1
744            let instruction = aarch64::build_msr(2, 3, 0, 5, 0, 1);
745            armv8a.execute_instruction_with_result_32(instruction)
746        })
747    }
748
749    fn read_cpu_memory_aarch64_64(&mut self, address: u64) -> Result<u64, Error> {
750        self.with_core_halted(|armv8a| {
751            // Save x0, x1
752            armv8a.prepare_for_clobber(0)?;
753            armv8a.prepare_for_clobber(1)?;
754
755            // Load x0 with the address to read from
756            armv8a.set_reg_value(0, address)?;
757
758            // Read data to x1 - LDR x1, [x0], #8
759            let instruction = aarch64::build_ldr(1, 0, 8);
760
761            armv8a.execute_instruction(instruction)?;
762
763            // MSR DBGDTR_EL0, X1
764            let instruction = aarch64::build_msr(2, 3, 0, 4, 0, 1);
765            armv8a.execute_instruction_with_result_64(instruction)
766        })
767    }
768
769    fn write_cpu_memory_aarch32_32(&mut self, address: u64, data: u32) -> Result<(), Error> {
770        let address = valid_32bit_address(address)?;
771        self.with_core_halted(|armv8a| {
772            // Save r0, r1
773            armv8a.prepare_for_clobber(0)?;
774            armv8a.prepare_for_clobber(1)?;
775
776            // Load r0 with the address to write to
777            armv8a.set_reg_value(0, address.into())?;
778            armv8a.set_reg_value(1, data.into())?;
779
780            // Write data to memory - STR r1, [r0], #4
781            let instruction = build_str(1, 0, 4);
782
783            armv8a.execute_instruction(instruction)?;
784            Ok(())
785        })
786    }
787
788    fn write_cpu_memory_aarch64_32(&mut self, address: u64, data: u32) -> Result<(), Error> {
789        self.with_core_halted(|armv8a| {
790            // Save x0, x1
791            armv8a.prepare_for_clobber(0)?;
792            armv8a.prepare_for_clobber(1)?;
793
794            // Load x0 with the address to write to
795            armv8a.set_reg_value(0, address)?;
796            armv8a.set_reg_value(1, data.into())?;
797
798            // Write data to memory - STR x1, [x0], #4
799            let instruction = aarch64::build_strw(1, 0, 4);
800
801            armv8a.execute_instruction(instruction)?;
802            Ok(())
803        })
804    }
805
806    fn write_cpu_memory_aarch64_64(&mut self, address: u64, data: u64) -> Result<(), Error> {
807        self.with_core_halted(|armv8a| {
808            // Save x0, x1
809            armv8a.prepare_for_clobber(0)?;
810            armv8a.prepare_for_clobber(1)?;
811
812            // Load x0 with the address to write to
813            armv8a.set_reg_value(0, address)?;
814            armv8a.set_reg_value(1, data)?;
815
816            // Write data to memory - STR x1, [x0], #8
817            let instruction = aarch64::build_str(1, 0, 8);
818
819            armv8a.execute_instruction(instruction)?;
820            Ok(())
821        })
822    }
823
824    fn set_memory_access_mode(&mut self, enable_ma_mode: bool) -> Result<(), Error> {
825        let address = Edscr::get_mmio_address_from_base(self.base_address)?;
826        let mut edscr: Edscr = Edscr(self.memory.read_word_32(address)?);
827        edscr.set_ma(enable_ma_mode);
828        self.memory.write_word_32(address, edscr.into())?;
829
830        Ok(())
831    }
832
833    fn write_cpu_memory_fast(&mut self, address: u64, data: &[u8]) -> Result<(), Error> {
834        self.with_core_halted(|armv8a| {
835            let (prefix, aligned, suffix) = armv8a.aligned_to_32(address, data);
836            let mut address = address;
837
838            // write unaligned part
839            for d in prefix {
840                armv8a.write_word_8(address, *d)?;
841                address += 1;
842            }
843
844            // write aligned part
845            armv8a.write_cpu_memory_fast_inner(address, aligned)?;
846            address += u64::try_from(aligned.len()).unwrap();
847
848            // write unaligned part
849            for d in suffix {
850                armv8a.write_word_8(address, *d)?;
851                address += 1;
852            }
853
854            Ok(())
855        })
856    }
857
858    /// Fast data download method
859    /// ref. ARM DDI 0487D.a, K9-7312, Figure K9-1 Fast data download in AArch64 state
860    fn write_cpu_memory_fast_inner(&mut self, address: u64, data: &[u8]) -> Result<(), Error> {
861        // assume only call from write_cpu_memory_fast
862        if data.is_empty() {
863            return Ok(());
864        }
865        if !data.len().is_multiple_of(4) || !address.is_multiple_of(4) {
866            return Err(MemoryNotAlignedError {
867                address,
868                alignment: 4,
869            }
870            .into());
871        }
872
873        // ref. ARM DDI 0600B.a shared/debug/dccanditr/DBGDTRRX_EL0 pseudocode
874        // x0/r0 will be used for the address, and x1/r1 is clobbered.
875        self.prepare_for_clobber(0)?;
876        self.prepare_for_clobber(1)?;
877
878        // Load x0/r0 with the address to write to.
879        self.set_reg_value(0, address)?;
880
881        self.with_memory_access_mode(|armv8a| {
882            for d in data.chunks(4) {
883                let word = u32::from_le_bytes([d[0], d[1], d[2], d[3]]);
884                // memory write loop
885                // With EDSCR.MA=1, any write to DBGDTRRX turns into:
886                // AArch64:
887                //  "MRS X1,DBGDTRRX_EL0"
888                //  "STR W1,[X0],#4"
889                // AArch32:
890                //  "MRS R1,DBGDTRRXint"
891                //  "STR R1,[R0],#4"
892                let dbgdtr_rx_address = Dbgdtrrx::get_mmio_address_from_base(armv8a.base_address)?;
893                armv8a.memory.write_word_32(dbgdtr_rx_address, word)?;
894            }
895            Ok(())
896        })?;
897
898        // error check
899        let edscr_address = Edscr::get_mmio_address_from_base(self.base_address)?;
900        if Edscr(self.memory.read_word_32(edscr_address)?).err() {
901            // under-run or abort
902
903            // clear error flag
904            let edrcr_address = Edrcr::get_mmio_address_from_base(self.base_address)?;
905            let mut edrcr = Edrcr(0);
906            edrcr.set_cse(true);
907            self.memory.write_word_32(edrcr_address, edrcr.into())?;
908
909            return Err(Error::Arm(ArmError::Armv8a(Armv8aError::DataAbort)));
910        }
911
912        Ok(())
913    }
914
915    fn aligned_to_32_split_offset(&self, address: u64, data: &[u8]) -> (usize, usize) {
916        // rounding up
917        let word_aligned_address = (address + 3) & (!0x03u64);
918        let unaligned_prefix_size = usize::try_from(word_aligned_address - address).unwrap();
919        let unaligned_suffix_size =
920            usize::try_from((address + u64::try_from(data.len()).unwrap()) % 4).unwrap();
921        let word_aligned_size = data.len() - (unaligned_prefix_size + unaligned_suffix_size);
922
923        (unaligned_prefix_size, word_aligned_size)
924    }
925
926    fn aligned_to_32_mut<'a>(
927        &self,
928        address: u64,
929        data: &'a mut [u8],
930    ) -> (&'a mut [u8], &'a mut [u8], &'a mut [u8]) {
931        // take out 32-bit aligned part
932        let (unaligned_prefix_size, word_aligned_size) =
933            self.aligned_to_32_split_offset(address, data);
934
935        // take out 32-bit aligned part
936        let (prefix, rest) = data.split_at_mut(unaligned_prefix_size);
937        let (aligned, suffix) = rest.split_at_mut(word_aligned_size);
938        (prefix, aligned, suffix)
939    }
940
941    fn aligned_to_32<'a>(&self, address: u64, data: &'a [u8]) -> (&'a [u8], &'a [u8], &'a [u8]) {
942        // take out 32-bit aligned part
943        let (unaligned_prefix_size, word_aligned_size) =
944            self.aligned_to_32_split_offset(address, data);
945
946        // take out 32-bit aligned part
947        let (prefix, rest) = data.split_at(unaligned_prefix_size);
948        let (aligned, suffix) = rest.split_at(word_aligned_size);
949        (prefix, aligned, suffix)
950    }
951
952    fn read_cpu_memory_aarch64_fast(&mut self, address: u64, data: &mut [u8]) -> Result<(), Error> {
953        self.with_core_halted(|armv8a| {
954            let (prefix, aligned, suffix) = armv8a.aligned_to_32_mut(address, data);
955            let mut address = address;
956
957            // read unaligned part
958            if !prefix.is_empty() {
959                armv8a.read_cpu_memory_aarch64_bytes(address, prefix)?;
960                address += u64::try_from(prefix.len()).unwrap();
961            }
962
963            // read aligned part
964            armv8a.read_cpu_memory_aarch64_fast_inner(address, aligned)?;
965            address += u64::try_from(aligned.len()).unwrap();
966
967            // read unaligned part
968            if !suffix.is_empty() {
969                armv8a.read_cpu_memory_aarch64_bytes(address, suffix)?;
970            }
971
972            Ok(())
973        })
974    }
975
976    /// Fast data download method
977    /// ref. ARM DDI 0487D.a, K9-7313, Figure K9-2 Fast data upload in AArch64 state
978    fn read_cpu_memory_aarch64_fast_inner(
979        &mut self,
980        address: u64,
981        data: &mut [u8],
982    ) -> Result<(), Error> {
983        // assume only call from read_cpu_memory_aarch64_fast
984        if data.is_empty() {
985            return Ok(());
986        }
987        if !data.len().is_multiple_of(4) || !address.is_multiple_of(4) {
988            return Err(MemoryNotAlignedError {
989                address,
990                alignment: 4,
991            }
992            .into());
993        }
994
995        // ref. ARM DDI 0600B.a shared/debug/dccanditr/DBGDTRRX_EL0 pseudocode
996        // x0/r0 will be used for the address, and x1/r1 is clobbered.
997        self.prepare_for_clobber(0)?;
998        self.prepare_for_clobber(1)?;
999
1000        // Load x0 with the address to read from
1001        self.set_reg_value(0, address)?;
1002
1003        // set "MSR DBGDTR_EL0, X0" opcode to EDITR
1004        let msr_instruction = aarch64::build_msr(2, 3, 0, 4, 0, 0);
1005        let editr_address = Editr::get_mmio_address_from_base(self.base_address)?;
1006        self.memory.write_word_32(editr_address, msr_instruction)?;
1007
1008        // wait for TXfull == 1
1009        let edscr_address = Edscr::get_mmio_address_from_base(self.base_address)?;
1010        let start = Instant::now();
1011        while !{
1012            if start.elapsed() > OPERATION_TIMEOUT {
1013                return Err(Error::Timeout);
1014            }
1015            Edscr(self.memory.read_word_32(edscr_address)?)
1016        }
1017        .txfull()
1018        {}
1019
1020        let dbgdtr_tx_address = Dbgdtrtx::get_mmio_address_from_base(self.base_address)?;
1021        let (data, last) = data.split_at_mut(data.len() - std::mem::size_of::<u32>());
1022
1023        self.with_memory_access_mode(|armv8a| {
1024            // discard first 32bit
1025            let _ = armv8a.memory.read_word_32(dbgdtr_tx_address)?;
1026            for d in data.chunks_mut(4) {
1027                // memory read loop
1028                let tmp = armv8a.memory.read_word_32(dbgdtr_tx_address)?.to_le_bytes();
1029                d.copy_from_slice(&tmp);
1030            }
1031
1032            Ok(())
1033        })?;
1034
1035        // read last 32bit
1036        let l = self.memory.read_word_32(dbgdtr_tx_address)?.to_le_bytes();
1037        last.copy_from_slice(&l);
1038
1039        // error check
1040        let address = Edscr::get_mmio_address_from_base(self.base_address)?;
1041        let edscr = Edscr(self.memory.read_word_32(address)?);
1042        if edscr.err() {
1043            // clear error flag
1044            let edrcr_address = Edrcr::get_mmio_address_from_base(self.base_address)?;
1045            let mut edrcr = Edrcr(0);
1046            edrcr.set_cse(true);
1047            self.memory.write_word_32(edrcr_address, edrcr.into())?;
1048
1049            Err(Error::Arm(ArmError::Armv8a(Armv8aError::DataAbort)))
1050        } else {
1051            Ok(())
1052        }
1053    }
1054
1055    fn set_core_status(&mut self, new_status: CoreStatus) {
1056        super::update_core_status(&mut self.memory, &mut self.state.current_state, new_status);
1057    }
1058}
1059
1060impl CoreInterface for Armv8a<'_> {
1061    fn wait_for_core_halted(&mut self, timeout: Duration) -> Result<(), Error> {
1062        // Wait until halted state is active again.
1063        let start = Instant::now();
1064
1065        while !self.core_halted()? {
1066            if start.elapsed() >= timeout {
1067                return Err(Error::Arm(ArmError::Timeout));
1068            }
1069            // Wait a bit before polling again.
1070            std::thread::sleep(Duration::from_millis(1));
1071        }
1072
1073        Ok(())
1074    }
1075
1076    fn core_halted(&mut self) -> Result<bool, Error> {
1077        let address = Edscr::get_mmio_address_from_base(self.base_address)?;
1078        let edscr = Edscr(self.memory.read_word_32(address)?);
1079
1080        Ok(edscr.halted())
1081    }
1082
1083    fn status(&mut self) -> Result<crate::core::CoreStatus, Error> {
1084        // determine current state
1085        let address = Edscr::get_mmio_address_from_base(self.base_address)?;
1086        let edscr = Edscr(self.memory.read_word_32(address)?);
1087
1088        if edscr.halted() {
1089            let reason = edscr.halt_reason();
1090
1091            self.set_core_status(CoreStatus::Halted(reason));
1092            self.state.is_64_bit = edscr.currently_64_bit();
1093
1094            return Ok(CoreStatus::Halted(reason));
1095        }
1096        // Core is neither halted nor sleeping, so we assume it is running.
1097        if self.state.current_state.is_halted() {
1098            tracing::warn!("Core is running, but we expected it to be halted");
1099        }
1100
1101        self.set_core_status(CoreStatus::Running);
1102
1103        Ok(CoreStatus::Running)
1104    }
1105
1106    fn halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
1107        if !matches!(self.state.current_state, CoreStatus::Halted(_)) {
1108            // Ungate halt CTI channel
1109            let mut cti_gate = CtiGate(0);
1110            cti_gate.set_en(0, 1);
1111
1112            let address = CtiGate::get_mmio_address_from_base(self.cti_address)?;
1113            self.memory.write_word_32(address, cti_gate.into())?;
1114
1115            // Pulse it
1116            let mut pulse = CtiApppulse(0);
1117            pulse.set_apppulse(0, 1);
1118
1119            let address = CtiApppulse::get_mmio_address_from_base(self.cti_address)?;
1120            self.memory.write_word_32(address, pulse.into())?;
1121
1122            // Wait for halt
1123            self.wait_for_core_halted(timeout)?;
1124
1125            // Reset our cached values
1126            self.reset_register_cache();
1127        }
1128
1129        // Update core status
1130        let _ = self.status()?;
1131
1132        // Gate halt channel
1133        let cti_gate = CtiGate(0);
1134
1135        let address = CtiGate::get_mmio_address_from_base(self.cti_address)?;
1136        self.memory.write_word_32(address, cti_gate.into())?;
1137
1138        // try to read the program counter
1139        let pc_value = self.read_core_reg(self.program_counter().into())?;
1140
1141        // get pc
1142        Ok(CoreInformation {
1143            pc: pc_value.try_into()?,
1144        })
1145    }
1146
1147    fn run(&mut self) -> Result<(), Error> {
1148        if matches!(self.state.current_state, CoreStatus::Running) {
1149            return Ok(());
1150        }
1151
1152        // set writeback values
1153        self.writeback_registers()?;
1154
1155        self.ack_cti_halt()?;
1156
1157        // Ungate restart CTI channel
1158        let mut cti_gate = CtiGate(0);
1159        cti_gate.set_en(1, 1);
1160
1161        let address = CtiGate::get_mmio_address_from_base(self.cti_address)?;
1162        self.memory.write_word_32(address, cti_gate.into())?;
1163
1164        // Pulse it
1165        let mut pulse = CtiApppulse(0);
1166        pulse.set_apppulse(1, 1);
1167
1168        let address = CtiApppulse::get_mmio_address_from_base(self.cti_address)?;
1169        self.memory.write_word_32(address, pulse.into())?;
1170
1171        // Wait for ack
1172        let address = Edprsr::get_mmio_address_from_base(self.base_address)?;
1173
1174        let start = Instant::now();
1175        loop {
1176            let edprsr = Edprsr(self.memory.read_word_32(address)?);
1177            if edprsr.sdr() {
1178                break;
1179            }
1180            if start.elapsed() > OPERATION_TIMEOUT {
1181                return Err(Error::Timeout);
1182            }
1183        }
1184
1185        // Recompute / verify current state
1186        self.set_core_status(CoreStatus::Running);
1187        let _ = self.status()?;
1188
1189        // Gate restart channel
1190        let cti_gate = CtiGate(0);
1191
1192        let address = CtiGate::get_mmio_address_from_base(self.cti_address)?;
1193        self.memory.write_word_32(address, cti_gate.into())?;
1194
1195        Ok(())
1196    }
1197
1198    fn reset(&mut self) -> Result<(), Error> {
1199        self.sequence.reset_system(
1200            &mut *self.memory,
1201            crate::CoreType::Armv8a,
1202            Some(self.base_address),
1203        )?;
1204
1205        // Reset our cached values
1206        self.reset_register_cache();
1207
1208        // Recompute / verify current state
1209        self.set_core_status(CoreStatus::Running);
1210        let _ = self.status()?;
1211
1212        Ok(())
1213    }
1214
1215    fn reset_and_halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
1216        self.sequence.reset_catch_set(
1217            &mut *self.memory,
1218            crate::CoreType::Armv8a,
1219            Some(self.base_address),
1220        )?;
1221        self.sequence.reset_system(
1222            &mut *self.memory,
1223            crate::CoreType::Armv8a,
1224            Some(self.base_address),
1225        )?;
1226
1227        // Release from reset
1228        self.sequence.reset_catch_clear(
1229            &mut *self.memory,
1230            crate::CoreType::Armv8a,
1231            Some(self.base_address),
1232        )?;
1233
1234        self.wait_for_core_halted(timeout)?;
1235
1236        // Update core status
1237        let _ = self.status()?;
1238
1239        // Reset our cached values
1240        self.reset_register_cache();
1241
1242        // try to read the program counter
1243        let pc_value = self.read_core_reg(self.program_counter().into())?;
1244
1245        // get pc
1246        Ok(CoreInformation {
1247            pc: pc_value.try_into()?,
1248        })
1249    }
1250
1251    fn step(&mut self) -> Result<CoreInformation, Error> {
1252        // Load EDECR, set SS bit for step mode
1253        let edecr_address = Edecr::get_mmio_address_from_base(self.base_address)?;
1254        let mut edecr = Edecr(self.memory.read_word_32(edecr_address)?);
1255
1256        edecr.set_ss(true);
1257        self.memory.write_word_32(edecr_address, edecr.into())?;
1258
1259        // Resume
1260        self.run()?;
1261
1262        // Wait for halt
1263        self.wait_for_core_halted(Duration::from_millis(100))?;
1264
1265        // Reset EDECR
1266        edecr.set_ss(false);
1267        self.memory.write_word_32(edecr_address, edecr.into())?;
1268
1269        // try to read the program counter
1270        let pc_value = self.read_core_reg(self.program_counter().into())?;
1271
1272        // get pc
1273        Ok(CoreInformation {
1274            pc: pc_value.try_into()?,
1275        })
1276    }
1277
1278    fn read_core_reg(&mut self, address: RegisterId) -> Result<RegisterValue, Error> {
1279        let reg_num = address.0;
1280
1281        // check cache
1282        if (reg_num as usize) < self.state.register_cache.len()
1283            && let Some(cached_result) = self.state.register_cache[reg_num as usize]
1284        {
1285            return Ok(cached_result.0);
1286        }
1287
1288        let result = if self.state.is_64_bit {
1289            self.read_core_reg_64(reg_num)
1290        } else {
1291            self.read_core_reg_32(reg_num)
1292        };
1293
1294        if let Ok(value) = result {
1295            self.state.register_cache[reg_num as usize] = Some((value, false));
1296
1297            Ok(value)
1298        } else {
1299            Err(result.err().unwrap())
1300        }
1301    }
1302
1303    fn write_core_reg(&mut self, address: RegisterId, value: RegisterValue) -> Result<(), Error> {
1304        let reg_num = address.0;
1305        let current_mode = if self.state.is_64_bit { 64 } else { 32 };
1306
1307        if (reg_num as usize) >= self.state.register_cache.len() {
1308            return Err(Error::Arm(
1309                Armv8aError::InvalidRegisterNumber(reg_num, current_mode).into(),
1310            ));
1311        }
1312        self.state.register_cache[reg_num as usize] = Some((value, true));
1313
1314        Ok(())
1315    }
1316
1317    fn available_breakpoint_units(&mut self) -> Result<u32, Error> {
1318        if self.num_breakpoints.is_none() {
1319            let address = Eddfr::get_mmio_address_from_base(self.base_address)?;
1320            let eddfr = Eddfr(self.memory.read_word_32(address)?);
1321
1322            self.num_breakpoints = Some(eddfr.brps() + 1);
1323        }
1324        Ok(self.num_breakpoints.unwrap())
1325    }
1326
1327    /// See docs on the [`CoreInterface::hw_breakpoints`] trait
1328    fn hw_breakpoints(&mut self) -> Result<Vec<Option<u64>>, Error> {
1329        let mut breakpoints = vec![];
1330        let num_hw_breakpoints = self.available_breakpoint_units()? as usize;
1331
1332        for bp_unit_index in 0..num_hw_breakpoints {
1333            let bp_value_addr = Dbgbvr::get_mmio_address_from_base(self.base_address)?
1334                + (bp_unit_index * 16) as u64;
1335            let mut bp_value = self.memory.read_word_32(bp_value_addr)? as u64;
1336            bp_value |= (self.memory.read_word_32(bp_value_addr + 4)? as u64) << 32;
1337
1338            let bp_control_addr = Dbgbcr::get_mmio_address_from_base(self.base_address)?
1339                + (bp_unit_index * 16) as u64;
1340            let bp_control = Dbgbcr(self.memory.read_word_32(bp_control_addr)?);
1341
1342            if bp_control.e() {
1343                breakpoints.push(Some(bp_value));
1344            } else {
1345                breakpoints.push(None);
1346            }
1347        }
1348        Ok(breakpoints)
1349    }
1350
1351    fn enable_breakpoints(&mut self, _state: bool) -> Result<(), Error> {
1352        // Breakpoints are always on with v7-A
1353        Ok(())
1354    }
1355
1356    fn set_hw_breakpoint(&mut self, bp_unit_index: usize, addr: u64) -> Result<(), Error> {
1357        let bp_value_addr =
1358            Dbgbvr::get_mmio_address_from_base(self.base_address)? + (bp_unit_index * 16) as u64;
1359        let bp_control_addr =
1360            Dbgbcr::get_mmio_address_from_base(self.base_address)? + (bp_unit_index * 16) as u64;
1361        let mut bp_control = Dbgbcr(0);
1362
1363        // Breakpoint type - address match
1364        bp_control.set_bt(0b0000);
1365        // Match on all modes
1366        bp_control.set_hmc(true);
1367        bp_control.set_pmc(0b11);
1368        // Match on all bytes
1369        bp_control.set_bas(0b1111);
1370        // Enable
1371        bp_control.set_e(true);
1372
1373        let addr_low = addr as u32;
1374        let addr_high = (addr >> 32) as u32;
1375
1376        self.memory.write_word_32(bp_value_addr, addr_low)?;
1377        self.memory.write_word_32(bp_value_addr + 4, addr_high)?;
1378        self.memory
1379            .write_word_32(bp_control_addr, bp_control.into())?;
1380
1381        Ok(())
1382    }
1383
1384    fn clear_hw_breakpoint(&mut self, bp_unit_index: usize) -> Result<(), Error> {
1385        let bp_value_addr =
1386            Dbgbvr::get_mmio_address_from_base(self.base_address)? + (bp_unit_index * 16) as u64;
1387        let bp_control_addr =
1388            Dbgbcr::get_mmio_address_from_base(self.base_address)? + (bp_unit_index * 16) as u64;
1389
1390        self.memory.write_word_32(bp_value_addr, 0)?;
1391        self.memory.write_word_32(bp_value_addr + 4, 0)?;
1392        self.memory.write_word_32(bp_control_addr, 0)?;
1393
1394        Ok(())
1395    }
1396
1397    fn registers(&self) -> &'static CoreRegisters {
1398        if self.state.is_64_bit {
1399            &AARCH64_CORE_REGISTERS
1400        } else {
1401            &AARCH32_WITH_FP_32_CORE_REGISTERS
1402        }
1403    }
1404
1405    fn program_counter(&self) -> &'static CoreRegister {
1406        if self.state.is_64_bit {
1407            &super::registers::aarch64::PC
1408        } else {
1409            &super::registers::cortex_m::PC
1410        }
1411    }
1412
1413    fn frame_pointer(&self) -> &'static CoreRegister {
1414        if self.state.is_64_bit {
1415            &super::registers::aarch64::FP
1416        } else {
1417            &super::registers::cortex_m::FP
1418        }
1419    }
1420
1421    fn stack_pointer(&self) -> &'static CoreRegister {
1422        if self.state.is_64_bit {
1423            &super::registers::aarch64::SP
1424        } else {
1425            &super::registers::cortex_m::SP
1426        }
1427    }
1428
1429    fn return_address(&self) -> &'static CoreRegister {
1430        if self.state.is_64_bit {
1431            &super::registers::aarch64::RA
1432        } else {
1433            &super::registers::cortex_m::RA
1434        }
1435    }
1436
1437    fn hw_breakpoints_enabled(&self) -> bool {
1438        true
1439    }
1440
1441    fn architecture(&self) -> Architecture {
1442        Architecture::Arm
1443    }
1444
1445    fn core_type(&self) -> CoreType {
1446        CoreType::Armv8a
1447    }
1448
1449    fn instruction_set(&mut self) -> Result<InstructionSet, Error> {
1450        if self.state.is_64_bit {
1451            Ok(InstructionSet::A64)
1452        } else {
1453            let cpsr: u32 = self.read_core_reg(RegisterId(16))?.try_into()?;
1454
1455            // CPSR bit 5 - T - Thumb mode
1456            match (cpsr >> 5) & 1 {
1457                1 => Ok(InstructionSet::Thumb2),
1458                _ => Ok(InstructionSet::A32),
1459            }
1460        }
1461    }
1462
1463    fn fpu_support(&mut self) -> Result<bool, crate::error::Error> {
1464        // Always available for v8-a
1465        Ok(true)
1466    }
1467
1468    fn floating_point_register_count(&mut self) -> Result<usize, crate::error::Error> {
1469        // Always available for v8-a
1470        Ok(self.state.fp_reg_count)
1471    }
1472
1473    #[tracing::instrument(skip(self))]
1474    fn reset_catch_set(&mut self) -> Result<(), Error> {
1475        self.sequence.reset_catch_set(
1476            &mut *self.memory,
1477            CoreType::Armv8a,
1478            Some(self.base_address),
1479        )?;
1480
1481        Ok(())
1482    }
1483
1484    #[tracing::instrument(skip(self))]
1485    fn reset_catch_clear(&mut self) -> Result<(), Error> {
1486        self.sequence.reset_catch_clear(
1487            &mut *self.memory,
1488            CoreType::Armv8a,
1489            Some(self.base_address),
1490        )?;
1491
1492        Ok(())
1493    }
1494
1495    #[tracing::instrument(skip(self))]
1496    fn debug_core_stop(&mut self) -> Result<(), Error> {
1497        if matches!(self.state.current_state, CoreStatus::Halted(_)) {
1498            // We may have clobbered registers we wrote during debugging
1499            // Best effort attempt to put them back before we exit
1500            self.writeback_registers()?;
1501        }
1502
1503        self.sequence
1504            .debug_core_stop(&mut *self.memory, CoreType::Armv8a)?;
1505
1506        Ok(())
1507    }
1508
1509    fn is_64_bit(&self) -> bool {
1510        self.state.is_64_bit
1511    }
1512}
1513
1514impl MemoryInterface for Armv8a<'_> {
1515    fn supports_native_64bit_access(&mut self) -> bool {
1516        self.state.is_64_bit
1517    }
1518
1519    fn read_word_64(&mut self, address: u64) -> Result<u64, Error> {
1520        if self.state.is_64_bit {
1521            self.read_cpu_memory_aarch64_64(address)
1522        } else {
1523            let mut ret = self.read_cpu_memory_aarch32_32(address)? as u64;
1524            ret |= (self.read_cpu_memory_aarch32_32(address + 4)? as u64) << 32;
1525
1526            Ok(ret)
1527        }
1528    }
1529
1530    fn read_word_32(&mut self, address: u64) -> Result<u32, Error> {
1531        if self.state.is_64_bit {
1532            self.read_cpu_memory_aarch64_32(address)
1533        } else {
1534            self.read_cpu_memory_aarch32_32(address)
1535        }
1536    }
1537
1538    fn read_word_16(&mut self, address: u64) -> Result<u16, Error> {
1539        // Find the word this is in and its byte offset
1540        let byte_offset = address % 4;
1541        let word_start = address - byte_offset;
1542
1543        // Read the word
1544        let data = self.read_word_32(word_start)?;
1545
1546        // Return the byte
1547        Ok((data >> (byte_offset * 8)) as u16)
1548    }
1549
1550    fn read_word_8(&mut self, address: u64) -> Result<u8, Error> {
1551        // Find the word this is in and its byte offset
1552        let byte_offset = address % 4;
1553        let word_start = address - byte_offset;
1554
1555        // Read the word
1556        let data = self.read_word_32(word_start)?;
1557
1558        // Return the byte
1559        Ok(data.to_le_bytes()[byte_offset as usize])
1560    }
1561
1562    fn read_64(&mut self, address: u64, data: &mut [u64]) -> Result<(), Error> {
1563        if self.state.is_64_bit {
1564            let (_prefix, data, _suffix) = unsafe { data.align_to_mut::<u8>() };
1565            self.read_cpu_memory_aarch64_fast(address, data)?;
1566        } else {
1567            for (i, word) in data.iter_mut().enumerate() {
1568                *word = self.read_word_64(address + ((i as u64) * 8))?;
1569            }
1570        }
1571
1572        Ok(())
1573    }
1574
1575    fn read_32(&mut self, address: u64, data: &mut [u32]) -> Result<(), Error> {
1576        if self.state.is_64_bit {
1577            let (_prefix, data, _suffix) = unsafe { data.align_to_mut::<u8>() };
1578            self.read_cpu_memory_aarch64_fast(address, data)?;
1579        } else {
1580            for (i, word) in data.iter_mut().enumerate() {
1581                *word = self.read_word_32(address + ((i as u64) * 4))?;
1582            }
1583        }
1584
1585        Ok(())
1586    }
1587
1588    fn read_16(&mut self, address: u64, data: &mut [u16]) -> Result<(), Error> {
1589        if self.state.is_64_bit {
1590            let (_prefix, data, _suffix) = unsafe { data.align_to_mut::<u8>() };
1591            self.read_cpu_memory_aarch64_fast(address, data)?;
1592        } else {
1593            for (i, word) in data.iter_mut().enumerate() {
1594                *word = self.read_word_16(address + ((i as u64) * 2))?;
1595            }
1596        }
1597
1598        Ok(())
1599    }
1600
1601    fn read_8(&mut self, address: u64, data: &mut [u8]) -> Result<(), Error> {
1602        if self.state.is_64_bit {
1603            self.read_cpu_memory_aarch64_fast(address, data)?;
1604        } else {
1605            for (i, byte) in data.iter_mut().enumerate() {
1606                *byte = self.read_word_8(address + (i as u64))?;
1607            }
1608        }
1609
1610        Ok(())
1611    }
1612
1613    fn write_word_64(&mut self, address: u64, data: u64) -> Result<(), Error> {
1614        if self.state.is_64_bit {
1615            self.write_cpu_memory_aarch64_64(address, data)
1616        } else {
1617            let low_word = data as u32;
1618            let high_word = (data >> 32) as u32;
1619
1620            self.write_cpu_memory_aarch32_32(address, low_word)?;
1621            self.write_cpu_memory_aarch32_32(address + 4, high_word)
1622        }
1623    }
1624
1625    fn write_word_32(&mut self, address: u64, data: u32) -> Result<(), Error> {
1626        if self.state.is_64_bit {
1627            self.write_cpu_memory_aarch64_32(address, data)
1628        } else {
1629            self.write_cpu_memory_aarch32_32(address, data)
1630        }
1631    }
1632
1633    fn write_word_16(&mut self, address: u64, data: u16) -> Result<(), Error> {
1634        // Find the word this is in and its byte offset
1635        let byte_offset = address % 4;
1636        let word_start = address - byte_offset;
1637
1638        // Get the current word value
1639        let mut word = self.read_word_32(word_start)?;
1640
1641        // patch the word into it
1642        word &= !(0xFFFFu32 << (byte_offset * 8));
1643        word |= (data as u32) << (byte_offset * 8);
1644
1645        self.write_word_32(word_start, word)
1646    }
1647
1648    fn write_word_8(&mut self, address: u64, data: u8) -> Result<(), Error> {
1649        // Find the word this is in and its byte offset
1650        let byte_offset = address % 4;
1651        let word_start = address - byte_offset;
1652
1653        // Get the current word value
1654        let current_word = self.read_word_32(word_start)?;
1655        let mut word_bytes = current_word.to_le_bytes();
1656        word_bytes[byte_offset as usize] = data;
1657
1658        self.write_word_32(word_start, u32::from_le_bytes(word_bytes))
1659    }
1660
1661    fn write_64(&mut self, address: u64, data: &[u64]) -> Result<(), Error> {
1662        // Note that the fast write path splits data into 32-bit words and does not guarantee 64-bit bus accesses.
1663        let (_prefix, data, _suffix) = unsafe { data.align_to::<u8>() };
1664        self.write_cpu_memory_fast(address, data)?;
1665
1666        Ok(())
1667    }
1668
1669    fn write_32(&mut self, address: u64, data: &[u32]) -> Result<(), Error> {
1670        let (_prefix, data, _suffix) = unsafe { data.align_to::<u8>() };
1671        self.write_cpu_memory_fast(address, data)?;
1672
1673        Ok(())
1674    }
1675
1676    fn write_16(&mut self, address: u64, data: &[u16]) -> Result<(), Error> {
1677        let (_prefix, data, _suffix) = unsafe { data.align_to::<u8>() };
1678        self.write_cpu_memory_fast(address, data)?;
1679
1680        Ok(())
1681    }
1682
1683    fn write_8(&mut self, address: u64, data: &[u8]) -> Result<(), Error> {
1684        self.write_cpu_memory_fast(address, data)?;
1685
1686        Ok(())
1687    }
1688
1689    fn supports_8bit_transfers(&self) -> Result<bool, Error> {
1690        Ok(false)
1691    }
1692
1693    fn flush(&mut self) -> Result<(), Error> {
1694        // Nothing to do - this runs through the CPU which automatically handles any caching
1695        Ok(())
1696    }
1697}
1698
1699#[cfg(test)]
1700mod test {
1701    use crate::{
1702        architecture::arm::{
1703            FullyQualifiedApAddress, communication_interface::SwdSequence,
1704            sequences::DefaultArmSequence,
1705        },
1706        probe::DebugProbeError,
1707    };
1708
1709    use super::*;
1710
1711    const TEST_BASE_ADDRESS: u64 = 0x8000_1000;
1712    const TEST_CTI_ADDRESS: u64 = 0x8000_2000;
1713
1714    fn address_to_reg_num(address: u64) -> u32 {
1715        ((address - TEST_BASE_ADDRESS) / 4) as u32
1716    }
1717
1718    pub struct ExpectedMemoryOp {
1719        read: bool,
1720        address: u64,
1721        value: u32,
1722    }
1723
1724    pub struct MockProbe {
1725        expected_ops: Vec<ExpectedMemoryOp>,
1726        is_64_bit: bool,
1727    }
1728
1729    impl MockProbe {
1730        pub fn new(is_64_bit: bool) -> Self {
1731            MockProbe {
1732                expected_ops: vec![],
1733                is_64_bit,
1734            }
1735        }
1736
1737        pub fn expected_read(&mut self, addr: u64, value: u32) {
1738            self.expected_ops.push(ExpectedMemoryOp {
1739                read: true,
1740                address: addr,
1741                value,
1742            });
1743        }
1744
1745        pub fn expected_write(&mut self, addr: u64, value: u32) {
1746            self.expected_ops.push(ExpectedMemoryOp {
1747                read: false,
1748                address: addr,
1749                value,
1750            });
1751        }
1752    }
1753    impl MemoryInterface<ArmError> for MockProbe {
1754        fn read_8(&mut self, _address: u64, _data: &mut [u8]) -> Result<(), ArmError> {
1755            todo!()
1756        }
1757
1758        fn read_16(&mut self, _address: u64, _data: &mut [u16]) -> Result<(), ArmError> {
1759            todo!()
1760        }
1761
1762        fn read_32(&mut self, address: u64, data: &mut [u32]) -> Result<(), ArmError> {
1763            if self.expected_ops.is_empty() {
1764                panic!(
1765                    "Received unexpected read_32 op: register {:#}",
1766                    address_to_reg_num(address)
1767                );
1768            }
1769
1770            assert_eq!(data.len(), 1);
1771
1772            let expected_op = self.expected_ops.remove(0);
1773
1774            assert!(
1775                expected_op.read,
1776                "R/W mismatch for register: Expected {:#} Actual: {:#}",
1777                address_to_reg_num(expected_op.address),
1778                address_to_reg_num(address)
1779            );
1780            assert_eq!(
1781                expected_op.address,
1782                address,
1783                "Read from unexpected register: Expected {:#} Actual: {:#}",
1784                address_to_reg_num(expected_op.address),
1785                address_to_reg_num(address)
1786            );
1787
1788            data[0] = expected_op.value;
1789
1790            Ok(())
1791        }
1792
1793        fn write_8(&mut self, _address: u64, _data: &[u8]) -> Result<(), ArmError> {
1794            todo!()
1795        }
1796
1797        fn write_16(&mut self, _address: u64, _data: &[u16]) -> Result<(), ArmError> {
1798            todo!()
1799        }
1800
1801        fn write_32(&mut self, address: u64, data: &[u32]) -> Result<(), ArmError> {
1802            if self.expected_ops.is_empty() {
1803                panic!(
1804                    "Received unexpected write_32 op: register {:#}",
1805                    address_to_reg_num(address)
1806                );
1807            }
1808
1809            assert_eq!(data.len(), 1);
1810
1811            let expected_op = self.expected_ops.remove(0);
1812
1813            assert!(!expected_op.read);
1814            assert_eq!(
1815                expected_op.address,
1816                address,
1817                "Write to unexpected register: Expected {:#} Actual: {:#}",
1818                address_to_reg_num(expected_op.address),
1819                address_to_reg_num(address)
1820            );
1821
1822            assert_eq!(
1823                expected_op.value, data[0],
1824                "Write value mismatch Expected {:#X} Actual: {:#X}",
1825                expected_op.value, data[0]
1826            );
1827
1828            Ok(())
1829        }
1830
1831        fn read_64(&mut self, _address: u64, _data: &mut [u64]) -> Result<(), ArmError> {
1832            todo!()
1833        }
1834
1835        fn write_64(&mut self, _address: u64, _data: &[u64]) -> Result<(), ArmError> {
1836            todo!()
1837        }
1838
1839        fn flush(&mut self) -> Result<(), ArmError> {
1840            todo!()
1841        }
1842
1843        fn supports_8bit_transfers(&self) -> Result<bool, ArmError> {
1844            Ok(false)
1845        }
1846
1847        fn supports_native_64bit_access(&mut self) -> bool {
1848            false
1849        }
1850    }
1851
1852    impl ArmMemoryInterface for MockProbe {
1853        fn fully_qualified_address(&self) -> FullyQualifiedApAddress {
1854            todo!()
1855        }
1856
1857        fn get_arm_debug_interface(
1858            &mut self,
1859        ) -> Result<&mut dyn crate::architecture::arm::ArmDebugInterface, DebugProbeError> {
1860            Err(DebugProbeError::NotImplemented {
1861                function_name: "get_arm_debug_interface",
1862            })
1863        }
1864
1865        fn generic_status(&mut self) -> Result<crate::architecture::arm::ap::CSW, ArmError> {
1866            Err(ArmError::Probe(DebugProbeError::NotImplemented {
1867                function_name: "generic_status",
1868            }))
1869        }
1870
1871        fn base_address(&mut self) -> Result<u64, ArmError> {
1872            todo!()
1873        }
1874    }
1875
1876    impl SwdSequence for MockProbe {
1877        fn swj_sequence(&mut self, _bit_len: u8, _bits: u64) -> Result<(), DebugProbeError> {
1878            todo!()
1879        }
1880
1881        fn swj_pins(
1882            &mut self,
1883            _pin_out: u32,
1884            _pin_select: u32,
1885            _pin_wait: u32,
1886        ) -> Result<u32, DebugProbeError> {
1887            todo!()
1888        }
1889    }
1890
1891    fn add_status_expectations(probe: &mut MockProbe, halted: bool) {
1892        let mut edscr = Edscr(0);
1893        edscr.set_status(if halted { 0b010011 } else { 0b000010 });
1894        if probe.is_64_bit {
1895            edscr.set_rw(0b1111);
1896        }
1897        probe.expected_read(
1898            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1899            edscr.into(),
1900        );
1901    }
1902
1903    fn add_read_reg_expectations(probe: &mut MockProbe, reg: u16, value: u32) {
1904        probe.expected_write(
1905            Editr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1906            prep_instr_for_itr_32(build_mcr(14, 0, reg, 0, 5, 0)),
1907        );
1908        let mut edscr = Edscr(0);
1909        edscr.set_ite(true);
1910        edscr.set_txfull(true);
1911
1912        probe.expected_read(
1913            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1914            edscr.into(),
1915        );
1916        probe.expected_read(
1917            Dbgdtrtx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1918            value,
1919        );
1920    }
1921
1922    fn add_read_reg_64_expectations(probe: &mut MockProbe, reg: u16, value: u64) {
1923        probe.expected_write(
1924            Editr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1925            aarch64::build_msr(2, 3, 0, 4, 0, reg),
1926        );
1927        let mut edscr = Edscr(0);
1928        edscr.set_ite(true);
1929        edscr.set_txfull(true);
1930
1931        probe.expected_read(
1932            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1933            edscr.into(),
1934        );
1935        probe.expected_read(
1936            Dbgdtrrx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1937            (value >> 32) as u32,
1938        );
1939        probe.expected_read(
1940            Dbgdtrtx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1941            value as u32,
1942        );
1943    }
1944
1945    fn add_read_pc_expectations(probe: &mut MockProbe, value: u32) {
1946        let mut edscr = Edscr(0);
1947        edscr.set_ite(true);
1948        edscr.set_txfull(true);
1949
1950        probe.expected_write(
1951            Editr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1952            prep_instr_for_itr_32(build_mrc(15, 3, 0, 4, 5, 1)),
1953        );
1954        probe.expected_read(
1955            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1956            edscr.into(),
1957        );
1958        add_read_reg_expectations(probe, 0, value);
1959    }
1960
1961    fn add_read_pc_64_expectations(probe: &mut MockProbe, value: u64) {
1962        let mut edscr = Edscr(0);
1963        edscr.set_ite(true);
1964        edscr.set_txfull(true);
1965
1966        probe.expected_write(
1967            Editr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1968            aarch64::build_mrs(3, 3, 4, 5, 1, 0),
1969        );
1970        probe.expected_read(
1971            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1972            edscr.into(),
1973        );
1974        add_read_reg_64_expectations(probe, 0, value);
1975    }
1976
1977    fn add_read_cpsr_expectations(probe: &mut MockProbe, value: u32) {
1978        let mut edscr = Edscr(0);
1979        edscr.set_ite(true);
1980        edscr.set_txfull(true);
1981
1982        probe.expected_write(
1983            Editr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1984            prep_instr_for_itr_32(build_mrc(15, 3, 0, 4, 5, 0)),
1985        );
1986        probe.expected_read(
1987            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1988            edscr.into(),
1989        );
1990        add_read_reg_expectations(probe, 0, value);
1991    }
1992
1993    fn add_read_cpsr_64_expectations(probe: &mut MockProbe, value: u32) {
1994        let mut edscr = Edscr(0);
1995        edscr.set_ite(true);
1996        edscr.set_txfull(true);
1997
1998        probe.expected_write(
1999            Editr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2000            aarch64::build_mrs(3, 3, 4, 5, 0, 0),
2001        );
2002        probe.expected_read(
2003            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2004            edscr.into(),
2005        );
2006        add_read_reg_64_expectations(probe, 0, value.into());
2007    }
2008
2009    fn add_halt_expectations(probe: &mut MockProbe) {
2010        let mut cti_gate = CtiGate(0);
2011        cti_gate.set_en(0, 1);
2012
2013        probe.expected_write(
2014            CtiGate::get_mmio_address_from_base(TEST_CTI_ADDRESS).unwrap(),
2015            cti_gate.into(),
2016        );
2017
2018        let mut pulse = CtiApppulse(0);
2019        pulse.set_apppulse(0, 1);
2020
2021        probe.expected_write(
2022            CtiApppulse::get_mmio_address_from_base(TEST_CTI_ADDRESS).unwrap(),
2023            pulse.into(),
2024        );
2025    }
2026
2027    fn add_halt_cleanup_expectations(probe: &mut MockProbe) {
2028        let cti_gate = CtiGate(0);
2029
2030        probe.expected_write(
2031            CtiGate::get_mmio_address_from_base(TEST_CTI_ADDRESS).unwrap(),
2032            cti_gate.into(),
2033        );
2034    }
2035
2036    fn add_resume_expectations(probe: &mut MockProbe) {
2037        let mut ack = CtiIntack(0);
2038        ack.set_ack(0, 1);
2039
2040        probe.expected_write(
2041            CtiIntack::get_mmio_address_from_base(TEST_CTI_ADDRESS).unwrap(),
2042            ack.into(),
2043        );
2044
2045        let status = CtiTrigoutstatus(0);
2046        probe.expected_read(
2047            CtiTrigoutstatus::get_mmio_address_from_base(TEST_CTI_ADDRESS).unwrap(),
2048            status.into(),
2049        );
2050
2051        let mut cti_gate = CtiGate(0);
2052        cti_gate.set_en(1, 1);
2053        probe.expected_write(
2054            CtiGate::get_mmio_address_from_base(TEST_CTI_ADDRESS).unwrap(),
2055            cti_gate.into(),
2056        );
2057
2058        let mut pulse = CtiApppulse(0);
2059        pulse.set_apppulse(1, 1);
2060        probe.expected_write(
2061            CtiApppulse::get_mmio_address_from_base(TEST_CTI_ADDRESS).unwrap(),
2062            pulse.into(),
2063        );
2064
2065        let mut edprsr = Edprsr(0);
2066        edprsr.set_sdr(true);
2067        probe.expected_read(
2068            Edprsr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2069            edprsr.into(),
2070        );
2071    }
2072
2073    fn add_resume_cleanup_expectations(probe: &mut MockProbe) {
2074        let cti_gate = CtiGate(0);
2075        probe.expected_write(
2076            CtiGate::get_mmio_address_from_base(TEST_CTI_ADDRESS).unwrap(),
2077            cti_gate.into(),
2078        );
2079    }
2080
2081    fn add_idr_expectations(probe: &mut MockProbe, bp_count: u32) {
2082        let mut eddfr = Eddfr(0);
2083        eddfr.set_brps(bp_count - 1);
2084        probe.expected_read(
2085            Eddfr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2086            eddfr.into(),
2087        );
2088    }
2089
2090    fn add_set_r0_expectation(probe: &mut MockProbe, value: u32) {
2091        let mut edscr = Edscr(0);
2092        edscr.set_ite(true);
2093        edscr.set_rxfull(true);
2094
2095        probe.expected_write(
2096            Dbgdtrrx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2097            value,
2098        );
2099        probe.expected_read(
2100            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2101            edscr.into(),
2102        );
2103
2104        probe.expected_write(
2105            Editr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2106            prep_instr_for_itr_32(build_mrc(14, 0, 0, 0, 5, 0)),
2107        );
2108        probe.expected_read(
2109            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2110            edscr.into(),
2111        );
2112    }
2113
2114    fn add_set_x0_expectation(probe: &mut MockProbe, value: u64) {
2115        let mut edscr = Edscr(0);
2116        edscr.set_ite(true);
2117        edscr.set_rxfull(true);
2118
2119        probe.expected_write(
2120            Dbgdtrtx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2121            (value >> 32) as u32,
2122        );
2123        probe.expected_write(
2124            Dbgdtrrx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2125            value as u32,
2126        );
2127        probe.expected_read(
2128            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2129            edscr.into(),
2130        );
2131
2132        probe.expected_write(
2133            Editr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2134            aarch64::build_mrs(2, 3, 0, 4, 0, 0),
2135        );
2136        probe.expected_read(
2137            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2138            edscr.into(),
2139        );
2140    }
2141
2142    fn add_read_memory_expectations(probe: &mut MockProbe, address: u64, value: u32) {
2143        add_set_r0_expectation(probe, address as u32);
2144
2145        let mut edscr = Edscr(0);
2146        edscr.set_ite(true);
2147        edscr.set_txfull(true);
2148
2149        probe.expected_write(
2150            Editr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2151            prep_instr_for_itr_32(build_ldr(1, 0, 4)),
2152        );
2153        probe.expected_read(
2154            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2155            edscr.into(),
2156        );
2157
2158        probe.expected_write(
2159            Editr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2160            prep_instr_for_itr_32(build_mcr(14, 0, 1, 0, 5, 0)),
2161        );
2162        probe.expected_read(
2163            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2164            edscr.into(),
2165        );
2166        probe.expected_read(
2167            Dbgdtrtx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2168            value,
2169        );
2170    }
2171
2172    fn add_read_memory_aarch64_expectations(probe: &mut MockProbe, address: u64, value: u32) {
2173        add_set_x0_expectation(probe, address);
2174
2175        let mut edscr = Edscr(0);
2176        edscr.set_ite(true);
2177        edscr.set_txfull(true);
2178
2179        probe.expected_write(
2180            Editr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2181            aarch64::build_ldrw(1, 0, 4),
2182        );
2183        probe.expected_read(
2184            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2185            edscr.into(),
2186        );
2187
2188        probe.expected_write(
2189            Editr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2190            aarch64::build_msr(2, 3, 0, 5, 0, 1),
2191        );
2192        probe.expected_read(
2193            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2194            edscr.into(),
2195        );
2196        probe.expected_read(
2197            Dbgdtrtx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2198            value,
2199        );
2200    }
2201
2202    #[test]
2203    fn armv8a_new() {
2204        let mut probe = MockProbe::new(false);
2205
2206        // Add expectations
2207        add_status_expectations(&mut probe, true);
2208
2209        let mock_mem = Box::new(probe) as _;
2210
2211        let mut state = CortexAState::new();
2212
2213        let core = Armv8a::new(
2214            mock_mem,
2215            &mut state,
2216            TEST_BASE_ADDRESS,
2217            TEST_CTI_ADDRESS,
2218            DefaultArmSequence::create(),
2219        )
2220        .unwrap();
2221
2222        assert!(!core.state.is_64_bit);
2223    }
2224
2225    #[test]
2226    fn armv8a_core_halted() {
2227        let mut probe = MockProbe::new(false);
2228        let mut state = CortexAState::new();
2229
2230        // Add expectations
2231        add_status_expectations(&mut probe, true);
2232
2233        let mut edscr = Edscr(0);
2234        edscr.set_status(0b000010);
2235        probe.expected_read(
2236            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2237            edscr.into(),
2238        );
2239
2240        edscr.set_status(0b010011);
2241        probe.expected_read(
2242            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2243            edscr.into(),
2244        );
2245
2246        let mock_mem = Box::new(probe) as _;
2247
2248        let mut armv8a = Armv8a::new(
2249            mock_mem,
2250            &mut state,
2251            TEST_BASE_ADDRESS,
2252            TEST_CTI_ADDRESS,
2253            DefaultArmSequence::create(),
2254        )
2255        .unwrap();
2256
2257        // First read false, second read true
2258        assert!(!armv8a.core_halted().unwrap());
2259        assert!(armv8a.core_halted().unwrap());
2260    }
2261
2262    #[test]
2263    fn armv8a_wait_for_core_halted() {
2264        let mut probe = MockProbe::new(false);
2265        let mut state = CortexAState::new();
2266
2267        // Add expectations
2268        add_status_expectations(&mut probe, true);
2269
2270        let mut edscr = Edscr(0);
2271        edscr.set_status(0b000010);
2272        probe.expected_read(
2273            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2274            edscr.into(),
2275        );
2276
2277        edscr.set_status(0b010011);
2278        probe.expected_read(
2279            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2280            edscr.into(),
2281        );
2282
2283        let mock_mem = Box::new(probe) as _;
2284
2285        let mut armv8a = Armv8a::new(
2286            mock_mem,
2287            &mut state,
2288            TEST_BASE_ADDRESS,
2289            TEST_CTI_ADDRESS,
2290            DefaultArmSequence::create(),
2291        )
2292        .unwrap();
2293
2294        // Should halt on second read
2295        armv8a
2296            .wait_for_core_halted(Duration::from_millis(100))
2297            .unwrap();
2298    }
2299
2300    #[test]
2301    fn armv8a_status_running() {
2302        let mut probe = MockProbe::new(false);
2303        let mut state = CortexAState::new();
2304
2305        // Add expectations
2306        add_status_expectations(&mut probe, true);
2307
2308        let mut edscr = Edscr(0);
2309        edscr.set_status(0b000010);
2310        probe.expected_read(
2311            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2312            edscr.into(),
2313        );
2314
2315        let mock_mem = Box::new(probe) as _;
2316
2317        let mut armv8a = Armv8a::new(
2318            mock_mem,
2319            &mut state,
2320            TEST_BASE_ADDRESS,
2321            TEST_CTI_ADDRESS,
2322            DefaultArmSequence::create(),
2323        )
2324        .unwrap();
2325
2326        assert_eq!(CoreStatus::Running, armv8a.status().unwrap());
2327    }
2328
2329    #[test]
2330    fn armv8a_status_halted() {
2331        let mut probe = MockProbe::new(false);
2332        let mut state = CortexAState::new();
2333
2334        // Add expectations
2335        add_status_expectations(&mut probe, true);
2336
2337        let mut edscr = Edscr(0);
2338        edscr.set_status(0b010011);
2339        probe.expected_read(
2340            Edscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2341            edscr.into(),
2342        );
2343
2344        let mock_mem = Box::new(probe) as _;
2345
2346        let mut armv8a = Armv8a::new(
2347            mock_mem,
2348            &mut state,
2349            TEST_BASE_ADDRESS,
2350            TEST_CTI_ADDRESS,
2351            DefaultArmSequence::create(),
2352        )
2353        .unwrap();
2354
2355        assert_eq!(
2356            CoreStatus::Halted(crate::HaltReason::Request),
2357            armv8a.status().unwrap()
2358        );
2359    }
2360
2361    #[test]
2362    fn armv8a_read_core_reg_common() {
2363        const REG_VALUE: u32 = 0xABCD;
2364
2365        let mut probe = MockProbe::new(false);
2366        let mut state = CortexAState::new();
2367
2368        // Add expectations
2369        add_status_expectations(&mut probe, true);
2370
2371        // Read register
2372        add_read_reg_expectations(&mut probe, 2, REG_VALUE);
2373
2374        let mock_mem = Box::new(probe) as _;
2375
2376        let mut armv8a = Armv8a::new(
2377            mock_mem,
2378            &mut state,
2379            TEST_BASE_ADDRESS,
2380            TEST_CTI_ADDRESS,
2381            DefaultArmSequence::create(),
2382        )
2383        .unwrap();
2384
2385        // First read will hit expectations
2386        assert_eq!(
2387            RegisterValue::from(REG_VALUE),
2388            armv8a.read_core_reg(RegisterId(2)).unwrap()
2389        );
2390
2391        // Second read will cache, no new expectations
2392        assert_eq!(
2393            RegisterValue::from(REG_VALUE),
2394            armv8a.read_core_reg(RegisterId(2)).unwrap()
2395        );
2396    }
2397
2398    #[test]
2399    fn armv8a_read_core_reg_common_64() {
2400        const REG_VALUE: u64 = 0xFFFF_EEEE_0000_ABCD;
2401
2402        let mut probe = MockProbe::new(true);
2403        let mut state = CortexAState::new();
2404
2405        // Add expectations
2406        add_status_expectations(&mut probe, true);
2407
2408        // Read register
2409        add_read_reg_64_expectations(&mut probe, 2, REG_VALUE);
2410
2411        let mock_mem = Box::new(probe) as _;
2412
2413        let mut armv8a = Armv8a::new(
2414            mock_mem,
2415            &mut state,
2416            TEST_BASE_ADDRESS,
2417            TEST_CTI_ADDRESS,
2418            DefaultArmSequence::create(),
2419        )
2420        .unwrap();
2421
2422        // First read will hit expectations
2423        assert_eq!(
2424            RegisterValue::from(REG_VALUE),
2425            armv8a.read_core_reg(RegisterId(2)).unwrap()
2426        );
2427
2428        // Second read will cache, no new expectations
2429        assert_eq!(
2430            RegisterValue::from(REG_VALUE),
2431            armv8a.read_core_reg(RegisterId(2)).unwrap()
2432        );
2433    }
2434
2435    #[test]
2436    fn armv8a_read_core_reg_pc() {
2437        const REG_VALUE: u32 = 0xABCD;
2438
2439        let mut probe = MockProbe::new(false);
2440        let mut state = CortexAState::new();
2441
2442        // Add expectations
2443        add_status_expectations(&mut probe, true);
2444
2445        // Read PC
2446        add_read_reg_expectations(&mut probe, 0, 0);
2447        add_read_pc_expectations(&mut probe, REG_VALUE);
2448
2449        let mock_mem = Box::new(probe) as _;
2450
2451        let mut armv8a = Armv8a::new(
2452            mock_mem,
2453            &mut state,
2454            TEST_BASE_ADDRESS,
2455            TEST_CTI_ADDRESS,
2456            DefaultArmSequence::create(),
2457        )
2458        .unwrap();
2459
2460        // First read will hit expectations
2461        assert_eq!(
2462            RegisterValue::from(REG_VALUE),
2463            armv8a.read_core_reg(RegisterId(15)).unwrap()
2464        );
2465
2466        // Second read will cache, no new expectations
2467        assert_eq!(
2468            RegisterValue::from(REG_VALUE),
2469            armv8a.read_core_reg(RegisterId(15)).unwrap()
2470        );
2471    }
2472
2473    #[test]
2474    fn armv8a_read_core_64_reg_pc() {
2475        const REG_VALUE: u64 = 0xFFFF_EEEE_0000_ABCD;
2476
2477        let mut probe = MockProbe::new(true);
2478        let mut state = CortexAState::new();
2479
2480        // Add expectations
2481        add_status_expectations(&mut probe, true);
2482
2483        // Read PC
2484        add_read_reg_64_expectations(&mut probe, 0, 0);
2485        add_read_pc_64_expectations(&mut probe, REG_VALUE);
2486
2487        let mock_mem = Box::new(probe) as _;
2488
2489        let mut armv8a = Armv8a::new(
2490            mock_mem,
2491            &mut state,
2492            TEST_BASE_ADDRESS,
2493            TEST_CTI_ADDRESS,
2494            DefaultArmSequence::create(),
2495        )
2496        .unwrap();
2497
2498        // First read will hit expectations
2499        assert_eq!(
2500            RegisterValue::from(REG_VALUE),
2501            armv8a.read_core_reg(RegisterId(32)).unwrap()
2502        );
2503
2504        // Second read will cache, no new expectations
2505        assert_eq!(
2506            RegisterValue::from(REG_VALUE),
2507            armv8a.read_core_reg(RegisterId(32)).unwrap()
2508        );
2509    }
2510
2511    #[test]
2512    fn armv8a_read_core_reg_cpsr() {
2513        const REG_VALUE: u32 = 0xABCD;
2514
2515        let mut probe = MockProbe::new(false);
2516        let mut state = CortexAState::new();
2517
2518        // Add expectations
2519        add_status_expectations(&mut probe, true);
2520
2521        // Read CPSR
2522        add_read_reg_expectations(&mut probe, 0, 0);
2523        add_read_cpsr_expectations(&mut probe, REG_VALUE);
2524
2525        let mock_mem = Box::new(probe) as _;
2526
2527        let mut armv8a = Armv8a::new(
2528            mock_mem,
2529            &mut state,
2530            TEST_BASE_ADDRESS,
2531            TEST_CTI_ADDRESS,
2532            DefaultArmSequence::create(),
2533        )
2534        .unwrap();
2535
2536        // First read will hit expectations
2537        assert_eq!(
2538            RegisterValue::from(REG_VALUE),
2539            armv8a.read_core_reg(RegisterId(16)).unwrap()
2540        );
2541
2542        // Second read will cache, no new expectations
2543        assert_eq!(
2544            RegisterValue::from(REG_VALUE),
2545            armv8a.read_core_reg(RegisterId(16)).unwrap()
2546        );
2547    }
2548
2549    #[test]
2550    fn armv8a_read_core_64_reg_cpsr() {
2551        const REG_VALUE: u32 = 0xABCD;
2552
2553        let mut probe = MockProbe::new(true);
2554        let mut state = CortexAState::new();
2555
2556        // Add expectations
2557        add_status_expectations(&mut probe, true);
2558
2559        // Read CPSR
2560        add_read_reg_64_expectations(&mut probe, 0, 0);
2561        add_read_cpsr_64_expectations(&mut probe, REG_VALUE);
2562
2563        let mock_mem = Box::new(probe) as _;
2564
2565        let mut armv8a = Armv8a::new(
2566            mock_mem,
2567            &mut state,
2568            TEST_BASE_ADDRESS,
2569            TEST_CTI_ADDRESS,
2570            DefaultArmSequence::create(),
2571        )
2572        .unwrap();
2573
2574        // First read will hit expectations
2575        assert_eq!(
2576            RegisterValue::from(REG_VALUE),
2577            armv8a.read_core_reg(RegisterId(33)).unwrap()
2578        );
2579
2580        // Second read will cache, no new expectations
2581        assert_eq!(
2582            RegisterValue::from(REG_VALUE),
2583            armv8a.read_core_reg(RegisterId(33)).unwrap()
2584        );
2585    }
2586
2587    #[test]
2588    fn armv8a_halt() {
2589        const REG_VALUE: u32 = 0xABCD;
2590
2591        let mut probe = MockProbe::new(false);
2592        let mut state = CortexAState::new();
2593
2594        // Add expectations
2595        add_status_expectations(&mut probe, false);
2596
2597        // Write halt request
2598        add_halt_expectations(&mut probe);
2599
2600        // Wait for halted
2601        add_status_expectations(&mut probe, true);
2602
2603        // Read status
2604        add_status_expectations(&mut probe, true);
2605        add_halt_cleanup_expectations(&mut probe);
2606
2607        // Read PC
2608        add_read_reg_expectations(&mut probe, 0, 0);
2609        add_read_pc_expectations(&mut probe, REG_VALUE);
2610
2611        let mock_mem = Box::new(probe) as _;
2612
2613        let mut armv8a = Armv8a::new(
2614            mock_mem,
2615            &mut state,
2616            TEST_BASE_ADDRESS,
2617            TEST_CTI_ADDRESS,
2618            DefaultArmSequence::create(),
2619        )
2620        .unwrap();
2621
2622        // Verify PC
2623        assert_eq!(
2624            REG_VALUE as u64,
2625            armv8a.halt(Duration::from_millis(100)).unwrap().pc
2626        );
2627    }
2628
2629    #[test]
2630    fn armv8a_run() {
2631        let mut probe = MockProbe::new(false);
2632        let mut state = CortexAState::new();
2633
2634        // Add expectations
2635        add_status_expectations(&mut probe, true);
2636
2637        // Write resume request
2638        add_resume_expectations(&mut probe);
2639
2640        // Read status
2641        add_status_expectations(&mut probe, false);
2642
2643        add_resume_cleanup_expectations(&mut probe);
2644
2645        let mock_mem = Box::new(probe) as _;
2646
2647        let mut armv8a = Armv8a::new(
2648            mock_mem,
2649            &mut state,
2650            TEST_BASE_ADDRESS,
2651            TEST_CTI_ADDRESS,
2652            DefaultArmSequence::create(),
2653        )
2654        .unwrap();
2655
2656        armv8a.run().unwrap();
2657    }
2658
2659    #[test]
2660    fn armv8a_available_breakpoint_units() {
2661        const BP_COUNT: u32 = 4;
2662        let mut probe = MockProbe::new(false);
2663        let mut state = CortexAState::new();
2664
2665        // Add expectations
2666        add_status_expectations(&mut probe, true);
2667
2668        // Read breakpoint count
2669        add_idr_expectations(&mut probe, BP_COUNT);
2670
2671        let mock_mem = Box::new(probe) as _;
2672
2673        let mut armv8a = Armv8a::new(
2674            mock_mem,
2675            &mut state,
2676            TEST_BASE_ADDRESS,
2677            TEST_CTI_ADDRESS,
2678            DefaultArmSequence::create(),
2679        )
2680        .unwrap();
2681
2682        assert_eq!(BP_COUNT, armv8a.available_breakpoint_units().unwrap());
2683    }
2684
2685    #[test]
2686    fn armv8a_hw_breakpoints() {
2687        const BP_COUNT: u32 = 4;
2688        const BP1: u64 = 0x2345;
2689        const BP2: u64 = 0x8000_0000;
2690        let mut probe = MockProbe::new(false);
2691        let mut state = CortexAState::new();
2692
2693        // Add expectations
2694        add_status_expectations(&mut probe, true);
2695
2696        // Read breakpoint count
2697        add_idr_expectations(&mut probe, BP_COUNT);
2698
2699        // Read BP values and controls
2700        probe.expected_read(
2701            Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2702            BP1 as u32,
2703        );
2704        probe.expected_read(
2705            Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + 4,
2706            0,
2707        );
2708        probe.expected_read(
2709            Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2710            1,
2711        );
2712
2713        probe.expected_read(
2714            Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + 16,
2715            BP2 as u32,
2716        );
2717        probe.expected_read(
2718            Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + 4 + 16,
2719            0,
2720        );
2721        probe.expected_read(
2722            Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + 16,
2723            1,
2724        );
2725
2726        probe.expected_read(
2727            Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (2 * 16),
2728            0,
2729        );
2730        probe.expected_read(
2731            Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + 4 + (2 * 16),
2732            0,
2733        );
2734        probe.expected_read(
2735            Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (2 * 16),
2736            0,
2737        );
2738
2739        probe.expected_read(
2740            Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (3 * 16),
2741            0,
2742        );
2743        probe.expected_read(
2744            Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + 4 + (3 * 16),
2745            0,
2746        );
2747        probe.expected_read(
2748            Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (3 * 16),
2749            0,
2750        );
2751
2752        let mock_mem = Box::new(probe) as _;
2753
2754        let mut armv8a = Armv8a::new(
2755            mock_mem,
2756            &mut state,
2757            TEST_BASE_ADDRESS,
2758            TEST_CTI_ADDRESS,
2759            DefaultArmSequence::create(),
2760        )
2761        .unwrap();
2762
2763        let results = armv8a.hw_breakpoints().unwrap();
2764        assert_eq!(Some(BP1), results[0]);
2765        assert_eq!(Some(BP2), results[1]);
2766        assert_eq!(None, results[2]);
2767        assert_eq!(None, results[3]);
2768    }
2769
2770    #[test]
2771    fn armv8a_set_hw_breakpoint() {
2772        const BP_VALUE: u64 = 0x2345;
2773        let mut probe = MockProbe::new(false);
2774        let mut state = CortexAState::new();
2775
2776        // Add expectations
2777        add_status_expectations(&mut probe, true);
2778
2779        // Update BP value and control
2780        let mut dbgbcr = Dbgbcr(0);
2781        // Match on all modes
2782        dbgbcr.set_hmc(true);
2783        dbgbcr.set_pmc(0b11);
2784        // Match on all bytes
2785        dbgbcr.set_bas(0b1111);
2786        // Enable
2787        dbgbcr.set_e(true);
2788
2789        probe.expected_write(
2790            Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2791            BP_VALUE as u32,
2792        );
2793        probe.expected_write(
2794            Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + 4,
2795            0,
2796        );
2797        probe.expected_write(
2798            Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2799            dbgbcr.into(),
2800        );
2801
2802        let mock_mem = Box::new(probe) as _;
2803
2804        let mut armv8a = Armv8a::new(
2805            mock_mem,
2806            &mut state,
2807            TEST_BASE_ADDRESS,
2808            TEST_CTI_ADDRESS,
2809            DefaultArmSequence::create(),
2810        )
2811        .unwrap();
2812
2813        armv8a.set_hw_breakpoint(0, BP_VALUE).unwrap();
2814    }
2815
2816    #[test]
2817    fn armv8a_clear_hw_breakpoint() {
2818        let mut probe = MockProbe::new(false);
2819        let mut state = CortexAState::new();
2820
2821        // Add expectations
2822        add_status_expectations(&mut probe, true);
2823
2824        // Update BP value and control
2825        probe.expected_write(
2826            Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2827            0,
2828        );
2829        probe.expected_write(
2830            Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + 4,
2831            0,
2832        );
2833        probe.expected_write(
2834            Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2835            0,
2836        );
2837
2838        let mock_mem = Box::new(probe) as _;
2839
2840        let mut armv8a = Armv8a::new(
2841            mock_mem,
2842            &mut state,
2843            TEST_BASE_ADDRESS,
2844            TEST_CTI_ADDRESS,
2845            DefaultArmSequence::create(),
2846        )
2847        .unwrap();
2848
2849        armv8a.clear_hw_breakpoint(0).unwrap();
2850    }
2851
2852    #[test]
2853    fn armv8a_read_word_32() {
2854        const MEMORY_VALUE: u32 = 0xBA5EBA11;
2855        const MEMORY_ADDRESS: u64 = 0x12345678;
2856
2857        let mut probe = MockProbe::new(false);
2858        let mut state = CortexAState::new();
2859
2860        // Add expectations
2861        add_status_expectations(&mut probe, true);
2862
2863        // Read memory
2864        add_read_reg_expectations(&mut probe, 0, 0);
2865        add_read_reg_expectations(&mut probe, 1, 0);
2866
2867        add_read_memory_expectations(&mut probe, MEMORY_ADDRESS, MEMORY_VALUE);
2868
2869        let mock_mem = Box::new(probe) as _;
2870
2871        let mut armv8a = Armv8a::new(
2872            mock_mem,
2873            &mut state,
2874            TEST_BASE_ADDRESS,
2875            TEST_CTI_ADDRESS,
2876            DefaultArmSequence::create(),
2877        )
2878        .unwrap();
2879
2880        assert_eq!(MEMORY_VALUE, armv8a.read_word_32(MEMORY_ADDRESS).unwrap());
2881    }
2882
2883    #[test]
2884    fn armv8a_read_word_32_aarch64() {
2885        const MEMORY_VALUE: u32 = 0xBA5EBA11;
2886        const MEMORY_ADDRESS: u64 = 0x12345678;
2887
2888        let mut probe = MockProbe::new(true);
2889        let mut state = CortexAState::new();
2890
2891        // Add expectations
2892        add_status_expectations(&mut probe, true);
2893
2894        // Read memory
2895        add_read_reg_64_expectations(&mut probe, 0, 0);
2896        add_read_reg_64_expectations(&mut probe, 1, 0);
2897
2898        add_read_memory_aarch64_expectations(&mut probe, MEMORY_ADDRESS, MEMORY_VALUE);
2899
2900        let mock_mem = Box::new(probe) as _;
2901
2902        let mut armv8a = Armv8a::new(
2903            mock_mem,
2904            &mut state,
2905            TEST_BASE_ADDRESS,
2906            TEST_CTI_ADDRESS,
2907            DefaultArmSequence::create(),
2908        )
2909        .unwrap();
2910
2911        assert_eq!(MEMORY_VALUE, armv8a.read_word_32(MEMORY_ADDRESS).unwrap());
2912    }
2913
2914    #[test]
2915    fn armv8a_read_word_8() {
2916        const MEMORY_VALUE: u32 = 0xBA5EBA11;
2917        const MEMORY_ADDRESS: u64 = 0x12345679;
2918        const MEMORY_WORD_ADDRESS: u64 = 0x12345678;
2919
2920        let mut probe = MockProbe::new(false);
2921        let mut state = CortexAState::new();
2922
2923        // Add expectations
2924        add_status_expectations(&mut probe, true);
2925
2926        // Read memory
2927        add_read_reg_expectations(&mut probe, 0, 0);
2928        add_read_reg_expectations(&mut probe, 1, 0);
2929        add_read_memory_expectations(&mut probe, MEMORY_WORD_ADDRESS, MEMORY_VALUE);
2930
2931        let mock_mem = Box::new(probe) as _;
2932
2933        let mut armv8a = Armv8a::new(
2934            mock_mem,
2935            &mut state,
2936            TEST_BASE_ADDRESS,
2937            TEST_CTI_ADDRESS,
2938            DefaultArmSequence::create(),
2939        )
2940        .unwrap();
2941
2942        assert_eq!(0xBA, armv8a.read_word_8(MEMORY_ADDRESS).unwrap());
2943    }
2944
2945    #[test]
2946    fn armv8a_read_word_aarch64_8() {
2947        const MEMORY_VALUE: u32 = 0xBA5EBA11;
2948        const MEMORY_ADDRESS: u64 = 0x12345679;
2949        const MEMORY_WORD_ADDRESS: u64 = 0x12345678;
2950
2951        let mut probe = MockProbe::new(true);
2952        let mut state = CortexAState::new();
2953
2954        // Add expectations
2955        add_status_expectations(&mut probe, true);
2956
2957        // Read memory
2958        add_read_reg_64_expectations(&mut probe, 0, 0);
2959        add_read_reg_64_expectations(&mut probe, 1, 0);
2960        add_read_memory_aarch64_expectations(&mut probe, MEMORY_WORD_ADDRESS, MEMORY_VALUE);
2961
2962        let mock_mem = Box::new(probe) as _;
2963
2964        let mut armv8a = Armv8a::new(
2965            mock_mem,
2966            &mut state,
2967            TEST_BASE_ADDRESS,
2968            TEST_CTI_ADDRESS,
2969            DefaultArmSequence::create(),
2970        )
2971        .unwrap();
2972
2973        assert_eq!(0xBA, armv8a.read_word_8(MEMORY_ADDRESS).unwrap());
2974    }
2975}