Re: [PATCH v3 1/1] x86/fred: Fix INT80 emulation for FRED

From: Xin Li
Date: Wed Apr 17 2024 - 11:35:13 EST


On 4/17/2024 7:59 AM, H. Peter Anvin wrote:
On 4/17/24 02:38, Borislav Petkov wrote:
On Tue, Apr 16, 2024 at 11:30:01PM -0700, Xin Li (Intel) wrote:
3) The FRED kernel entry handler does *NOT* dispatch INT instructions,
    which is of event type EVENT_TYPE_SWINT, so compared with
    do_int80_emulation(), there is no need to do any user mode check.

What does that mean?

An event handler doesn't dispatch INT insns?

/me is confused.

FRED has separate entry flows depending on if the event came from user space or kernel space:

asm_fred_entrypoint_user -> fred_entry_from_user

asm_fred_entrypoint_kernel -> fred_entry_from_kernel

fred_entry_from_kernel does not invoke fred_intx() if the event type is EVENT_TYPE_SWINT, instead it falls through to fred_bad_type(). Perhaps fred_intx() should be renamed fred_intx_user() for additional clarity.

This is a good idea, and again naming is so important.


(It might also we worth noting in that function that the reason int $0x03 and int $0x04 are dispatched as INT3 and INTO is to be fully user space compatible with legacy IDT, which behaves similarly.)

Yeah, this is subtle, and we'd better make it explicit with comments.

FRED distinguishes int $0x03/$0x04 from INT3/INTO with event type EVENT_TYPE_SWINT and EVENT_TYPE_SWEXC, and the Linux kernel itself can still use INT3/INTO, however int $0x03/$0x04 is NOT allowed from kernel context.


Thus, the int $0x80 code is simply not reachable from kernel space; if kernel code were to invoke int $0x80 or any other INT instruction it will error out before getting to this code.

+#ifdef CONFIG_X86_FRED
+/*
+ * A FRED-specific INT80 handler fred_int80_emulation() is required:
+ *
+ * 1) As INT instructions and hardware interrupts are separate event
+ *    types, FRED does not preclude the use of vector 0x80 for external
+ *    interrupts. As a result the FRED setup code does *NOT* reserve
+ *    vector 0x80 and calling int80_is_external() is not merely
+ *    suboptimal but actively incorrect: it could cause a system call
+ *    to be incorrectly ignored.
+ *
+ * 2) fred_int80_emulation(), only called for handling vector 0x80 of
+ *    event type EVENT_TYPE_SWINT, will NEVER be called to handle any
+ *    external interrupt (event type EVENT_TYPE_EXTINT).
+ *
+ * 3) The FRED kernel entry handler does *NOT* dispatch INT instructions,
+ *    which is of event type EVENT_TYPE_SWINT, so compared with
+ *    do_int80_emulation(), there is no need to do any user mode check.
+ *
+ * 4) int80_emulation() does a CLEAR_BRANCH_HISTORY, which is likely
+ *    overkill for new x86 CPU implementations that support FRED.
+ *
+ * 5) int $0x80 is the FAST path for 32-bit system calls under FRED.
+ *
+ * A dedicated FRED INT80 handler duplicates quite a bit of the code in
+ * do_int80_emulation(), but it avoids sprinkling more tests and seems
+ * more readable. Just remember that we can always unify common stuff
+ * later if it turns out that it won't diverge anymore, i.e., after the
+ * FRED code settles.
+ */

And this is talking about duplication above and that text is duplicated
from the commit message. :)

I'll zap it when applying.


I suggested putting it into a comment for future reference. Obviously no need to duplicate it in the commit message :)


yes!