Re: [PATCH 07/21] KVM: VMX: Introduce test mode related to EPT violation VE

From: Sean Christopherson
Date: Tue Mar 12 2024 - 12:54:52 EST


On Tue, Mar 12, 2024, Kai Huang wrote:
> On 28/02/2024 12:20 pm, Paolo Bonzini wrote:
> > From: Isaku Yamahata <isaku.yamahata@xxxxxxxxx>
> >
> > To support TDX, KVM is enhanced to operate with #VE. For TDX, KVM uses the
> > suppress #VE bit in EPT entries selectively, in order to be able to trap
> > non-present conditions. However, #VE isn't used for VMX and it's a bug
> > if it happens. To be defensive and test that VMX case isn't broken
> > introduce an option ept_violation_ve_test and when it's set, BUG the vm.
>
> I am wondering from HW's point of view, is it OK for the kernel to
> explicitly send #VE IPI, in which case, IIUC, the guest can legally get the
> #VE w/o being a TDX guest?

Ooh, fun. Short answer: there's nothing to worry about here.

Legally, no. Vectors 0-31 are reserved. However, I do _think_ the guest could
technically send IPIs on vectors 16-31, as the local APIC doesn't outright reject
such vectors. But such software would be in clear violation of the SDM.

11.5.2 Valid Interrupt Vectors

The Intel 64 and IA-32 architectures define 256 vector numbers, ranging from
0 through 255 (see Section 6.2, “Exception and Interrupt Vectors”). Local and
I/O APICs support 240 of these vectors (in the range of 16 to 255) as valid
interrupts.

When an interrupt vector in the range of 0 to 15 is sent or received through
the local APIC, the APIC indicates an illegal vector in its Error Status
Register (see Section 11.5.3, “Error Handling”). The Intel 64 and IA-32
architectures reserve vectors 16 through 31 for predefined interrupts,
exceptions, and Intel-reserved encodings (see Table 6-1). However, the local
APIC does not treat vectors in this range as illegal.

When an illegal vector value (0 to 15) is written to an LVT entry and the delivery
mode is Fixed (bits 8-11 equal 0), the APIC may signal an illegal vector error,
without regard to whether the mask bit is set or whether an interrupt is actually
seen on the input.

where Table 6-1 defines the various exceptions, including #VE, and for vectors
22-31 says "Intel reserved. Do not use." Vectors 32-255 are explicitly described
as "User Defined (Non-reserved) Interrupts" that can be generated via "External
interrupt or INT n instruction."

However, INTn is far more interesting than IPIs, as INTn can definitely generate
interrupts for vectors 0-31, and the legality of software generating such interrupts
is questionable. E.g. KVM used to "forward" NMI VM-Exits to the kernel by doing
INTn with vector 2.

Key word "interrupts"! IPIs are hardware interrupts, and INTn generates software
interrupts, neither of which are subject to exception bitmap interception:

Exceptions (faults, traps, and aborts) cause VM exits based on the exception
bitmap (see Section 25.6.3). If an exception occurs, its vector (in the range
0–31) is used to select a bit in the exception bitmap. If the bit is 1, a VM
exit occurs; if the bit is 0, the exception is delivered normally through the
guest IDT. This use of the exception bitmap applies also to exceptions generated
by the instructions INT1, INT3, INTO, BOUND, UD0, UD1, and UD2.

with a footnote that further says:

INT1 and INT3 refer to the instructions with opcodes F1 and CC, respectively,
and not to INT n with value 1 or 3 for n.

So while a misbehaving guest could generate a software interrupt on vector 20,
it would not be a true #VE, i.e. not an exception, and thus would not generate
an EXCEPTION_NMI VM-Exit. I.e. the KVM_BUG_ON() can't be triggered by the guest
(assuming hardware isn't broken).