Skip to content

Commit 4a68408

Browse files
ouptonMarc Zyngier
authored andcommitted
KVM: arm64: nv: Trap debug registers when in hyp context
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> Signed-off-by: Marc Zyngier <maz@kernel.org>
1 parent b320789 commit 4a68408

3 files changed

Lines changed: 16 additions & 0 deletions

File tree

arch/arm64/include/asm/kvm_nested.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ extern void check_nested_vcpu_requests(struct kvm_vcpu *vcpu);
8383
extern void kvm_nested_flush_hwstate(struct kvm_vcpu *vcpu);
8484
extern void kvm_nested_sync_hwstate(struct kvm_vcpu *vcpu);
8585

86+
extern void kvm_nested_setup_mdcr_el2(struct kvm_vcpu *vcpu);
87+
8688
struct kvm_s2_trans {
8789
phys_addr_t output;
8890
unsigned long block_size;

arch/arm64/kvm/debug.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ static void kvm_arm_setup_mdcr_el2(struct kvm_vcpu *vcpu)
5656
if (!kvm_guest_owns_debug_regs(vcpu))
5757
vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;
5858

59+
if (vcpu_has_nv(vcpu))
60+
kvm_nested_setup_mdcr_el2(vcpu);
61+
5962
/* Write MDCR_EL2 directly if we're already at EL2 */
6063
if (has_vhe())
6164
write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);

arch/arm64/kvm/nested.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,3 +1796,14 @@ void kvm_nested_sync_hwstate(struct kvm_vcpu *vcpu)
17961796
if (unlikely(vcpu_test_and_clear_flag(vcpu, NESTED_SERROR_PENDING)))
17971797
kvm_inject_serror_esr(vcpu, vcpu_get_vsesr(vcpu));
17981798
}
1799+
1800+
void kvm_nested_setup_mdcr_el2(struct kvm_vcpu *vcpu)
1801+
{
1802+
/*
1803+
* In yet another example where FEAT_NV2 is fscking broken, accesses
1804+
* to MDSCR_EL1 are redirected to the VNCR despite having an effect
1805+
* at EL2. Use a big hammer to apply sanity.
1806+
*/
1807+
if (is_hyp_ctxt(vcpu))
1808+
vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;
1809+
}

0 commit comments

Comments
 (0)