1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/kvm_host.h>
21#include <linux/hw_breakpoint.h>
22
23#include <asm/debug-monitors.h>
24#include <asm/kvm_asm.h>
25#include <asm/kvm_arm.h>
26#include <asm/kvm_emulate.h>
27
28#include "trace.h"
29
30
31#define MDSCR_EL1_DEBUG_MASK (DBG_MDSCR_SS | \
32 DBG_MDSCR_KDE | \
33 DBG_MDSCR_MDE)
34
35static DEFINE_PER_CPU(u32, mdcr_el2);
36
37
38
39
40
41
42
43
44
45
46
47static void save_guest_debug_regs(struct kvm_vcpu *vcpu)
48{
49 u64 val = vcpu_read_sys_reg(vcpu, MDSCR_EL1);
50
51 vcpu->arch.guest_debug_preserved.mdscr_el1 = val;
52
53 trace_kvm_arm_set_dreg32("Saved MDSCR_EL1",
54 vcpu->arch.guest_debug_preserved.mdscr_el1);
55}
56
57static void restore_guest_debug_regs(struct kvm_vcpu *vcpu)
58{
59 u64 val = vcpu->arch.guest_debug_preserved.mdscr_el1;
60
61 vcpu_write_sys_reg(vcpu, val, MDSCR_EL1);
62
63 trace_kvm_arm_set_dreg32("Restored MDSCR_EL1",
64 vcpu_read_sys_reg(vcpu, MDSCR_EL1));
65}
66
67
68
69
70
71
72
73
74
75
76
77void kvm_arm_init_debug(void)
78{
79 __this_cpu_write(mdcr_el2, kvm_call_hyp(__kvm_get_mdcr_el2));
80}
81
82
83
84
85
86void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu)
87{
88 vcpu->arch.debug_ptr = &vcpu->arch.vcpu_debug_state;
89}
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
113{
114 bool trap_debug = !(vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY);
115 unsigned long mdscr;
116
117 trace_kvm_arm_setup_debug(vcpu, vcpu->guest_debug);
118
119
120
121
122
123 vcpu->arch.mdcr_el2 = __this_cpu_read(mdcr_el2) & MDCR_EL2_HPMN_MASK;
124 vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM |
125 MDCR_EL2_TPMS |
126 MDCR_EL2_TPMCR |
127 MDCR_EL2_TDRA |
128 MDCR_EL2_TDOSA);
129
130
131 if (vcpu->guest_debug) {
132
133 vcpu->arch.mdcr_el2 |= MDCR_EL2_TDE;
134
135
136 save_guest_debug_regs(vcpu);
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158 if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
159 *vcpu_cpsr(vcpu) |= DBG_SPSR_SS;
160 mdscr = vcpu_read_sys_reg(vcpu, MDSCR_EL1);
161 mdscr |= DBG_MDSCR_SS;
162 vcpu_write_sys_reg(vcpu, mdscr, MDSCR_EL1);
163 } else {
164 mdscr = vcpu_read_sys_reg(vcpu, MDSCR_EL1);
165 mdscr &= ~DBG_MDSCR_SS;
166 vcpu_write_sys_reg(vcpu, mdscr, MDSCR_EL1);
167 }
168
169 trace_kvm_arm_set_dreg32("SPSR_EL2", *vcpu_cpsr(vcpu));
170
171
172
173
174
175
176
177
178
179
180 if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW) {
181
182 mdscr = vcpu_read_sys_reg(vcpu, MDSCR_EL1);
183 mdscr |= DBG_MDSCR_MDE;
184 vcpu_write_sys_reg(vcpu, mdscr, MDSCR_EL1);
185
186 vcpu->arch.debug_ptr = &vcpu->arch.external_debug_state;
187 vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
188 trap_debug = true;
189
190 trace_kvm_arm_set_regset("BKPTS", get_num_brps(),
191 &vcpu->arch.debug_ptr->dbg_bcr[0],
192 &vcpu->arch.debug_ptr->dbg_bvr[0]);
193
194 trace_kvm_arm_set_regset("WAPTS", get_num_wrps(),
195 &vcpu->arch.debug_ptr->dbg_wcr[0],
196 &vcpu->arch.debug_ptr->dbg_wvr[0]);
197 }
198 }
199
200 BUG_ON(!vcpu->guest_debug &&
201 vcpu->arch.debug_ptr != &vcpu->arch.vcpu_debug_state);
202
203
204 if (trap_debug)
205 vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;
206
207
208 if (vcpu_read_sys_reg(vcpu, MDSCR_EL1) & (DBG_MDSCR_KDE | DBG_MDSCR_MDE))
209 vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
210
211 trace_kvm_arm_set_dreg32("MDCR_EL2", vcpu->arch.mdcr_el2);
212 trace_kvm_arm_set_dreg32("MDSCR_EL1", vcpu_read_sys_reg(vcpu, MDSCR_EL1));
213}
214
215void kvm_arm_clear_debug(struct kvm_vcpu *vcpu)
216{
217 trace_kvm_arm_clear_debug(vcpu->guest_debug);
218
219 if (vcpu->guest_debug) {
220 restore_guest_debug_regs(vcpu);
221
222
223
224
225
226 if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW) {
227 kvm_arm_reset_debug_ptr(vcpu);
228
229 trace_kvm_arm_set_regset("BKPTS", get_num_brps(),
230 &vcpu->arch.debug_ptr->dbg_bcr[0],
231 &vcpu->arch.debug_ptr->dbg_bvr[0]);
232
233 trace_kvm_arm_set_regset("WAPTS", get_num_wrps(),
234 &vcpu->arch.debug_ptr->dbg_wcr[0],
235 &vcpu->arch.debug_ptr->dbg_wvr[0]);
236 }
237 }
238}
239
240
241
242
243
244
245
246
247
248
249
250
251bool kvm_arm_handle_step_debug(struct kvm_vcpu *vcpu, struct kvm_run *run)
252{
253 if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
254 run->exit_reason = KVM_EXIT_DEBUG;
255 run->debug.arch.hsr = ESR_ELx_EC_SOFTSTP_LOW << ESR_ELx_EC_SHIFT;
256 return true;
257 }
258 return false;
259}
260