]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: nVMX: Allow emulating RDPID on behalf of L2
authorSean Christopherson <seanjc@google.com>
Sat, 1 Feb 2025 01:55:10 +0000 (17:55 -0800)
committerSean Christopherson <seanjc@google.com>
Mon, 24 Feb 2025 17:01:06 +0000 (09:01 -0800)
Return X86EMUL_CONTINUE instead X86EMUL_UNHANDLEABLE when emulating RDPID
on behalf of L2 and L1 _does_ expose RDPID/RDTSCP to L2.  When RDPID
emulation was added by commit fb6d4d340e05 ("KVM: x86: emulate RDPID"),
KVM incorrectly allowed emulation by default.  Commit 07721feee46b ("KVM:
nVMX: Don't emulate instructions in guest mode") fixed that flaw, but
missed that RDPID emulation was relying on the common return path to allow
emulation on behalf of L2.

Fixes: 07721feee46b ("KVM: nVMX: Don't emulate instructions in guest mode")
Link: https://lore.kernel.org/r/20250201015518.689704-4-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/vmx/vmx.c

index e8672c4cb6250e07722b7e40805490643e4bab13..f03d1dc63de05d1ddefe58af078f4a7cad27e4a4 100644 (file)
@@ -8049,18 +8049,19 @@ int vmx_check_intercept(struct kvm_vcpu *vcpu,
        struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
 
        switch (info->intercept) {
-       /*
-        * RDPID causes #UD if disabled through secondary execution controls.
-        * Because it is marked as EmulateOnUD, we need to intercept it here.
-        * Note, RDPID is hidden behind ENABLE_RDTSCP.
-        */
        case x86_intercept_rdpid:
+               /*
+                * RDPID causes #UD if not enabled through secondary execution
+                * controls (ENABLE_RDTSCP).  Note, the implicit MSR access to
+                * TSC_AUX is NOT subject to interception, i.e. checking only
+                * the dedicated execution control is architecturally correct.
+                */
                if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_RDTSCP)) {
                        exception->vector = UD_VECTOR;
                        exception->error_code_valid = false;
                        return X86EMUL_PROPAGATE_FAULT;
                }
-               break;
+               return X86EMUL_CONTINUE;
 
        case x86_intercept_in:
        case x86_intercept_ins: