]> git.baikalelectronics.ru Git - kernel.git/commitdiff
KVM: x86: Introduce KVM_CAP_DISABLE_QUIRKS2
authorOliver Upton <oupton@google.com>
Tue, 1 Mar 2022 06:03:47 +0000 (06:03 +0000)
committerPaolo Bonzini <pbonzini@redhat.com>
Mon, 21 Mar 2022 13:28:41 +0000 (09:28 -0400)
KVM_CAP_DISABLE_QUIRKS is irrevocably broken. The capability does not
advertise the set of quirks which may be disabled to userspace, so it is
impossible to predict the behavior of KVM. Worse yet,
KVM_CAP_DISABLE_QUIRKS will tolerate any value for cap->args[0], meaning
it fails to reject attempts to set invalid quirk bits.

The only valid workaround for the quirky quirks API is to add a new CAP.
Actually advertise the set of quirks that can be disabled to userspace
so it can predict KVM's behavior. Reject values for cap->args[0] that
contain invalid bits.

Finally, add documentation for the new capability and describe the
existing quirks.

Signed-off-by: Oliver Upton <oupton@google.com>
Message-Id: <20220301060351.442881-5-oupton@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Documentation/virt/kvm/api.rst
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/x86.c
include/uapi/linux/kvm.h

index 55efa82e37eba258b95c0d2f8c54842622dc37e5..07a45474abe905ac2dfeb11e37d2eb513efff550 100644 (file)
@@ -7083,6 +7083,56 @@ resource that is controlled with the H_SET_MODE hypercall.
 This capability allows a guest kernel to use a better-performance mode for
 handling interrupts and system calls.
 
+7.31 KVM_CAP_DISABLE_QUIRKS2
+----------------------------
+
+:Capability: KVM_CAP_DISABLE_QUIRKS2
+:Parameters: args[0] - set of KVM quirks to disable
+:Architectures: x86
+:Type: vm
+
+This capability, if enabled, will cause KVM to disable some behavior
+quirks.
+
+Calling KVM_CHECK_EXTENSION for this capability returns a bitmask of
+quirks that can be disabled in KVM.
+
+The argument to KVM_ENABLE_CAP for this capability is a bitmask of
+quirks to disable, and must be a subset of the bitmask returned by
+KVM_CHECK_EXTENSION.
+
+The valid bits in cap.args[0] are:
+
+=================================== ============================================
+ KVM_X86_QUIRK_LINT0_REENABLED      By default, the reset value for the LVT
+                                    LINT0 register is 0x700 (APIC_MODE_EXTINT).
+                                    When this quirk is disabled, the reset value
+                                    is 0x10000 (APIC_LVT_MASKED).
+
+ KVM_X86_QUIRK_CD_NW_CLEARED        By default, KVM clears CR0.CD and CR0.NW.
+                                    When this quirk is disabled, KVM does not
+                                    change the value of CR0.CD and CR0.NW.
+
+ KVM_X86_QUIRK_LAPIC_MMIO_HOLE      By default, the MMIO LAPIC interface is
+                                    available even when configured for x2APIC
+                                    mode. When this quirk is disabled, KVM
+                                    disables the MMIO LAPIC interface if the
+                                    LAPIC is in x2APIC mode.
+
+ KVM_X86_QUIRK_OUT_7E_INC_RIP       By default, KVM pre-increments %rip before
+                                    exiting to userspace for an OUT instruction
+                                    to port 0x7e. When this quirk is disabled,
+                                    KVM does not pre-increment %rip before
+                                    exiting to userspace.
+
+ KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT When this quirk is disabled, KVM sets
+                                    CPUID.01H:ECX[bit 3] (MONITOR/MWAIT) if
+                                    IA32_MISC_ENABLE[bit 18] (MWAIT) is set.
+                                    Additionally, when this quirk is disabled,
+                                    KVM clears CPUID.01H:ECX[bit 3] if
+                                    IA32_MISC_ENABLE[bit 18] is cleared.
+=================================== ============================================
+
 8. Other capabilities.
 ======================
 
index 3a2c855f04e32060d96bc317583a63402124ca19..0ddc2e67a731adf87e806ff5968402efc5305edc 100644 (file)
@@ -1966,4 +1966,11 @@ int memslot_rmap_alloc(struct kvm_memory_slot *slot, unsigned long npages);
 #define KVM_CLOCK_VALID_FLAGS                                          \
        (KVM_CLOCK_TSC_STABLE | KVM_CLOCK_REALTIME | KVM_CLOCK_HOST_TSC)
 
+#define KVM_X86_VALID_QUIRKS                   \
+       (KVM_X86_QUIRK_LINT0_REENABLED |        \
+        KVM_X86_QUIRK_CD_NW_CLEARED |          \
+        KVM_X86_QUIRK_LAPIC_MMIO_HOLE |        \
+        KVM_X86_QUIRK_OUT_7E_INC_RIP |         \
+        KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT)
+
 #endif /* _ASM_X86_KVM_HOST_H */
index c58265d9f1b23f4fea5b70b4c785aa6fc37ad49e..fe2171b114413fb175dfe3d2e7e7c999c4e5dc9d 100644 (file)
@@ -4363,6 +4363,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
                r = enable_pmu ? KVM_CAP_PMU_VALID_MASK : 0;
                break;
        }
+       case KVM_CAP_DISABLE_QUIRKS2:
+               r = KVM_X86_VALID_QUIRKS;
+               break;
        default:
                break;
        }
@@ -5909,6 +5912,11 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
                return -EINVAL;
 
        switch (cap->cap) {
+       case KVM_CAP_DISABLE_QUIRKS2:
+               r = -EINVAL;
+               if (cap->args[0] & ~KVM_X86_VALID_QUIRKS)
+                       break;
+               fallthrough;
        case KVM_CAP_DISABLE_QUIRKS:
                kvm->arch.disabled_quirks = cap->args[0];
                r = 0;
index d2f1efc3aa3590bcb8fa621c8808a2d02757aabd..91a6fe4e02c08c4b6ac6f1fb91f8f9e3fce85c0f 100644 (file)
@@ -1143,6 +1143,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_PPC_AIL_MODE_3 210
 #define KVM_CAP_S390_MEM_OP_EXTENSION 211
 #define KVM_CAP_PMU_CAPABILITY 212
+#define KVM_CAP_DISABLE_QUIRKS2 213
 
 #ifdef KVM_CAP_IRQ_ROUTING