On Sat, Sep 12, 2026 at 11:44 PM Tina Zhang <[email protected]> wrote:
>
> VMCB02 instruction bytes are valid only for the hardware VM-Exit that
> populated them. Track whether VMCB02 contains instruction bytes for the
> data #PF or #NPF currently being reflected to L1 so that stale bytes are
> not copied to VMCB12.
>
> Invalidate VMCB02's instruction-byte state when preparing VMCB02,
> normally in response to an emulated VMRUN. Mark the bytes as valid only
> when the current VMCB02 exit is a data #PF or #NPF. Opcode exits and
> instruction-fetch faults are excluded by inspecting the exit state.
>
> A subsequent change will use this state when propagating hardware
> DecodeAssist instruction bytes to VMCB12.
>
> Signed-off-by: Tina Zhang <[email protected]>
> ---
> arch/x86/kvm/svm/nested.c | 38 +++++++++++++++++++++++++++++++++++++-
> arch/x86/kvm/svm/svm.h | 3 +++
> 2 files changed, 40 insertions(+), 1 deletion(-)
>
> diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
> index 73f37b050d0a..1cc3af8247f2 100644
> --- a/arch/x86/kvm/svm/nested.c
> +++ b/arch/x86/kvm/svm/nested.c
> @@ -35,6 +35,35 @@
>
> #define CC KVM_NESTED_VMENTER_CONSISTENCY_CHECK
>
> +static void nested_svm_invalidate_insn_bytes(struct vmcb *vmcb)
> +{
> + vmcb->control.insn_len = 0;
> +}
> +
> +static bool nested_svm_vmexit_supports_insn_bytes(const struct vmcb *vmcb)
> +{
> + u64 exit_code = vmcb->control.exit_code;
> +
> + if (exit_code != SVM_EXIT_NPF &&
> + exit_code != SVM_EXIT_EXCP_BASE + PF_VECTOR)
> + return false;
> +
> + return !(vmcb->control.exit_info_1 & PFERR_FETCH_MASK);
> +}
> +
> +static void nested_svm_set_vmcb02_insn_bytes_valid(struct vcpu_svm *svm)
> +{
> + svm->nested.vmcb02_insn_bytes_valid =
> + static_cpu_has(X86_FEATURE_DECODEASSISTS) &&
> + nested_svm_vmexit_supports_insn_bytes(svm->nested.vmcb02.ptr);
> +}
> +
> +static void nested_svm_invalidate_vmcb02_insn_bytes(struct vcpu_svm *svm)
> +{
> + nested_svm_invalidate_insn_bytes(svm->nested.vmcb02.ptr);
> + svm->nested.vmcb02_insn_bytes_valid = false;
> +}
> +
> static void nested_svm_inject_npf_exit(struct kvm_vcpu *vcpu,
> struct x86_exception *fault,
> bool from_hardware)
> @@ -68,6 +97,10 @@ static void nested_svm_inject_npf_exit(struct kvm_vcpu
> *vcpu,
> (fault->error_code &
> ~PFERR_GUEST_FAULT_STAGE_MASK);
> vmcb->control.exit_info_2 = fault->address;
>
> + if (from_hardware)
> + nested_svm_set_vmcb02_insn_bytes_valid(svm);
> + else
> + svm->nested.vmcb02_insn_bytes_valid = false;
For consistency, should the line above be:
nested_svm_invalidate_vmcb02_insn_bytes(svm);
> nested_svm_vmexit(svm);
> }
>
> @@ -869,6 +902,7 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm
> *svm)
> * Filled at exit: exit_code, exit_info_1, exit_info_2, exit_int_info,
> * exit_int_info_err, next_rip, insn_len, insn_bytes.
> */
> + nested_svm_invalidate_vmcb02_insn_bytes(svm);
>
> if (guest_cpu_cap_has(vcpu, X86_FEATURE_VGIF) &&
> (vmcb12_ctrl->int_ctl & V_GIF_ENABLE_MASK))
> @@ -1649,8 +1683,10 @@ int nested_svm_exit_handled(struct vcpu_svm *svm)
>
> vmexit = nested_svm_intercept(svm);
>
> - if (vmexit == NESTED_EXIT_DONE)
> + if (vmexit == NESTED_EXIT_DONE) {
> + nested_svm_set_vmcb02_insn_bytes_valid(svm);
> nested_svm_vmexit(svm);
> + }
>
> return vmexit;
> }
> diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
> index e958943b8162..1e12ef1105c0 100644
> --- a/arch/x86/kvm/svm/svm.h
> +++ b/arch/x86/kvm/svm/svm.h
> @@ -243,6 +243,9 @@ struct svm_nested_state {
> * on its side.
> */
> bool force_msr_bitmap_recalc;
> +
> + /* True if VMCB02 has instruction bytes for the current nested exit.
> */
> + bool vmcb02_insn_bytes_valid;
> };
>
> struct vcpu_sev_es_state {
> --
> 2.43.7
>