mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
KVM: VMX: Prioritize DR7.GD=1 #DB over CPL>0 #GP on Intel
When emulating a MOV DR on Intel with DR7.GD=1 at CPL>0, prioritize the #DB
due to DR7.GD over the #GP due to CPL>0, as empirical testing shows that
Intel CPUs (Skylake, Icelake and Emerald Rapids) prioritize the DR7.GD #DB
over all #GPs, whereas AMD CPUs prioritize the CPL>0 #GP (but not illegal
value #GPs) over the #DB.
Outside of the emulator, don't bother trying to provide the "correct"
priority based on the virtual CPU model, as it's simply impossible to do
so without intercepting *all* MOV DR accesses, which would result in a
massive, unacceptable performance hit. Note, getting the priority right
when advertising Intel on AMD would also require intercepting #GP, as SVM
prioritizes all exceptions over the instruction intercept.
Note, neither Intel's SDM nor AMD's APM says anything about the relative
priority, hence the empirical testing. Arguably Intel's description of
DR7.GD:
causes a debug exception to be generated prior to any MOV instruction
that accesses a debug register.
implies that DR7.GD has higher priority. But that's a fairly weak argument
as the statement would still hold true if the #GP due to CPL>0 had higher
priority, as the #GP would prevent any access to a DR.
Fixes: 3b88e41a41 ("KVM: SVM: Add intercept check for accessing dr registers")
Link: https://patch.msgid.link/20260612230113.684301-6-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
parent
32a7188a66
commit
48512697c0
|
|
@ -3834,6 +3834,7 @@ static int check_cr_access(struct x86_emulate_ctxt *ctxt)
|
|||
|
||||
static int check_dr_read(struct x86_emulate_ctxt *ctxt)
|
||||
{
|
||||
bool is_intel = ctxt->ops->guest_cpuid_is_intel_compatible(ctxt);
|
||||
int dr = ctxt->modrm_reg;
|
||||
u64 cr4;
|
||||
|
||||
|
|
@ -3844,12 +3845,16 @@ static int check_dr_read(struct x86_emulate_ctxt *ctxt)
|
|||
if ((cr4 & X86_CR4_DE) && (dr == 4 || dr == 5))
|
||||
return emulate_ud(ctxt);
|
||||
|
||||
if (ctxt->ops->cpl(ctxt))
|
||||
/* Intel CPUs prioritize the DR7.GD=1 #DB over the CPL>0 #GP. */
|
||||
if (!is_intel && ctxt->ops->cpl(ctxt))
|
||||
return emulate_gp(ctxt, 0);
|
||||
|
||||
if (ctxt->ops->get_effective_dr7(ctxt) & DR7_GD)
|
||||
return emulate_db(ctxt, DR6_BD);
|
||||
|
||||
if (is_intel && ctxt->ops->cpl(ctxt))
|
||||
return emulate_gp(ctxt, 0);
|
||||
|
||||
return X86EMUL_CONTINUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5762,9 +5762,6 @@ static int handle_dr(struct kvm_vcpu *vcpu)
|
|||
if (!kvm_require_dr(vcpu, dr))
|
||||
return 1;
|
||||
|
||||
if (vmx_get_cpl(vcpu) > 0)
|
||||
goto out;
|
||||
|
||||
dr7 = vmcs_readl(GUEST_DR7);
|
||||
if (dr7 & DR7_GD) {
|
||||
/*
|
||||
|
|
@ -5785,6 +5782,9 @@ static int handle_dr(struct kvm_vcpu *vcpu)
|
|||
}
|
||||
}
|
||||
|
||||
if (vmx_get_cpl(vcpu) > 0)
|
||||
goto out;
|
||||
|
||||
if (vcpu->guest_debug == 0) {
|
||||
exec_controls_clearbit(to_vmx(vcpu), CPU_BASED_MOV_DR_EXITING);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user