From: Neeraj Upadhyay Set injected-event data (in EVENTINJDATA) when injecting an event, use EXITINTDATA for populating the injected-event data during reinjection. Unlike IDT using some extra CPU register as part of an event context, e.g., %cr2 for #PF, FRED saves a complete event context in its stack frame, e.g., FRED saves the faulting linear address of a #PF into the event data field defined in its stack frame. Populate the EVENTINJDATA during event injection. The event data will be pushed into a FRED stack frame for VM entries that inject an event using FRED event delivery. Signed-off-by: Neeraj Upadhyay Co-developed-by: Shivansh Dhiman Signed-off-by: Shivansh Dhiman --- arch/x86/kvm/svm/svm.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index ddd8941af6f0..693b46d715b4 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -374,6 +374,10 @@ static void svm_inject_exception(struct kvm_vcpu *vcpu) | SVM_EVTINJ_VALID | (ex->has_error_code ? SVM_EVTINJ_VALID_ERR : 0) | SVM_EVTINJ_TYPE_EXEPT; + + if (is_fred_enabled(vcpu)) + svm->vmcb->control.event_inj_data = ex->event_data; + svm->vmcb->control.event_inj_err = ex->error_code; } @@ -4066,7 +4070,7 @@ static void svm_complete_soft_interrupt(struct kvm_vcpu *vcpu, u8 vector, kvm_rip_write(vcpu, svm->soft_int_old_rip); } -static void svm_complete_interrupts(struct kvm_vcpu *vcpu) +static void svm_complete_interrupts(struct kvm_vcpu *vcpu, bool reinject_on_vmexit) { struct vcpu_svm *svm = to_svm(vcpu); u8 vector; @@ -4111,6 +4115,7 @@ static void svm_complete_interrupts(struct kvm_vcpu *vcpu) break; case SVM_EXITINTINFO_TYPE_EXEPT: { u32 error_code = 0; + u64 event_data = 0; /* * Never re-inject a #VC exception. @@ -4121,9 +4126,18 @@ static void svm_complete_interrupts(struct kvm_vcpu *vcpu) if (exitintinfo & SVM_EXITINTINFO_VALID_ERR) error_code = svm->vmcb->control.exit_int_info_err; + /* + * FRED requires an additional field to pass injected-event + * data to the guest. + */ + if (is_fred_enabled(vcpu) && (vector == PF_VECTOR || vector == DB_VECTOR)) + event_data = reinject_on_vmexit ? + svm->vmcb->control.exit_int_data : + svm->vmcb->control.event_inj_data; + kvm_requeue_exception(vcpu, vector, exitintinfo & SVM_EXITINTINFO_VALID_ERR, - error_code, false, 0); + error_code, false, event_data); break; } case SVM_EXITINTINFO_TYPE_INTR: @@ -4146,7 +4160,7 @@ static void svm_cancel_injection(struct kvm_vcpu *vcpu) control->exit_int_info = control->event_inj; control->exit_int_info_err = control->event_inj_err; control->event_inj = 0; - svm_complete_interrupts(vcpu); + svm_complete_interrupts(vcpu, false); } static int svm_vcpu_pre_run(struct kvm_vcpu *vcpu) @@ -4382,7 +4396,7 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags) trace_kvm_exit(vcpu, KVM_ISA_SVM); - svm_complete_interrupts(vcpu); + svm_complete_interrupts(vcpu, true); return svm_exit_handlers_fastpath(vcpu); } -- 2.43.0