1 /*
2 * Copyright 2019 The Hafnium Authors.
3 *
4 * Use of this source code is governed by a BSD-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/BSD-3-Clause.
7 */
8
9 #include "debug_el1.h"
10
11 #include "hf/check.h"
12 #include "hf/dlog.h"
13 #include "hf/types.h"
14
15 #include "msr.h"
16 #include "sysregs.h"
17
18 /* clang-format off */
19
20 /**
21 * Definitions of read-only debug registers' encodings.
22 * See Arm Architecture Reference Manual Armv8-A, D12.2.
23 * NAME, op0, op1, crn, crm, op2
24 */
25 #define EL1_DEBUG_REGISTERS_READ \
26 X(MDRAR_EL1 , 2, 0, 1, 0, 0) \
27 X(OSLSR_EL1 , 2, 0, 1, 1, 4) \
28 X(DBGAUTHSTATUS_EL1 , 2, 0, 7, 14, 6) \
29
30 /**
31 * Definitions of write-only debug registers' encodings.
32 * See Arm Architecture Reference Manual Armv8-A, D12.2.
33 * NAME, op0, op1, crn, crm, op2
34 */
35 #define EL1_DEBUG_REGISTERS_WRITE \
36 X(OSLAR_EL1 , 2, 0, 1, 0, 4) \
37
38 /**
39 * Definitions of readable and writeable debug registers' encodings.
40 * See Arm Architecture Reference Manual Armv8-A, D12.2.
41 * NAME, op0, op1, crn, crm, op2
42 */
43 #define EL1_DEBUG_REGISTERS_READ_WRITE \
44 X(OSDTRRX_EL1 , 2, 0, 0, 0, 2) \
45 X(MDCCINT_EL1 , 2, 0, 0, 2, 0) \
46 X(MDSCR_EL1 , 2, 0, 0, 2, 2) \
47 X(OSDTRTX_EL1 , 2, 0, 0, 3, 2) \
48 X(OSECCR_EL1 , 2, 0, 0, 6, 2) \
49 X(DBGBVR0_EL1 , 2, 0, 0, 0, 4) \
50 X(DBGBVR1_EL1 , 2, 0, 0, 1, 4) \
51 X(DBGBVR2_EL1 , 2, 0, 0, 2, 4) \
52 X(DBGBVR3_EL1 , 2, 0, 0, 3, 4) \
53 X(DBGBVR4_EL1 , 2, 0, 0, 4, 4) \
54 X(DBGBVR5_EL1 , 2, 0, 0, 5, 4) \
55 X(DBGBVR6_EL1 , 2, 0, 0, 6, 4) \
56 X(DBGBVR7_EL1 , 2, 0, 0, 7, 4) \
57 X(DBGBVR8_EL1 , 2, 0, 0, 8, 4) \
58 X(DBGBVR9_EL1 , 2, 0, 0, 9, 4) \
59 X(DBGBVR10_EL1 , 2, 0, 0, 10, 4) \
60 X(DBGBVR11_EL1 , 2, 0, 0, 11, 4) \
61 X(DBGBVR12_EL1 , 2, 0, 0, 12, 4) \
62 X(DBGBVR13_EL1 , 2, 0, 0, 13, 4) \
63 X(DBGBVR14_EL1 , 2, 0, 0, 14, 4) \
64 X(DBGBVR15_EL1 , 2, 0, 0, 15, 4) \
65 X(DBGBCR0_EL1 , 2, 0, 0, 0, 5) \
66 X(DBGBCR1_EL1 , 2, 0, 0, 1, 5) \
67 X(DBGBCR2_EL1 , 2, 0, 0, 2, 5) \
68 X(DBGBCR3_EL1 , 2, 0, 0, 3, 5) \
69 X(DBGBCR4_EL1 , 2, 0, 0, 4, 5) \
70 X(DBGBCR5_EL1 , 2, 0, 0, 5, 5) \
71 X(DBGBCR6_EL1 , 2, 0, 0, 6, 5) \
72 X(DBGBCR7_EL1 , 2, 0, 0, 7, 5) \
73 X(DBGBCR8_EL1 , 2, 0, 0, 8, 5) \
74 X(DBGBCR9_EL1 , 2, 0, 0, 9, 5) \
75 X(DBGBCR10_EL1 , 2, 0, 0, 10, 5) \
76 X(DBGBCR11_EL1 , 2, 0, 0, 11, 5) \
77 X(DBGBCR12_EL1 , 2, 0, 0, 12, 5) \
78 X(DBGBCR13_EL1 , 2, 0, 0, 13, 5) \
79 X(DBGBCR14_EL1 , 2, 0, 0, 14, 5) \
80 X(DBGBCR15_EL1 , 2, 0, 0, 15, 5) \
81 X(DBGWVR0_EL1 , 2, 0, 0, 0, 6) \
82 X(DBGWVR1_EL1 , 2, 0, 0, 1, 6) \
83 X(DBGWVR2_EL1 , 2, 0, 0, 2, 6) \
84 X(DBGWVR3_EL1 , 2, 0, 0, 3, 6) \
85 X(DBGWVR4_EL1 , 2, 0, 0, 4, 6) \
86 X(DBGWVR5_EL1 , 2, 0, 0, 5, 6) \
87 X(DBGWVR6_EL1 , 2, 0, 0, 6, 6) \
88 X(DBGWVR7_EL1 , 2, 0, 0, 7, 6) \
89 X(DBGWVR8_EL1 , 2, 0, 0, 8, 6) \
90 X(DBGWVR9_EL1 , 2, 0, 0, 9, 6) \
91 X(DBGWVR10_EL1 , 2, 0, 0, 10, 6) \
92 X(DBGWVR11_EL1 , 2, 0, 0, 11, 6) \
93 X(DBGWVR12_EL1 , 2, 0, 0, 12, 6) \
94 X(DBGWVR13_EL1 , 2, 0, 0, 13, 6) \
95 X(DBGWVR14_EL1 , 2, 0, 0, 14, 6) \
96 X(DBGWVR15_EL1 , 2, 0, 0, 15, 6) \
97 X(DBGWCR0_EL1 , 2, 0, 0, 0, 7) \
98 X(DBGWCR1_EL1 , 2, 0, 0, 1, 7) \
99 X(DBGWCR2_EL1 , 2, 0, 0, 2, 7) \
100 X(DBGWCR3_EL1 , 2, 0, 0, 3, 7) \
101 X(DBGWCR4_EL1 , 2, 0, 0, 4, 7) \
102 X(DBGWCR5_EL1 , 2, 0, 0, 5, 7) \
103 X(DBGWCR6_EL1 , 2, 0, 0, 6, 7) \
104 X(DBGWCR7_EL1 , 2, 0, 0, 7, 7) \
105 X(DBGWCR8_EL1 , 2, 0, 0, 8, 7) \
106 X(DBGWCR9_EL1 , 2, 0, 0, 9, 7) \
107 X(DBGWCR10_EL1 , 2, 0, 0, 10, 7) \
108 X(DBGWCR11_EL1 , 2, 0, 0, 11, 7) \
109 X(DBGWCR12_EL1 , 2, 0, 0, 12, 7) \
110 X(DBGWCR13_EL1 , 2, 0, 0, 13, 7) \
111 X(DBGWCR14_EL1 , 2, 0, 0, 14, 7) \
112 X(DBGWCR15_EL1 , 2, 0, 0, 15, 7) \
113 X(OSDLR_EL1 , 2, 0, 1, 3, 4) \
114 X(DBGPRCR_EL1 , 2, 0, 1, 4, 4) \
115 X(DBGCLAIMSET_EL1 , 2, 0, 7, 8, 6) \
116 X(DBGCLAIMCLR_EL1 , 2, 0, 7, 9, 6)
117
118 /* clang-format on */
119
120 /**
121 * Returns true if the ESR register shows an access to an EL1 debug register.
122 */
debug_el1_is_register_access(uintreg_t esr)123 bool debug_el1_is_register_access(uintreg_t esr)
124 {
125 /*
126 * Architecture Reference Manual D12.2: op0 == 2 is for debug and trace
127 * system registers, op1 == 1 for trace, remaining are debug.
128 */
129 return GET_ISS_OP0(esr) == 2 && GET_ISS_OP1(esr) != 1;
130 }
131
132 /**
133 * Processes an access (msr, mrs) to an EL1 debug register.
134 * Returns true if the access was allowed and performed, false otherwise.
135 */
debug_el1_process_access(struct vcpu * vcpu,ffa_vm_id_t vm_id,uintreg_t esr)136 bool debug_el1_process_access(struct vcpu *vcpu, ffa_vm_id_t vm_id,
137 uintreg_t esr)
138 {
139 /*
140 * For now, debug registers are not supported by secondary VMs.
141 * Disallow accesses to them.
142 */
143 if (vm_id != HF_PRIMARY_VM_ID) {
144 return false;
145 }
146
147 uintreg_t sys_register = GET_ISS_SYSREG(esr);
148 uintreg_t rt_register = GET_ISS_RT(esr);
149 uintreg_t value;
150
151 /* +1 because Rt can access register XZR */
152 CHECK(rt_register < NUM_GP_REGS + 1);
153
154 if (ISS_IS_READ(esr)) {
155 switch (sys_register) {
156 #define X(reg_name, op0, op1, crn, crm, op2) \
157 case (GET_ISS_ENCODING(op0, op1, crn, crm, op2)): \
158 value = read_msr(reg_name); \
159 break;
160 EL1_DEBUG_REGISTERS_READ
161 EL1_DEBUG_REGISTERS_READ_WRITE
162 #undef X
163 default:
164 value = vcpu->regs.r[rt_register];
165 dlog_notice(
166 "Unsupported debug system register read: "
167 "op0=%d, op1=%d, crn=%d, crm=%d, op2=%d, "
168 "rt=%d.\n",
169 GET_ISS_OP0(esr), GET_ISS_OP1(esr),
170 GET_ISS_CRN(esr), GET_ISS_CRM(esr),
171 GET_ISS_OP2(esr), GET_ISS_RT(esr));
172 break;
173 }
174 if (rt_register != RT_REG_XZR) {
175 vcpu->regs.r[rt_register] = value;
176 }
177 } else {
178 if (rt_register != RT_REG_XZR) {
179 value = vcpu->regs.r[rt_register];
180 } else {
181 value = 0;
182 }
183 switch (sys_register) {
184 #define X(reg_name, op0, op1, crn, crm, op2) \
185 case (GET_ISS_ENCODING(op0, op1, crn, crm, op2)): \
186 write_msr(reg_name, value); \
187 break;
188 EL1_DEBUG_REGISTERS_WRITE
189 EL1_DEBUG_REGISTERS_READ_WRITE
190 #undef X
191 default:
192 dlog_notice(
193 "Unsupported debug system register write: "
194 "op0=%d, op1=%d, crn=%d, crm=%d, op2=%d, "
195 "rt=%d.\n",
196 GET_ISS_OP0(esr), GET_ISS_OP1(esr),
197 GET_ISS_CRN(esr), GET_ISS_CRM(esr),
198 GET_ISS_OP2(esr), GET_ISS_RT(esr));
199 break;
200 }
201 }
202
203 return true;
204 }
205