* [PATCH 1/2] KVM: arm64: nv: Trap debug registers when in hyp context
2025-09-17 20:31 [PATCH 0/2] KVM: arm64: nv: Fixes for handling debug, MDCR_EL2 Oliver Upton
@ 2025-09-17 20:31 ` Oliver Upton
2025-09-17 20:31 ` [PATCH 2/2] KVM: arm64: nv: Apply guest's MDCR traps in nested context Oliver Upton
2025-09-18 15:49 ` [PATCH 0/2] KVM: arm64: nv: Fixes for handling debug, MDCR_EL2 Marc Zyngier
2 siblings, 0 replies; 4+ messages in thread
From: Oliver Upton @ 2025-09-17 20:31 UTC (permalink / raw)
To: kvmarm; +Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Oliver Upton
In case you haven't realized it yet, the architecture is _slightly_
broken in the context of nested virt. Here we have another example of
FEAT_NV2 redirecting a sysreg (MDSCR_EL1) to memory that actually
affects execution at vEL2.
Fortunately, MDCR_EL2.TDA provides the necessary traps to hide this
mess at the expense of unnecessarily trapping the breakpoint/watchpoint
registers. Yes, FEAT_FGT gives us a precise trap but let's just opt for
obvious correctness to start.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/include/asm/kvm_nested.h | 2 ++
arch/arm64/kvm/debug.c | 3 +++
arch/arm64/kvm/nested.c | 11 +++++++++++
3 files changed, 16 insertions(+)
diff --git a/arch/arm64/include/asm/kvm_nested.h b/arch/arm64/include/asm/kvm_nested.h
index 7fd76f41c296..cd3ab06abdca 100644
--- a/arch/arm64/include/asm/kvm_nested.h
+++ b/arch/arm64/include/asm/kvm_nested.h
@@ -83,6 +83,8 @@ extern void check_nested_vcpu_requests(struct kvm_vcpu *vcpu);
extern void kvm_nested_flush_hwstate(struct kvm_vcpu *vcpu);
extern void kvm_nested_sync_hwstate(struct kvm_vcpu *vcpu);
+extern void kvm_nested_setup_mdcr_el2(struct kvm_vcpu *vcpu);
+
struct kvm_s2_trans {
phys_addr_t output;
unsigned long block_size;
diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c
index 381382c19fe4..fc275335c0ee 100644
--- a/arch/arm64/kvm/debug.c
+++ b/arch/arm64/kvm/debug.c
@@ -56,6 +56,9 @@ static void kvm_arm_setup_mdcr_el2(struct kvm_vcpu *vcpu)
if (!kvm_guest_owns_debug_regs(vcpu))
vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;
+ if (vcpu_has_nv(vcpu))
+ kvm_nested_setup_mdcr_el2(vcpu);
+
/* Write MDCR_EL2 directly if we're already at EL2 */
if (has_vhe())
write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index 77db81bae86f..9559c64e7e0c 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -1796,3 +1796,14 @@ void kvm_nested_sync_hwstate(struct kvm_vcpu *vcpu)
if (unlikely(vcpu_test_and_clear_flag(vcpu, NESTED_SERROR_PENDING)))
kvm_inject_serror_esr(vcpu, vcpu_get_vsesr(vcpu));
}
+
+void kvm_nested_setup_mdcr_el2(struct kvm_vcpu *vcpu)
+{
+ /*
+ * In yet another example where FEAT_NV2 is fscking broken, accesses
+ * to MDSCR_EL1 are redirected to the VNCR despite having an effect
+ * at EL2. Use a big hammer to apply sanity.
+ */
+ if (is_hyp_ctxt(vcpu))
+ vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;
+}
--
2.47.3
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 2/2] KVM: arm64: nv: Apply guest's MDCR traps in nested context
2025-09-17 20:31 [PATCH 0/2] KVM: arm64: nv: Fixes for handling debug, MDCR_EL2 Oliver Upton
2025-09-17 20:31 ` [PATCH 1/2] KVM: arm64: nv: Trap debug registers when in hyp context Oliver Upton
@ 2025-09-17 20:31 ` Oliver Upton
2025-09-18 15:49 ` [PATCH 0/2] KVM: arm64: nv: Fixes for handling debug, MDCR_EL2 Marc Zyngier
2 siblings, 0 replies; 4+ messages in thread
From: Oliver Upton @ 2025-09-17 20:31 UTC (permalink / raw)
To: kvmarm; +Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Oliver Upton
KVM needs to ensure the guest hypervisor's traps take effect when the
vCPU is in a nested context. While supporting infrastructure is in place
for most of the EL2 trap registers, MDCR_EL2 is not.
Fold the guest's trap configuration into the effective MDCR_EL2. Apply
it directly to the in-memory representation as it gets recomputed on
every vcpu_load() anyway.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/kvm/nested.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index 9559c64e7e0c..61542d6fd8f5 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -1797,8 +1797,25 @@ void kvm_nested_sync_hwstate(struct kvm_vcpu *vcpu)
kvm_inject_serror_esr(vcpu, vcpu_get_vsesr(vcpu));
}
+/*
+ * KVM unconditionally sets most of these traps anyway but use an allowlist
+ * to document the guest hypervisor traps that may take precedence and guard
+ * against future changes to the non-nested trap configuration.
+ */
+#define NV_MDCR_GUEST_INCLUDE (MDCR_EL2_TDE | \
+ MDCR_EL2_TDA | \
+ MDCR_EL2_TDRA | \
+ MDCR_EL2_TTRF | \
+ MDCR_EL2_TPMS | \
+ MDCR_EL2_TPM | \
+ MDCR_EL2_TPMCR | \
+ MDCR_EL2_TDCC | \
+ MDCR_EL2_TDOSA)
+
void kvm_nested_setup_mdcr_el2(struct kvm_vcpu *vcpu)
{
+ u64 guest_mdcr = __vcpu_sys_reg(vcpu, MDCR_EL2);
+
/*
* In yet another example where FEAT_NV2 is fscking broken, accesses
* to MDSCR_EL1 are redirected to the VNCR despite having an effect
@@ -1806,4 +1823,6 @@ void kvm_nested_setup_mdcr_el2(struct kvm_vcpu *vcpu)
*/
if (is_hyp_ctxt(vcpu))
vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;
+ else
+ vcpu->arch.mdcr_el2 |= (guest_mdcr & NV_MDCR_GUEST_INCLUDE);
}
--
2.47.3
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH 0/2] KVM: arm64: nv: Fixes for handling debug, MDCR_EL2
2025-09-17 20:31 [PATCH 0/2] KVM: arm64: nv: Fixes for handling debug, MDCR_EL2 Oliver Upton
2025-09-17 20:31 ` [PATCH 1/2] KVM: arm64: nv: Trap debug registers when in hyp context Oliver Upton
2025-09-17 20:31 ` [PATCH 2/2] KVM: arm64: nv: Apply guest's MDCR traps in nested context Oliver Upton
@ 2025-09-18 15:49 ` Marc Zyngier
2 siblings, 0 replies; 4+ messages in thread
From: Marc Zyngier @ 2025-09-18 15:49 UTC (permalink / raw)
To: kvmarm, Oliver Upton; +Cc: Joey Gouly, Suzuki K Poulose, Zenghui Yu
On Wed, 17 Sep 2025 13:31:23 -0700, Oliver Upton wrote:
> As I was working on EL2 support for KVM selftests I realized that use of
> self-hosted debug inside of the VM is completely broken. Further
> inspection reveals yet another case where FEAT_NV2 does something
> insane -- MDSCR_EL1 is redirected to the VNCR page in spite of affecting
> the EL2 context.
>
> The situation can be remedied with traps. And after implementing that it
> became clear we make no effort of honoring the guest's MDCR traps.
> Whoops.
>
> [...]
Applied to next, thanks!
[1/2] KVM: arm64: nv: Trap debug registers when in hyp context
commit: 4a684088421d5a1ffb3b13243c58a9078c99e4b9
[2/2] KVM: arm64: nv: Apply guest's MDCR traps in nested context
commit: 3af1105c4fa362d17d577b55d2b8a7c4609f16fc
Cheers,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 4+ messages in thread