From nobody Sat Nov 15 14:52:41 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linux.microsoft.com ARC-Seal: i=1; a=rsa-sha256; t=1751391036; cv=none; d=zohomail.com; s=zohoarc; b=GHn+M4GnU9IjnAspOvT2Obg1rvf0rV630Q+wVMOXcYFQU0kutoLxrL6DZRz/TRenqu+A9Ot+in2p913LE95K1t1c3BZ36zTgm9bUigjXtV6VMobyC5q1zx759+AF+VQBvfkG8ZxZ8Iw7S5l6gjwzbwZQBVI+RzqtX18/n+tLQOY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751391036; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=k9Vqnknl7noR3cqrniCSd1rI0N2lT3zf5F9ifkoQOh0=; b=LWuK+uJgGTE4TEap7X2SG0VTyJ+kg65zmf96DT+iTpCUD4qtvS2jTBrTAXezGbQqSfnG+vbDzSzgjGPKpLvRI/EaAH9Tp25FihZqmatOVL+gS+Azy0aH2DMsCOJRKDiYSQdVri7cviw/Zo/Gg2dtGKsbmv2czdYp3QDxjA8SKfQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751391036216709.7494528087808; Tue, 1 Jul 2025 10:30:36 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWeng-0003R1-II; Tue, 01 Jul 2025 13:29:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWenb-00039T-55 for qemu-devel@nongnu.org; Tue, 01 Jul 2025 13:29:40 -0400 Received: from linux.microsoft.com ([13.77.154.182]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWenY-0006gq-QT for qemu-devel@nongnu.org; Tue, 01 Jul 2025 13:29:38 -0400 Received: from localhost.localdomain (unknown [167.220.208.67]) by linux.microsoft.com (Postfix) with ESMTPSA id 4FE872112233; Tue, 1 Jul 2025 10:29:31 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 4FE872112233 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1751390974; bh=k9Vqnknl7noR3cqrniCSd1rI0N2lT3zf5F9ifkoQOh0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qHzOz+SwjcZrIPYJrJI/QMvdkgiOF7V7mQFHDbD0IxGMqYTb0d+Cc/GaqxStBZDuj jRyIhFG0JgoSGfUJNGOh31Hv/jh8X4aEDatzBNKD/0yESLE60S1LW0wOMmMaCAazye u+Ba83BsfACzn4acufzruh/OqdIgv5jqREzVAmB4= From: Magnus Kulke To: qemu-devel@nongnu.org Cc: Cameron Esfahani , Phil Dennis-Jordan , Roman Bolshakov , Thomas Huth , Zhao Liu , Wei Liu , Paolo Bonzini , Wei Liu , Richard Henderson , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Markus Armbruster , Cornelia Huck , Magnus Kulke , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Michael S. Tsirkin" , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH v2 08/27] accel/mshv: Initialize VM partition Date: Tue, 1 Jul 2025 19:28:15 +0200 Message-Id: <20250701172834.44849-9-magnuskulke@linux.microsoft.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250701172834.44849-1-magnuskulke@linux.microsoft.com> References: <20250701172834.44849-1-magnuskulke@linux.microsoft.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=13.77.154.182; envelope-from=magnuskulke@linux.microsoft.com; helo=linux.microsoft.com X-Spam_score_int: -19 X-Spam_score: -2.0 X-Spam_bar: -- X-Spam_report: (-2.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linux.microsoft.com) X-ZM-MESSAGEID: 1751391038077116600 Content-Type: text/plain; charset="utf-8" Create the MSHV virtual machine by opening a partition and issuing the necessary ioctl to initialize it. This sets up the basic VM structure and initial configuration used by MSHV to manage guest state. Signed-off-by: Magnus Kulke --- accel/mshv/mshv-all.c | 210 ++++++++++++++++++++++++++++++++++- accel/mshv/trace-events | 3 + accel/mshv/trace.h | 1 + include/system/mshv.h | 20 +++- meson.build | 1 + target/i386/mshv/meson.build | 1 + target/i386/mshv/mshv-cpu.c | 71 ++++++++++++ 7 files changed, 300 insertions(+), 7 deletions(-) create mode 100644 accel/mshv/trace-events create mode 100644 accel/mshv/trace.h create mode 100644 target/i386/mshv/mshv-cpu.c diff --git a/accel/mshv/mshv-all.c b/accel/mshv/mshv-all.c index 9e0590c4f9..712e651627 100644 --- a/accel/mshv/mshv-all.c +++ b/accel/mshv/mshv-all.c @@ -46,8 +46,177 @@ DECLARE_INSTANCE_CHECKER(MshvState, MSHV_STATE, TYPE_MS= HV_ACCEL) =20 bool mshv_allowed; =20 -MshvState *mshv_state; +MshvState *mshv_state =3D NULL; =20 +static int init_mshv(int *mshv_fd) +{ + int fd =3D open("/dev/mshv", O_RDWR | O_CLOEXEC); + if (fd < 0) { + error_report("Failed to open /dev/mshv: %s", strerror(errno)); + return -1; + } + *mshv_fd =3D fd; + return 0; +} + +/* freeze 1 to pause, 0 to resume */ +static int set_time_freeze(int vm_fd, int freeze) +{ + int ret; + + if (freeze !=3D 0 && freeze !=3D 1) { + error_report("Invalid time freeze value"); + return -1; + } + + struct hv_input_set_partition_property in =3D {0}; + in.property_code =3D HV_PARTITION_PROPERTY_TIME_FREEZE; + in.property_value =3D freeze; + + struct mshv_root_hvcall args =3D {0}; + args.code =3D HVCALL_SET_PARTITION_PROPERTY; + args.in_sz =3D sizeof(in); + args.in_ptr =3D (uint64_t)∈ + + ret =3D mshv_hvcall(vm_fd, &args); + if (ret < 0) { + error_report("Failed to set time freeze"); + return -1; + } + + return 0; +} + +static int pause_vm(int vm_fd) +{ + int ret; + + ret =3D set_time_freeze(vm_fd, 1); + if (ret < 0) { + error_report("Failed to pause partition: %s", strerror(errno)); + return -1; + } + + return 0; +} + +static int resume_vm(int vm_fd) +{ + int ret; + + ret =3D set_time_freeze(vm_fd, 0); + if (ret < 0) { + error_report("Failed to resume partition: %s", strerror(errno)); + return -1; + } + + return 0; +} + +static int create_partition(int mshv_fd, int *vm_fd) +{ + int ret; + struct mshv_create_partition args =3D {0}; + + /* Initialize pt_flags with the desired features */ + uint64_t pt_flags =3D (1ULL << MSHV_PT_BIT_LAPIC) | + (1ULL << MSHV_PT_BIT_X2APIC) | + (1ULL << MSHV_PT_BIT_GPA_SUPER_PAGES); + + /* Set default isolation type */ + uint64_t pt_isolation =3D MSHV_PT_ISOLATION_NONE; + + args.pt_flags =3D pt_flags; + args.pt_isolation =3D pt_isolation; + + ret =3D ioctl(mshv_fd, MSHV_CREATE_PARTITION, &args); + if (ret < 0) { + error_report("Failed to create partition: %s", strerror(errno)); + return -1; + } + + *vm_fd =3D ret; + return 0; +} + +static int set_synthetic_proc_features(int vm_fd) +{ + int ret; + struct hv_input_set_partition_property in =3D {0}; + union hv_partition_synthetic_processor_features features =3D {0}; + + /* Access the bitfield and set the desired features */ + features.hypervisor_present =3D 1; + features.hv1 =3D 1; + features.access_partition_reference_counter =3D 1; + features.access_synic_regs =3D 1; + features.access_synthetic_timer_regs =3D 1; + features.access_partition_reference_tsc =3D 1; + features.access_frequency_regs =3D 1; + features.access_intr_ctrl_regs =3D 1; + features.access_vp_index =3D 1; + features.access_hypercall_regs =3D 1; + features.tb_flush_hypercalls =3D 1; + features.synthetic_cluster_ipi =3D 1; + features.direct_synthetic_timers =3D 1; + + mshv_arch_amend_proc_features(&features); + + in.property_code =3D HV_PARTITION_PROPERTY_SYNTHETIC_PROC_FEATURES; + in.property_value =3D features.as_uint64[0]; + + struct mshv_root_hvcall args =3D {0}; + args.code =3D HVCALL_SET_PARTITION_PROPERTY; + args.in_sz =3D sizeof(in); + args.in_ptr =3D (uint64_t)∈ + + trace_mshv_hvcall_args("synthetic_proc_features", args.code, args.in_s= z); + + ret =3D mshv_hvcall(vm_fd, &args); + if (ret < 0) { + error_report("Failed to set synthethic proc features"); + return -errno; + } + return 0; +} + +static int initialize_vm(int vm_fd) +{ + int ret =3D ioctl(vm_fd, MSHV_INITIALIZE_PARTITION); + if (ret < 0) { + error_report("Failed to initialize partition: %s", strerror(errno)= ); + return -1; + } + return 0; +} + +static int create_vm(int mshv_fd, int *vm_fd) +{ + int ret =3D create_partition(mshv_fd, vm_fd); + if (ret < 0) { + return -1; + } + + ret =3D set_synthetic_proc_features(*vm_fd); + if (ret < 0) { + return -1; + } + + ret =3D initialize_vm(*vm_fd); + if (ret < 0) { + return -1; + } + + ret =3D mshv_arch_post_init_vm(*vm_fd); + if (ret < 0) { + return -1; + } + + /* Always create a frozen partition */ + pause_vm(*vm_fd); + + return 0; +} =20 static void mem_region_add(MemoryListener *listener, MemoryRegionSection *section) @@ -97,16 +266,55 @@ static void register_mshv_memory_listener(MshvState *s= , MshvMemoryListener *mml, } } =20 +int mshv_hvcall(int vm_fd, const struct mshv_root_hvcall *args) +{ + int ret =3D 0; + + ret =3D ioctl(vm_fd, MSHV_ROOT_HVCALL, args); + if (ret < 0) { + error_report("Failed to perform hvcall: %s", strerror(errno)); + return -1; + } + return ret; +} + =20 static int mshv_init(MachineState *ms) { MshvState *s; + int mshv_fd, vm_fd, ret; + + if (mshv_state) { + warn_report("MSHV accelerator already initialized"); + return 0; + } + s =3D MSHV_STATE(ms->accelerator); =20 accel_blocker_init(); =20 s->vm =3D 0; =20 + ret =3D init_mshv(&mshv_fd); + if (ret < 0) { + return -1; + } + + ret =3D create_vm(mshv_fd, &vm_fd); + if (ret < 0) { + close(mshv_fd); + return -1; + } + + ret =3D resume_vm(vm_fd); + if (ret < 0) { + close(mshv_fd); + close(vm_fd); + return -1; + } + + s->vm =3D vm_fd; + s->fd =3D mshv_fd; s->nr_as =3D 1; s->as =3D g_new0(MshvAddressSpace, s->nr_as); =20 diff --git a/accel/mshv/trace-events b/accel/mshv/trace-events new file mode 100644 index 0000000000..f99e8c5a41 --- /dev/null +++ b/accel/mshv/trace-events @@ -0,0 +1,3 @@ +# See docs/devel/tracing.rst for syntax documentation. + +mshv_hvcall_args(const char* hvcall, uint16_t code, uint16_t in_sz) "built= args for '%s' code: %d in_sz: %d" diff --git a/accel/mshv/trace.h b/accel/mshv/trace.h new file mode 100644 index 0000000000..da5b40cd24 --- /dev/null +++ b/accel/mshv/trace.h @@ -0,0 +1 @@ +#include "trace/trace-accel_mshv.h" diff --git a/include/system/mshv.h b/include/system/mshv.h index 43a22e0f48..2ac594d0aa 100644 --- a/include/system/mshv.h +++ b/include/system/mshv.h @@ -45,12 +45,13 @@ typedef struct MshvAddressSpace { } MshvAddressSpace; =20 typedef struct MshvState { - AccelState parent_obj; - int vm; - MshvMemoryListener memory_listener; - /* number of listeners */ - int nr_as; - MshvAddressSpace *as; + AccelState parent_obj; + int vm; + MshvMemoryListener memory_listener; + /* number of listeners */ + int nr_as; + MshvAddressSpace *as; + int fd; } MshvState; extern MshvState *mshv_state; =20 @@ -68,6 +69,13 @@ struct AccelCPUState { #define mshv_msi_via_irqfd_enabled() false #endif =20 +/* cpu */ +void mshv_arch_amend_proc_features( + union hv_partition_synthetic_processor_features *features); +int mshv_arch_post_init_vm(int vm_fd); + +int mshv_hvcall(int mshv_fd, const struct mshv_root_hvcall *args); + /* memory */ void mshv_set_phys_mem(MshvMemoryListener *mml, MemoryRegionSection *secti= on, bool add); diff --git a/meson.build b/meson.build index 927f3474ea..b19772d27f 100644 --- a/meson.build +++ b/meson.build @@ -3640,6 +3640,7 @@ endif if have_system trace_events_subdirs +=3D [ 'accel/kvm', + 'accel/mshv', 'audio', 'backends', 'backends/tpm', diff --git a/target/i386/mshv/meson.build b/target/i386/mshv/meson.build index 8ddaa7c11d..647e5dafb7 100644 --- a/target/i386/mshv/meson.build +++ b/target/i386/mshv/meson.build @@ -1,6 +1,7 @@ i386_mshv_ss =3D ss.source_set() =20 i386_mshv_ss.add(files( + 'mshv-cpu.c', 'x86.c', )) =20 diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c new file mode 100644 index 0000000000..c00e98dfba --- /dev/null +++ b/target/i386/mshv/mshv-cpu.c @@ -0,0 +1,71 @@ +/* + * QEMU MSHV support + * + * Copyright Microsoft, Corp. 2025 + * + * Authors: Ziqiao Zhou + * Magnus Kulke + * Jinank Jain + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/typedefs.h" + +#include "system/mshv.h" +#include "system/address-spaces.h" +#include "linux/mshv.h" +#include "hw/hyperv/hvhdk_mini.h" +#include "hw/hyperv/hvgdk.h" + + +#include "trace-accel_mshv.h" +#include "trace.h" + +void mshv_arch_amend_proc_features( + union hv_partition_synthetic_processor_features *features) +{ + features->access_guest_idle_reg =3D 1; +} + +/* + * Default Microsoft Hypervisor behavior for unimplemented MSR is to send a + * fault to the guest if it tries to access it. It is possible to override + * this behavior with a more suitable option i.e., ignore writes from the = guest + * and return zero in attempt to read unimplemented. + */ +static int set_unimplemented_msr_action(int vm_fd) +{ + struct hv_input_set_partition_property in =3D {0}; + struct mshv_root_hvcall args =3D {0}; + + in.property_code =3D HV_PARTITION_PROPERTY_UNIMPLEMENTED_MSR_ACTION; + in.property_value =3D HV_UNIMPLEMENTED_MSR_ACTION_IGNORE_WRITE_READ_ZE= RO; + + args.code =3D HVCALL_SET_PARTITION_PROPERTY; + args.in_sz =3D sizeof(in); + args.in_ptr =3D (uint64_t)∈ + + trace_mshv_hvcall_args("unimplemented_msr_action", args.code, args.in_= sz); + + int ret =3D mshv_hvcall(vm_fd, &args); + if (ret < 0) { + error_report("Failed to set unimplemented MSR action"); + return -1; + } + return 0; +} + +int mshv_arch_post_init_vm(int vm_fd) +{ + int ret; + + ret =3D set_unimplemented_msr_action(vm_fd); + if (ret < 0) { + error_report("Failed to set unimplemented MSR action"); + } + + return ret; +} --=20 2.34.1