1 // SPDX-License-Identifier: GPL-2.0-only 1 2 /* 3 * Debug and Guest Debug support 4 * 5 * Copyright (C) 2015 - Linaro Ltd 6 * Author: Alex Bennée <alex.bennee@linaro.or 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 /* These are the bits of MDSCR_EL1 we may mani 20 #define MDSCR_EL1_DEBUG_MASK (DBG_MDSCR_SS 21 DBG_MDSCR_KDE 22 DBG_MDSCR_MDE) 23 24 static DEFINE_PER_CPU(u64, mdcr_el2); 25 26 /* 27 * save/restore_guest_debug_regs 28 * 29 * For some debug operations we need to tweak 30 * a result we need to save the state of those 31 * make those modifications. 32 * 33 * Guest access to MDSCR_EL1 is trapped by the 34 * after we have restored the preserved value 35 * 36 * When single-step is enabled by userspace, w 37 * guest entry. Preserve PSTATE.SS so we can r 38 * for the vcpu after the single-step is disab 39 */ 40 static void save_guest_debug_regs(struct kvm_v 41 { 42 u64 val = vcpu_read_sys_reg(vcpu, MDSC 43 44 vcpu->arch.guest_debug_preserved.mdscr 45 46 trace_kvm_arm_set_dreg32("Saved MDSCR_ 47 vcpu->arch.gue 48 49 vcpu->arch.guest_debug_preserved.pstat 50 (*vcpu 51 } 52 53 static void restore_guest_debug_regs(struct kv 54 { 55 u64 val = vcpu->arch.guest_debug_prese 56 57 vcpu_write_sys_reg(vcpu, val, MDSCR_EL 58 59 trace_kvm_arm_set_dreg32("Restored MDS 60 vcpu_read_sys_ 61 62 if (vcpu->arch.guest_debug_preserved.p 63 *vcpu_cpsr(vcpu) |= DBG_SPSR_S 64 else 65 *vcpu_cpsr(vcpu) &= ~DBG_SPSR_ 66 } 67 68 /** 69 * kvm_arm_init_debug - grab what we need for 70 * 71 * Currently the sole task of this function is 72 * value of mdcr_el2 so we can preserve MDCR_E 73 * presumably been set-up by some knowledgeabl 74 * 75 * It is called once per-cpu during CPU hyp in 76 */ 77 78 void kvm_arm_init_debug(void) 79 { 80 __this_cpu_write(mdcr_el2, kvm_call_hy 81 } 82 83 /** 84 * kvm_arm_setup_mdcr_el2 - configure vcpu mdc 85 * 86 * @vcpu: the vcpu pointer 87 * 88 * This ensures we will trap access to: 89 * - Performance monitors (MDCR_EL2_TPM/MDCR_ 90 * - Debug ROM Address (MDCR_EL2_TDRA) 91 * - OS related registers (MDCR_EL2_TDOSA) 92 * - Statistical profiler (MDCR_EL2_TPMS/MDCR 93 * - Self-hosted Trace Filter controls (MDCR_ 94 * - Self-hosted Trace (MDCR_EL2_TTRF/MDCR_EL 95 */ 96 static void kvm_arm_setup_mdcr_el2(struct kvm_ 97 { 98 /* 99 * This also clears MDCR_EL2_E2PB_MASK 100 * to disable guest access to the prof 101 */ 102 vcpu->arch.mdcr_el2 = __this_cpu_read( 103 vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM | 104 MDCR_EL2_TPMS 105 MDCR_EL2_TTRF 106 MDCR_EL2_TPMCR 107 MDCR_EL2_TDRA 108 MDCR_EL2_TDOSA 109 110 /* Is the VM being debugged by userspa 111 if (vcpu->guest_debug) 112 /* Route all software debug ex 113 vcpu->arch.mdcr_el2 |= MDCR_EL 114 115 /* 116 * Trap debug register access when one 117 * - Userspace is using the hardware 118 * (KVM_GUESTDBG_USE_HW is set). 119 * - The guest is not using debug (DE 120 * - The guest has enabled the OS Loc 121 */ 122 if ((vcpu->guest_debug & KVM_GUESTDBG_ 123 !vcpu_get_flag(vcpu, DEBUG_DIRTY) 124 kvm_vcpu_os_lock_enabled(vcpu)) 125 vcpu->arch.mdcr_el2 |= MDCR_EL 126 127 trace_kvm_arm_set_dreg32("MDCR_EL2", v 128 } 129 130 /** 131 * kvm_arm_vcpu_init_debug - setup vcpu debug 132 * 133 * @vcpu: the vcpu pointer 134 * 135 * Set vcpu initial mdcr_el2 value. 136 */ 137 void kvm_arm_vcpu_init_debug(struct kvm_vcpu * 138 { 139 preempt_disable(); 140 kvm_arm_setup_mdcr_el2(vcpu); 141 preempt_enable(); 142 } 143 144 /** 145 * kvm_arm_reset_debug_ptr - reset the debug p 146 * @vcpu: the vcpu pointer 147 */ 148 149 void kvm_arm_reset_debug_ptr(struct kvm_vcpu * 150 { 151 vcpu->arch.debug_ptr = &vcpu->arch.vcp 152 } 153 154 /** 155 * kvm_arm_setup_debug - set up debug related 156 * 157 * @vcpu: the vcpu pointer 158 * 159 * This is called before each entry into the h 160 * debug related registers. 161 * 162 * Additionally, KVM only traps guest accesses 163 * the guest is not actively using them (see t 164 * flag on vcpu->arch.iflags). Since the gues 165 * with the hardware state when debugging the 166 * trapping is enabled whenever we are debuggi 167 * debug registers. 168 */ 169 170 void kvm_arm_setup_debug(struct kvm_vcpu *vcpu 171 { 172 unsigned long mdscr, orig_mdcr_el2 = v 173 174 trace_kvm_arm_setup_debug(vcpu, vcpu-> 175 176 kvm_arm_setup_mdcr_el2(vcpu); 177 178 /* Check if we need to use the debug r 179 if (vcpu->guest_debug || kvm_vcpu_os_l 180 /* Save guest debug state */ 181 save_guest_debug_regs(vcpu); 182 183 /* 184 * Single Step (ARM ARM D2.12. 185 * machine) 186 * 187 * If we are doing Single Step 188 * the guest's MDSCR_EL1.SS an 189 * step has occurred the hyper 190 * debug exception and we retu 191 * 192 * If the guest attempts to si 193 * we would have to deal with 194 * while in the guest kernel. 195 * hard to unwind we suppress 196 * do so by masking MDSCR_EL.S 197 * 198 * This confuses guest debugge 199 * single-step behind the scen 200 * returns to normal once the 201 * debugging the system. 202 */ 203 if (vcpu->guest_debug & KVM_GU 204 /* 205 * If the software ste 206 * was Active-pending, 207 * that the state is m 208 * single-step until t 209 * exception is taken) 210 */ 211 if (!vcpu_get_flag(vcp 212 *vcpu_cpsr(vcp 213 else 214 *vcpu_cpsr(vcp 215 216 mdscr = vcpu_read_sys_ 217 mdscr |= DBG_MDSCR_SS; 218 vcpu_write_sys_reg(vcp 219 } else { 220 mdscr = vcpu_read_sys_ 221 mdscr &= ~DBG_MDSCR_SS 222 vcpu_write_sys_reg(vcp 223 } 224 225 trace_kvm_arm_set_dreg32("SPSR 226 227 /* 228 * HW Breakpoints and watchpoi 229 * 230 * We simply switch the debug_ 231 * external_debug_state which 232 * debug ioctl. The existing D 233 * the registers are updated o 234 */ 235 if (vcpu->guest_debug & KVM_GU 236 /* Enable breakpoints/ 237 mdscr = vcpu_read_sys_ 238 mdscr |= DBG_MDSCR_MDE 239 vcpu_write_sys_reg(vcp 240 241 vcpu->arch.debug_ptr = 242 vcpu_set_flag(vcpu, DE 243 244 trace_kvm_arm_set_regs 245 246 247 248 trace_kvm_arm_set_regs 249 250 251 252 /* 253 * The OS Lock blocks debug ex 254 * enabled. If the guest has e 255 * effects to the guest. Emula 256 * MDSCR_EL1.MDE. In so doing, 257 * exceptions are unaffected b 258 * Lock. 259 */ 260 } else if (kvm_vcpu_os_lock_en 261 mdscr = vcpu_read_sys_ 262 mdscr &= ~DBG_MDSCR_MD 263 vcpu_write_sys_reg(vcp 264 } 265 } 266 267 BUG_ON(!vcpu->guest_debug && 268 vcpu->arch.debug_ptr != &vcpu- 269 270 /* If KDE or MDE are set, perform a fu 271 if (vcpu_read_sys_reg(vcpu, MDSCR_EL1) 272 vcpu_set_flag(vcpu, DEBUG_DIRT 273 274 /* Write mdcr_el2 changes since vcpu_l 275 if (has_vhe() && orig_mdcr_el2 != vcpu 276 write_sysreg(vcpu->arch.mdcr_e 277 278 trace_kvm_arm_set_dreg32("MDSCR_EL1", 279 } 280 281 void kvm_arm_clear_debug(struct kvm_vcpu *vcpu 282 { 283 trace_kvm_arm_clear_debug(vcpu->guest_ 284 285 /* 286 * Restore the guest's debug registers 287 */ 288 if (vcpu->guest_debug || kvm_vcpu_os_l 289 if (vcpu->guest_debug & KVM_GU 290 if (!(*vcpu_cpsr(vcpu) 291 /* 292 * Mark the vc 293 * until Softw 294 */ 295 vcpu_set_flag( 296 } 297 298 restore_guest_debug_regs(vcpu) 299 300 /* 301 * If we were using HW debug w 302 * debug_ptr to the guest debu 303 */ 304 if (vcpu->guest_debug & KVM_GU 305 kvm_arm_reset_debug_pt 306 307 trace_kvm_arm_set_regs 308 309 310 311 trace_kvm_arm_set_regs 312 313 314 } 315 } 316 } 317 318 void kvm_arch_vcpu_load_debug_state_flags(stru 319 { 320 u64 dfr0; 321 322 /* For VHE, there is nothing to do */ 323 if (has_vhe()) 324 return; 325 326 dfr0 = read_sysreg(id_aa64dfr0_el1); 327 /* 328 * If SPE is present on this CPU and i 329 * we may need to check if the host st 330 */ 331 if (cpuid_feature_extract_unsigned_fie 332 !(read_sysreg_s(SYS_PMBIDR_EL1) & 333 vcpu_set_flag(vcpu, DEBUG_STAT 334 335 /* Check if we have TRBE implemented a 336 if (cpuid_feature_extract_unsigned_fie 337 !(read_sysreg_s(SYS_TRBIDR_EL1) & 338 vcpu_set_flag(vcpu, DEBUG_STAT 339 } 340 341 void kvm_arch_vcpu_put_debug_state_flags(struc 342 { 343 vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE 344 vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE 345 } 346
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.