xref: /linux/arch/arm64/kvm/debug.c (revision 4bd611ca60afa155bca25b40312ed61c4d46237f)
156c7f5e7SAlex Bennée /*
256c7f5e7SAlex Bennée  * Debug and Guest Debug support
356c7f5e7SAlex Bennée  *
456c7f5e7SAlex Bennée  * Copyright (C) 2015 - Linaro Ltd
556c7f5e7SAlex Bennée  * Author: Alex Bennée <alex.bennee@linaro.org>
656c7f5e7SAlex Bennée  *
756c7f5e7SAlex Bennée  * This program is free software; you can redistribute it and/or modify
856c7f5e7SAlex Bennée  * it under the terms of the GNU General Public License version 2 as
956c7f5e7SAlex Bennée  * published by the Free Software Foundation.
1056c7f5e7SAlex Bennée  *
1156c7f5e7SAlex Bennée  * This program is distributed in the hope that it will be useful,
1256c7f5e7SAlex Bennée  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1356c7f5e7SAlex Bennée  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1456c7f5e7SAlex Bennée  * GNU General Public License for more details.
1556c7f5e7SAlex Bennée  *
1656c7f5e7SAlex Bennée  * You should have received a copy of the GNU General Public License
1756c7f5e7SAlex Bennée  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
1856c7f5e7SAlex Bennée  */
1956c7f5e7SAlex Bennée 
2056c7f5e7SAlex Bennée #include <linux/kvm_host.h>
2156c7f5e7SAlex Bennée 
2256c7f5e7SAlex Bennée #include <asm/kvm_arm.h>
2356c7f5e7SAlex Bennée 
2456c7f5e7SAlex Bennée static DEFINE_PER_CPU(u32, mdcr_el2);
2556c7f5e7SAlex Bennée 
2656c7f5e7SAlex Bennée /**
2756c7f5e7SAlex Bennée  * kvm_arm_init_debug - grab what we need for debug
2856c7f5e7SAlex Bennée  *
2956c7f5e7SAlex Bennée  * Currently the sole task of this function is to retrieve the initial
3056c7f5e7SAlex Bennée  * value of mdcr_el2 so we can preserve MDCR_EL2.HPMN which has
3156c7f5e7SAlex Bennée  * presumably been set-up by some knowledgeable bootcode.
3256c7f5e7SAlex Bennée  *
3356c7f5e7SAlex Bennée  * It is called once per-cpu during CPU hyp initialisation.
3456c7f5e7SAlex Bennée  */
3556c7f5e7SAlex Bennée 
3656c7f5e7SAlex Bennée void kvm_arm_init_debug(void)
3756c7f5e7SAlex Bennée {
3856c7f5e7SAlex Bennée 	__this_cpu_write(mdcr_el2, kvm_call_hyp(__kvm_get_mdcr_el2));
3956c7f5e7SAlex Bennée }
4056c7f5e7SAlex Bennée 
4156c7f5e7SAlex Bennée 
4256c7f5e7SAlex Bennée /**
4356c7f5e7SAlex Bennée  * kvm_arm_setup_debug - set up debug related stuff
4456c7f5e7SAlex Bennée  *
4556c7f5e7SAlex Bennée  * @vcpu:	the vcpu pointer
4656c7f5e7SAlex Bennée  *
4756c7f5e7SAlex Bennée  * This is called before each entry into the hypervisor to setup any
4856c7f5e7SAlex Bennée  * debug related registers. Currently this just ensures we will trap
4956c7f5e7SAlex Bennée  * access to:
5056c7f5e7SAlex Bennée  *  - Performance monitors (MDCR_EL2_TPM/MDCR_EL2_TPMCR)
5156c7f5e7SAlex Bennée  *  - Debug ROM Address (MDCR_EL2_TDRA)
5256c7f5e7SAlex Bennée  *  - OS related registers (MDCR_EL2_TDOSA)
5356c7f5e7SAlex Bennée  *
5456c7f5e7SAlex Bennée  * Additionally, KVM only traps guest accesses to the debug registers if
5556c7f5e7SAlex Bennée  * the guest is not actively using them (see the KVM_ARM64_DEBUG_DIRTY
5656c7f5e7SAlex Bennée  * flag on vcpu->arch.debug_flags).  Since the guest must not interfere
5756c7f5e7SAlex Bennée  * with the hardware state when debugging the guest, we must ensure that
5856c7f5e7SAlex Bennée  * trapping is enabled whenever we are debugging the guest using the
5956c7f5e7SAlex Bennée  * debug registers.
6056c7f5e7SAlex Bennée  */
6156c7f5e7SAlex Bennée 
6256c7f5e7SAlex Bennée void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
6356c7f5e7SAlex Bennée {
6456c7f5e7SAlex Bennée 	bool trap_debug = !(vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY);
6556c7f5e7SAlex Bennée 
6656c7f5e7SAlex Bennée 	vcpu->arch.mdcr_el2 = __this_cpu_read(mdcr_el2) & MDCR_EL2_HPMN_MASK;
6756c7f5e7SAlex Bennée 	vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM |
6856c7f5e7SAlex Bennée 				MDCR_EL2_TPMCR |
6956c7f5e7SAlex Bennée 				MDCR_EL2_TDRA |
7056c7f5e7SAlex Bennée 				MDCR_EL2_TDOSA);
7156c7f5e7SAlex Bennée 
7256c7f5e7SAlex Bennée 	/* Trap on access to debug registers? */
7356c7f5e7SAlex Bennée 	if (trap_debug)
7456c7f5e7SAlex Bennée 		vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;
7556c7f5e7SAlex Bennée 
76*4bd611caSAlex Bennée 	/* Trap breakpoints? */
77*4bd611caSAlex Bennée 	if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
78*4bd611caSAlex Bennée 		vcpu->arch.mdcr_el2 |= MDCR_EL2_TDE;
7956c7f5e7SAlex Bennée }
8056c7f5e7SAlex Bennée 
8156c7f5e7SAlex Bennée void kvm_arm_clear_debug(struct kvm_vcpu *vcpu)
8256c7f5e7SAlex Bennée {
8356c7f5e7SAlex Bennée 	/* Nothing to do yet */
8456c7f5e7SAlex Bennée }
85