]> git.baikalelectronics.ru Git - kernel.git/commitdiff
KVM: x86: Extend KVM_{G,S}ET_VCPU_EVENTS to support pending triple fault
authorChenyi Qiang <chenyi.qiang@intel.com>
Tue, 24 May 2022 13:56:21 +0000 (21:56 +0800)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 8 Jun 2022 09:20:53 +0000 (05:20 -0400)
For the triple fault sythesized by KVM, e.g. the RSM path or
nested_vmx_abort(), if KVM exits to userspace before the request is
serviced, userspace could migrate the VM and lose the triple fault.

Extend KVM_{G,S}ET_VCPU_EVENTS to support pending triple fault with a
new event KVM_VCPUEVENT_VALID_FAULT_FAULT so that userspace can save and
restore the triple fault event. This extension is guarded by a new KVM
capability KVM_CAP_TRIPLE_FAULT_EVENT.

Note that in the set_vcpu_events path, userspace is able to set/clear
the triple fault request through triple_fault.pending field.

Signed-off-by: Chenyi Qiang <chenyi.qiang@intel.com>
Message-Id: <20220524135624.22988-2-chenyi.qiang@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Documentation/virt/kvm/api.rst
arch/x86/include/asm/kvm_host.h
arch/x86/include/uapi/asm/kvm.h
arch/x86/kvm/x86.c
include/uapi/linux/kvm.h

index 421479a67da502c25169c3c1a29720051ffa4ad6..f67e367c4059425bb846a7771d2cdce7857df661 100644 (file)
@@ -1150,6 +1150,10 @@ The following bits are defined in the flags field:
   fields contain a valid state. This bit will be set whenever
   KVM_CAP_EXCEPTION_PAYLOAD is enabled.
 
+- KVM_VCPUEVENT_VALID_TRIPLE_FAULT may be set to signal that the
+  triple_fault_pending field contains a valid state. This bit will
+  be set whenever KVM_CAP_TRIPLE_FAULT_EVENT is enabled.
+
 ARM64:
 ^^^^^^
 
@@ -1245,6 +1249,10 @@ can be set in the flags field to signal that the
 exception_has_payload, exception_payload, and exception.pending fields
 contain a valid state and shall be written into the VCPU.
 
+If KVM_CAP_TRIPLE_FAULT_EVENT is enabled, KVM_VCPUEVENT_VALID_TRIPLE_FAULT
+can be set in flags field to signal that the triple_fault field contains
+a valid state and shall be written into the VCPU.
+
 ARM64:
 ^^^^^^
 
index 032278f0ee6dc87d8666c1544cf062471ce1a800..d6c62276e131868deb3d738f38350797f7c83682 100644 (file)
@@ -1174,6 +1174,8 @@ struct kvm_arch {
        bool guest_can_read_msr_platform_info;
        bool exception_payload_enabled;
 
+       bool triple_fault_event;
+
        bool bus_lock_detection_enabled;
        bool enable_pmu;
        /*
index 21614807a2cbb35912c169abe76e9ef649d0ae5b..24c807c8d5f7a828e7b9b472c80c48e7514a0f96 100644 (file)
@@ -325,6 +325,7 @@ struct kvm_reinject_control {
 #define KVM_VCPUEVENT_VALID_SHADOW     0x00000004
 #define KVM_VCPUEVENT_VALID_SMM                0x00000008
 #define KVM_VCPUEVENT_VALID_PAYLOAD    0x00000010
+#define KVM_VCPUEVENT_VALID_TRIPLE_FAULT       0x00000020
 
 /* Interrupt shadow states */
 #define KVM_X86_SHADOW_INT_MOV_SS      0x01
@@ -359,7 +360,10 @@ struct kvm_vcpu_events {
                __u8 smm_inside_nmi;
                __u8 latched_init;
        } smi;
-       __u8 reserved[27];
+       struct {
+               __u8 pending;
+       } triple_fault;
+       __u8 reserved[26];
        __u8 exception_has_payload;
        __u64 exception_payload;
 };
index c8dfdef9e52f5f0521d5d3f41df34daf089f5fe8..422fbb0d751885da7de7511c97768251edcf9399 100644 (file)
@@ -4296,6 +4296,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_GET_MSR_FEATURES:
        case KVM_CAP_MSR_PLATFORM_INFO:
        case KVM_CAP_EXCEPTION_PAYLOAD:
+       case KVM_CAP_X86_TRIPLE_FAULT_EVENT:
        case KVM_CAP_SET_GUEST_DEBUG:
        case KVM_CAP_LAST_CPU:
        case KVM_CAP_X86_USER_SPACE_MSR:
@@ -4942,6 +4943,10 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu,
                         | KVM_VCPUEVENT_VALID_SMM);
        if (vcpu->kvm->arch.exception_payload_enabled)
                events->flags |= KVM_VCPUEVENT_VALID_PAYLOAD;
+       if (vcpu->kvm->arch.triple_fault_event) {
+               events->triple_fault.pending = kvm_test_request(KVM_REQ_TRIPLE_FAULT, vcpu);
+               events->flags |= KVM_VCPUEVENT_VALID_TRIPLE_FAULT;
+       }
 
        memset(&events->reserved, 0, sizeof(events->reserved));
 }
@@ -4955,7 +4960,8 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
                              | KVM_VCPUEVENT_VALID_SIPI_VECTOR
                              | KVM_VCPUEVENT_VALID_SHADOW
                              | KVM_VCPUEVENT_VALID_SMM
-                             | KVM_VCPUEVENT_VALID_PAYLOAD))
+                             | KVM_VCPUEVENT_VALID_PAYLOAD
+                             | KVM_VCPUEVENT_VALID_TRIPLE_FAULT))
                return -EINVAL;
 
        if (events->flags & KVM_VCPUEVENT_VALID_PAYLOAD) {
@@ -5028,6 +5034,15 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
                }
        }
 
+       if (events->flags & KVM_VCPUEVENT_VALID_TRIPLE_FAULT) {
+               if (!vcpu->kvm->arch.triple_fault_event)
+                       return -EINVAL;
+               if (events->triple_fault.pending)
+                       kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
+               else
+                       kvm_clear_request(KVM_REQ_TRIPLE_FAULT, vcpu);
+       }
+
        kvm_make_request(KVM_REQ_EVENT, vcpu);
 
        return 0;
@@ -6029,6 +6044,10 @@ split_irqchip_unlock:
                kvm->arch.exception_payload_enabled = cap->args[0];
                r = 0;
                break;
+       case KVM_CAP_X86_TRIPLE_FAULT_EVENT:
+               kvm->arch.triple_fault_event = cap->args[0];
+               r = 0;
+               break;
        case KVM_CAP_X86_USER_SPACE_MSR:
                kvm->arch.user_space_msr_mask = cap->args[0];
                r = 0;
index c4a32910b88aaad56fd07a84c08daf90d69703fa..ca799319acfd7bb9acc1e2dad84bbc279573d436 100644 (file)
@@ -1158,6 +1158,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_SYSTEM_EVENT_DATA 215
 #define KVM_CAP_ARM_SYSTEM_SUSPEND 216
 #define KVM_CAP_S390_PROTECTED_DUMP 217
+#define KVM_CAP_X86_TRIPLE_FAULT_EVENT 218
 
 #ifdef KVM_CAP_IRQ_ROUTING