[PATCH v3 4/8] KVM: x86: Prioritize #UD on MOV DR over #GP due to non-zero CPL

From: Sean Christopherson

Date: Fri Jun 12 2026 - 19:02:12 EST


Manually handle the CPL check for MOV DR instructions instead of using the
Priv flag, *after* checking for #UD scenarios, as #GP due to CPL>0 has
lower priority than all #UDs.

Fixes: 1e470be5a108 ("KVM: x86 emulator: fix mov dr to inject #UD when needed.")
Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
---
arch/x86/kvm/emulate.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index a1bccab0eefe..127a21eeef66 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -3844,6 +3844,9 @@ 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))
+ return emulate_gp(ctxt, 0);
+
if (ctxt->ops->get_effective_dr7(ctxt) & DR7_GD)
return emulate_db(ctxt, DR6_BD);

@@ -4380,11 +4383,10 @@ static const struct opcode twobyte_table[256] = {
D(ImplicitOps | ModRM | SrcMem | NoAccess), /* NOP + 7 * reserved NOP */
/* 0x20 - 0x2F */
DIP(ModRM | DstMem | Priv | Op3264 | NoMod, cr_read, check_cr_access),
- DIP(ModRM | DstMem | Priv | Op3264 | NoMod, dr_read, check_dr_read),
+ DIP(ModRM | DstMem | Op3264 | NoMod, dr_read, check_dr_read),
IIP(ModRM | SrcMem | Priv | Op3264 | NoMod, em_cr_write, cr_write,
check_cr_access),
- IIP(ModRM | SrcMem | Priv | Op3264 | NoMod, em_dr_write, dr_write,
- check_dr_write),
+ IIP(ModRM | SrcMem | Op3264 | NoMod, em_dr_write, dr_write, check_dr_write),
N, N, N, N,
GP(ModRM | DstReg | SrcMem | Mov | Sse | Avx, &pfx_0f_28_0f_29),
GP(ModRM | DstMem | SrcReg | Mov | Sse | Avx, &pfx_0f_28_0f_29),
--
2.54.0.1136.gdb2ca164c4-goog