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