@@ -7664,29 +7664,78 @@ void kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip)
76647664}
76657665EXPORT_SYMBOL_GPL (kvm_inject_realmode_interrupt );
76667666
7667- static void prepare_emulation_failure_exit (struct kvm_vcpu * vcpu )
7667+ static void prepare_emulation_failure_exit (struct kvm_vcpu * vcpu , u64 * data ,
7668+ u8 ndata , u8 * insn_bytes , u8 insn_size )
76687669{
7669- struct x86_emulate_ctxt * ctxt = vcpu -> arch .emulate_ctxt ;
7670- u32 insn_size = ctxt -> fetch .end - ctxt -> fetch .data ;
76717670 struct kvm_run * run = vcpu -> run ;
7671+ u64 info [5 ];
7672+ u8 info_start ;
7673+
7674+ /*
7675+ * Zero the whole array used to retrieve the exit info, as casting to
7676+ * u32 for select entries will leave some chunks uninitialized.
7677+ */
7678+ memset (& info , 0 , sizeof (info ));
7679+
7680+ static_call (kvm_x86_get_exit_info )(vcpu , (u32 * )& info [0 ], & info [1 ],
7681+ & info [2 ], (u32 * )& info [3 ],
7682+ (u32 * )& info [4 ]);
76727683
76737684 run -> exit_reason = KVM_EXIT_INTERNAL_ERROR ;
76747685 run -> emulation_failure .suberror = KVM_INTERNAL_ERROR_EMULATION ;
7675- run -> emulation_failure .ndata = 0 ;
7686+
7687+ /*
7688+ * There's currently space for 13 entries, but 5 are used for the exit
7689+ * reason and info. Restrict to 4 to reduce the maintenance burden
7690+ * when expanding kvm_run.emulation_failure in the future.
7691+ */
7692+ if (WARN_ON_ONCE (ndata > 4 ))
7693+ ndata = 4 ;
7694+
7695+ /* Always include the flags as a 'data' entry. */
7696+ info_start = 1 ;
76767697 run -> emulation_failure .flags = 0 ;
76777698
76787699 if (insn_size ) {
7679- run -> emulation_failure .ndata = 3 ;
7700+ BUILD_BUG_ON ((sizeof (run -> emulation_failure .insn_size ) +
7701+ sizeof (run -> emulation_failure .insn_bytes ) != 16 ));
7702+ info_start += 2 ;
76807703 run -> emulation_failure .flags |=
76817704 KVM_INTERNAL_ERROR_EMULATION_FLAG_INSTRUCTION_BYTES ;
76827705 run -> emulation_failure .insn_size = insn_size ;
76837706 memset (run -> emulation_failure .insn_bytes , 0x90 ,
76847707 sizeof (run -> emulation_failure .insn_bytes ));
7685- memcpy (run -> emulation_failure .insn_bytes ,
7686- ctxt -> fetch .data , insn_size );
7708+ memcpy (run -> emulation_failure .insn_bytes , insn_bytes , insn_size );
76877709 }
7710+
7711+ memcpy (& run -> internal .data [info_start ], info , sizeof (info ));
7712+ memcpy (& run -> internal .data [info_start + ARRAY_SIZE (info )], data ,
7713+ ndata * sizeof (data [0 ]));
7714+
7715+ run -> emulation_failure .ndata = info_start + ARRAY_SIZE (info ) + ndata ;
76887716}
76897717
7718+ static void prepare_emulation_ctxt_failure_exit (struct kvm_vcpu * vcpu )
7719+ {
7720+ struct x86_emulate_ctxt * ctxt = vcpu -> arch .emulate_ctxt ;
7721+
7722+ prepare_emulation_failure_exit (vcpu , NULL , 0 , ctxt -> fetch .data ,
7723+ ctxt -> fetch .end - ctxt -> fetch .data );
7724+ }
7725+
7726+ void __kvm_prepare_emulation_failure_exit (struct kvm_vcpu * vcpu , u64 * data ,
7727+ u8 ndata )
7728+ {
7729+ prepare_emulation_failure_exit (vcpu , data , ndata , NULL , 0 );
7730+ }
7731+ EXPORT_SYMBOL_GPL (__kvm_prepare_emulation_failure_exit );
7732+
7733+ void kvm_prepare_emulation_failure_exit (struct kvm_vcpu * vcpu )
7734+ {
7735+ __kvm_prepare_emulation_failure_exit (vcpu , NULL , 0 );
7736+ }
7737+ EXPORT_SYMBOL_GPL (kvm_prepare_emulation_failure_exit );
7738+
76907739static int handle_emulation_failure (struct kvm_vcpu * vcpu , int emulation_type )
76917740{
76927741 struct kvm * kvm = vcpu -> kvm ;
@@ -7701,16 +7750,14 @@ static int handle_emulation_failure(struct kvm_vcpu *vcpu, int emulation_type)
77017750
77027751 if (kvm -> arch .exit_on_emulation_error ||
77037752 (emulation_type & EMULTYPE_SKIP )) {
7704- prepare_emulation_failure_exit (vcpu );
7753+ prepare_emulation_ctxt_failure_exit (vcpu );
77057754 return 0 ;
77067755 }
77077756
77087757 kvm_queue_exception (vcpu , UD_VECTOR );
77097758
77107759 if (!is_guest_mode (vcpu ) && static_call (kvm_x86_get_cpl )(vcpu ) == 0 ) {
7711- vcpu -> run -> exit_reason = KVM_EXIT_INTERNAL_ERROR ;
7712- vcpu -> run -> internal .suberror = KVM_INTERNAL_ERROR_EMULATION ;
7713- vcpu -> run -> internal .ndata = 0 ;
7760+ prepare_emulation_ctxt_failure_exit (vcpu );
77147761 return 0 ;
77157762 }
77167763
@@ -12336,9 +12383,7 @@ int kvm_handle_memory_failure(struct kvm_vcpu *vcpu, int r,
1233612383 * doesn't seem to be a real use-case behind such requests, just return
1233712384 * KVM_EXIT_INTERNAL_ERROR for now.
1233812385 */
12339- vcpu -> run -> exit_reason = KVM_EXIT_INTERNAL_ERROR ;
12340- vcpu -> run -> internal .suberror = KVM_INTERNAL_ERROR_EMULATION ;
12341- vcpu -> run -> internal .ndata = 0 ;
12386+ kvm_prepare_emulation_failure_exit (vcpu );
1234212387
1234312388 return 0 ;
1234412389}
0 commit comments