Commit | Line | Data |
---|---|---|
56c7f5e7 AB |
1 | /* |
2 | * Debug and Guest Debug support | |
3 | * | |
4 | * Copyright (C) 2015 - Linaro Ltd | |
5 | * Author: Alex Bennée <alex.bennee@linaro.org> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License version 2 as | |
9 | * published by the Free Software Foundation. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | ||
20 | #include <linux/kvm_host.h> | |
eef8c85a | 21 | #include <linux/hw_breakpoint.h> |
56c7f5e7 | 22 | |
337b99bf AB |
23 | #include <asm/debug-monitors.h> |
24 | #include <asm/kvm_asm.h> | |
56c7f5e7 | 25 | #include <asm/kvm_arm.h> |
337b99bf AB |
26 | #include <asm/kvm_emulate.h> |
27 | ||
eef8c85a AB |
28 | #include "trace.h" |
29 | ||
337b99bf AB |
30 | /* These are the bits of MDSCR_EL1 we may manipulate */ |
31 | #define MDSCR_EL1_DEBUG_MASK (DBG_MDSCR_SS | \ | |
32 | DBG_MDSCR_KDE | \ | |
33 | DBG_MDSCR_MDE) | |
56c7f5e7 AB |
34 | |
35 | static DEFINE_PER_CPU(u32, mdcr_el2); | |
36 | ||
337b99bf AB |
37 | /** |
38 | * save/restore_guest_debug_regs | |
39 | * | |
40 | * For some debug operations we need to tweak some guest registers. As | |
41 | * a result we need to save the state of those registers before we | |
42 | * make those modifications. | |
43 | * | |
44 | * Guest access to MDSCR_EL1 is trapped by the hypervisor and handled | |
45 | * after we have restored the preserved value to the main context. | |
46 | */ | |
47 | static void save_guest_debug_regs(struct kvm_vcpu *vcpu) | |
48 | { | |
49 | vcpu->arch.guest_debug_preserved.mdscr_el1 = vcpu_sys_reg(vcpu, MDSCR_EL1); | |
eef8c85a AB |
50 | |
51 | trace_kvm_arm_set_dreg32("Saved MDSCR_EL1", | |
52 | vcpu->arch.guest_debug_preserved.mdscr_el1); | |
337b99bf AB |
53 | } |
54 | ||
55 | static void restore_guest_debug_regs(struct kvm_vcpu *vcpu) | |
56 | { | |
57 | vcpu_sys_reg(vcpu, MDSCR_EL1) = vcpu->arch.guest_debug_preserved.mdscr_el1; | |
eef8c85a AB |
58 | |
59 | trace_kvm_arm_set_dreg32("Restored MDSCR_EL1", | |
60 | vcpu_sys_reg(vcpu, MDSCR_EL1)); | |
337b99bf AB |
61 | } |
62 | ||
56c7f5e7 AB |
63 | /** |
64 | * kvm_arm_init_debug - grab what we need for debug | |
65 | * | |
66 | * Currently the sole task of this function is to retrieve the initial | |
67 | * value of mdcr_el2 so we can preserve MDCR_EL2.HPMN which has | |
68 | * presumably been set-up by some knowledgeable bootcode. | |
69 | * | |
70 | * It is called once per-cpu during CPU hyp initialisation. | |
71 | */ | |
72 | ||
73 | void kvm_arm_init_debug(void) | |
74 | { | |
75 | __this_cpu_write(mdcr_el2, kvm_call_hyp(__kvm_get_mdcr_el2)); | |
76 | } | |
77 | ||
84e690bf AB |
78 | /** |
79 | * kvm_arm_reset_debug_ptr - reset the debug ptr to point to the vcpu state | |
80 | */ | |
81 | ||
82 | void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu) | |
83 | { | |
84 | vcpu->arch.debug_ptr = &vcpu->arch.vcpu_debug_state; | |
85 | } | |
86 | ||
56c7f5e7 AB |
87 | /** |
88 | * kvm_arm_setup_debug - set up debug related stuff | |
89 | * | |
90 | * @vcpu: the vcpu pointer | |
91 | * | |
92 | * This is called before each entry into the hypervisor to setup any | |
93 | * debug related registers. Currently this just ensures we will trap | |
94 | * access to: | |
95 | * - Performance monitors (MDCR_EL2_TPM/MDCR_EL2_TPMCR) | |
96 | * - Debug ROM Address (MDCR_EL2_TDRA) | |
97 | * - OS related registers (MDCR_EL2_TDOSA) | |
98 | * | |
99 | * Additionally, KVM only traps guest accesses to the debug registers if | |
100 | * the guest is not actively using them (see the KVM_ARM64_DEBUG_DIRTY | |
101 | * flag on vcpu->arch.debug_flags). Since the guest must not interfere | |
102 | * with the hardware state when debugging the guest, we must ensure that | |
103 | * trapping is enabled whenever we are debugging the guest using the | |
104 | * debug registers. | |
105 | */ | |
106 | ||
107 | void kvm_arm_setup_debug(struct kvm_vcpu *vcpu) | |
108 | { | |
109 | bool trap_debug = !(vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY); | |
110 | ||
eef8c85a AB |
111 | trace_kvm_arm_setup_debug(vcpu, vcpu->guest_debug); |
112 | ||
56c7f5e7 AB |
113 | vcpu->arch.mdcr_el2 = __this_cpu_read(mdcr_el2) & MDCR_EL2_HPMN_MASK; |
114 | vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM | | |
115 | MDCR_EL2_TPMCR | | |
116 | MDCR_EL2_TDRA | | |
117 | MDCR_EL2_TDOSA); | |
118 | ||
337b99bf AB |
119 | /* Is Guest debugging in effect? */ |
120 | if (vcpu->guest_debug) { | |
121 | /* Route all software debug exceptions to EL2 */ | |
4bd611ca | 122 | vcpu->arch.mdcr_el2 |= MDCR_EL2_TDE; |
337b99bf AB |
123 | |
124 | /* Save guest debug state */ | |
125 | save_guest_debug_regs(vcpu); | |
126 | ||
127 | /* | |
128 | * Single Step (ARM ARM D2.12.3 The software step state | |
129 | * machine) | |
130 | * | |
131 | * If we are doing Single Step we need to manipulate | |
132 | * the guest's MDSCR_EL1.SS and PSTATE.SS. Once the | |
133 | * step has occurred the hypervisor will trap the | |
134 | * debug exception and we return to userspace. | |
135 | * | |
136 | * If the guest attempts to single step its userspace | |
137 | * we would have to deal with a trapped exception | |
138 | * while in the guest kernel. Because this would be | |
139 | * hard to unwind we suppress the guest's ability to | |
140 | * do so by masking MDSCR_EL.SS. | |
141 | * | |
142 | * This confuses guest debuggers which use | |
143 | * single-step behind the scenes but everything | |
144 | * returns to normal once the host is no longer | |
145 | * debugging the system. | |
146 | */ | |
147 | if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) { | |
148 | *vcpu_cpsr(vcpu) |= DBG_SPSR_SS; | |
149 | vcpu_sys_reg(vcpu, MDSCR_EL1) |= DBG_MDSCR_SS; | |
150 | } else { | |
151 | vcpu_sys_reg(vcpu, MDSCR_EL1) &= ~DBG_MDSCR_SS; | |
152 | } | |
834bf887 | 153 | |
eef8c85a AB |
154 | trace_kvm_arm_set_dreg32("SPSR_EL2", *vcpu_cpsr(vcpu)); |
155 | ||
834bf887 AB |
156 | /* |
157 | * HW Breakpoints and watchpoints | |
158 | * | |
159 | * We simply switch the debug_ptr to point to our new | |
160 | * external_debug_state which has been populated by the | |
161 | * debug ioctl. The existing KVM_ARM64_DEBUG_DIRTY | |
162 | * mechanism ensures the registers are updated on the | |
163 | * world switch. | |
164 | */ | |
165 | if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW) { | |
166 | /* Enable breakpoints/watchpoints */ | |
167 | vcpu_sys_reg(vcpu, MDSCR_EL1) |= DBG_MDSCR_MDE; | |
168 | ||
169 | vcpu->arch.debug_ptr = &vcpu->arch.external_debug_state; | |
170 | vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY; | |
171 | trap_debug = true; | |
eef8c85a AB |
172 | |
173 | trace_kvm_arm_set_regset("BKPTS", get_num_brps(), | |
174 | &vcpu->arch.debug_ptr->dbg_bcr[0], | |
175 | &vcpu->arch.debug_ptr->dbg_bvr[0]); | |
176 | ||
177 | trace_kvm_arm_set_regset("WAPTS", get_num_wrps(), | |
178 | &vcpu->arch.debug_ptr->dbg_wcr[0], | |
179 | &vcpu->arch.debug_ptr->dbg_wvr[0]); | |
834bf887 | 180 | } |
337b99bf | 181 | } |
834bf887 AB |
182 | |
183 | BUG_ON(!vcpu->guest_debug && | |
184 | vcpu->arch.debug_ptr != &vcpu->arch.vcpu_debug_state); | |
185 | ||
186 | /* Trap debug register access */ | |
187 | if (trap_debug) | |
188 | vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA; | |
eef8c85a AB |
189 | |
190 | trace_kvm_arm_set_dreg32("MDCR_EL2", vcpu->arch.mdcr_el2); | |
191 | trace_kvm_arm_set_dreg32("MDSCR_EL1", vcpu_sys_reg(vcpu, MDSCR_EL1)); | |
56c7f5e7 AB |
192 | } |
193 | ||
194 | void kvm_arm_clear_debug(struct kvm_vcpu *vcpu) | |
195 | { | |
eef8c85a AB |
196 | trace_kvm_arm_clear_debug(vcpu->guest_debug); |
197 | ||
834bf887 | 198 | if (vcpu->guest_debug) { |
337b99bf | 199 | restore_guest_debug_regs(vcpu); |
834bf887 AB |
200 | |
201 | /* | |
202 | * If we were using HW debug we need to restore the | |
203 | * debug_ptr to the guest debug state. | |
204 | */ | |
eef8c85a | 205 | if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW) { |
834bf887 AB |
206 | kvm_arm_reset_debug_ptr(vcpu); |
207 | ||
eef8c85a AB |
208 | trace_kvm_arm_set_regset("BKPTS", get_num_brps(), |
209 | &vcpu->arch.debug_ptr->dbg_bcr[0], | |
210 | &vcpu->arch.debug_ptr->dbg_bvr[0]); | |
211 | ||
212 | trace_kvm_arm_set_regset("WAPTS", get_num_wrps(), | |
213 | &vcpu->arch.debug_ptr->dbg_wcr[0], | |
214 | &vcpu->arch.debug_ptr->dbg_wvr[0]); | |
215 | } | |
834bf887 | 216 | } |
56c7f5e7 | 217 | } |