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