1 // Copyright 2018 The Fuchsia Authors
2 //
3 // Use of this source code is governed by a MIT-style
4 // license that can be found in the LICENSE file or at
5 // https://opensource.org/licenses/MIT
6
7 #include <arch/arm64.h>
8 #include <arch/arm64/registers.h>
9 #include <vm/vm.h>
10
arm64_disable_debug_state()11 void arm64_disable_debug_state() {
12 // The KDE bit enables and disables debug exceptions for the current execution.
13 // Instruction Breakpoint Exceptions (software breakpoints) cannot be deactivated.
14 uint32_t mdscr_val = __arm_rsr("mdscr_el1") & ~ARM64_MDSCR_EL1_KDE;
15 __arm_wsr("mdscr_el1", mdscr_val);
16 __isb(ARM_MB_SY);
17 }
18
arm64_enable_debug_state()19 void arm64_enable_debug_state() {
20 // The KDE bit enables and disables debug exceptions for the current execution.
21 // Instruction Breakpoint Exceptions (software breakpoints) cannot be deactivated.
22 uint32_t mdscr_val = __arm_rsr("mdscr_el1") | ARM64_MDSCR_EL1_KDE;
23 __arm_wsr("mdscr_el1", mdscr_val);
24 __isb(ARM_MB_SY);
25 }
26
arm64_validate_debug_state(arm64_debug_state_t * state)27 bool arm64_validate_debug_state(arm64_debug_state_t* state) {
28 // Validate that the addresses are valid.
29 size_t hw_bp_count = arm64_hw_breakpoint_count();
30 for (size_t i = 0; i < hw_bp_count; i++) {
31 uint64_t addr = state->hw_bps[i].dbgbvr;
32 if (addr != 0 && !is_user_address(addr)) {
33 return false;
34 }
35
36 // Mask out the fields that userspace is not allowed to modify.
37 uint32_t masked_user_bcr = state->hw_bps[i].dbgbcr & ARM64_DBGBCR_USER_MASK;
38 state->hw_bps[i].dbgbcr = ARM64_DBGBCR_MASK | masked_user_bcr;
39 }
40
41 return true;
42 }
43
arm64_hw_breakpoint_count()44 uint8_t arm64_hw_breakpoint_count() {
45 // TODO(donoso): Eventually this should be cached as a boot time constant.
46 uint64_t dfr0 = __arm_rsr64("id_aa64dfr0_el1");
47 uint8_t count = (uint8_t)(((dfr0 & ARM64_ID_AADFR0_EL1_BRPS) >>
48 ARM64_ID_AADFR0_EL1_BRPS_SHIFT) +
49 1lu);
50 // ARMv8 assures at least 2 hw registers.
51 DEBUG_ASSERT(count >= 2 && count <= 16);
52 return count;
53 }
54
55 // Read Debug State ------------------------------------------------------------------------------
56
arm64_read_hw_breakpoint_by_index(arm64_debug_state_t * debug_state,unsigned int index)57 static void arm64_read_hw_breakpoint_by_index(arm64_debug_state_t* debug_state,
58 unsigned int index) {
59 DEBUG_ASSERT(index < arm64_hw_breakpoint_count());
60
61 switch (index) {
62 case 0:
63 debug_state->hw_bps[0].dbgbcr = __arm_rsr("dbgbcr0_el1");
64 debug_state->hw_bps[0].dbgbvr = __arm_rsr64("dbgbvr0_el1");
65 break;
66 case 1:
67 debug_state->hw_bps[1].dbgbcr = __arm_rsr("dbgbcr1_el1");
68 debug_state->hw_bps[1].dbgbvr = __arm_rsr64("dbgbvr1_el1");
69 break;
70 case 2:
71 debug_state->hw_bps[2].dbgbcr = __arm_rsr("dbgbcr2_el1");
72 debug_state->hw_bps[2].dbgbvr = __arm_rsr64("dbgbvr2_el1");
73 break;
74 case 3:
75 debug_state->hw_bps[3].dbgbcr = __arm_rsr("dbgbcr3_el1");
76 debug_state->hw_bps[3].dbgbvr = __arm_rsr64("dbgbvr3_el1");
77 break;
78 case 4:
79 debug_state->hw_bps[4].dbgbcr = __arm_rsr("dbgbcr4_el1");
80 debug_state->hw_bps[4].dbgbvr = __arm_rsr64("dbgbvr4_el1");
81 break;
82 case 5:
83 debug_state->hw_bps[5].dbgbcr = __arm_rsr("dbgbcr5_el1");
84 debug_state->hw_bps[5].dbgbvr = __arm_rsr64("dbgbvr5_el1");
85 break;
86 case 6:
87 debug_state->hw_bps[6].dbgbcr = __arm_rsr("dbgbcr6_el1");
88 debug_state->hw_bps[6].dbgbvr = __arm_rsr64("dbgbvr6_el1");
89 break;
90 case 7:
91 debug_state->hw_bps[7].dbgbcr = __arm_rsr("dbgbcr7_el1");
92 debug_state->hw_bps[7].dbgbvr = __arm_rsr64("dbgbvr7_el1");
93 break;
94 case 8:
95 debug_state->hw_bps[8].dbgbcr = __arm_rsr("dbgbcr8_el1");
96 debug_state->hw_bps[8].dbgbvr = __arm_rsr64("dbgbvr8_el1");
97 break;
98 case 9:
99 debug_state->hw_bps[9].dbgbcr = __arm_rsr("dbgbcr9_el1");
100 debug_state->hw_bps[9].dbgbvr = __arm_rsr64("dbgbvr9_el1");
101 break;
102 case 10:
103 debug_state->hw_bps[10].dbgbcr = __arm_rsr("dbgbcr10_el1");
104 debug_state->hw_bps[10].dbgbvr = __arm_rsr64("dbgbvr10_el1");
105 break;
106 case 11:
107 debug_state->hw_bps[11].dbgbcr = __arm_rsr("dbgbcr11_el1");
108 debug_state->hw_bps[11].dbgbvr = __arm_rsr64("dbgbvr11_el1");
109 break;
110 case 12:
111 debug_state->hw_bps[12].dbgbcr = __arm_rsr("dbgbcr12_el1");
112 debug_state->hw_bps[12].dbgbvr = __arm_rsr64("dbgbvr12_el1");
113 break;
114 case 13:
115 debug_state->hw_bps[13].dbgbcr = __arm_rsr("dbgbcr13_el1");
116 debug_state->hw_bps[13].dbgbvr = __arm_rsr64("dbgbvr13_el1");
117 break;
118 case 14:
119 debug_state->hw_bps[14].dbgbcr = __arm_rsr("dbgbcr14_el1");
120 debug_state->hw_bps[14].dbgbvr = __arm_rsr64("dbgbvr14_el1");
121 break;
122 case 15:
123 debug_state->hw_bps[15].dbgbcr = __arm_rsr("dbgbcr15_el1");
124 debug_state->hw_bps[15].dbgbvr = __arm_rsr64("dbgbvr15_el1");
125 break;
126 default:
127 DEBUG_ASSERT(false);
128 }
129 }
130
arm64_read_hw_debug_regs(arm64_debug_state_t * debug_state)131 void arm64_read_hw_debug_regs(arm64_debug_state_t* debug_state) {
132 uint8_t count = arm64_hw_breakpoint_count();
133 for (unsigned int i = 0; i < count; i++) {
134 arm64_read_hw_breakpoint_by_index(debug_state, i);
135 }
136 }
137
138 // Writing Debug State ---------------------------------------------------------------------------
139
arm64_write_hw_breakpoint_by_index(const arm64_debug_state_t * debug_state,unsigned int index)140 static void arm64_write_hw_breakpoint_by_index(const arm64_debug_state_t* debug_state,
141 unsigned int index) {
142 DEBUG_ASSERT(index < arm64_hw_breakpoint_count());
143
144 switch (index) {
145 case 0:
146 __arm_wsr("dbgbcr0_el1", debug_state->hw_bps[0].dbgbcr);
147 __isb(ARM_MB_SY);
148 __arm_wsr64("dbgbvr0_el1", debug_state->hw_bps[0].dbgbvr);
149 __isb(ARM_MB_SY);
150 break;
151 case 1:
152 __arm_wsr("dbgbcr1_el1", debug_state->hw_bps[1].dbgbcr);
153 __isb(ARM_MB_SY);
154 __arm_wsr64("dbgbvr1_el1", debug_state->hw_bps[1].dbgbvr);
155 __isb(ARM_MB_SY);
156 break;
157 case 2:
158 __arm_wsr("dbgbcr2_el1", debug_state->hw_bps[2].dbgbcr);
159 __isb(ARM_MB_SY);
160 __arm_wsr64("dbgbvr2_el1", debug_state->hw_bps[2].dbgbvr);
161 __isb(ARM_MB_SY);
162 break;
163 case 3:
164 __arm_wsr("dbgbcr3_el1", debug_state->hw_bps[3].dbgbcr);
165 __isb(ARM_MB_SY);
166 __arm_wsr64("dbgbvr3_el1", debug_state->hw_bps[3].dbgbvr);
167 __isb(ARM_MB_SY);
168 break;
169 case 4:
170 __arm_wsr("dbgbcr4_el1", debug_state->hw_bps[4].dbgbcr);
171 __isb(ARM_MB_SY);
172 __arm_wsr64("dbgbvr4_el1", debug_state->hw_bps[4].dbgbvr);
173 __isb(ARM_MB_SY);
174 break;
175 case 5:
176 __arm_wsr("dbgbcr5_el1", debug_state->hw_bps[5].dbgbcr);
177 __isb(ARM_MB_SY);
178 __arm_wsr64("dbgbvr5_el1", debug_state->hw_bps[5].dbgbvr);
179 __isb(ARM_MB_SY);
180 break;
181 case 6:
182 __arm_wsr("dbgbcr6_el1", debug_state->hw_bps[6].dbgbcr);
183 __isb(ARM_MB_SY);
184 __arm_wsr64("dbgbvr6_el1", debug_state->hw_bps[6].dbgbvr);
185 __isb(ARM_MB_SY);
186 break;
187 case 7:
188 __arm_wsr("dbgbcr7_el1", debug_state->hw_bps[7].dbgbcr);
189 __isb(ARM_MB_SY);
190 __arm_wsr64("dbgbvr7_el1", debug_state->hw_bps[7].dbgbvr);
191 __isb(ARM_MB_SY);
192 break;
193 case 8:
194 __arm_wsr("dbgbcr8_el1", debug_state->hw_bps[8].dbgbcr);
195 __isb(ARM_MB_SY);
196 __arm_wsr64("dbgbvr8_el1", debug_state->hw_bps[8].dbgbvr);
197 __isb(ARM_MB_SY);
198 break;
199 case 9:
200 __arm_wsr("dbgbcr9_el1", debug_state->hw_bps[9].dbgbcr);
201 __isb(ARM_MB_SY);
202 __arm_wsr64("dbgbvr9_el1", debug_state->hw_bps[9].dbgbvr);
203 __isb(ARM_MB_SY);
204 break;
205 case 10:
206 __arm_wsr("dbgbcr10_el1", debug_state->hw_bps[10].dbgbcr);
207 __isb(ARM_MB_SY);
208 __arm_wsr64("dbgbvr10_el1", debug_state->hw_bps[10].dbgbvr);
209 __isb(ARM_MB_SY);
210 break;
211 case 11:
212 __arm_wsr("dbgbcr11_el1", debug_state->hw_bps[11].dbgbcr);
213 __isb(ARM_MB_SY);
214 __arm_wsr64("dbgbvr11_el1", debug_state->hw_bps[11].dbgbvr);
215 __isb(ARM_MB_SY);
216 break;
217 case 12:
218 __arm_wsr("dbgbcr12_el1", debug_state->hw_bps[12].dbgbcr);
219 __isb(ARM_MB_SY);
220 __arm_wsr64("dbgbvr12_el1", debug_state->hw_bps[12].dbgbvr);
221 __isb(ARM_MB_SY);
222 break;
223 case 13:
224 __arm_wsr("dbgbcr13_el1", debug_state->hw_bps[13].dbgbcr);
225 __isb(ARM_MB_SY);
226 __arm_wsr64("dbgbvr13_el1", debug_state->hw_bps[13].dbgbvr);
227 __isb(ARM_MB_SY);
228 break;
229 case 14:
230 __arm_wsr("dbgbcr14_el1", debug_state->hw_bps[14].dbgbcr);
231 __isb(ARM_MB_SY);
232 __arm_wsr64("dbgbvr14_el1", debug_state->hw_bps[14].dbgbvr);
233 __isb(ARM_MB_SY);
234 break;
235 case 15:
236 __arm_wsr("dbgbcr15_el1", debug_state->hw_bps[15].dbgbcr);
237 __isb(ARM_MB_SY);
238 __arm_wsr64("dbgbvr15_el1", debug_state->hw_bps[15].dbgbvr);
239 __isb(ARM_MB_SY);
240 break;
241 default:
242 DEBUG_ASSERT(false);
243 }
244 }
245
arm64_write_hw_debug_regs(const arm64_debug_state_t * debug_state)246 void arm64_write_hw_debug_regs(const arm64_debug_state_t* debug_state) {
247 uint64_t bps_count = arm64_hw_breakpoint_count();
248 for (unsigned int i = 0; i < bps_count; i++) {
249 arm64_write_hw_breakpoint_by_index(debug_state, i);
250 }
251 }
252