Commit ed235117 authored by Chenyi Qiang's avatar Chenyi Qiang Committed by Paolo Bonzini

KVM: x86: Extend KVM_{G,S}ET_VCPU_EVENTS to support pending triple fault

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: default avatarChenyi Qiang <chenyi.qiang@intel.com>
Message-Id: <20220524135624.22988-2-chenyi.qiang@intel.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 7aadaa98
...@@ -1150,6 +1150,10 @@ The following bits are defined in the flags field: ...@@ -1150,6 +1150,10 @@ The following bits are defined in the flags field:
fields contain a valid state. This bit will be set whenever fields contain a valid state. This bit will be set whenever
KVM_CAP_EXCEPTION_PAYLOAD is enabled. 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: ARM64:
^^^^^^ ^^^^^^
...@@ -1245,6 +1249,10 @@ can be set in the flags field to signal that the ...@@ -1245,6 +1249,10 @@ can be set in the flags field to signal that the
exception_has_payload, exception_payload, and exception.pending fields exception_has_payload, exception_payload, and exception.pending fields
contain a valid state and shall be written into the VCPU. 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: ARM64:
^^^^^^ ^^^^^^
......
...@@ -1174,6 +1174,8 @@ struct kvm_arch { ...@@ -1174,6 +1174,8 @@ struct kvm_arch {
bool guest_can_read_msr_platform_info; bool guest_can_read_msr_platform_info;
bool exception_payload_enabled; bool exception_payload_enabled;
bool triple_fault_event;
bool bus_lock_detection_enabled; bool bus_lock_detection_enabled;
bool enable_pmu; bool enable_pmu;
/* /*
......
...@@ -325,6 +325,7 @@ struct kvm_reinject_control { ...@@ -325,6 +325,7 @@ struct kvm_reinject_control {
#define KVM_VCPUEVENT_VALID_SHADOW 0x00000004 #define KVM_VCPUEVENT_VALID_SHADOW 0x00000004
#define KVM_VCPUEVENT_VALID_SMM 0x00000008 #define KVM_VCPUEVENT_VALID_SMM 0x00000008
#define KVM_VCPUEVENT_VALID_PAYLOAD 0x00000010 #define KVM_VCPUEVENT_VALID_PAYLOAD 0x00000010
#define KVM_VCPUEVENT_VALID_TRIPLE_FAULT 0x00000020
/* Interrupt shadow states */ /* Interrupt shadow states */
#define KVM_X86_SHADOW_INT_MOV_SS 0x01 #define KVM_X86_SHADOW_INT_MOV_SS 0x01
...@@ -359,7 +360,10 @@ struct kvm_vcpu_events { ...@@ -359,7 +360,10 @@ struct kvm_vcpu_events {
__u8 smm_inside_nmi; __u8 smm_inside_nmi;
__u8 latched_init; __u8 latched_init;
} smi; } smi;
__u8 reserved[27]; struct {
__u8 pending;
} triple_fault;
__u8 reserved[26];
__u8 exception_has_payload; __u8 exception_has_payload;
__u64 exception_payload; __u64 exception_payload;
}; };
......
...@@ -4296,6 +4296,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) ...@@ -4296,6 +4296,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_GET_MSR_FEATURES: case KVM_CAP_GET_MSR_FEATURES:
case KVM_CAP_MSR_PLATFORM_INFO: case KVM_CAP_MSR_PLATFORM_INFO:
case KVM_CAP_EXCEPTION_PAYLOAD: case KVM_CAP_EXCEPTION_PAYLOAD:
case KVM_CAP_X86_TRIPLE_FAULT_EVENT:
case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_SET_GUEST_DEBUG:
case KVM_CAP_LAST_CPU: case KVM_CAP_LAST_CPU:
case KVM_CAP_X86_USER_SPACE_MSR: case KVM_CAP_X86_USER_SPACE_MSR:
...@@ -4942,6 +4943,10 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu, ...@@ -4942,6 +4943,10 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu,
| KVM_VCPUEVENT_VALID_SMM); | KVM_VCPUEVENT_VALID_SMM);
if (vcpu->kvm->arch.exception_payload_enabled) if (vcpu->kvm->arch.exception_payload_enabled)
events->flags |= KVM_VCPUEVENT_VALID_PAYLOAD; 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)); memset(&events->reserved, 0, sizeof(events->reserved));
} }
...@@ -4955,7 +4960,8 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu, ...@@ -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_SIPI_VECTOR
| KVM_VCPUEVENT_VALID_SHADOW | KVM_VCPUEVENT_VALID_SHADOW
| KVM_VCPUEVENT_VALID_SMM | KVM_VCPUEVENT_VALID_SMM
| KVM_VCPUEVENT_VALID_PAYLOAD)) | KVM_VCPUEVENT_VALID_PAYLOAD
| KVM_VCPUEVENT_VALID_TRIPLE_FAULT))
return -EINVAL; return -EINVAL;
if (events->flags & KVM_VCPUEVENT_VALID_PAYLOAD) { if (events->flags & KVM_VCPUEVENT_VALID_PAYLOAD) {
...@@ -5028,6 +5034,15 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu, ...@@ -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); kvm_make_request(KVM_REQ_EVENT, vcpu);
return 0; return 0;
...@@ -6029,6 +6044,10 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm, ...@@ -6029,6 +6044,10 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
kvm->arch.exception_payload_enabled = cap->args[0]; kvm->arch.exception_payload_enabled = cap->args[0];
r = 0; r = 0;
break; 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: case KVM_CAP_X86_USER_SPACE_MSR:
kvm->arch.user_space_msr_mask = cap->args[0]; kvm->arch.user_space_msr_mask = cap->args[0];
r = 0; r = 0;
......
...@@ -1158,6 +1158,7 @@ struct kvm_ppc_resize_hpt { ...@@ -1158,6 +1158,7 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_SYSTEM_EVENT_DATA 215 #define KVM_CAP_SYSTEM_EVENT_DATA 215
#define KVM_CAP_ARM_SYSTEM_SUSPEND 216 #define KVM_CAP_ARM_SYSTEM_SUSPEND 216
#define KVM_CAP_S390_PROTECTED_DUMP 217 #define KVM_CAP_S390_PROTECTED_DUMP 217
#define KVM_CAP_X86_TRIPLE_FAULT_EVENT 218
#ifdef KVM_CAP_IRQ_ROUTING #ifdef KVM_CAP_IRQ_ROUTING
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment