From nobody Tue Feb 10 02:43:39 2026 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=1751391038; cv=none; d=zohomail.com; s=zohoarc; b=PYNBaCHwQsa3SejonICcd+0PMdtjc6J4OyZpCgy6T9T5byBBpLmocMzJMgqGjX1gwfgj122ogGntKpswM4CX9USV6Pe1Ol7Gu/6AMpWgQRwEBdb6NnIo2tTTR2966g9KU1OyFR2XP3HNggQVr2l1O2HgOkvIzNAh6MmzteICx8M= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751391038; 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=zf2TV5FOzkuzCPJD7r+iNLBabEyrEw/LvBzD8827WT8=; b=jalWktTa3VbFq7Q75/GaoxEnDGUT/LCgYh2VV6FDL8TrMDHy/B3PA332j5XlTuX3Dxr8leYw6oInzyUq5g9kr6HeKMFas8nkSP4L8GLTAnwdmhPk06Zz5fYp6yneqzx8xoaS8gnMI40SFuwMlh1UBBwkgci/VysBVqEz8vqSjMk= 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 17513910388450.5768415113944911; Tue, 1 Jul 2025 10:30:38 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWenl-0003ww-1I; Tue, 01 Jul 2025 13:29:49 -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 1uWeni-0003iM-Ii for qemu-devel@nongnu.org; Tue, 01 Jul 2025 13:29:46 -0400 Received: from linux.microsoft.com ([13.77.154.182]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWenc-0006jf-7a for qemu-devel@nongnu.org; Tue, 01 Jul 2025 13:29:46 -0400 Received: from localhost.localdomain (unknown [167.220.208.67]) by linux.microsoft.com (Postfix) with ESMTPSA id 4C1632112234; Tue, 1 Jul 2025 10:29:35 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 4C1632112234 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1751390979; bh=zf2TV5FOzkuzCPJD7r+iNLBabEyrEw/LvBzD8827WT8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=J3a4DYeIan81StTRhJu3Bx+xoCIwt0Wb62hrTRbgALSL7GG+4FU79Sm4uqCdPHHXj Cd4ZtK+PoicjR7JmkMHrG+Xw/8qJYI3vmJH7EWgrDI4L1sQzrTcVxpgAuSmGnRcYgH gvrJyLzPa1UP+exyq/vKF3MhB/eEMmnzk6KXI4ac= 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 09/27] accel/mshv: Register guest memory regions with hypervisor Date: Tue, 1 Jul 2025 19:28:16 +0200 Message-Id: <20250701172834.44849-10-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: 1751391039954116600 Content-Type: text/plain; charset="utf-8" Handle region_add events by invoking the MSHV memory registration ioctl to map guest memory into the hypervisor partition. This allows the guest to access memory through MSHV-managed mappings. Note that this assumes the hypervisor will accept regions that overlap in userspace_addr. Currently that's not the case, it will be addressed in a later commit in the series. Signed-off-by: Magnus Kulke --- accel/mshv/mem.c | 127 +++++++++++++++++++++++++++++++++++++++- accel/mshv/trace-events | 16 +++++ include/system/mshv.h | 11 ++++ 3 files changed, 151 insertions(+), 3 deletions(-) diff --git a/accel/mshv/mem.c b/accel/mshv/mem.c index eddd83ae83..f51e9fee8e 100644 --- a/accel/mshv/mem.c +++ b/accel/mshv/mem.c @@ -13,13 +13,134 @@ =20 #include "qemu/osdep.h" #include "qemu/error-report.h" +#include "linux/mshv.h" #include "system/address-spaces.h" #include "system/mshv.h" +#include "exec/memattrs.h" +#include +#include "trace.h" + +static int set_guest_memory(int vm_fd, const mshv_user_mem_region *region) +{ + int ret; + + ret =3D ioctl(vm_fd, MSHV_SET_GUEST_MEMORY, region); + if (ret < 0) { + error_report("failed to set guest memory"); + return -errno; + } + + return 0; +} + +static int map_or_unmap(int vm_fd, const MshvMemoryRegion *mr, bool map) +{ + struct mshv_user_mem_region region =3D {0}; + + region.guest_pfn =3D mr->guest_phys_addr >> MSHV_PAGE_SHIFT; + region.size =3D mr->memory_size; + region.userspace_addr =3D mr->userspace_addr; + + if (!map) { + region.flags |=3D (1 << MSHV_SET_MEM_BIT_UNMAP); + trace_mshv_unmap_memory(mr->userspace_addr, mr->guest_phys_addr, + mr->memory_size); + return set_guest_memory(vm_fd, ®ion); + } + + region.flags =3D BIT(MSHV_SET_MEM_BIT_EXECUTABLE); + if (!mr->readonly) { + region.flags |=3D BIT(MSHV_SET_MEM_BIT_WRITABLE); + } + + trace_mshv_map_memory(mr->userspace_addr, mr->guest_phys_addr, + mr->memory_size); + return set_guest_memory(vm_fd, ®ion); +} + +static int set_memory(const MshvMemoryRegion *mshv_mr, bool add) +{ + int ret =3D 0; + + if (!mshv_mr) { + error_report("Invalid mshv_mr"); + return -1; + } + + trace_mshv_set_memory(add, mshv_mr->guest_phys_addr, + mshv_mr->memory_size, + mshv_mr->userspace_addr, mshv_mr->readonly, + ret); + return map_or_unmap(mshv_state->vm, mshv_mr, add); +} + +/* + * Calculate and align the start address and the size of the section. + * Return the size. If the size is 0, the aligned section is empty. + */ +static hwaddr align_section(MemoryRegionSection *section, hwaddr *start) +{ + hwaddr size =3D int128_get64(section->size); + hwaddr delta, aligned; + + /* + * works in page size chunks, but the function may be called + * with sub-page size and unaligned start address. Pad the start + * address to next and truncate size to previous page boundary. + */ + aligned =3D ROUND_UP(section->offset_within_address_space, + qemu_real_host_page_size()); + delta =3D aligned - section->offset_within_address_space; + *start =3D aligned; + if (delta > size) { + return 0; + } + + return (size - delta) & qemu_real_host_page_mask(); +} =20 void mshv_set_phys_mem(MshvMemoryListener *mml, MemoryRegionSection *secti= on, bool add) { - error_report("unimplemented"); - abort(); -} + int ret =3D 0; + MemoryRegion *area =3D section->mr; + bool writable =3D !area->readonly && !area->rom_device; + hwaddr start_addr, mr_offset, size; + void *ram; + MshvMemoryRegion mshv_mr =3D {0}; + + trace_mshv_set_phys_mem(add, section->mr->name); + + /* If the memory device is a writable non-ram area, we do not + * want to map it into the guest memory. If it is not a ROM device, + * we want to remove mshv memory mapping, so accesses will trap. + */ + if (!memory_region_is_ram(area)) { + if (writable) { + return; + } else if (!area->romd_mode) { + add =3D false; + } + } + + size =3D align_section(section, &start_addr); + if (!size) { + return; + } =20 + mr_offset =3D section->offset_within_region + start_addr - + section->offset_within_address_space; + + ram =3D memory_region_get_ram_ptr(area) + mr_offset; + + mshv_mr.guest_phys_addr =3D start_addr; + mshv_mr.memory_size =3D size; + mshv_mr.readonly =3D !writable; + mshv_mr.userspace_addr =3D (uint64_t)ram; + + ret =3D set_memory(&mshv_mr, add); + if (ret < 0) { + error_report("Failed to set memory region"); + abort(); + } +} diff --git a/accel/mshv/trace-events b/accel/mshv/trace-events index f99e8c5a41..9a3af6b8be 100644 --- a/accel/mshv/trace-events +++ b/accel/mshv/trace-events @@ -1,3 +1,19 @@ # See docs/devel/tracing.rst for syntax documentation. =20 +mshv_set_memory(bool add, uint64_t gpa, uint64_t size, uint64_t user_addr,= bool readonly, int ret) "[add =3D %d] gpa =3D %lx size =3D %lx user =3D %l= x readonly =3D %d result =3D %d" mshv_hvcall_args(const char* hvcall, uint16_t code, uint16_t in_sz) "built= args for '%s' code: %d in_sz: %d" + +mshv_set_msi_routing(uint32_t gsi, uint64_t addr, uint32_t data) "gsi=3D%d= addr=3D%lx data=3D%x" +mshv_remove_msi_routing(uint32_t gsi) "gsi=3D%d" +mshv_add_msi_routing(uint64_t addr, uint32_t data) "addr=3D%lx data=3D%x" +mshv_commit_msi_routing_table(int vm_fd, int len) "vm_fd=3D%d table_size= =3D%d" +mshv_register_irqfd(int vm_fd, int event_fd, uint32_t gsi) "vm_fd=3D%d eve= nt_fd=3D%d gsi=3D%d" +mshv_irqchip_update_irqfd_notifier_gsi(int event_fd, int resample_fd, int = virq, bool add) "event_fd=3D%d resample_fd=3D%d virq=3D%d add=3D%d" + +mshv_insn_fetch(uint64_t addr, size_t size) "gpa=3D%lx size=3D%lu" +mshv_mem_write(uint64_t addr, size_t size) "\tgpa=3D%lx size=3D%lu" +mshv_mem_read(uint64_t addr, size_t size) "\tgpa=3D%lx size=3D%lu" +mshv_map_memory(uint64_t userspace_addr, uint64_t gpa, uint64_t size) "\tu= _a=3D%lx gpa=3D%010lx size=3D%08lx" +mshv_unmap_memory(uint64_t userspace_addr, uint64_t gpa, uint64_t size) "\= tu_a=3D%lx gpa=3D%010lx size=3D%08lx" +mshv_set_phys_mem(bool add, const char *name) "\tadd=3D%d name=3D%s" +mshv_handle_mmio(uint64_t gva, uint64_t gpa, uint64_t size, uint8_t access= _type) "\tgva=3D%lx gpa=3D%010lx size=3D%lx access_type=3D%d" diff --git a/include/system/mshv.h b/include/system/mshv.h index 2ac594d0aa..3624d9477f 100644 --- a/include/system/mshv.h +++ b/include/system/mshv.h @@ -30,6 +30,8 @@ #define CONFIG_MSHV_IS_POSSIBLE #endif =20 +#define MSHV_PAGE_SHIFT 12 + #ifdef CONFIG_MSHV_IS_POSSIBLE extern bool mshv_allowed; #define mshv_enabled() (mshv_allowed) @@ -77,6 +79,15 @@ int mshv_arch_post_init_vm(int vm_fd); int mshv_hvcall(int mshv_fd, const struct mshv_root_hvcall *args); =20 /* memory */ +typedef struct MshvMemoryRegion { + uint64_t guest_phys_addr; + uint64_t memory_size; + uint64_t userspace_addr; + bool readonly; +} MshvMemoryRegion; + +int mshv_add_mem(int vm_fd, const MshvMemoryRegion *mr); +int mshv_remove_mem(int vm_fd, const MshvMemoryRegion *mr); void mshv_set_phys_mem(MshvMemoryListener *mml, MemoryRegionSection *secti= on, bool add); =20 --=20 2.34.1