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