From 9eacd1a6df6861b76663e98133adb15059bf65cc Mon Sep 17 00:00:00 2001 From: gongchangsui Date: Mon, 17 Mar 2025 02:40:50 -0400 Subject: [PATCH 1/6] arm: VirtCCA: CVM support UEFI boot 1. Add UEFI boot support for Confidential VMs. 2. Modify the base memory address of Confidential VMs from 3GB to 1GB. 3. Disable pflash boot support for Confidential VMs; use the`-bios`option to specify`QEMU_EFI.fd`during launch. Signed-off-by: gongchangsui --- hw/arm/boot.c | 38 ++++++++++++++++++++++++++++++++++++-- hw/arm/virt.c | 33 ++++++++++++++++++++++++++++++++- include/hw/arm/boot.h | 3 +++ 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 42110b0f18..6b2f46af4d 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -43,6 +43,9 @@ #define BOOTLOADER_MAX_SIZE (4 * KiB) +#define UEFI_MAX_SIZE 0x8000000 +#define UEFI_LOADER_START 0x0 +#define DTB_MAX 0x200000 AddressSpace *arm_boot_address_space(ARMCPU *cpu, const struct arm_boot_info *info) { @@ -1155,7 +1158,31 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu, } } -static void arm_setup_firmware_boot(ARMCPU *cpu, struct arm_boot_info *info) +static void arm_setup_confidential_firmware_boot(ARMCPU *cpu, + struct arm_boot_info *info, + const char *firmware_filename) +{ + ssize_t fw_size; + const char *fname; + AddressSpace *as = arm_boot_address_space(cpu, info); + + fname = qemu_find_file(QEMU_FILE_TYPE_BIOS, firmware_filename); + if (!fname) { + error_report("Could not find firmware image '%s'", firmware_filename); + exit(EXIT_FAILURE); + } + + fw_size = load_image_targphys_as(firmware_filename, + info->firmware_base, + info->firmware_max_size, as); + + if (fw_size <= 0) { + error_report("could not load firmware '%s'", firmware_filename); + exit(EXIT_FAILURE); + } +} + +static void arm_setup_firmware_boot(ARMCPU *cpu, struct arm_boot_info *info, const char *firmware_filename) { /* Set up for booting firmware (which might load a kernel via fw_cfg) */ @@ -1166,6 +1193,8 @@ static void arm_setup_firmware_boot(ARMCPU *cpu, struct arm_boot_info *info) * DTB to the base of RAM for the bootloader to pick up. */ info->dtb_start = info->loader_start; + if (info->confidential) + tmm_add_ram_region(UEFI_LOADER_START, UEFI_MAX_SIZE, info->dtb_start, DTB_MAX , true); } if (info->kernel_filename) { @@ -1206,6 +1235,11 @@ static void arm_setup_firmware_boot(ARMCPU *cpu, struct arm_boot_info *info) } } + if (info->confidential) { + arm_setup_confidential_firmware_boot(cpu, info, firmware_filename); + kvm_load_user_data(UEFI_LOADER_START, UEFI_MAX_SIZE, info->loader_start, info->loader_start + DTB_MAX, info->ram_size, + (struct kvm_numa_info *)info->numa_info); + } /* * We will start from address 0 (typically a boot ROM image) in the * same way as hardware. Leave env->boot_info NULL, so that @@ -1282,7 +1316,7 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info) /* Load the kernel. */ if (!info->kernel_filename || info->firmware_loaded) { - arm_setup_firmware_boot(cpu, info); + arm_setup_firmware_boot(cpu, info, ms->firmware); } else { arm_setup_direct_kernel_boot(cpu, info); } diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 8823f2ed1c..6ffb26e7e6 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1398,6 +1398,9 @@ static void virt_flash_map1(PFlashCFI01 *flash, qdev_prop_set_uint32(dev, "num-blocks", size / VIRT_FLASH_SECTOR_SIZE); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + if (virtcca_cvm_enabled()) { + return; + } memory_region_add_subregion(sysmem, base, sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0)); @@ -1433,6 +1436,10 @@ static void virt_flash_fdt(VirtMachineState *vms, MachineState *ms = MACHINE(vms); char *nodename; + if (virtcca_cvm_enabled()) { + return; + } + if (sysmem == secure_sysmem) { /* Report both flash devices as a single node in the DT */ nodename = g_strdup_printf("/flash@%" PRIx64, flashbase); @@ -1468,6 +1475,23 @@ static void virt_flash_fdt(VirtMachineState *vms, } } +static bool virt_confidential_firmware_init(VirtMachineState *vms, + MemoryRegion *sysmem) +{ + MemoryRegion *fw_ram; + hwaddr fw_base = vms->memmap[VIRT_FLASH].base; + hwaddr fw_size = vms->memmap[VIRT_FLASH].size; + + if (!MACHINE(vms)->firmware) { + return false; + } + + fw_ram = g_new(MemoryRegion, 1); + memory_region_init_ram(fw_ram, NULL, "fw_ram", fw_size, NULL); + memory_region_add_subregion(sysmem, fw_base, fw_ram); + return true; +} + static bool virt_firmware_init(VirtMachineState *vms, MemoryRegion *sysmem, MemoryRegion *secure_sysmem) @@ -1486,6 +1510,10 @@ static bool virt_firmware_init(VirtMachineState *vms, pflash_blk0 = pflash_cfi01_get_blk(vms->flash[0]); + if (virtcca_cvm_enabled()) { + return virt_confidential_firmware_init(vms, sysmem); + } + bios_name = MACHINE(vms)->firmware; if (bios_name) { char *fname; @@ -2023,7 +2051,7 @@ static void virt_set_memmap(VirtMachineState *vms, int pa_bits) vms->memmap[VIRT_PCIE_MMIO] = (MemMapEntry) { 0x10000000, 0x2edf0000 }; vms->memmap[VIRT_KAE_DEVICE] = (MemMapEntry) { 0x3edf0000, 0x00200000 }; - vms->memmap[VIRT_MEM].base = 3 * GiB; + vms->memmap[VIRT_MEM].base = 1 * GiB; vms->memmap[VIRT_MEM].size = ms->ram_size; info_report("[qemu] fix VIRT_MEM range 0x%llx - 0x%llx\n", (unsigned long long)(vms->memmap[VIRT_MEM].base), (unsigned long long)(vms->memmap[VIRT_MEM].base + ms->ram_size)); @@ -2822,6 +2850,9 @@ static void machvirt_init(MachineState *machine) vms->bootinfo.get_dtb = machvirt_dtb; vms->bootinfo.skip_dtb_autoload = true; vms->bootinfo.firmware_loaded = firmware_loaded; + vms->bootinfo.firmware_base = vms->memmap[VIRT_FLASH].base; + vms->bootinfo.firmware_max_size = vms->memmap[VIRT_FLASH].size; + vms->bootinfo.confidential = virtcca_cvm_enabled(); vms->bootinfo.psci_conduit = vms->psci_conduit; arm_load_kernel(ARM_CPU(first_cpu), machine, &vms->bootinfo); diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h index 4491b1f85b..06ca1d90b2 100644 --- a/include/hw/arm/boot.h +++ b/include/hw/arm/boot.h @@ -133,6 +133,9 @@ struct arm_boot_info { bool secure_board_setup; arm_endianness endianness; + hwaddr firmware_base; + hwaddr firmware_max_size; + bool confidential; }; /** -- Gitee From 5bffeb311c969a0e05106e4bf54282431c5ba907 Mon Sep 17 00:00:00 2001 From: gongchangsui Date: Mon, 17 Mar 2025 02:42:43 -0400 Subject: [PATCH 2/6] arm: VirtCCA: qemu uefi boot support kae This commit introduces modifications to enable KAE functionality during UEFI boot in cVMs. Additionally,the ACPI feature must be configured in cVM. Signed-off-by: gongchangsui --- hw/arm/virt-acpi-build.c | 58 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 076781423b..f78331d69f 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -58,6 +58,7 @@ #include "migration/vmstate.h" #include "hw/acpi/ghes.h" #include "hw/acpi/viot.h" +#include "kvm_arm.h" #define ARM_SPI_BASE 32 @@ -405,6 +406,54 @@ static void acpi_dsdt_add_virtio(Aml *scope, } } +static void acpi_dsdt_add_hisi_sec(Aml *scope, + const MemMapEntry *virtio_mmio_memmap, + int dev_id) +{ + hwaddr size = 0x10000; + + /* + * Calculate the base address for the sec device node. + * Each device group contains one sec device and one hpre device,spaced by 2 * size. + */ + hwaddr base = virtio_mmio_memmap->base + dev_id * 2 * size; + + Aml *dev = aml_device("SE%02u", dev_id); + aml_append(dev, aml_name_decl("_HID", aml_string("SEC07"))); + aml_append(dev, aml_name_decl("_UID", aml_int(dev_id))); + aml_append(dev, aml_name_decl("_CCA", aml_int(1))); + + Aml *crs = aml_resource_template(); + + aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE)); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); +} + +static void acpi_dsdt_add_hisi_hpre(Aml *scope, + const MemMapEntry *virtio_mmio_memmap, + int dev_id) +{ + hwaddr size = 0x10000; + + /* + * Calculate the base address for the hpre device node. + * Each hpre device follows the corresponding sec device by an additional offset of size. + */ + hwaddr base = virtio_mmio_memmap->base + dev_id * 2 * size + size; + + Aml *dev = aml_device("HP%02u", dev_id); + aml_append(dev, aml_name_decl("_HID", aml_string("HPRE07"))); + aml_append(dev, aml_name_decl("_UID", aml_int(dev_id))); + aml_append(dev, aml_name_decl("_CCA", aml_int(1))); + + Aml *crs = aml_resource_template(); + + aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE)); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); +} + static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, uint32_t irq, VirtMachineState *vms) { @@ -1201,6 +1250,15 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO], (irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS); acpi_dsdt_add_pci(scope, memmap, irqmap[VIRT_PCIE] + ARM_SPI_BASE, vms); + + if (virtcca_cvm_enabled()) { + int kae_num = tmm_get_kae_num(); + for (int i = 0; i < kae_num; i++) { + acpi_dsdt_add_hisi_sec(scope, &memmap[VIRT_KAE_DEVICE], i); + acpi_dsdt_add_hisi_hpre(scope, &memmap[VIRT_KAE_DEVICE], i); + } + } + if (vms->acpi_dev) { build_ged_aml(scope, "\\_SB."GED_DEVICE, HOTPLUG_HANDLER(vms->acpi_dev), -- Gitee From 5ed17a43a4cc7fc76397d6d8cad8246063b5b2f3 Mon Sep 17 00:00:00 2001 From: gongchangsui Date: Mon, 17 Mar 2025 02:43:55 -0400 Subject: [PATCH 3/6] arm: VirtCCA: Compatibility with older versions of TMM and the kernel Since the base memory address of Confidential VMs in QEMU was changed from 3GB to 1GB, corresponding adjustments are required in both the TMM and kernel components. To maintain backward compatibility, the following modifications were implemented: 1. **TMM Versioning**: The TMM version number was incremented to reflect the update 2. **Kernel Interface**: A new interface was exposed in the kernel to retrieve the TMM version number. 3. **QEMU Compatibility Logic**: During initialization, QEMU checks the TMM version via the kernel interface. If the TMM version is**<2.1**(legacy), QEMU sets the Confidential VM's base memory address to**3GB**. For TMM versions **2.1**(updated), the address is configured to**1GB**to align with the new memory layout This approach ensures seamless backward compatibility while transitioning to the revised memory addressing scheme. Signed-off-by: gongchangsui --- accel/kvm/kvm-all.c | 3 +-- hw/arm/boot.c | 9 +++++++++ hw/arm/virt.c | 9 +++++++-- linux-headers/asm-arm64/kvm.h | 2 ++ linux-headers/linux/kvm.h | 3 +++ 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index a8e29f148e..38a48cc031 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -2390,6 +2390,7 @@ static int kvm_init(MachineState *ms) qemu_mutex_init(&kml_slots_lock); s = KVM_STATE(ms->accelerator); + kvm_state = s; /* * On systems where the kernel can support different base page @@ -2609,8 +2610,6 @@ static int kvm_init(MachineState *ms) #endif } - kvm_state = s; - ret = kvm_arch_init(ms, s); if (ret < 0) { goto err; diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 6b2f46af4d..ca9f69fd3d 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -1162,6 +1162,15 @@ static void arm_setup_confidential_firmware_boot(ARMCPU *cpu, struct arm_boot_info *info, const char *firmware_filename) { + uint64_t tmi_version = 0; + if (kvm_ioctl(kvm_state, KVM_GET_TMI_VERSION, &tmi_version) < 0) { + error_report("please check the kernel version!"); + exit(EXIT_FAILURE); + } + if (tmi_version < MIN_TMI_VERSION_FOR_UEFI_BOOTED_CVM) { + error_report("please check the tmi version!"); + exit(EXIT_FAILURE); + } ssize_t fw_size; const char *fname; AddressSpace *as = arm_boot_address_space(cpu, info); diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 6ffb26e7e6..39dfec0877 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -2050,8 +2050,13 @@ static void virt_set_memmap(VirtMachineState *vms, int pa_bits) /* support kae vf device tree nodes */ vms->memmap[VIRT_PCIE_MMIO] = (MemMapEntry) { 0x10000000, 0x2edf0000 }; vms->memmap[VIRT_KAE_DEVICE] = (MemMapEntry) { 0x3edf0000, 0x00200000 }; - - vms->memmap[VIRT_MEM].base = 1 * GiB; + uint64_t tmi_version = 0; + if (kvm_ioctl(kvm_state, KVM_GET_TMI_VERSION, &tmi_version) < 0) { + warn_report("can not get tmi version"); + } + if (tmi_version < MIN_TMI_VERSION_FOR_UEFI_BOOTED_CVM) { + vms->memmap[VIRT_MEM].base = 3 * GiB; + } vms->memmap[VIRT_MEM].size = ms->ram_size; info_report("[qemu] fix VIRT_MEM range 0x%llx - 0x%llx\n", (unsigned long long)(vms->memmap[VIRT_MEM].base), (unsigned long long)(vms->memmap[VIRT_MEM].base + ms->ram_size)); diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h index 552fdcb18f..d69a71cbec 100644 --- a/linux-headers/asm-arm64/kvm.h +++ b/linux-headers/asm-arm64/kvm.h @@ -597,4 +597,6 @@ struct kvm_cap_arm_tmm_populate_region_args { #endif +#define MIN_TMI_VERSION_FOR_UEFI_BOOTED_CVM 0x20001 + #endif /* __ARM_KVM_H__ */ diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 84cec64b88..7a08f9b1e9 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -2422,4 +2422,7 @@ struct kvm_s390_zpci_op { /* flags for kvm_s390_zpci_op->u.reg_aen.flags */ #define KVM_S390_ZPCIOP_REGAEN_HOST (1 << 0) +/* get tmi version */ +#define KVM_GET_TMI_VERSION _IOR(KVMIO, 0xd2, uint64_t) + #endif /* __LINUX_KVM_H */ -- Gitee From 0119389040e4d78c6238875b812827d4f07b5f0f Mon Sep 17 00:00:00 2001 From: gongchangsui Date: Mon, 17 Mar 2025 02:51:16 -0400 Subject: [PATCH 4/6] arm: VirtCCA: qemu CoDA support UEFI boot 1. Expose PCIe MMIO region from QEMU memory map. 2. Refactor struct kvm_user_data data_start and data_size represent the address base and size of the MMIO in UEFI boot modedata_start and data_size represent the address base and size of the DTB in direct boot mode. Signed-off-by: gongchangsui --- accel/kvm/kvm-all.c | 8 ++++---- hw/arm/boot.c | 10 ++++++---- hw/arm/virt.c | 6 ++++++ linux-headers/linux/kvm.h | 12 +++++++++--- target/arm/kvm_arm.h | 2 ++ 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 38a48cc031..57c6718b77 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -3527,7 +3527,7 @@ int kvm_get_one_reg(CPUState *cs, uint64_t id, void *target) return r; } -int kvm_load_user_data(hwaddr loader_start, hwaddr image_end, hwaddr initrd_start, hwaddr dtb_end, hwaddr ram_size, +int kvm_load_user_data(hwaddr loader_start, hwaddr dtb_info, hwaddr data_start, hwaddr data_size, hwaddr ram_size, struct kvm_numa_info *numa_info) { KVMState *state = kvm_state; @@ -3535,9 +3535,9 @@ int kvm_load_user_data(hwaddr loader_start, hwaddr image_end, hwaddr initrd_star int ret; data.loader_start = loader_start; - data.image_end = image_end; - data.initrd_start = initrd_start; - data.dtb_end = dtb_end; + data.dtb_info = dtb_info; + data.data_start = data_start; + data.data_size = data_size; data.ram_size = ram_size; memcpy(&data.numa_info, numa_info, sizeof(struct kvm_numa_info)); diff --git a/hw/arm/boot.c b/hw/arm/boot.c index ca9f69fd3d..a3e0dbb68c 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -1149,10 +1149,10 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu, if (kvm_enabled() && virtcca_cvm_enabled()) { if (info->dtb_limit == 0) { - info->dtb_limit = info->dtb_start + 0x200000; + info->dtb_limit = info->dtb_start + DTB_MAX; } - kvm_load_user_data(info->loader_start, image_high_addr, info->initrd_start, - info->dtb_limit, info->ram_size, (struct kvm_numa_info *)info->numa_info); + kvm_load_user_data(info->loader_start, 0x1, info->dtb_start, + info->dtb_limit - info->dtb_start, info->ram_size, (struct kvm_numa_info *)info->numa_info); tmm_add_ram_region(info->loader_start, image_high_addr - info->loader_start, info->initrd_start, info->dtb_limit - info->initrd_start, true); } @@ -1193,6 +1193,7 @@ static void arm_setup_confidential_firmware_boot(ARMCPU *cpu, static void arm_setup_firmware_boot(ARMCPU *cpu, struct arm_boot_info *info, const char *firmware_filename) { + hwaddr mmio_start, mmio_size; /* Set up for booting firmware (which might load a kernel via fw_cfg) */ if (have_dtb(info)) { @@ -1246,7 +1247,8 @@ static void arm_setup_firmware_boot(ARMCPU *cpu, struct arm_boot_info *info, con if (info->confidential) { arm_setup_confidential_firmware_boot(cpu, info, firmware_filename); - kvm_load_user_data(UEFI_LOADER_START, UEFI_MAX_SIZE, info->loader_start, info->loader_start + DTB_MAX, info->ram_size, + virtcca_kvm_get_mmio_addr(&mmio_start, &mmio_size); + kvm_load_user_data(info->loader_start, DTB_MAX, mmio_start, mmio_size, info->ram_size, (struct kvm_numa_info *)info->numa_info); } /* diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 39dfec0877..6c5611826c 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -176,6 +176,12 @@ static const MemMapEntry base_memmap[] = { [VIRT_MEM] = { GiB, LEGACY_RAMLIMIT_BYTES }, }; +void virtcca_kvm_get_mmio_addr(hwaddr *mmio_start, hwaddr *mmio_size) +{ + *mmio_start = base_memmap[VIRT_PCIE_MMIO].base; + *mmio_size = base_memmap[VIRT_PCIE_MMIO].size; +} + /* * Highmem IO Regions: This memory map is floating, located after the RAM. * Each MemMapEntry base (GPA) will be dynamically computed, depending on the diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 7a08f9b1e9..c9ec7f862a 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -1510,9 +1510,15 @@ struct kvm_numa_info { struct kvm_user_data { __u64 loader_start; - __u64 image_end; - __u64 initrd_start; - __u64 dtb_end; + /* + * When the lowest bit of dtb_info is 0, the value of dtb_info represents the size of the DTB, + * and data_start and data_size represent the address base and size of the MMIO. + * When the lowest bit of dtb_info is 1, data_start and data_size represent the address base + * and size of the DTB. + */ + __u64 dtb_info; + __u64 data_start; + __u64 data_size; __u64 ram_size; struct kvm_numa_info numa_info; }; diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h index 31457a57f7..62fbb713f4 100644 --- a/target/arm/kvm_arm.h +++ b/target/arm/kvm_arm.h @@ -73,6 +73,8 @@ int kvm_arm_vcpu_finalize(CPUState *cs, int feature); void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group, uint64_t attr, int dev_fd, uint64_t addr_ormask); +void virtcca_kvm_get_mmio_addr(hwaddr *mmio_start, hwaddr *mmio_size); + /** * kvm_arm_init_cpreg_list: * @cpu: ARMCPU -- Gitee From 458d90e226d5833661f9257f6af57c14f9b9bdfe Mon Sep 17 00:00:00 2001 From: gongchangsui Date: Mon, 17 Mar 2025 02:52:21 -0400 Subject: [PATCH 5/6] BUGFIX: Enforce isolation for virtcca_shared_hugepage Add memory isolation enforcement when virtcca hugepage is disabled. Signed-off-by: gongchangsui --- hw/core/numa.c | 3 ++- hw/virtio/vhost.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/core/numa.c b/hw/core/numa.c index e7c48dab61..c691578ef5 100644 --- a/hw/core/numa.c +++ b/hw/core/numa.c @@ -728,7 +728,8 @@ 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) { + if (virtcca_cvm_enabled() && virtcca_shared_hugepage && + virtcca_shared_hugepage->ram_block) { virtcca_shared_memory_configuration(ms); } } diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 8b95558013..4bf0b03977 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -1617,7 +1617,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, hdev->log_size = 0; hdev->log_enabled = false; hdev->started = false; - if (virtcca_cvm_enabled()) { + if (virtcca_cvm_enabled() && virtcca_shared_hugepage && virtcca_shared_hugepage->ram_block) { memory_listener_register(&hdev->memory_listener, &address_space_virtcca_shared_memory); } else { -- Gitee From bc08940ad3c75da49e05c596f79e9e0164573709 Mon Sep 17 00:00:00 2001 From: gongchangsui Date: Mon, 17 Mar 2025 02:56:40 -0400 Subject: [PATCH 6/6] backends: VirtCCA: cvm_gpa_start supports both 1GB and 3GB For TMM versions 2.1 and above, `cvm_gpa_start` is 1GB, while for versions prior to 2.1, `cvm_gpa_start` is 3GB. Shared huge page memory supports both `cvm_gpa_start` values. Signed-off-by: gongchangsui --- backends/hostmem-file.c | 17 ++++++++++++++--- hw/arm/virt.c | 1 + hw/core/numa.c | 2 +- include/exec/memory.h | 11 +++++++---- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c index 891fe4ac4a..ce63a372a3 100644 --- a/backends/hostmem-file.c +++ b/backends/hostmem-file.c @@ -27,6 +27,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(HostMemoryBackendFile, MEMORY_BACKEND_FILE) bool virtcca_shared_hugepage_mapped = false; uint64_t virtcca_cvm_ram_size = 0; +uint64_t virtcca_cvm_gpa_start = 0; struct HostMemoryBackendFile { HostMemoryBackend parent_obj; @@ -101,8 +102,16 @@ virtcca_shared_backend_memory_alloc(char *mem_path, uint32_t ram_flags, Error ** 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; + + /* + * 1) CVM_GPA_START = 3GB --> fix size = 1GB + * 2) CVM_GPA_START = 1GB && ram_size >= 3GB --> size = 3GB + * 3) CVM_GPA_START = 1GB && ram_size < 3GB --> size = ram_size + */ + if (virtcca_cvm_gpa_start != DEFAULT_VM_GPA_START) { + size = VIRTCCA_SHARED_HUGEPAGE_ADDR_LIMIT - virtcca_cvm_gpa_start; + } else if (virtcca_cvm_ram_size >= VIRTCCA_SHARED_HUGEPAGE_ADDR_LIMIT - DEFAULT_VM_GPA_START) { + size = VIRTCCA_SHARED_HUGEPAGE_ADDR_LIMIT - DEFAULT_VM_GPA_START; } virtcca_shared_hugepage = g_new(MemoryRegion, 1); @@ -172,7 +181,9 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp) fb->mem_path, fb->offset, errp); g_free(name); - if (virtcca_cvm_enabled() && backend->share && !virtcca_shared_hugepage_mapped) { + if (virtcca_cvm_enabled() && backend->share && + (strcmp(fb->mem_path, "/dev/shm") != 0) && + !virtcca_shared_hugepage_mapped) { virtcca_shared_backend_memory_alloc(fb->mem_path, ram_flags, errp); } #endif diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 6c5611826c..3c31d3667e 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -2063,6 +2063,7 @@ static void virt_set_memmap(VirtMachineState *vms, int pa_bits) if (tmi_version < MIN_TMI_VERSION_FOR_UEFI_BOOTED_CVM) { vms->memmap[VIRT_MEM].base = 3 * GiB; } + virtcca_cvm_gpa_start = vms->memmap[VIRT_MEM].base; vms->memmap[VIRT_MEM].size = ms->ram_size; info_report("[qemu] fix VIRT_MEM range 0x%llx - 0x%llx\n", (unsigned long long)(vms->memmap[VIRT_MEM].base), (unsigned long long)(vms->memmap[VIRT_MEM].base + ms->ram_size)); diff --git a/hw/core/numa.c b/hw/core/numa.c index c691578ef5..98d896e687 100644 --- a/hw/core/numa.c +++ b/hw/core/numa.c @@ -655,7 +655,7 @@ static void virtcca_shared_memory_configuration(MachineState *ms) 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); + virtcca_cvm_gpa_start, alias_mr); } void numa_complete_configuration(MachineState *ms) diff --git a/include/exec/memory.h b/include/exec/memory.h index 33778f5c64..c14dc69d27 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -243,14 +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 address limit of the VirtCCA bounce buffer is 4GB. */ +#define VIRTCCA_SHARED_HUGEPAGE_ADDR_LIMIT 0x100000000ULL /* 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 +/* The default GPA starting address of VM is 1GB */ +#define DEFAULT_VM_GPA_START 0x40000000ULL + +/* The GPA starting address of the VirtCCA CVM is 1GB or 3GB */ +extern uint64_t virtcca_cvm_gpa_start; extern uint64_t virtcca_cvm_ram_size; -- Gitee