Skip to main content

libarch/arm64/
debug.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use bitrs::layout;
6use regio::arm64::{SysReg, spec};
7
8/// The number of registers in each of the `DBGB{C,V}R<n>_EL1` and
9/// `DBGW{C,V}R<n>_EL1` banks; the count actually implemented is reported by
10/// `ID_AA64DFR0_EL1`.
11pub const DEBUG_BANK_SIZE: usize = 16;
12
13layout!({
14    /// The layout of `DBGBCR<n>_EL1`.
15    pub struct BreakpointControlRegister(u64);
16    {
17        let __ @ 63..24;
18        let bt @ 23..20; // Breakpoint type
19        let lbn @ 19..16; // Linked breakpoint number
20        let ssc @ 15..14; // Security state control
21        let hmc @ 13; // Higher mode control
22        let __ @ 12..9;
23        let bas @ 8..5; // Byte address select
24        let __ @ 4..3;
25        let pmc @ 2..1; // Privilege mode control
26        let e @ 0; // Enable
27    }
28});
29
30layout!({
31    /// The layout of `DBGWCR<n>_EL1`.
32    pub struct WatchpointControlRegister(u64);
33    {
34        let __ @ 63..29;
35        let mask @ 28..24; // Address mask
36        let __ @ 23..21;
37        let wt @ 20; // Watchpoint type
38        let lbn @ 19..16; // Linked breakpoint number
39        let ssc @ 15..14; // Security state control
40        let hmc @ 13; // Higher mode control
41        let bas @ 12..5; // Byte address select
42        let lsc @ 4..3; // Load/store control
43        let pac @ 2..1; // Privilege access control
44        let e @ 0; // Enable
45    }
46});
47
48// Stamps out the consts of an indexed register bank, along with accessors
49// dispatching on a runtime index. Register instances are distinct types, so a
50// bank cannot be an array.
51macro_rules! sysreg_bank {
52    (
53        $doc:literal, $layout:ty, $read:ident, $write:ident;
54        $($n:literal => $name:ident),* $(,)?
55    ) => {
56        $(
57            #[doc = $doc]
58            pub const $name: SysReg<spec::$name, $layout> = SysReg::new();
59        )*
60
61        /// Reads register `n` of the bank.
62        ///
63        /// Panics if `n` is not below [`DEBUG_BANK_SIZE`].
64        #[cfg(target_arch = "aarch64")]
65        pub fn $read(n: usize) -> $layout {
66            match n {
67                $($n => $name.read(),)*
68                _ => panic!("debug register index {n} out of range"),
69            }
70        }
71
72        /// Writes register `n` of the bank.
73        ///
74        /// Panics if `n` is not below [`DEBUG_BANK_SIZE`].
75        #[cfg(target_arch = "aarch64")]
76        pub fn $write(n: usize, value: $layout) {
77            match n {
78                $($n => $name.write(value),)*
79                _ => panic!("debug register index {n} out of range"),
80            }
81        }
82    };
83}
84
85sysreg_bank!(
86    "[arm/sysreg]/dbgbcrn_el1: DBGBCR<n>_EL1, Debug Breakpoint Control Registers",
87    BreakpointControlRegister, read_dbgbcr, write_dbgbcr;
88    0 => DBGBCR0_EL1, 1 => DBGBCR1_EL1, 2 => DBGBCR2_EL1, 3 => DBGBCR3_EL1,
89    4 => DBGBCR4_EL1, 5 => DBGBCR5_EL1, 6 => DBGBCR6_EL1, 7 => DBGBCR7_EL1,
90    8 => DBGBCR8_EL1, 9 => DBGBCR9_EL1, 10 => DBGBCR10_EL1, 11 => DBGBCR11_EL1,
91    12 => DBGBCR12_EL1, 13 => DBGBCR13_EL1, 14 => DBGBCR14_EL1, 15 => DBGBCR15_EL1,
92);
93
94sysreg_bank!(
95    "[arm/sysreg]/dbgbvrn_el1: DBGBVR<n>_EL1, Debug Breakpoint Value Registers",
96    u64, read_dbgbvr, write_dbgbvr;
97    0 => DBGBVR0_EL1, 1 => DBGBVR1_EL1, 2 => DBGBVR2_EL1, 3 => DBGBVR3_EL1,
98    4 => DBGBVR4_EL1, 5 => DBGBVR5_EL1, 6 => DBGBVR6_EL1, 7 => DBGBVR7_EL1,
99    8 => DBGBVR8_EL1, 9 => DBGBVR9_EL1, 10 => DBGBVR10_EL1, 11 => DBGBVR11_EL1,
100    12 => DBGBVR12_EL1, 13 => DBGBVR13_EL1, 14 => DBGBVR14_EL1, 15 => DBGBVR15_EL1,
101);
102
103sysreg_bank!(
104    "[arm/sysreg]/dbgwcrn_el1: DBGWCR<n>_EL1, Debug Watchpoint Control Registers",
105    WatchpointControlRegister, read_dbgwcr, write_dbgwcr;
106    0 => DBGWCR0_EL1, 1 => DBGWCR1_EL1, 2 => DBGWCR2_EL1, 3 => DBGWCR3_EL1,
107    4 => DBGWCR4_EL1, 5 => DBGWCR5_EL1, 6 => DBGWCR6_EL1, 7 => DBGWCR7_EL1,
108    8 => DBGWCR8_EL1, 9 => DBGWCR9_EL1, 10 => DBGWCR10_EL1, 11 => DBGWCR11_EL1,
109    12 => DBGWCR12_EL1, 13 => DBGWCR13_EL1, 14 => DBGWCR14_EL1, 15 => DBGWCR15_EL1,
110);
111
112sysreg_bank!(
113    "[arm/sysreg]/dbgwvrn_el1: DBGWVR<n>_EL1, Debug Watchpoint Value Registers",
114    u64, read_dbgwvr, write_dbgwvr;
115    0 => DBGWVR0_EL1, 1 => DBGWVR1_EL1, 2 => DBGWVR2_EL1, 3 => DBGWVR3_EL1,
116    4 => DBGWVR4_EL1, 5 => DBGWVR5_EL1, 6 => DBGWVR6_EL1, 7 => DBGWVR7_EL1,
117    8 => DBGWVR8_EL1, 9 => DBGWVR9_EL1, 10 => DBGWVR10_EL1, 11 => DBGWVR11_EL1,
118    12 => DBGWVR12_EL1, 13 => DBGWVR13_EL1, 14 => DBGWVR14_EL1, 15 => DBGWVR15_EL1,
119);