[PATCH v3 0/7] target/i386/mshv: use hv_vp_register_page for fast register access

Doru Blânzeanu posted 7 patches 5 days, 4 hours ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260521165041.131477-1-dblanzeanu@linux.microsoft.com
Maintainers: Magnus Kulke <magnuskulke@linux.microsoft.com>, Wei Liu <wei.liu@kernel.org>, "Doru Blânzeanu" <dblanzeanu@linux.microsoft.com>, Paolo Bonzini <pbonzini@redhat.com>, Zhao Liu <zhao1.liu@intel.com>
accel/mshv/mshv-all.c       |  12 +-
include/hw/hyperv/hvgdk.h   |   2 +
include/hw/hyperv/hvhdk.h   | 106 +++++++++++++
include/system/mshv_int.h   |   4 +-
target/i386/cpu.h           |   4 +
target/i386/mshv/mshv-cpu.c | 300 ++++++++++++++++++++++++++----------
6 files changed, 332 insertions(+), 96 deletions(-)
[PATCH v3 0/7] target/i386/mshv: use hv_vp_register_page for fast register access
Posted by Doru Blânzeanu 5 days, 4 hours ago
This series adds support for using the hypervisor's vp register page
in the mshv accelerator to optimize vcpu register access on mmio and pio
exits.

Currently, all register reads and writes go through hypercalls (ioctls),
which add overhead on every VM exit. The VP register page is a shared
memory page that the hypervisor populates with vcpu register state,
allowing Qemu to read and write registers directly without hypercalls.

The series is structured as follows:
1. Remove the duplicate `fetch_guest_state` function, consolidating
  register loading into `mshv_load_regs`.
2. Move `mshv_arch_init_vcpu` after vcpu creation so the vcpu fd is
  valid when we need it for mmap.
3. Define the `hv_vp_register_page` structure in `hvgdk_mini.h`, matching
  the layout used by the Linux kernel's mshv driver.
4. Set up the register page by mmapping the vcpu fd at init time. If the
  mmap fails, we abort signaling an issue in the system.
5. Use the register page to read registers on VM exit. General purpose
  registers, RIP, RFLAGS, segment registers, and control registers
  (CR0, CR4, CR4, CR8, EFER) are read directly from the page. Registers
  not present on the page (TR, LDTR, GDTR, IDTR, CR2, APIC_BASE) are not
  fetched anymore for performance reasons.
6. Use register page to write registers on vmentry. GP registers,
  RIP, and RFLAGS are written to the page with the appropriate dirty
  bits set, avoiding the hypercall for the standard register store.

The register page is only used when it has been successfully mmapped and
the hypervisor has marked it as valid (`isvalid != 0`). Otherwise, an error is
returned and execution aborted to signal something faulty and unexpected.

Changes since v2:
- Rebased on the current master
- Add HV_VP_REGISTER_PAGE_VERSION_1 to `hvhdk.h` and verify the register page
  version after mmap.
- Remove fallback to ioctl for when mmap fails, or the register page pointer is
  invalid. Now the mmap, or register page pointer is not valid, we abort with an
  error message indicating what went wrong.
  The mshv_load_regs and mshv_store_regs functions now abort in case the
  register page is not valid.
- Move the regs_page field to a place that is preserved across CPU reset inside
  the CPUArchState struct

Changes since v1:
- move hv_register_page struct definition to hvhdk.h
- add a compile time guard around regs_page in CPUArchState
- modify mshv_get_special_regs_vp_page to only retrieve the special
  registers present in the register page (removed TR, LDTR, GDTR, IDTR,
  CR2, APIC_BASE)
  In local testing this hasn't created any regressions, and it is unlikely
  that the mmio operations need this registers.
  We'll want to keep an eye on this in case there are decoded operations
  that rely on fetching these registers on every VM exit.
- add commit to fix handle_pio_non_str and handle_pio_str to correctly
  store modified registers back to the register page after the pio
  operation, and clear the cpu->accel->dirty flag to avoid the
  mshv_arch_put_registers from resetting some registers state (fpu).
- modified register page setup to signal an error instead of a warning
  in case mmap fails.
  I am not sure aborting here is fine because it would make some of the
  fallback logic redundant, and I think that's a bigger refactoring.

Doru Blânzeanu (7):
  target/i386/mshv: remove duplicate function for reading vcpu registers
  accel/mshv: move vcpu arch specific initialization after vcpu creation
  include/hw/hyperv: add hv_vp_register_page struct definition
  target/i386/mshv: hv_vp_register_page setup for the vcpu
  target/i386/mshv: use the register page to get registers
  target/i386/mshv: use the register page to set registers
  target/i386/mshv: fix pio handlers clobbering device-modified
    registers

 accel/mshv/mshv-all.c       |  12 +-
 include/hw/hyperv/hvgdk.h   |   2 +
 include/hw/hyperv/hvhdk.h   | 106 +++++++++++++
 include/system/mshv_int.h   |   4 +-
 target/i386/cpu.h           |   4 +
 target/i386/mshv/mshv-cpu.c | 300 ++++++++++++++++++++++++++----------
 6 files changed, 332 insertions(+), 96 deletions(-)

-- 
2.53.0