Re: [PATCH v10 11/28] KVM: x86: Add a helper to detect if FRED is enabled for a vCPU

From: Binbin Wu

Date: Thu Nov 05 2026 - 00:17:01 EST


On 11/5/2026 4:01 AM, Sohil Mehta wrote:
> On 10/23/2026 2:21 AM, Binbin Wu wrote:
>> On 9/12/2026 5:36 AM, Sohil Mehta wrote:
>>> +/*
>>> + * It's enough to check just CR4.FRED (X86_CR4_FRED) to tell if
>>> + * a vCPU is running with FRED enabled, because:
>>> + * 1) CR4.FRED can be set to 1 only _after_ IA32_EFER.LMA = 1.
>>> + * 2) To leave IA-32e mode, CR4.FRED must be cleared first.
>>
>> It seems KVM doesn't enforce it in kvm_set_cr0() for 2).
>>
>
> I think the comment is slightly misleading. The spec doesn't directly
> enforce leaving IA-32e mode with CR4.FRED. It is just expected to be
> unreachable.
>
> 1) Based on FRED spec section 4.2 Enabling in CR4, setting CR4.FRED
> prevents compatibility mode entry while CPL = 0.
>
> 2) But leaving IA-32e can only happen when CR0.PG is cleared which can
> only be done in compatibility mode while CPL = 0.
>

Right, on bare metal, if CR4.FRED = 1, it is impossible to enter compatibility
mode while CPL = 0.

> Currently, for KVM, the CPU enforces the first one and the second one is
> enforced by kvm_set_cr0().
>
> Is the suggestion to add an explicit check in kvm_set_cr0() that
> mirrors the PCIDE one? But there isn't a fault specified by the spec for
> this case.

Had a second thought. As you mentioned below, if em_{jmp,call,ret}_far() is
triggered and CS.L is cleared on ring 0, even KVM doesn't check FRED status on
far transitions, the next VM entry would fail. So I think it's not needed
to mirror the PCIDE for FRED in kvm_set_cr0().

>
> Sean also requested negative tests for things like leaving 64-bit mode
> with FRED=1. But, I am not sure how to test this.

Maybe it can use KVM_FEP to force the instruction emulation in kvm sefltest
when force_emulation_prefix for KVM.

>
> AI tells me such a mode change can happen with emulated far transfer
> through an MMIO far pointer. "em_jmp_far(), em_call_far(), em_ret_far()
> and __load_segment_descriptor() have no FRED checks, so none of them
> raise the #GP that FRED spec 8.2 requires."
>
> Chao had brought up enhancing emulator code and making it FRED aware
> [1]. I am wondering if we should revisit it?

Without the check the next VM-entry fails the guest-state check according to
FRED spec 11.5.2.3 ("If the DPL value in the SS attributes field is 0, the L
bit in the CS attributes field (bit 13) must be 1") VS. With the check, raise
#GP instead.

Not sure about the maintainers' preference. But a check on FRED in
__load_segment_descriptor() looks simple though.

>
> [1]: https://lore.kernel.org/all/aapnI6KN7Flal8kg@xxxxxxxxx/
>
> Please let me know if I misunderstood something.