forked from Minki/linux
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: Chenyi Qiang <chenyi.qiang@intel.com> Message-Id: <20220524135624.22988-2-chenyi.qiang@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
7aadaa988c
commit
ed2351174e
@ -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:
|
||||
^^^^^^
|
||||
|
||||
|
@ -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;
|
||||
/*
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user