Message ID | 20220923073333.23381-2-chenyi.qiang@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Enable notify VM exit | expand |
On 9/23/22 09:33, Chenyi Qiang wrote: > For the direct triple faults, i.e. hardware detected and KVM morphed > to VM-Exit, KVM will never lose them. But for triple faults sythesized > by KVM, e.g. the RSM path, if KVM exits to userspace before the request > is serviced, userspace could migrate the VM and lose the triple fault. > > A new flag KVM_VCPUEVENT_VALID_TRIPLE_FAULT is defined to signal that > the event.triple_fault_pending field contains a valid state if the > KVM_CAP_X86_TRIPLE_FAULT_EVENT capability is enabled. Note that you are not transmitting the field on migration. You need this on top: diff --git a/target/i386/cpu.h b/target/i386/cpu.h index b97d182e28..d4124973ce 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1739,7 +1739,7 @@ typedef struct CPUArchState { uint8_t has_error_code; uint8_t exception_has_payload; uint64_t exception_payload; - bool triple_fault_pending; + uint8_t triple_fault_pending; uint32_t ins_len; uint32_t sipi_vector; bool tsc_valid; diff --git a/target/i386/machine.c b/target/i386/machine.c index cecd476e98..310b125235 100644 --- a/target/i386/machine.c +++ b/target/i386/machine.c @@ -1562,6 +1562,25 @@ static const VMStateDescription vmstate_arch_lbr = { } }; +static bool triple_fault_needed(void *opaque) +{ + X86CPU *cpu = opaque; + CPUX86State *env = &cpu->env; + + return env->triple_fault_pending; +} + +static const VMStateDescription vmstate_triple_fault = { + .name = "cpu/triple_fault", + .version_id = 1, + .minimum_version_id = 1, + .needed = triple_fault_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT8(env.triple_fault_pending, X86CPU), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_x86_cpu = { .name = "cpu", .version_id = 12, @@ -1706,6 +1725,7 @@ const VMStateDescription vmstate_x86_cpu = { &vmstate_amx_xtile, #endif &vmstate_arch_lbr, + &vmstate_triple_fault, NULL } };
On 9/27/2022 9:14 PM, Paolo Bonzini wrote: > On 9/23/22 09:33, Chenyi Qiang wrote: >> For the direct triple faults, i.e. hardware detected and KVM morphed >> to VM-Exit, KVM will never lose them. But for triple faults sythesized >> by KVM, e.g. the RSM path, if KVM exits to userspace before the request >> is serviced, userspace could migrate the VM and lose the triple fault. >> >> A new flag KVM_VCPUEVENT_VALID_TRIPLE_FAULT is defined to signal that >> the event.triple_fault_pending field contains a valid state if the >> KVM_CAP_X86_TRIPLE_FAULT_EVENT capability is enabled. > > Note that you are not transmitting the field on migration. You need > this on top: > > diff --git a/target/i386/cpu.h b/target/i386/cpu.h > index b97d182e28..d4124973ce 100644 > --- a/target/i386/cpu.h > +++ b/target/i386/cpu.h > @@ -1739,7 +1739,7 @@ typedef struct CPUArchState { > uint8_t has_error_code; > uint8_t exception_has_payload; > uint64_t exception_payload; > - bool triple_fault_pending; > + uint8_t triple_fault_pending; > uint32_t ins_len; > uint32_t sipi_vector; > bool tsc_valid; > diff --git a/target/i386/machine.c b/target/i386/machine.c > index cecd476e98..310b125235 100644 > --- a/target/i386/machine.c > +++ b/target/i386/machine.c > @@ -1562,6 +1562,25 @@ static const VMStateDescription vmstate_arch_lbr = { > } > }; > > +static bool triple_fault_needed(void *opaque) > +{ > + X86CPU *cpu = opaque; > + CPUX86State *env = &cpu->env; > + > + return env->triple_fault_pending; > +} > + > +static const VMStateDescription vmstate_triple_fault = { > + .name = "cpu/triple_fault", > + .version_id = 1, > + .minimum_version_id = 1, > + .needed = triple_fault_needed, > + .fields = (VMStateField[]) { > + VMSTATE_UINT8(env.triple_fault_pending, X86CPU), > + VMSTATE_END_OF_LIST() > + } > +}; > + > const VMStateDescription vmstate_x86_cpu = { > .name = "cpu", > .version_id = 12, > @@ -1706,6 +1725,7 @@ const VMStateDescription vmstate_x86_cpu = { > &vmstate_amx_xtile, > #endif > &vmstate_arch_lbr, > + &vmstate_triple_fault, > NULL > } > }; Thanks Paolo for your review! I'll add this in next version. >
diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 1db1278a59..6e107466b3 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -6017,6 +6017,7 @@ static void x86_cpu_reset(DeviceState *dev) env->exception_has_payload = false; env->exception_payload = 0; env->nmi_injected = false; + env->triple_fault_pending = false; #if !defined(CONFIG_USER_ONLY) /* We hard-wire the BSP to the first CPU. */ apic_designate_bsp(cpu->apic_state, s->cpu_index == 0); diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 82004b65b9..b97d182e28 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1739,6 +1739,7 @@ typedef struct CPUArchState { uint8_t has_error_code; uint8_t exception_has_payload; uint64_t exception_payload; + bool triple_fault_pending; uint32_t ins_len; uint32_t sipi_vector; bool tsc_valid; diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index a1fd1f5379..3838827134 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -132,6 +132,7 @@ static int has_xcrs; static int has_pit_state2; static int has_sregs2; static int has_exception_payload; +static int has_triple_fault_event; static bool has_msr_mcg_ext_ctl; @@ -2483,6 +2484,16 @@ int kvm_arch_init(MachineState *ms, KVMState *s) } } + has_triple_fault_event = kvm_check_extension(s, KVM_CAP_X86_TRIPLE_FAULT_EVENT); + if (has_triple_fault_event) { + ret = kvm_vm_enable_cap(s, KVM_CAP_X86_TRIPLE_FAULT_EVENT, 0, true); + if (ret < 0) { + error_report("kvm: Failed to enable triple fault event cap: %s", + strerror(-ret)); + return ret; + } + } + ret = kvm_get_supported_msrs(s); if (ret < 0) { return ret; @@ -4299,6 +4310,11 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level) } } + if (has_triple_fault_event) { + events.flags |= KVM_VCPUEVENT_VALID_TRIPLE_FAULT; + events.triple_fault.pending = env->triple_fault_pending; + } + return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_VCPU_EVENTS, &events); } @@ -4368,6 +4384,10 @@ static int kvm_get_vcpu_events(X86CPU *cpu) } } + if (events.flags & KVM_VCPUEVENT_VALID_TRIPLE_FAULT) { + env->triple_fault_pending = events.triple_fault.pending; + } + env->sipi_vector = events.sipi_vector; return 0;