]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
KVM: arm64: Flush/sync debug state in protected mode
authorOliver Upton <oliver.upton@linux.dev>
Fri, 31 Jan 2025 22:29:24 +0000 (22:29 +0000)
committerMarc Zyngier <maz@kernel.org>
Sat, 1 Feb 2025 09:31:11 +0000 (09:31 +0000)
The recent changes to debug state management broke self-hosted debug for
guests when running in protected mode, since both the debug owner and
the debug state itself aren't shared with the hyp's view of the vcpu.

Fix it by flushing/syncing the relevant bits with the hyp vcpu.

Fixes: beb470d96cec ("KVM: arm64: Use debug_owner to track if debug regs need save/restore")
Reported-by: Mark Brown <broonie@kernel.org>
Closes: https://lore.kernel.org/kvmarm/5f62740f-a065-42d9-9f56-8fb648b9c63f@sirena.org.uk/
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
Link: https://lore.kernel.org/r/20250131222922.1548780-3-oliver.upton@linux.dev
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/hyp/nvhe/hyp-main.c

index 5c134520e18058f5c7e94835e74eb4f3eb013688..6e12c070832f79abea4ed908428beed01b31e936 100644 (file)
@@ -91,11 +91,34 @@ static void fpsimd_sve_sync(struct kvm_vcpu *vcpu)
        *host_data_ptr(fp_owner) = FP_STATE_HOST_OWNED;
 }
 
+static void flush_debug_state(struct pkvm_hyp_vcpu *hyp_vcpu)
+{
+       struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
+
+       hyp_vcpu->vcpu.arch.debug_owner = host_vcpu->arch.debug_owner;
+
+       if (kvm_guest_owns_debug_regs(&hyp_vcpu->vcpu))
+               hyp_vcpu->vcpu.arch.vcpu_debug_state = host_vcpu->arch.vcpu_debug_state;
+       else if (kvm_host_owns_debug_regs(&hyp_vcpu->vcpu))
+               hyp_vcpu->vcpu.arch.external_debug_state = host_vcpu->arch.external_debug_state;
+}
+
+static void sync_debug_state(struct pkvm_hyp_vcpu *hyp_vcpu)
+{
+       struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
+
+       if (kvm_guest_owns_debug_regs(&hyp_vcpu->vcpu))
+               host_vcpu->arch.vcpu_debug_state = hyp_vcpu->vcpu.arch.vcpu_debug_state;
+       else if (kvm_host_owns_debug_regs(&hyp_vcpu->vcpu))
+               host_vcpu->arch.external_debug_state = hyp_vcpu->vcpu.arch.external_debug_state;
+}
+
 static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
 {
        struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
 
        fpsimd_sve_flush();
+       flush_debug_state(hyp_vcpu);
 
        hyp_vcpu->vcpu.arch.ctxt        = host_vcpu->arch.ctxt;
 
@@ -123,6 +146,7 @@ static void sync_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
        unsigned int i;
 
        fpsimd_sve_sync(&hyp_vcpu->vcpu);
+       sync_debug_state(hyp_vcpu);
 
        host_vcpu->arch.ctxt            = hyp_vcpu->vcpu.arch.ctxt;