ANDROID: KVM: arm64: Monitor Debug support for non-protected guests

Add monitor debug support for non-protected guests in protected
mode.

Save and restore the monitor debug state when running a
non-protected guest, and propagate the monitor debug
configuration of non-protected vcpus from the host.

This patch assumes that the hyp vcpu debug iflags are kept in
sync with the host.

Bug: 228011917
Signed-off-by: Fuad Tabba <tabba@google.com>
Change-Id: Ie525693a6a6f236e388b16a1af297403e729057f
Signed-off-by: Quentin Perret <qperret@google.com>
This commit is contained in:
Fuad Tabba
2022-11-08 10:23:24 +00:00
committed by Quentin Perret
parent b34bc46188
commit 0a1f3a1f7b
2 changed files with 57 additions and 3 deletions

View File

@@ -491,6 +491,57 @@ static void __flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
__copy_vcpu_state(hyp_vcpu->host_vcpu, &hyp_vcpu->vcpu);
}
static void flush_debug_state(struct pkvm_hyp_vcpu *hyp_vcpu)
{
struct kvm_vcpu *vcpu = &hyp_vcpu->vcpu;
struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
u64 mdcr_el2 = READ_ONCE(host_vcpu->arch.mdcr_el2);
/*
* Propagate the monitor debug configuration of the vcpu from host.
* Preserve HPMN, which is set-up by some knowledgeable bootcode.
* Ensure that MDCR_EL2_E2PB_MASK and MDCR_EL2_E2TB_MASK are clear,
* as guests should not be able to access profiling and trace buffers.
* Ensure that RES0 bits are clear.
*/
mdcr_el2 &= ~(MDCR_EL2_RES0 |
MDCR_EL2_HPMN_MASK |
(MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT) |
(MDCR_EL2_E2TB_MASK << MDCR_EL2_E2TB_SHIFT));
vcpu->arch.mdcr_el2 = read_sysreg(mdcr_el2) & MDCR_EL2_HPMN_MASK;
vcpu->arch.mdcr_el2 |= mdcr_el2;
vcpu->arch.pmu = host_vcpu->arch.pmu;
vcpu->guest_debug = READ_ONCE(host_vcpu->guest_debug);
if (!kvm_vcpu_needs_debug_regs(vcpu))
return;
__vcpu_save_guest_debug_regs(vcpu);
/* Switch debug_ptr to the external_debug_state if done by the host. */
if (kern_hyp_va(READ_ONCE(host_vcpu->arch.debug_ptr)) ==
&host_vcpu->arch.external_debug_state)
vcpu->arch.debug_ptr = &host_vcpu->arch.external_debug_state;
/* Propagate any special handling for single step from host. */
vcpu_write_sys_reg(vcpu, vcpu_read_sys_reg(host_vcpu, MDSCR_EL1),
MDSCR_EL1);
*vcpu_cpsr(vcpu) = *vcpu_cpsr(host_vcpu);
}
static void sync_debug_state(struct pkvm_hyp_vcpu *hyp_vcpu)
{
struct kvm_vcpu *vcpu = &hyp_vcpu->vcpu;
struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
if (!kvm_vcpu_needs_debug_regs(vcpu))
return;
__vcpu_restore_guest_debug_regs(vcpu);
vcpu->arch.debug_ptr = &host_vcpu->arch.vcpu_debug_state;
}
static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
{
struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
@@ -510,11 +561,10 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
__flush_hyp_vcpu(hyp_vcpu);
hyp_vcpu->vcpu.arch.iflags = READ_ONCE(host_vcpu->arch.iflags);
flush_debug_state(hyp_vcpu);
hyp_vcpu->vcpu.arch.hcr_el2 = HCR_GUEST_FLAGS & ~(HCR_RW | HCR_TWI | HCR_TWE);
hyp_vcpu->vcpu.arch.hcr_el2 |= READ_ONCE(host_vcpu->arch.hcr_el2);
hyp_vcpu->vcpu.arch.mdcr_el2 = host_vcpu->arch.mdcr_el2;
hyp_vcpu->vcpu.arch.debug_ptr = kern_hyp_va(host_vcpu->arch.debug_ptr);
}
hyp_vcpu->vcpu.arch.vsesr_el2 = host_vcpu->arch.vsesr_el2;
@@ -551,6 +601,9 @@ static void sync_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu, u32 exit_reason)
hyp_entry_exit_handler_fn ec_handler;
u8 esr_ec;
if (!pkvm_hyp_vcpu_is_protected(hyp_vcpu))
sync_debug_state(hyp_vcpu);
/*
* Don't sync the vcpu GPR/sysreg state after a run. Instead,
* leave it in the hyp vCPU until someone actually requires it.

View File

@@ -495,6 +495,7 @@ static int init_pkvm_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu,
hyp_vcpu->vcpu.arch.hw_mmu = &hyp_vm->kvm.arch.mmu;
hyp_vcpu->vcpu.arch.cflags = READ_ONCE(host_vcpu->arch.cflags);
hyp_vcpu->vcpu.arch.mp_state.mp_state = KVM_MP_STATE_STOPPED;
hyp_vcpu->vcpu.arch.debug_ptr = &host_vcpu->arch.vcpu_debug_state;
pkvm_vcpu_init_features_from_host(hyp_vcpu);