Re: [Discussion] x86: Guest Support for APX

Paolo Bonzini
2025-09-19T22:14:03Z

On Fri, Sep 19, 2025, 22:16 Chang S. Bae <chang.seok.bae@intel.com> wrote:
> Dear KVM maintainers,
>
> Since APX introduces new general-purpose registers (GPRs), legacy
> instructions are extended to access them, which may lead to associated
> VM exits. For example, MOV may now reference these registers in MMIO
> operations for emulated devices. The spec [3] lists other instructions
> that may similarly exit.

You're right that gets very complicated quickly, while most cases of
MMIO emulation are for legacy devices and R16-R31 are unlikely to
appear in MMIO instructions for these legacy devices.

However, at least MOVs should be extended to support APX registers as
source or destination operands, and there should also be support for
base and index in the addresses. This means you have to parse REX2,
but EVEX shouldn't be needed as these instructions are in "legacy map
0" (aka one-byte).

At this point, singling out MOVs is not useful and you might as well
implement REX2 for all instructions. EVEX adds a lot of extra cases
including three operand integer instructions and no flag update, but
REX2 is relatively simple.

> In summary, we'd like to clarify:
>
> * Should we target complete emulation coverage for all APX-induced
> exits (from the start)?
>
> * Or is a narrower scope (e.g., only MOV) practically a considerable
> option, given the limited likelihood of other exits?

See above. I hope it answers both questions.

> * Alternatively, can we even consider a pragmatic path like MOVDIR* --
> supporting only when practically useful?

I think pragmatic is fine, but in some cases too restrictive makes it
harder to track what is implemented and what isn't. Again, see the
above comment about implementing REX2 fully while limiting EVEX
support to the minimum (or hopefully leaving it out altogether).

> [4] The MOVDIR64 opcode is "66 0F 38 F8 ..." but opcode_table[] in
> emulate.c looks currently missing it:
>
> /* 0x60 - 0x67 */
> I(ImplicitOps | Stack | No64, em_pusha),
> I(ImplicitOps | Stack | No64, em_popa),
> N, MD(ModRM, &mode_dual_63),
> N, N, N, N,

0x66 is a prefix so you have to look at F8 in the table for the 0F 38
three-byte opcodes (opcode_map_0f_38) and add a new
three_byte_0f_38_f8 table.

MOVDIR* and many other instructions are not implemented because they
are pretty much never used with emulated (legacy) MMIO such as VGA
framebuffers. By the way MOVDIR* is not a REX2-accepted instruction,
so you would have to implement EVEX in order to support it for APX
registers.

Paolo