else if (is_nm_fault(intr_info) &&
vcpu->arch.guest_fpu.fpstate->xfd)
does this necessarily mean the #NM is caused by XFD?
Then the event data should be 0. Or I missed something obvious? I.e., it can be easily differentiated and we should just explicitly set it to 0.
event_data = vcpu->arch.guest_fpu.xfd_err;
vmcs_write64(INJECTED_EVENT_DATA, event_data);
}
}
vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info);
vmx_clear_hlt(vcpu);
@@ -7226,7 +7247,8 @@ static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx) static void __vmx_complete_interrupts(struct kvm_vcpu *vcpu, u32 idt_vectoring_info, int instr_len_field,
int error_code_field)
int error_code_field,
int event_data_field)
event_data_field is used to indicate whether this is a "cancel". I may think it is better to simply use a boolean e.g., bool cancel.
I'm fine with the idea if no objections.
{ u8 vector; int type; @@ -7260,6 +7282,37 @@ static void __vmx_complete_interrupts(struct
kvm_vcpu *vcpu,
vcpu->arch.event_exit_inst_len = vmcs_read32(instr_len_field); fallthrough;
case INTR_TYPE_HARD_EXCEPTION:
if (kvm_is_fred_enabled(vcpu) && event_data_field) {
/*
* Save original-event data for being used as injected-
event data.
*/
Looks we also expect CPU will update CR2/DR6/XFD_ERR. this hunk looks to me just a paranoid check to ensure the cpu works as expected. if that's the case, I suggest documenting it a bit in the comment.
These checks are not intended for hw, they make sure nVMX FRED is correctly implemented and catch regressions.
And yes, in the early stage, I prefer to be paranoid.
u64 event_data = vmcs_read64(event_data_field);
switch (vector) {
case DB_VECTOR:
get_debugreg(vcpu->arch.dr6, 6);
WARN_ON(vcpu->arch.dr6 != (event_data ^
DR6_RESERVED));
vcpu->arch.dr6 = event_data ^ DR6_RESERVED;
break;
case NM_VECTOR:
if (vcpu->arch.guest_fpu.fpstate->xfd) {
rdmsrl(MSR_IA32_XFD_ERR, vcpu-
arch.guest_fpu.xfd_err);
WARN_ON(vcpu-
arch.guest_fpu.xfd_err != event_data);
vcpu->arch.guest_fpu.xfd_err =
event_data;
} else {
WARN_ON(event_data != 0);
}
break;
case PF_VECTOR:
WARN_ON(vcpu->arch.cr2 != event_data);
vcpu->arch.cr2 = event_data;
break;
default:
WARN_ON(event_data != 0);
I am not sure if this WARN_ON() can be triggeded by nested VMX. It is legitimate for L1 VMM to inject any event w/ an event_data.
FRED spec says:
Section 5.2.1 specifies the event data that FRED event delivery of certain events saves on the stack. When FRED event delivery is used for an event injected by VM entry, the event data saved is the value of the injected-event-data field in the VMCS. This value is used instead of what is specified in Section 5.2.1 and is done for __ALL__ injected events using FRED event delivery
5.2.1 Saving Information on the Regular Stack also says: - For any other event, the event data are not currently defined and will be zero until they are.
Or you mean something else?