/* * QEMU MSHV support * * Copyright Microsoft, Corp. 2025 * * Authors: Ziqiao Zhou * Magnus Kulke * Jinank Jain * * SPDX-License-Identifier: GPL-2.0-or-later * */ #ifndef QEMU_MSHV_INT_H #define QEMU_MSHV_INT_H #include "hw/hyperv/hvhdk.h" #define MSHV_MSR_ENTRIES_COUNT 64 /* * Interruption-type encoding, used by the hypervisor in * hv_x64_pending_interruption_register.interruption_type * See TLFS 6.0 section 7.9.2, p55 * https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/tlfs */ #define MSHV_HV_INTERRUPTION_TYPE_EXT_INT 0 #define MSHV_HV_INTERRUPTION_TYPE_NMI 2 #define MSHV_HV_INTERRUPTION_TYPE_HW_EXC 3 #define MSHV_HV_INTERRUPTION_TYPE_SW_INT 4 #define MSHV_HV_INTERRUPTION_TYPE_PRIV_SW_EXC 5 #define MSHV_HV_INTERRUPTION_TYPE_SW_EXC 6 #define MSHV_DIRTY_PAGES_BATCH_SIZE 0x10000 typedef struct hyperv_message hv_message; typedef struct MshvHvCallArgs { void *base; void *input_page; void *output_page; } MshvHvCallArgs; struct AccelCPUState { int cpufd; MshvHvCallArgs hvcall_args; }; typedef struct MshvMemoryListener { MemoryListener listener; int as_id; } MshvMemoryListener; typedef struct MshvAddressSpace { MshvMemoryListener *ml; AddressSpace *as; } MshvAddressSpace; struct MshvState { AccelState parent_obj; int vm; MshvMemoryListener memory_listener; /* number of listeners */ int nr_as; MshvAddressSpace *as; int fd; /* irqchip routing */ struct mshv_user_irq_table *irq_routes; int nr_allocated_irq_routes; unsigned long *used_gsi_bitmap; unsigned int gsi_count; union hv_partition_processor_features processor_features; }; typedef struct MshvMsiControl { bool updated; GHashTable *gsi_routes; } MshvMsiControl; #define mshv_vcpufd(cpu) (cpu->accel->cpufd) /* cpu */ typedef enum MshvVmExit { MshvVmExitIgnore = 0, MshvVmExitShutdown = 1, MshvVmExitSpecial = 2, } MshvVmExit; void mshv_init_mmio_emu(void); int mshv_create_vcpu(int vm_fd, uint8_t vp_index, int *cpu_fd); void mshv_remove_vcpu(int vm_fd, int cpu_fd); int mshv_configure_vcpu(const CPUState *cpu); int mshv_run_vcpu(int vm_fd, CPUState *cpu, hv_message *msg, MshvVmExit *exit); int mshv_set_generic_regs(const CPUState *cpu, const hv_register_assoc *assocs, size_t n_regs); int mshv_get_generic_regs(CPUState *cpu, hv_register_assoc *assocs, size_t n_regs); int mshv_arch_store_vcpu_state(const CPUState *cpu); int mshv_arch_load_vcpu_state(CPUState *cpu); int mshv_arch_set_partition_msrs(const CPUState *cpu); int mshv_arch_set_mp_state(const CPUState *cpu); void mshv_arch_init_vcpu(CPUState *cpu); void mshv_arch_destroy_vcpu(CPUState *cpu); void mshv_arch_amend_proc_features( union hv_partition_synthetic_processor_features *features); void mshv_arch_disable_partition_proc_features( union hv_partition_processor_features *disabled_features); int mshv_arch_post_init_vm(int vm_fd); int mshv_get_vp_state(int cpu_fd, struct mshv_get_set_vp_state *state); int mshv_set_vp_state(int cpu_fd, const struct mshv_get_set_vp_state *state); typedef struct mshv_root_hvcall mshv_root_hvcall; int mshv_hvcall(int fd, const mshv_root_hvcall *args); /* apic */ int mshv_init_lint(CPUState *cpu); int mshv_set_lapic(const CPUState *cpu); int mshv_get_lapic(CPUState *cpu); /* memory */ typedef struct MshvMemoryRegion { uint64_t guest_phys_addr; uint64_t memory_size; uint64_t userspace_addr; bool readonly; } MshvMemoryRegion; int mshv_guest_mem_read(uint64_t gpa, uint8_t *data, uintptr_t size, bool is_secure_mode, bool instruction_fetch); int mshv_guest_mem_write(uint64_t gpa, const uint8_t *data, uintptr_t size, bool is_secure_mode); void mshv_set_phys_mem(MshvMemoryListener *mml, MemoryRegionSection *section, bool add); void mshv_log_sync(MemoryListener *listener, MemoryRegionSection *section); bool mshv_log_global_start(MemoryListener *listener, Error **errp); void mshv_log_global_stop(MemoryListener *listener); /* msr */ int mshv_init_msrs(const CPUState *cpu); int mshv_get_msrs(CPUState *cpu); int mshv_set_msrs(const CPUState *cpu); /* synic */ int mshv_get_simp(int cpu_fd, uint8_t *page); int mshv_set_simp(int cpu_fd, const uint8_t *page); int mshv_get_siefp(int cpu_fd, uint8_t *page); int mshv_set_siefp(int cpu_fd, const uint8_t *page); bool mshv_synic_enabled(const CPUState *cpu); int mshv_get_synthetic_timers(int cpu_fd, uint8_t *state); int mshv_set_synthetic_timers(int cpu_fd, const uint8_t *state); #endif