Re: [PATCH v10 14/28] KVM: VMX: Virtualize FRED event_data

From: Sohil Mehta

Date: Fri Nov 06 2026 - 16:32:58 EST


On 10/29/2026 3:55 AM, Binbin Wu wrote:
> On 9/12/2026 5:36 AM, Sohil Mehta wrote:
>>
>> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
>> index 94d684210cf6..e10ac6b280f6 100644
>> --- a/arch/x86/kvm/x86.c
>> +++ b/arch/x86/kvm/x86.c
>> @@ -431,9 +431,22 @@ void kvm_deliver_exception_payload(struct kvm_vcpu *vcpu,
>
> kvm_deliver_exception_payload() returns early if !ex->has_payload.
>
> For example, if a #PF is injected, kvm_deliver_exception_payload() sets
> ex->event_data to cr2.
> Later, if a #DB without payload is queued via KVM_GUESTDBG_INJECT_DB, the
> event_data is not updated.
> It seems the stale #PF event_data will be write to INJECTED_EVENT_DATA and
> delivered to #DB handler in the guest.
>

AFAIU, if the #PF is injected, the next VM exit would call
vm_clear_exception_queue() which would zero out the event_data. Also,
based on commit e907b4e72488 ("KVM: x86: Check for injected exceptions
before queuing a debug exception"), even if the exit interrupted the #PF
delivery it shouldn't be an issue.

But, I agree with you in principle. kvm_multiple_exception() leaves
event_data alone when it queues an exception, so an exception without a
payload would inherit the old event data which makes it a little fragile.

To solidify this, I am thinking that event_data can be zeroed in
kvm_multiple_exception() similar to how is_nested is handled. Later,
kvm_deliver_exception_payload() can fill it from the payload.

>> * breakpoint), it is reserved and must be zero in DR6.
>> */
>> vcpu->arch.dr6 &= ~BIT(12);
>> +
>> + /*
>> + * FRED #DB event data matches DR6, but follows the polarity of
>> + * VMX's pending debug exceptions, not DR6.
>> + */
>> + ex->event_data = ex->payload & ~BIT(12);
>> + break;
>> + case NM_VECTOR:
>> + ex->event_data = ex->payload;
>> break;
>> case PF_VECTOR:
>> vcpu->arch.cr2 = ex->payload;
>> + ex->event_data = ex->payload;
>> + break;
>> + default:
>> + ex->event_data = 0;
>> break;
>> }
>>
>