3
3
* Debug and Guest Debug support
4
4
*
5
5
* Copyright (C) 2015 - Linaro Ltd
6
- * Author: Alex Bennée <[email protected] >
6
+ * Authors: Alex Bennée <[email protected] >
7
+ * Oliver Upton <[email protected] >
7
8
*/
8
9
9
10
#include <linux/kvm_host.h>
14
15
#include <asm/kvm_arm.h>
15
16
#include <asm/kvm_emulate.h>
16
17
17
-
18
- /*
19
- * save/restore_guest_debug_regs
20
- *
21
- * For some debug operations we need to tweak some guest registers. As
22
- * a result we need to save the state of those registers before we
23
- * make those modifications.
24
- *
25
- * Guest access to MDSCR_EL1 is trapped by the hypervisor and handled
26
- * after we have restored the preserved value to the main context.
27
- *
28
- * When single-step is enabled by userspace, we tweak PSTATE.SS on every
29
- * guest entry. Preserve PSTATE.SS so we can restore the original value
30
- * for the vcpu after the single-step is disabled.
31
- */
32
- static void save_guest_debug_regs (struct kvm_vcpu * vcpu )
33
- {
34
- vcpu -> arch .guest_debug_preserved .pstate_ss =
35
- (* vcpu_cpsr (vcpu ) & DBG_SPSR_SS );
36
- }
37
-
38
- static void restore_guest_debug_regs (struct kvm_vcpu * vcpu )
39
- {
40
- if (vcpu -> arch .guest_debug_preserved .pstate_ss )
41
- * vcpu_cpsr (vcpu ) |= DBG_SPSR_SS ;
42
- else
43
- * vcpu_cpsr (vcpu ) &= ~DBG_SPSR_SS ;
44
- }
45
-
46
18
/**
47
19
* kvm_arm_setup_mdcr_el2 - configure vcpu mdcr_el2 value
48
20
*
@@ -91,83 +63,6 @@ static void kvm_arm_setup_mdcr_el2(struct kvm_vcpu *vcpu)
91
63
preempt_enable ();
92
64
}
93
65
94
- /**
95
- * kvm_arm_setup_debug - set up debug related stuff
96
- *
97
- * @vcpu: the vcpu pointer
98
- *
99
- * This is called before each entry into the hypervisor to setup any
100
- * debug related registers.
101
- *
102
- * Additionally, KVM only traps guest accesses to the debug registers if
103
- * the guest is not actively using them. Since the guest must not interfere
104
- * with the hardware state when debugging the guest, we must ensure that
105
- * trapping is enabled whenever we are debugging the guest using the
106
- * debug registers.
107
- */
108
-
109
- void kvm_arm_setup_debug (struct kvm_vcpu * vcpu )
110
- {
111
- /* Check if we need to use the debug registers. */
112
- if (vcpu -> guest_debug || kvm_vcpu_os_lock_enabled (vcpu )) {
113
- /* Save guest debug state */
114
- save_guest_debug_regs (vcpu );
115
-
116
- /*
117
- * Single Step (ARM ARM D2.12.3 The software step state
118
- * machine)
119
- *
120
- * If we are doing Single Step we need to manipulate
121
- * the guest's MDSCR_EL1.SS and PSTATE.SS. Once the
122
- * step has occurred the hypervisor will trap the
123
- * debug exception and we return to userspace.
124
- *
125
- * If the guest attempts to single step its userspace
126
- * we would have to deal with a trapped exception
127
- * while in the guest kernel. Because this would be
128
- * hard to unwind we suppress the guest's ability to
129
- * do so by masking MDSCR_EL.SS.
130
- *
131
- * This confuses guest debuggers which use
132
- * single-step behind the scenes but everything
133
- * returns to normal once the host is no longer
134
- * debugging the system.
135
- */
136
- if (vcpu -> guest_debug & KVM_GUESTDBG_SINGLESTEP ) {
137
- /*
138
- * If the software step state at the last guest exit
139
- * was Active-pending, we don't set DBG_SPSR_SS so
140
- * that the state is maintained (to not run another
141
- * single-step until the pending Software Step
142
- * exception is taken).
143
- */
144
- if (!vcpu_get_flag (vcpu , DBG_SS_ACTIVE_PENDING ))
145
- * vcpu_cpsr (vcpu ) |= DBG_SPSR_SS ;
146
- else
147
- * vcpu_cpsr (vcpu ) &= ~DBG_SPSR_SS ;
148
- }
149
- }
150
- }
151
-
152
- void kvm_arm_clear_debug (struct kvm_vcpu * vcpu )
153
- {
154
- /*
155
- * Restore the guest's debug registers if we were using them.
156
- */
157
- if (vcpu -> guest_debug || kvm_vcpu_os_lock_enabled (vcpu )) {
158
- if (vcpu -> guest_debug & KVM_GUESTDBG_SINGLESTEP ) {
159
- if (!(* vcpu_cpsr (vcpu ) & DBG_SPSR_SS ))
160
- /*
161
- * Mark the vcpu as ACTIVE_PENDING
162
- * until Software Step exception is taken.
163
- */
164
- vcpu_set_flag (vcpu , DBG_SS_ACTIVE_PENDING );
165
- }
166
-
167
- restore_guest_debug_regs (vcpu );
168
- }
169
- }
170
-
171
66
void kvm_init_host_debug_data (void )
172
67
{
173
68
u64 dfr0 = read_sysreg (id_aa64dfr0_el1 );
@@ -246,6 +141,22 @@ void kvm_vcpu_load_debug(struct kvm_vcpu *vcpu)
246
141
if (vcpu -> guest_debug || kvm_vcpu_os_lock_enabled (vcpu )) {
247
142
vcpu -> arch .debug_owner = VCPU_DEBUG_HOST_OWNED ;
248
143
setup_external_mdscr (vcpu );
144
+
145
+ /*
146
+ * Steal the guest's single-step state machine if userspace wants
147
+ * single-step the guest.
148
+ */
149
+ if (vcpu -> guest_debug & KVM_GUESTDBG_SINGLESTEP ) {
150
+ if (* vcpu_cpsr (vcpu ) & DBG_SPSR_SS )
151
+ vcpu_clear_flag (vcpu , GUEST_SS_ACTIVE_PENDING );
152
+ else
153
+ vcpu_set_flag (vcpu , GUEST_SS_ACTIVE_PENDING );
154
+
155
+ if (!vcpu_get_flag (vcpu , HOST_SS_ACTIVE_PENDING ))
156
+ * vcpu_cpsr (vcpu ) |= DBG_SPSR_SS ;
157
+ else
158
+ * vcpu_cpsr (vcpu ) &= ~DBG_SPSR_SS ;
159
+ }
249
160
} else {
250
161
mdscr = vcpu_read_sys_reg (vcpu , MDSCR_EL1 );
251
162
@@ -258,6 +169,26 @@ void kvm_vcpu_load_debug(struct kvm_vcpu *vcpu)
258
169
kvm_arm_setup_mdcr_el2 (vcpu );
259
170
}
260
171
172
+ void kvm_vcpu_put_debug (struct kvm_vcpu * vcpu )
173
+ {
174
+ if (likely (!(vcpu -> guest_debug & KVM_GUESTDBG_SINGLESTEP )))
175
+ return ;
176
+
177
+ /*
178
+ * Save the host's software step state and restore the guest's before
179
+ * potentially returning to userspace.
180
+ */
181
+ if (!(* vcpu_cpsr (vcpu ) & DBG_SPSR_SS ))
182
+ vcpu_set_flag (vcpu , HOST_SS_ACTIVE_PENDING );
183
+ else
184
+ vcpu_clear_flag (vcpu , HOST_SS_ACTIVE_PENDING );
185
+
186
+ if (vcpu_get_flag (vcpu , GUEST_SS_ACTIVE_PENDING ))
187
+ * vcpu_cpsr (vcpu ) &= ~DBG_SPSR_SS ;
188
+ else
189
+ * vcpu_cpsr (vcpu ) |= DBG_SPSR_SS ;
190
+ }
191
+
261
192
/*
262
193
* Updates ownership of the debug registers after a trapped guest access to a
263
194
* breakpoint/watchpoint register. Host ownership of the debug registers is of
0 commit comments