31
31
*/
32
32
static void save_guest_debug_regs (struct kvm_vcpu * vcpu )
33
33
{
34
- u64 val = vcpu_read_sys_reg (vcpu , MDSCR_EL1 );
35
-
36
- vcpu -> arch .guest_debug_preserved .mdscr_el1 = val ;
37
34
vcpu -> arch .guest_debug_preserved .pstate_ss =
38
35
(* vcpu_cpsr (vcpu ) & DBG_SPSR_SS );
39
36
}
40
37
41
38
static void restore_guest_debug_regs (struct kvm_vcpu * vcpu )
42
39
{
43
- u64 val = vcpu -> arch .guest_debug_preserved .mdscr_el1 ;
44
-
45
- vcpu_write_sys_reg (vcpu , val , MDSCR_EL1 );
46
-
47
40
if (vcpu -> arch .guest_debug_preserved .pstate_ss )
48
41
* vcpu_cpsr (vcpu ) |= DBG_SPSR_SS ;
49
42
else
@@ -115,8 +108,6 @@ static void kvm_arm_setup_mdcr_el2(struct kvm_vcpu *vcpu)
115
108
116
109
void kvm_arm_setup_debug (struct kvm_vcpu * vcpu )
117
110
{
118
- unsigned long mdscr ;
119
-
120
111
/* Check if we need to use the debug registers. */
121
112
if (vcpu -> guest_debug || kvm_vcpu_os_lock_enabled (vcpu )) {
122
113
/* Save guest debug state */
@@ -154,36 +145,6 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
154
145
* vcpu_cpsr (vcpu ) |= DBG_SPSR_SS ;
155
146
else
156
147
* vcpu_cpsr (vcpu ) &= ~DBG_SPSR_SS ;
157
-
158
- mdscr = vcpu_read_sys_reg (vcpu , MDSCR_EL1 );
159
- mdscr |= DBG_MDSCR_SS ;
160
- vcpu_write_sys_reg (vcpu , mdscr , MDSCR_EL1 );
161
- } else {
162
- mdscr = vcpu_read_sys_reg (vcpu , MDSCR_EL1 );
163
- mdscr &= ~DBG_MDSCR_SS ;
164
- vcpu_write_sys_reg (vcpu , mdscr , MDSCR_EL1 );
165
- }
166
-
167
- /*
168
- * Enable breakpoints and watchpoints if userspace wants them.
169
- */
170
- if (vcpu -> guest_debug & KVM_GUESTDBG_USE_HW ) {
171
- mdscr = vcpu_read_sys_reg (vcpu , MDSCR_EL1 );
172
- mdscr |= DBG_MDSCR_MDE ;
173
- vcpu_write_sys_reg (vcpu , mdscr , MDSCR_EL1 );
174
-
175
- /*
176
- * The OS Lock blocks debug exceptions in all ELs when it is
177
- * enabled. If the guest has enabled the OS Lock, constrain its
178
- * effects to the guest. Emulate the behavior by clearing
179
- * MDSCR_EL1.MDE. In so doing, we ensure that host debug
180
- * exceptions are unaffected by guest configuration of the OS
181
- * Lock.
182
- */
183
- } else if (kvm_vcpu_os_lock_enabled (vcpu )) {
184
- mdscr = vcpu_read_sys_reg (vcpu , MDSCR_EL1 );
185
- mdscr &= ~DBG_MDSCR_MDE ;
186
- vcpu_write_sys_reg (vcpu , mdscr , MDSCR_EL1 );
187
148
}
188
149
}
189
150
}
@@ -227,6 +188,41 @@ void kvm_init_host_debug_data(void)
227
188
host_data_set_flag (HAS_TRBE );
228
189
}
229
190
191
+ /*
192
+ * Configures the 'external' MDSCR_EL1 value for the guest, i.e. when the host
193
+ * has taken over MDSCR_EL1.
194
+ *
195
+ * - Userspace is single-stepping the guest, and MDSCR_EL1.SS is forced to 1.
196
+ *
197
+ * - Userspace is using the breakpoint/watchpoint registers to debug the
198
+ * guest, and MDSCR_EL1.MDE is forced to 1.
199
+ *
200
+ * - The guest has enabled the OS Lock, and KVM is forcing MDSCR_EL1.MDE to 0,
201
+ * masking all debug exceptions affected by the OS Lock.
202
+ */
203
+ static void setup_external_mdscr (struct kvm_vcpu * vcpu )
204
+ {
205
+ /*
206
+ * Use the guest's MDSCR_EL1 as a starting point, since there are
207
+ * several other features controlled by MDSCR_EL1 that are not relevant
208
+ * to the host.
209
+ *
210
+ * Clear the bits that KVM may use which also satisfies emulation of
211
+ * the OS Lock as MDSCR_EL1.MDE is cleared.
212
+ */
213
+ u64 mdscr = vcpu_read_sys_reg (vcpu , MDSCR_EL1 ) & ~(MDSCR_EL1_SS |
214
+ MDSCR_EL1_MDE |
215
+ MDSCR_EL1_KDE );
216
+
217
+ if (vcpu -> guest_debug & KVM_GUESTDBG_SINGLESTEP )
218
+ mdscr |= MDSCR_EL1_SS ;
219
+
220
+ if (vcpu -> guest_debug & KVM_GUESTDBG_USE_HW )
221
+ mdscr |= MDSCR_EL1_MDE | MDSCR_EL1_KDE ;
222
+
223
+ vcpu -> arch .external_mdscr_el1 = mdscr ;
224
+ }
225
+
230
226
void kvm_vcpu_load_debug (struct kvm_vcpu * vcpu )
231
227
{
232
228
u64 mdscr ;
@@ -249,6 +245,7 @@ void kvm_vcpu_load_debug(struct kvm_vcpu *vcpu)
249
245
*/
250
246
if (vcpu -> guest_debug || kvm_vcpu_os_lock_enabled (vcpu )) {
251
247
vcpu -> arch .debug_owner = VCPU_DEBUG_HOST_OWNED ;
248
+ setup_external_mdscr (vcpu );
252
249
} else {
253
250
mdscr = vcpu_read_sys_reg (vcpu , MDSCR_EL1 );
254
251
0 commit comments