qemu/bakcend-VirtCCA-resolve-hugepage-memory-waste-issue-.patch

321 lines
11 KiB
Diff
Raw Normal View History

QEMU update to version 8.2.0-29: - target/i386: csv: Support inject secret for CSV3 guest only if the extension is enabled - target/i386: csv: Support load kernel hashes for CSV3 guest only if the extension is enabled - target/i386: csv: Request to set private memory of CSV3 guest if the extension is enabled - target/i386: kvm: Support to get and enable extensions for Hygon CoCo guest - qapi/qom,target/i386: csv-guest: Introduce secret-header-file=str and secret-file=str options - bakcend: VirtCCA:resolve hugepage memory waste issue in vhost-user scenario - parallels: fix ext_off assertion failure due to overflow - backends/cryptodev-vhost-user: Fix local_error leaks - hw/usb/hcd-ehci: Fix debug printf format string - target/riscv/vector_helper.c: fix 'vmvr_v' memcpy endianess - target/riscv/vector_helper.c: optimize loops in ldst helpers - target/riscv/vector_helper.c: set vstart = 0 in GEN_VEXT_VSLIDEUP_VX() - target/hexagon: don't look for static glib - virtio-net: Fix network stall at the host side waiting for kick - Add if condition to avoid assertion failed error in blockdev_init - target/arm: Use float_status copy in sme_fmopa_s - target/arm: take HSTR traps of cp15 accesses to EL2, not EL1 - target/arm: Reinstate "vfp" property on AArch32 CPUs - target/i386/cpu: Fix notes for CPU models - target/arm: LDAPR should honour SCTLR_ELx.nAA - target/riscv: Avoid bad shift in riscv_cpu_do_interrupt() - hvf: remove unused but set variable - hw/misc/nrf51_rng: Don't use BIT_MASK() when we mean BIT() - Avoid taking address of out-of-bounds array index - target/arm: Fix VCMLA Dd, Dn, Dm[idx] - target/arm: Fix UMOPA/UMOPS of 16-bit values - target/arm: Fix SVE/SME gross MTE suppression checks - target/arm: Fix nregs computation in do_{ld,st}_zpa - crypto: fix error check on gcry_md_open - Change vmstate_cpuhp_sts vmstateDescription version_id - hw/pci: Remove unused pci_irq_pulse() method - hw/intc: Don't clear pending bits on IRQ lowering - target/arm: Drop user-only special case in sve_stN_r - migration: Ensure vmstate_save() sets errp - target/i386: fix hang when using slow path for ptw_setl - contrib/plugins: add compat for g_memdup2 - hw/audio/hda: fix memory leak on audio setup - crypto: perform runtime check for hash/hmac support in gcrypt - target/arm: Fix incorrect aa64_tidcp1 feature check - target/arm: fix exception syndrome for AArch32 bkpt insn - target/arm: Don't get MDCR_EL2 in pmu_counter_enabled() before checking ARM_FEATURE_PMU - linux-user: Print tid not pid with strace - target/arm: Fix A64 scalar SQSHRN and SQRSHRN - target/arm: Don't assert for 128-bit tile accesses when SVL is 128 - hw/timer/exynos4210_mct: fix possible int overflow - target/arm: Avoid shifts by -1 in tszimm_shr() and tszimm_shl() - hw/audio/virtio-snd: Always use little endian audio format - target/riscv: Fix vcompress with rvv_ta_all_1s - usb-hub: Fix handling port power control messages Signed-off-by: Jiabo Feng <fengjiabo1@huawei.com> (cherry picked from commit d4a20b24ff377fd07fcbf2b72eecaf07a3ac4cc0)
2025-02-21 15:08:43 +08:00
From da6ee14de85b4e619eedfbe3a6cac3f09d948589 Mon Sep 17 00:00:00 2001
From: nonce <2774337358@qq.com>
Date: Thu, 23 Jan 2025 21:03:10 +0800
Subject: [PATCH] bakcend: VirtCCA:resolve hugepage memory waste issue in
vhost-user scenario
VirtCCA is based on SWIOTLB to implement virtio and will only allocate
Bounce Buffer in the lower address range below 4GB. Therefore, the
backend hugepages memory allocated above 4GB will not be used, resulting
in significant waste.
New address space and memory region are added to manage the backend
hugepages memory corresponding to the GPA below 4GB, and there are
shared with the vhostuser backend.
Signed-off-by: nonce0_0 <2774337358@qq.com>
---
backends/hostmem-file.c | 85 +++++++++++++++++++++++++++++++++++
hw/core/numa.c | 20 +++++++++
hw/virtio/vhost.c | 8 +++-
include/exec/address-spaces.h | 3 ++
include/exec/cpu-common.h | 1 +
include/exec/memory.h | 11 +++++
system/physmem.c | 17 +++++++
system/vl.c | 9 ++++
8 files changed, 153 insertions(+), 1 deletion(-)
diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
index 361d4a8103..891fe4ac4a 100644
--- a/backends/hostmem-file.c
+++ b/backends/hostmem-file.c
@@ -20,9 +20,13 @@
#include "qom/object.h"
#include "qapi/visitor.h"
#include "qapi/qapi-visit-common.h"
+#include "sysemu/kvm.h"
+#include "exec/address-spaces.h"
OBJECT_DECLARE_SIMPLE_TYPE(HostMemoryBackendFile, MEMORY_BACKEND_FILE)
+bool virtcca_shared_hugepage_mapped = false;
+uint64_t virtcca_cvm_ram_size = 0;
struct HostMemoryBackendFile {
HostMemoryBackend parent_obj;
@@ -36,6 +40,83 @@ struct HostMemoryBackendFile {
OnOffAuto rom;
};
+/* Parse the path of the hugepages memory file used for memory sharing */
+static int virtcca_parse_share_mem_path(char *src, char *dst)
+{
+ int ret = 0;
+ char src_copy[PATH_MAX];
+ char *token = NULL;
+ char *last_dir = NULL;
+ char *second_last_dir = NULL;
+ static const char delimiter[] = "/";
+
+ if (src == NULL || dst == NULL ||
+ strlen(src) == 0 || strlen(src) > PATH_MAX - 1) {
+ error_report("Invalid input: NULL pointer or invalid string length.");
+ return -1;
+ }
+
+ strcpy(src_copy, src);
+ token = strtok(src_copy, delimiter);
+
+ /* Iterate over the path segments to find the second-to-last directory */
+ while (token != NULL) {
+ second_last_dir = last_dir;
+ last_dir = token;
+ token = strtok(NULL, delimiter);
+ }
+
+ /* Check if the second-to-last directory is found */
+ if (second_last_dir == NULL) {
+ error_report("Invalid path: second-to-last directory not found.");
+ return -1;
+ }
+
+ /*
+ * Construct the share memory path by appending the extracted domain name
+ * to the hugepages memory filesystem prefix
+ */
+ ret = snprintf(dst, PATH_MAX, "/dev/hugepages/libvirt/qemu/%s",
+ second_last_dir);
+
+ if (ret < 0 || ret >= PATH_MAX) {
+ error_report("Error: snprintf failed to construct the share mem path");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Create a hugepage memory region in the virtcca scenario
+ * for sharing with process like vhost-user and others.
+ */
+static void
+virtcca_shared_backend_memory_alloc(char *mem_path, uint32_t ram_flags, Error **errp)
+{
+ char dst[PATH_MAX];
+ uint64_t size = virtcca_cvm_ram_size;
+
+ if (virtcca_parse_share_mem_path(mem_path, dst)) {
+ error_report("parse virtcca share memory path failed");
+ exit(1);
+ }
+ if (virtcca_cvm_ram_size >= VIRTCCA_SHARED_HUGEPAGE_MAX_SIZE) {
+ size = VIRTCCA_SHARED_HUGEPAGE_MAX_SIZE;
+ }
+
+ virtcca_shared_hugepage = g_new(MemoryRegion, 1);
+ memory_region_init_ram_from_file(virtcca_shared_hugepage, NULL,
+ "virtcca_shared_hugepage", size,
+ VIRTCCA_SHARED_HUGEPAGE_ALIGN,
+ ram_flags, dst, 0, errp);
+ if (*errp) {
+ error_reportf_err(*errp, "cannot init RamBlock for virtcca_shared_hugepage: ");
+ exit(1);
+ }
+ virtcca_shared_hugepage_mapped = true;
+}
+
static void
file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
{
@@ -90,6 +171,10 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
backend->size, fb->align, ram_flags,
fb->mem_path, fb->offset, errp);
g_free(name);
+
+ if (virtcca_cvm_enabled() && backend->share && !virtcca_shared_hugepage_mapped) {
+ virtcca_shared_backend_memory_alloc(fb->mem_path, ram_flags, errp);
+ }
#endif
}
diff --git a/hw/core/numa.c b/hw/core/numa.c
index f08956ddb0..e7c48dab61 100644
--- a/hw/core/numa.c
+++ b/hw/core/numa.c
@@ -42,6 +42,8 @@
#include "qemu/option.h"
#include "qemu/config-file.h"
#include "qemu/cutils.h"
+#include "exec/address-spaces.h"
+#include "sysemu/kvm.h"
QemuOptsList qemu_numa_opts = {
.name = "numa",
@@ -641,6 +643,21 @@ static void numa_init_memdev_container(MachineState *ms, MemoryRegion *ram)
}
}
+/*
+ * Add virtcca_shared_hugepage as a sub-MR to the root MR of address space
+ * address_space_memory and address_space_virtcca_shared_memory.
+ */
+static void virtcca_shared_memory_configuration(MachineState *ms)
+{
+ MemoryRegion *alias_mr = g_new(MemoryRegion, 1);
+
+ memory_region_add_subregion_overlap(ms->ram, 0, virtcca_shared_hugepage, 1);
+ memory_region_init_alias(alias_mr, NULL, "alias-mr", virtcca_shared_hugepage,
+ 0, int128_get64(virtcca_shared_hugepage->size));
+ memory_region_add_subregion(address_space_virtcca_shared_memory.root,
+ VIRTCCA_GPA_START, alias_mr);
+}
+
void numa_complete_configuration(MachineState *ms)
{
int i;
@@ -711,6 +728,9 @@ void numa_complete_configuration(MachineState *ms)
memory_region_init(ms->ram, OBJECT(ms), mc->default_ram_id,
ms->ram_size);
numa_init_memdev_container(ms, ms->ram);
+ if (virtcca_cvm_enabled() && virtcca_shared_hugepage->ram_block) {
+ virtcca_shared_memory_configuration(ms);
+ }
}
/* QEMU needs at least all unique node pair distances to build
* the whole NUMA distance table. QEMU treats the distance table
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index d29075aa04..8b95558013 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -30,6 +30,7 @@
#include "sysemu/dma.h"
#include "trace.h"
#include "qapi/qapi-commands-migration.h"
+#include "sysemu/kvm.h"
/* enabled until disconnected backend stabilizes */
#define _VHOST_DEBUG 1
@@ -1616,7 +1617,12 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
hdev->log_size = 0;
hdev->log_enabled = false;
hdev->started = false;
- memory_listener_register(&hdev->memory_listener, &address_space_memory);
+ if (virtcca_cvm_enabled()) {
+ memory_listener_register(&hdev->memory_listener,
+ &address_space_virtcca_shared_memory);
+ } else {
+ memory_listener_register(&hdev->memory_listener, &address_space_memory);
+ }
QLIST_INSERT_HEAD(&vhost_devices, hdev, entry);
/*
diff --git a/include/exec/address-spaces.h b/include/exec/address-spaces.h
index 0d0aa61d68..4518b5da86 100644
--- a/include/exec/address-spaces.h
+++ b/include/exec/address-spaces.h
@@ -33,6 +33,9 @@ MemoryRegion *get_system_io(void);
extern AddressSpace address_space_memory;
extern AddressSpace address_space_io;
+extern AddressSpace address_space_virtcca_shared_memory;
+
+extern MemoryRegion *virtcca_shared_hugepage;
#endif
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index c7fd30d5b9..d21d9990ad 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -28,6 +28,7 @@ typedef uint64_t vaddr;
void cpu_exec_init_all(void);
void cpu_exec_step_atomic(CPUState *cpu);
+void virtcca_shared_memory_address_space_init(void);
/* Using intptr_t ensures that qemu_*_page_mask is sign-extended even
* when intptr_t is 32-bit and we are aligning a long long.
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 542c9da918..33778f5c64 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -243,6 +243,17 @@ typedef struct IOMMUTLBEvent {
/* RAM FD is opened read-only */
#define RAM_READONLY_FD (1 << 11)
+/* The GPA range of the VirtCCA bounce buffer is from 1GB to 4GB. */
+#define VIRTCCA_SHARED_HUGEPAGE_MAX_SIZE 0xc0000000ULL
+
+/* The VirtCCA shared hugepage memory granularity is 1GB */
+#define VIRTCCA_SHARED_HUGEPAGE_ALIGN 0x40000000ULL
+
+/* The GPA starting address of the VirtCCA CVM is 1GB */
+#define VIRTCCA_GPA_START 0x40000000ULL
+
+extern uint64_t virtcca_cvm_ram_size;
+
static inline void iommu_notifier_init(IOMMUNotifier *n, IOMMUNotify fn,
IOMMUNotifierFlag flags,
hwaddr start, hwaddr end,
diff --git a/system/physmem.c b/system/physmem.c
index 250f315bc8..8f4be2d131 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -89,9 +89,17 @@ RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list.blocks) };
static MemoryRegion *system_memory;
static MemoryRegion *system_io;
+static MemoryRegion *virtcca_shared_memory;
+
+/*
+ * Serves as the sub-MR of the root MR (virtcca_shared_memory)
+ * and is associated with the RAMBlock.
+ */
+MemoryRegion *virtcca_shared_hugepage;
AddressSpace address_space_io;
AddressSpace address_space_memory;
+AddressSpace address_space_virtcca_shared_memory;
static MemoryRegion io_mem_unassigned;
@@ -2586,6 +2594,15 @@ static void memory_map_init(void)
address_space_init(&address_space_io, system_io, "I/O");
}
+void virtcca_shared_memory_address_space_init(void)
+{
+ virtcca_shared_memory = g_malloc(sizeof(*virtcca_shared_memory));
+ memory_region_init(virtcca_shared_memory, NULL,
+ "virtcca_shared_memory", UINT64_MAX);
+ address_space_init(&address_space_virtcca_shared_memory,
+ virtcca_shared_memory, "virtcca_shared_memory");
+}
+
MemoryRegion *get_system_memory(void)
{
return system_memory;
diff --git a/system/vl.c b/system/vl.c
index a1e5e68773..7c10cd1337 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -3784,6 +3784,15 @@ void qemu_init(int argc, char **argv)
configure_accelerators(argv[0]);
phase_advance(PHASE_ACCEL_CREATED);
+ /*
+ * Must run after kvm_init completes, as virtcca_cvm_enabled()
+ * depends on initialization performed in kvm_init.
+ */
+ if (virtcca_cvm_enabled()) {
+ virtcca_cvm_ram_size = current_machine->ram_size;
+ virtcca_shared_memory_address_space_init();
+ }
+
/*
* Beware, QOM objects created before this point miss global and
* compat properties.
--
2.41.0.windows.1