Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2015 - ARM Ltd
0004  * Author: Marc Zyngier <marc.zyngier@arm.com>
0005  */
0006 
0007 #include <hyp/debug-sr.h>
0008 
0009 #include <linux/compiler.h>
0010 #include <linux/kvm_host.h>
0011 
0012 #include <asm/debug-monitors.h>
0013 #include <asm/kvm_asm.h>
0014 #include <asm/kvm_hyp.h>
0015 #include <asm/kvm_mmu.h>
0016 
0017 static void __debug_save_spe(u64 *pmscr_el1)
0018 {
0019     u64 reg;
0020 
0021     /* Clear pmscr in case of early return */
0022     *pmscr_el1 = 0;
0023 
0024     /*
0025      * At this point, we know that this CPU implements
0026      * SPE and is available to the host.
0027      * Check if the host is actually using it ?
0028      */
0029     reg = read_sysreg_s(SYS_PMBLIMITR_EL1);
0030     if (!(reg & BIT(SYS_PMBLIMITR_EL1_E_SHIFT)))
0031         return;
0032 
0033     /* Yes; save the control register and disable data generation */
0034     *pmscr_el1 = read_sysreg_s(SYS_PMSCR_EL1);
0035     write_sysreg_s(0, SYS_PMSCR_EL1);
0036     isb();
0037 
0038     /* Now drain all buffered data to memory */
0039     psb_csync();
0040     dsb(nsh);
0041 }
0042 
0043 static void __debug_restore_spe(u64 pmscr_el1)
0044 {
0045     if (!pmscr_el1)
0046         return;
0047 
0048     /* The host page table is installed, but not yet synchronised */
0049     isb();
0050 
0051     /* Re-enable data generation */
0052     write_sysreg_s(pmscr_el1, SYS_PMSCR_EL1);
0053 }
0054 
0055 static void __debug_save_trace(u64 *trfcr_el1)
0056 {
0057     *trfcr_el1 = 0;
0058 
0059     /* Check if the TRBE is enabled */
0060     if (!(read_sysreg_s(SYS_TRBLIMITR_EL1) & TRBLIMITR_ENABLE))
0061         return;
0062     /*
0063      * Prohibit trace generation while we are in guest.
0064      * Since access to TRFCR_EL1 is trapped, the guest can't
0065      * modify the filtering set by the host.
0066      */
0067     *trfcr_el1 = read_sysreg_s(SYS_TRFCR_EL1);
0068     write_sysreg_s(0, SYS_TRFCR_EL1);
0069     isb();
0070     /* Drain the trace buffer to memory */
0071     tsb_csync();
0072     dsb(nsh);
0073 }
0074 
0075 static void __debug_restore_trace(u64 trfcr_el1)
0076 {
0077     if (!trfcr_el1)
0078         return;
0079 
0080     /* Restore trace filter controls */
0081     write_sysreg_s(trfcr_el1, SYS_TRFCR_EL1);
0082 }
0083 
0084 void __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu)
0085 {
0086     /* Disable and flush SPE data generation */
0087     if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_SPE))
0088         __debug_save_spe(&vcpu->arch.host_debug_state.pmscr_el1);
0089     /* Disable and flush Self-Hosted Trace generation */
0090     if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRBE))
0091         __debug_save_trace(&vcpu->arch.host_debug_state.trfcr_el1);
0092 }
0093 
0094 void __debug_switch_to_guest(struct kvm_vcpu *vcpu)
0095 {
0096     __debug_switch_to_guest_common(vcpu);
0097 }
0098 
0099 void __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu)
0100 {
0101     if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_SPE))
0102         __debug_restore_spe(vcpu->arch.host_debug_state.pmscr_el1);
0103     if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRBE))
0104         __debug_restore_trace(vcpu->arch.host_debug_state.trfcr_el1);
0105 }
0106 
0107 void __debug_switch_to_host(struct kvm_vcpu *vcpu)
0108 {
0109     __debug_switch_to_host_common(vcpu);
0110 }
0111 
0112 u64 __kvm_get_mdcr_el2(void)
0113 {
0114     return read_sysreg(mdcr_el2);
0115 }