From b36d41c5195d4fff8bec16a2226f0a9a616be4a1 Mon Sep 17 00:00:00 2001 From: Jiabo Feng Date: Wed, 21 Aug 2024 14:56:27 +0800 Subject: [PATCH] QEMU update to version 8.2.0-17: - cvm : bug fix for undefined reference to 'virtcca_cvm_allowed' while compiling - cvm : bug-fix for incorrect device name check for vhost-user-fs - target/i386: add control bits support for LAM - target/i386: add support for LAM in CPUID enumeration - Add support for the virtcca cvm feature. - target/sparc: use signed denominator in sdiv helper - crypto: Introduce SM4 symmetric cipher algorithm - ppc/vof: Fix unaligned FDT property access - vl: fix "type is NULL" in -vga help - hw/display/bcm2835_fb: fix fb_use_offsets condition - aspeed/smc: Fix possible integer overflow - hw/nvme: fix number of PIDs for FDP RUH update - hw/nvme: fix memory leak in nvme_dsm - hvf: arm: Do not advance PC when raising an exception - physmem: Bail out qemu_ram_block_from_host() for invalid ram addrs Signed-off-by: Jiabo Feng --- Add-support-for-the-virtcca-cvm-feature.patch | 1047 +++++++++++++++++ ...ed-smc-Fix-possible-integer-overflow.patch | 45 + ...oduce-SM4-symmetric-cipher-algorithm.patch | 306 +++++ ...incorrect-device-name-check-for-vhos.patch | 34 + ...undefined-reference-to-virtcca_cvm_a.patch | 30 + ...advance-PC-when-raising-an-exception.patch | 39 + ...2835_fb-fix-fb_use_offsets-condition.patch | 51 + hw-nvme-fix-memory-leak-in-nvme_dsm.patch | 49 + ...ix-number-of-PIDs-for-FDP-RUH-update.patch | 35 + ...-qemu_ram_block_from_host-for-invali.patch | 40 + ...of-Fix-unaligned-FDT-property-access.patch | 34 + qemu.spec | 34 +- ...386-add-control-bits-support-for-LAM.patch | 99 ++ ...support-for-LAM-in-CPUID-enumeration.patch | 69 ++ ...se-signed-denominator-in-sdiv-helper.patch | 41 + vl-fix-type-is-NULL-in-vga-help.patch | 49 + 16 files changed, 2001 insertions(+), 1 deletion(-) create mode 100644 Add-support-for-the-virtcca-cvm-feature.patch create mode 100644 aspeed-smc-Fix-possible-integer-overflow.patch create mode 100644 crypto-Introduce-SM4-symmetric-cipher-algorithm.patch create mode 100644 cvm-bug-fix-for-incorrect-device-name-check-for-vhos.patch create mode 100644 cvm-bug-fix-for-undefined-reference-to-virtcca_cvm_a.patch create mode 100644 hvf-arm-Do-not-advance-PC-when-raising-an-exception.patch create mode 100644 hw-display-bcm2835_fb-fix-fb_use_offsets-condition.patch create mode 100644 hw-nvme-fix-memory-leak-in-nvme_dsm.patch create mode 100644 hw-nvme-fix-number-of-PIDs-for-FDP-RUH-update.patch create mode 100644 physmem-Bail-out-qemu_ram_block_from_host-for-invali.patch create mode 100644 ppc-vof-Fix-unaligned-FDT-property-access.patch create mode 100644 target-i386-add-control-bits-support-for-LAM.patch create mode 100644 target-i386-add-support-for-LAM-in-CPUID-enumeration.patch create mode 100644 target-sparc-use-signed-denominator-in-sdiv-helper.patch create mode 100644 vl-fix-type-is-NULL-in-vga-help.patch diff --git a/Add-support-for-the-virtcca-cvm-feature.patch b/Add-support-for-the-virtcca-cvm-feature.patch new file mode 100644 index 0000000..79d0fca --- /dev/null +++ b/Add-support-for-the-virtcca-cvm-feature.patch @@ -0,0 +1,1047 @@ +From 5db954cb188d3775aec053fad8a39bf4c26a2b92 Mon Sep 17 00:00:00 2001 +From: liupingwei +Date: Fri, 2 Aug 2024 11:55:43 +0800 +Subject: [PATCH] Add support for the virtcca cvm feature. + +With this commit,we can append new startup parameters :"cma=64M +cvm_guest=1" and "kvm_type=cvm" to use virtcca cvm feature. +Here is a full example of the append parameters for a cvm : +-M virt,gic-version=3,accel=kvm,kernel_irqchip=on,kvm_type=cvm \ +-append "swiotlb=force console=tty0 console=ttyAMA0 kaslr.disabled=1 +cma=64M cvm_guest=1 rodata=off rootfstype=ext4 root=/dev/vad rw" \ + +Additionally,the SVE and PMU are optional configurations for cvm,here is +an example: +-object tmm-guest,id=tmm0,sve-vector-length=128,num-pmu-counters=1 + +Signed-off-by: liupingwei +--- + accel/kvm/kvm-all.c | 36 ++++ + hw/arm/boot.c | 49 +++++ + hw/arm/virt.c | 61 +++++- + hw/virtio/virtio-bus.c | 6 + + include/hw/arm/boot.h | 1 + + include/hw/arm/virt.h | 1 + + include/sysemu/kvm.h | 9 + + linux-headers/asm-arm64/kvm.h | 62 ++++++ + linux-headers/linux/kvm.h | 32 +++- + qapi/qom.json | 29 ++- + target/arm/kvm-tmm.c | 344 ++++++++++++++++++++++++++++++++++ + target/arm/kvm.c | 6 +- + target/arm/kvm64.c | 5 + + target/arm/kvm_arm.h | 16 ++ + target/arm/meson.build | 1 + + 15 files changed, 651 insertions(+), 7 deletions(-) + create mode 100644 target/arm/kvm-tmm.c + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index ade7841ca3..dc3605e648 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -52,6 +52,8 @@ + #include "hw/boards.h" + #include "sysemu/stats.h" + ++#include "sysemu/kvm.h" ++ + /* This check must be after config-host.h is included */ + #ifdef CONFIG_EVENTFD + #include +@@ -86,6 +88,9 @@ struct KVMParkedVcpu { + }; + + KVMState *kvm_state; ++ ++bool virtcca_cvm_allowed = false; ++ + bool kvm_kernel_irqchip; + bool kvm_split_irqchip; + bool kvm_async_interrupts_allowed; +@@ -2355,6 +2360,11 @@ uint32_t kvm_dirty_ring_size(void) + return kvm_state->kvm_dirty_ring_size; + } + ++static inline bool kvm_is_virtcca_cvm_type(int type) ++{ ++ return type & VIRTCCA_CVM_TYPE; ++} ++ + static int kvm_init(MachineState *ms) + { + MachineClass *mc = MACHINE_GET_CLASS(ms); +@@ -2447,6 +2457,10 @@ static int kvm_init(MachineState *ms) + goto err; + } + ++ if (kvm_is_virtcca_cvm_type(type)) { ++ virtcca_cvm_allowed = true; ++ } ++ + do { + ret = kvm_ioctl(s, KVM_CREATE_VM, type); + } while (ret == -EINTR); +@@ -3503,6 +3517,28 @@ 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, ++ struct kvm_numa_info *numa_info) ++{ ++ KVMState *state = kvm_state; ++ struct kvm_user_data data; ++ int ret; ++ ++ data.loader_start = loader_start; ++ data.image_end = image_end; ++ data.initrd_start = initrd_start; ++ data.dtb_end = dtb_end; ++ data.ram_size = ram_size; ++ memcpy(&data.numa_info, numa_info, sizeof(struct kvm_numa_info)); ++ ++ ret = kvm_vm_ioctl(state, KVM_LOAD_USER_DATA, &data); ++ if (ret < 0) { ++ error_report("%s: KVM_LOAD_USER_DATA failed!\n", __func__); ++ } ++ ++ return ret; ++} ++ + static bool kvm_accel_has_memory(MachineState *ms, AddressSpace *as, + hwaddr start_addr, hwaddr size) + { +diff --git a/hw/arm/boot.c b/hw/arm/boot.c +index 345c7cfa19..42110b0f18 100644 +--- a/hw/arm/boot.c ++++ b/hw/arm/boot.c +@@ -27,6 +27,7 @@ + #include "qemu/config-file.h" + #include "qemu/option.h" + #include "qemu/units.h" ++#include "kvm_arm.h" + + /* Kernel boot protocol is specified in the kernel docs + * Documentation/arm/Booting and Documentation/arm64/booting.txt +@@ -1142,6 +1143,16 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu, + for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) { + ARM_CPU(cs)->env.boot_info = info; + } ++ ++ if (kvm_enabled() && virtcca_cvm_enabled()) { ++ if (info->dtb_limit == 0) { ++ info->dtb_limit = info->dtb_start + 0x200000; ++ } ++ 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); ++ tmm_add_ram_region(info->loader_start, image_high_addr - info->loader_start, ++ info->initrd_start, info->dtb_limit - info->initrd_start, true); ++ } + } + + static void arm_setup_firmware_boot(ARMCPU *cpu, struct arm_boot_info *info) +@@ -1235,6 +1246,39 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info) + info->initrd_filename = ms->initrd_filename; + info->dtb_filename = ms->dtb; + info->dtb_limit = 0; ++ if (kvm_enabled() && virtcca_cvm_enabled()) { ++ info->ram_size = ms->ram_size; ++ info->numa_info = g_malloc(sizeof(struct kvm_numa_info)); ++ struct kvm_numa_info *numa_info = (struct kvm_numa_info *) info->numa_info; ++ if (ms->numa_state != NULL && ms->numa_state->num_nodes > 0) { ++ numa_info->numa_cnt = ms->numa_state->num_nodes; ++ uint64_t mem_base = info->loader_start; ++ for (int64_t i = 0; i < ms->numa_state->num_nodes && i < MAX_NUMA_NODE; i++) { ++ uint64_t mem_len = ms->numa_state->nodes[i].node_mem; ++ numa_info->numa_nodes[i].numa_id = i; ++ numa_info->numa_nodes[i].ipa_start = mem_base; ++ numa_info->numa_nodes[i].ipa_size = mem_len; ++ memcpy(numa_info->numa_nodes[i].host_numa_nodes, ms->numa_state->nodes[i].node_memdev->host_nodes, ++ MAX_NODES / BITS_PER_LONG * sizeof(uint64_t)); ++ mem_base += mem_len; ++ } ++ } else { ++ numa_info->numa_cnt = 1; ++ numa_info->numa_nodes[0].numa_id = 0; ++ numa_info->numa_nodes[0].ipa_start = info->loader_start; ++ numa_info->numa_nodes[0].ipa_size = info->ram_size; ++ memset(numa_info->numa_nodes[0].host_numa_nodes, 0, MAX_NODES / BITS_PER_LONG * sizeof(uint64_t)); ++ } ++ ++ for (int cpu_idx = ms->smp.cpus - 1; cpu_idx >= 0; cpu_idx--) { ++ ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu_idx)); ++ CPUState *local_cs = CPU(armcpu); ++ uint64_t node_id = 0; ++ if (ms->possible_cpus->cpus[local_cs->cpu_index].props.has_node_id) ++ node_id = ms->possible_cpus->cpus[local_cs->cpu_index].props.node_id; ++ bitmap_set((unsigned long *)numa_info->numa_nodes[node_id].cpu_id, cpu_idx, 1); ++ } ++ } + + /* Load the kernel. */ + if (!info->kernel_filename || info->firmware_loaded) { +@@ -1243,6 +1287,11 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info) + arm_setup_direct_kernel_boot(cpu, info); + } + ++ if (kvm_enabled() && virtcca_cvm_enabled()) { ++ g_free(info->numa_info); ++ info->numa_info = NULL; ++ } ++ + /* + * Disable the PSCI conduit if it is set up to target the same + * or a lower EL than the one we're going to start the guest code in. +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index a6e324c6f8..e73a795d3d 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -285,8 +285,16 @@ static void create_fdt(VirtMachineState *vms) + + /* /chosen must exist for load_dtb to fill in necessary properties later */ + qemu_fdt_add_subnode(fdt, "/chosen"); ++ ++ g_autofree char *kvm_type = NULL; ++ if (object_property_find(OBJECT(current_machine), "kvm-type")) { ++ kvm_type = object_property_get_str(OBJECT(current_machine), ++ "kvm-type", &error_abort); ++ } + if (vms->dtb_randomness) { +- create_randomness(ms, "/chosen"); ++ if (!(kvm_type && !strcmp(kvm_type, "cvm"))) { ++ create_randomness(ms, "/chosen"); ++ } + } + + if (vms->secure) { +@@ -1953,6 +1961,19 @@ static void virt_set_memmap(VirtMachineState *vms, int pa_bits) + vms->memmap[i] = base_memmap[i]; + } + ++ /* fix VIRT_MEM range */ ++ if (object_property_find(OBJECT(current_machine), "kvm-type")) { ++ g_autofree char *kvm_type = object_property_get_str(OBJECT(current_machine), ++ "kvm-type", &error_abort); ++ ++ if (!strcmp(kvm_type, "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)); ++ } ++ } ++ + if (ms->ram_slots > ACPI_MAX_RAM_SLOTS) { + error_report("unsupported number of memory slots: %"PRIu64, + ms->ram_slots); +@@ -2440,7 +2461,7 @@ static void machvirt_init(MachineState *machine) + */ + if (vms->secure && firmware_loaded) { + vms->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED; +- } else if (vms->virt) { ++ } else if (vms->virt || virtcca_cvm_enabled()) { + vms->psci_conduit = QEMU_PSCI_CONDUIT_SMC; + } else { + vms->psci_conduit = QEMU_PSCI_CONDUIT_HVC; +@@ -2509,6 +2530,13 @@ static void machvirt_init(MachineState *machine) + } + } + ++ if (virtcca_cvm_enabled()) { ++ int ret = kvm_arm_tmm_init(machine->cgs, &error_fatal); ++ if (ret != 0) { ++ error_report("fail to initialize TMM"); ++ exit(1); ++ } ++ } + create_fdt(vms); + qemu_log("cpu init start\n"); + +@@ -3592,6 +3620,15 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, + static int virt_kvm_type(MachineState *ms, const char *type_str) + { + VirtMachineState *vms = VIRT_MACHINE(ms); ++ int virtcca_cvm_type = 0; ++ if (object_property_find(OBJECT(current_machine), "kvm-type")) { ++ g_autofree char *kvm_type = object_property_get_str(OBJECT(current_machine), ++ "kvm-type", &error_abort); ++ ++ if (!strcmp(kvm_type, "cvm")) { ++ virtcca_cvm_type = VIRTCCA_CVM_TYPE; ++ } ++ } + int max_vm_pa_size, requested_pa_size; + bool fixed_ipa; + +@@ -3621,7 +3658,9 @@ static int virt_kvm_type(MachineState *ms, const char *type_str) + * the implicit legacy 40b IPA setting, in which case the kvm_type + * must be 0. + */ +- return fixed_ipa ? 0 : requested_pa_size; ++ return strcmp(type_str, "cvm") == 0 ? ++ ((fixed_ipa ? 0 : requested_pa_size) | virtcca_cvm_type) : ++ (fixed_ipa ? 0 : requested_pa_size); + } + + static void virt_machine_class_init(ObjectClass *oc, void *data) +@@ -3793,6 +3832,19 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) + + } + ++static char *virt_get_kvm_type(Object *obj, Error **errp G_GNUC_UNUSED) ++{ ++ VirtMachineState *vms = VIRT_MACHINE(obj); ++ return g_strdup(vms->kvm_type); ++} ++ ++static void virt_set_kvm_type(Object *obj, const char *value, Error **errp G_GNUC_UNUSED) ++{ ++ VirtMachineState *vms = VIRT_MACHINE(obj); ++ g_free(vms->kvm_type); ++ vms->kvm_type = g_strdup(value); ++} ++ + static void virt_instance_init(Object *obj) + { + VirtMachineState *vms = VIRT_MACHINE(obj); +@@ -3853,6 +3905,9 @@ static void virt_instance_init(Object *obj) + + vms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6); + vms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8); ++ ++ object_property_add_str(obj, "kvm-type", virt_get_kvm_type, virt_set_kvm_type); ++ object_property_set_description(obj, "kvm-type", "CVM or Normal VM"); + } + + static const TypeInfo virt_machine_info = { +diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c +index 896feb37a1..7e750d073d 100644 +--- a/hw/virtio/virtio-bus.c ++++ b/hw/virtio/virtio-bus.c +@@ -25,6 +25,7 @@ + #include "qemu/osdep.h" + #include "qemu/error-report.h" + #include "qemu/module.h" ++#include "sysemu/kvm.h" + #include "qapi/error.h" + #include "hw/virtio/virtio-bus.h" + #include "hw/virtio/virtio.h" +@@ -81,6 +82,11 @@ void virtio_bus_device_plugged(VirtIODevice *vdev, Error **errp) + vdev->dma_as = &address_space_memory; + if (has_iommu) { + vdev_has_iommu = virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); ++ ++ if (virtcca_cvm_enabled() && (strcmp(vdev->name, "vhost-user-fs") == 0)) { ++ vdev_has_iommu = true; ++ } ++ + /* + * Present IOMMU_PLATFORM to the driver iff iommu_plattform=on and + * device operational. If the driver does not accept IOMMU_PLATFORM +diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h +index f81326a1dc..4491b1f85b 100644 +--- a/include/hw/arm/boot.h ++++ b/include/hw/arm/boot.h +@@ -39,6 +39,7 @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, + /* arm_boot.c */ + struct arm_boot_info { + uint64_t ram_size; ++ void *numa_info; + const char *kernel_filename; + const char *kernel_cmdline; + const char *initrd_filename; +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index 7a734f07f7..27f5333772 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -182,6 +182,7 @@ struct VirtMachineState { + PCIBus *bus; + char *oem_id; + char *oem_table_id; ++ char *kvm_type; + NotifierList cpuhp_notifiers; + }; + +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index cfa77cc15b..31af5f0e24 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -19,6 +19,7 @@ + #include "exec/memattrs.h" + #include "qemu/accel.h" + #include "qom/object.h" ++#include "linux-headers/linux/kvm.h" + + #ifdef NEED_CPU_H + # ifdef CONFIG_KVM +@@ -32,6 +33,7 @@ + #ifdef CONFIG_KVM_IS_POSSIBLE + + extern bool kvm_allowed; ++extern bool virtcca_cvm_allowed; + extern bool kvm_kernel_irqchip; + extern bool kvm_split_irqchip; + extern bool kvm_async_interrupts_allowed; +@@ -44,6 +46,8 @@ extern bool kvm_readonly_mem_allowed; + extern bool kvm_msi_use_devid; + + #define kvm_enabled() (kvm_allowed) ++#define virtcca_cvm_enabled() (virtcca_cvm_allowed) ++#define VIRTCCA_CVM_TYPE (1UL << 8) + /** + * kvm_irqchip_in_kernel: + * +@@ -146,6 +150,8 @@ extern bool kvm_msi_use_devid; + #else + + #define kvm_enabled() (0) ++#define virtcca_cvm_enabled() (0) ++#define VIRTCCA_CVM_TYPE (0) + #define kvm_irqchip_in_kernel() (false) + #define kvm_irqchip_is_split() (false) + #define kvm_async_interrupts_enabled() (false) +@@ -543,6 +549,9 @@ bool kvm_dirty_ring_enabled(void); + + uint32_t kvm_dirty_ring_size(void); + ++int kvm_load_user_data(hwaddr loader_start, hwaddr image_end, hwaddr initrd_start, hwaddr dtb_end, hwaddr ram_size, ++ struct kvm_numa_info *numa_info); ++ + #ifdef __aarch64__ + int kvm_create_shadow_device(PCIDevice *dev); + int kvm_delete_shadow_device(PCIDevice *dev); +diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h +index c59ea55cd8..2b040b5d60 100644 +--- a/linux-headers/asm-arm64/kvm.h ++++ b/linux-headers/asm-arm64/kvm.h +@@ -110,6 +110,7 @@ struct kvm_regs { + #define KVM_ARM_VCPU_PTRAUTH_ADDRESS 5 /* VCPU uses address authentication */ + #define KVM_ARM_VCPU_PTRAUTH_GENERIC 6 /* VCPU uses generic authentication */ + #define KVM_ARM_VCPU_HAS_EL2 7 /* Support nested virtualization */ ++#define KVM_ARM_VCPU_TEC 8 /* VCPU TEC state as part of cvm */ + + struct kvm_vcpu_init { + __u32 target; +@@ -523,6 +524,67 @@ struct reg_mask_range { + __u32 reserved[13]; + }; + ++/* KVM_CAP_ARM_TMM on VM fd */ ++#define KVM_CAP_ARM_TMM_CONFIG_CVM 0 ++#define KVM_CAP_ARM_TMM_CREATE_RD 1 ++#define KVM_CAP_ARM_TMM_POPULATE_CVM 2 ++#define KVM_CAP_ARM_TMM_ACTIVATE_CVM 3 ++ ++#define KVM_CAP_ARM_TMM_MEASUREMENT_ALGO_SHA256 0 ++#define KVM_CAP_ARM_TMM_MEASUREMENT_ALGO_SHA512 1 ++ ++#define KVM_CAP_ARM_TMM_RPV_SIZE 64 ++ ++/* List of configuration items accepted for KVM_CAP_ARM_RME_CONFIG_REALM */ ++#define KVM_CAP_ARM_TMM_CFG_RPV 0 ++#define KVM_CAP_ARM_TMM_CFG_HASH_ALGO 1 ++#define KVM_CAP_ARM_TMM_CFG_SVE 2 ++#define KVM_CAP_ARM_TMM_CFG_DBG 3 ++#define KVM_CAP_ARM_TMM_CFG_PMU 4 ++ ++struct kvm_cap_arm_tmm_config_item { ++ __u32 cfg; ++ union { ++ /* cfg == KVM_CAP_ARM_TMM_CFG_RPV */ ++ struct { ++ __u8 rpv[KVM_CAP_ARM_TMM_RPV_SIZE]; ++ }; ++ ++ /* cfg == KVM_CAP_ARM_TMM_CFG_HASH_ALGO */ ++ struct { ++ __u32 hash_algo; ++ }; ++ ++ /* cfg == KVM_CAP_ARM_TMM_CFG_SVE */ ++ struct { ++ __u32 sve_vq; ++ }; ++ ++ /* cfg == KVM_CAP_ARM_TMM_CFG_DBG */ ++ struct { ++ __u32 num_brps; ++ __u32 num_wrps; ++ }; ++ ++ /* cfg == KVM_CAP_ARM_TMM_CFG_PMU */ ++ struct { ++ __u32 num_pmu_cntrs; ++ }; ++ /* Fix the size of the union */ ++ __u8 reserved[256]; ++ }; ++}; ++ ++#define KVM_ARM_TMM_POPULATE_FLAGS_MEASURE (1U << 0) ++struct kvm_cap_arm_tmm_populate_region_args { ++ __u64 populate_ipa_base1; ++ __u64 populate_ipa_size1; ++ __u64 populate_ipa_base2; ++ __u64 populate_ipa_size2; ++ __u32 flags; ++ __u32 reserved[3]; ++}; ++ + #endif + + #endif /* __ARM_KVM_H__ */ +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index 56f6b2583f..8d12435e41 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -14,6 +14,8 @@ + #include + #include + ++#include "sysemu/numa.h" ++ + #define KVM_API_VERSION 12 + + /* *** Deprecated interfaces *** */ +@@ -1198,6 +1200,8 @@ struct kvm_ppc_resize_hpt { + #define KVM_CAP_ARM_SUPPORTED_BLOCK_SIZES 229 + #define KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES 230 + ++#define KVM_CAP_ARM_TMM 300 ++ + #define KVM_CAP_ARM_VIRT_MSI_BYPASS 799 + + #ifdef KVM_CAP_IRQ_ROUTING +@@ -1469,6 +1473,32 @@ struct kvm_vfio_spapr_tce { + __s32 tablefd; + }; + ++#define MAX_NUMA_NODE 8 ++#define MAX_CPU_BIT_MAP 4 ++#define MAX_NODE_BIT_MAP (MAX_NODES / BITS_PER_LONG) ++ ++struct kvm_numa_node { ++ __u64 numa_id; ++ __u64 ipa_start; ++ __u64 ipa_size; ++ __u64 host_numa_nodes[MAX_NODE_BIT_MAP]; ++ __u64 cpu_id[MAX_CPU_BIT_MAP]; ++}; ++ ++struct kvm_numa_info { ++ __u64 numa_cnt; ++ struct kvm_numa_node numa_nodes[MAX_NUMA_NODE]; ++}; ++ ++struct kvm_user_data { ++ __u64 loader_start; ++ __u64 image_end; ++ __u64 initrd_start; ++ __u64 dtb_end; ++ __u64 ram_size; ++ struct kvm_numa_info numa_info; ++}; ++ + /* + * KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns + * a vcpu fd. +@@ -1481,7 +1511,7 @@ struct kvm_vfio_spapr_tce { + struct kvm_userspace_memory_region) + #define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47) + #define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64) +- ++#define KVM_LOAD_USER_DATA _IOW(KVMIO, 0x49, struct kvm_user_data) + /* enable ucontrol for s390 */ + struct kvm_s390_ucas_mapping { + __u64 user_addr; +diff --git a/qapi/qom.json b/qapi/qom.json +index c53ef978ff..213edd8db2 100644 +--- a/qapi/qom.json ++++ b/qapi/qom.json +@@ -899,6 +899,29 @@ + 'data': { '*cpu-affinity': ['uint16'], + '*node-affinity': ['uint16'] } } + ++## ++# @TmmGuestMeasurementAlgo: ++# ++# Algorithm to use for cvm measurements ++# ++# Since: FIXME ++## ++{ 'enum': 'TmmGuestMeasurementAlgo', ++'data': ['default', 'sha256', 'sha512'] } ++ ++## ++# @TmmGuestProperties: ++# ++# Properties for tmm-guest objects. ++# ++# @sve-vector-length: SVE vector length (default: 0, SVE disabled) ++# ++# Since: FIXME ++## ++{ 'struct': 'TmmGuestProperties', ++ 'data': { '*sve-vector-length': 'uint32', ++ '*num-pmu-counters': 'uint32', ++ '*measurement-algo': 'TmmGuestMeasurementAlgo' } } + + ## + # @ObjectType: +@@ -962,7 +985,8 @@ + 'tls-creds-x509', + 'tls-cipher-suites', + { 'name': 'x-remote-object', 'features': [ 'unstable' ] }, +- { 'name': 'x-vfio-user-server', 'features': [ 'unstable' ] } ++ { 'name': 'x-vfio-user-server', 'features': [ 'unstable' ] }, ++ 'tmm-guest' + ] } + + ## +@@ -1029,7 +1053,8 @@ + 'tls-creds-x509': 'TlsCredsX509Properties', + 'tls-cipher-suites': 'TlsCredsProperties', + 'x-remote-object': 'RemoteObjectProperties', +- 'x-vfio-user-server': 'VfioUserServerProperties' ++ 'x-vfio-user-server': 'VfioUserServerProperties', ++ 'tmm-guest': 'TmmGuestProperties' + } } + + ## +diff --git a/target/arm/kvm-tmm.c b/target/arm/kvm-tmm.c +new file mode 100644 +index 0000000000..efe2ca0006 +--- /dev/null ++++ b/target/arm/kvm-tmm.c +@@ -0,0 +1,344 @@ ++/* ++ * QEMU add virtcca cvm feature. ++ * ++ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ * ++ */ ++ ++#include "qemu/osdep.h" ++#include "exec/confidential-guest-support.h" ++#include "hw/boards.h" ++#include "hw/core/cpu.h" ++#include "kvm_arm.h" ++#include "migration/blocker.h" ++#include "qapi/error.h" ++#include "qom/object_interfaces.h" ++#include "sysemu/kvm.h" ++#include "sysemu/runstate.h" ++#include "hw/loader.h" ++ ++#define TYPE_TMM_GUEST "tmm-guest" ++OBJECT_DECLARE_SIMPLE_TYPE(TmmGuest, TMM_GUEST) ++ ++#define TMM_PAGE_SIZE qemu_real_host_page_size() ++#define TMM_MAX_PMU_CTRS 0x20 ++#define TMM_MAX_CFG 5 ++ ++struct TmmGuest { ++ ConfidentialGuestSupport parent_obj; ++ GSList *ram_regions; ++ TmmGuestMeasurementAlgo measurement_algo; ++ uint32_t sve_vl; ++ uint32_t num_pmu_cntrs; ++}; ++ ++typedef struct { ++ hwaddr base1; ++ hwaddr len1; ++ hwaddr base2; ++ hwaddr len2; ++ bool populate; ++} TmmRamRegion; ++ ++static TmmGuest *tmm_guest; ++ ++bool kvm_arm_tmm_enabled(void) ++{ ++ return !!tmm_guest; ++} ++ ++static int tmm_configure_one(TmmGuest *guest, uint32_t cfg, Error **errp) ++{ ++ int ret = 1; ++ const char *cfg_str; ++ struct kvm_cap_arm_tmm_config_item args = { ++ .cfg = cfg, ++ }; ++ ++ switch (cfg) { ++ case KVM_CAP_ARM_TMM_CFG_RPV: ++ return 0; ++ case KVM_CAP_ARM_TMM_CFG_HASH_ALGO: ++ switch (guest->measurement_algo) { ++ case TMM_GUEST_MEASUREMENT_ALGO_DEFAULT: ++ return 0; ++ case TMM_GUEST_MEASUREMENT_ALGO_SHA256: ++ args.hash_algo = KVM_CAP_ARM_TMM_MEASUREMENT_ALGO_SHA256; ++ break; ++ case TMM_GUEST_MEASUREMENT_ALGO_SHA512: ++ args.hash_algo = KVM_CAP_ARM_TMM_MEASUREMENT_ALGO_SHA512; ++ break; ++ default: ++ g_assert_not_reached(); ++ } ++ cfg_str = "hash algorithm"; ++ break; ++ case KVM_CAP_ARM_TMM_CFG_SVE: ++ if (!guest->sve_vl) { ++ return 0; ++ } ++ args.sve_vq = guest->sve_vl / 128; ++ cfg_str = "SVE"; ++ break; ++ case KVM_CAP_ARM_TMM_CFG_DBG: ++ return 0; ++ case KVM_CAP_ARM_TMM_CFG_PMU: ++ if (!guest->num_pmu_cntrs) { ++ return 0; ++ } ++ args.num_pmu_cntrs = guest->num_pmu_cntrs; ++ cfg_str = "PMU"; ++ break; ++ default: ++ g_assert_not_reached(); ++ } ++ ++ ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_ARM_TMM, 0, ++ KVM_CAP_ARM_TMM_CONFIG_CVM, (intptr_t)&args); ++ if (ret) { ++ error_setg_errno(errp, -ret, "TMM: failed to configure %s", cfg_str); ++ } ++ ++ return ret; ++} ++ ++static gint tmm_compare_ram_regions(gconstpointer a, gconstpointer b) ++{ ++ const TmmRamRegion *ra = a; ++ const TmmRamRegion *rb = b; ++ ++ g_assert(ra->base1 != rb->base1); ++ return ra->base1 < rb->base1 ? -1 : 1; ++} ++ ++void tmm_add_ram_region(hwaddr base1, hwaddr len1, hwaddr base2, hwaddr len2, bool populate) ++{ ++ TmmRamRegion *region; ++ ++ region = g_new0(TmmRamRegion, 1); ++ region->base1 = QEMU_ALIGN_DOWN(base1, TMM_PAGE_SIZE); ++ region->len1 = QEMU_ALIGN_UP(len1, TMM_PAGE_SIZE); ++ region->base2 = QEMU_ALIGN_DOWN(base2, TMM_PAGE_SIZE); ++ region->len2 = QEMU_ALIGN_UP(len2, TMM_PAGE_SIZE); ++ region->populate = populate; ++ ++ tmm_guest->ram_regions = g_slist_insert_sorted(tmm_guest->ram_regions, ++ region, tmm_compare_ram_regions); ++} ++ ++static void tmm_populate_region(gpointer data, gpointer unused) ++{ ++ int ret; ++ const TmmRamRegion *region = data; ++ struct kvm_cap_arm_tmm_populate_region_args populate_args = { ++ .populate_ipa_base1 = region->base1, ++ .populate_ipa_size1 = region->len1, ++ .populate_ipa_base2 = region->base2, ++ .populate_ipa_size2 = region->len2, ++ .flags = KVM_ARM_TMM_POPULATE_FLAGS_MEASURE, ++ }; ++ ++ if (!region->populate) { ++ return; ++ } ++ ++ ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_ARM_TMM, 0, ++ KVM_CAP_ARM_TMM_POPULATE_CVM, ++ (intptr_t)&populate_args); ++ if (ret) { ++ error_report("TMM: failed to populate cvm region (0x%"HWADDR_PRIx", 0x%"HWADDR_PRIx", 0x%"HWADDR_PRIx", 0x%"HWADDR_PRIx"): %s", ++ region->base1, region->len1, region->base2, region->len2, strerror(-ret)); ++ exit(1); ++ } ++} ++ ++static int tmm_create_rd(Error **errp) ++{ ++ int ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_ARM_TMM, 0, ++ KVM_CAP_ARM_TMM_CREATE_RD); ++ if (ret) { ++ error_setg_errno(errp, -ret, "TMM: failed to create tmm Descriptor"); ++ } ++ return ret; ++} ++ ++static void tmm_vm_state_change(void *opaque, bool running, RunState state) ++{ ++ int ret; ++ CPUState *cs; ++ ++ if (!running) { ++ return; ++ } ++ ++ g_slist_foreach(tmm_guest->ram_regions, tmm_populate_region, NULL); ++ g_slist_free_full(g_steal_pointer(&tmm_guest->ram_regions), g_free); ++ ++ CPU_FOREACH(cs) { ++ ret = kvm_arm_vcpu_finalize(cs, KVM_ARM_VCPU_TEC); ++ if (ret) { ++ error_report("TMM: failed to finalize vCPU: %s", strerror(-ret)); ++ exit(1); ++ } ++ } ++ ++ ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_ARM_TMM, 0, ++ KVM_CAP_ARM_TMM_ACTIVATE_CVM); ++ if (ret) { ++ error_report("TMM: failed to activate cvm: %s", strerror(-ret)); ++ exit(1); ++ } ++} ++ ++int kvm_arm_tmm_init(ConfidentialGuestSupport *cgs, Error **errp) ++{ ++ int ret; ++ int cfg; ++ ++ if (!tmm_guest) { ++ return -ENODEV; ++ } ++ ++ if (!kvm_check_extension(kvm_state, KVM_CAP_ARM_TMM)) { ++ error_setg(errp, "KVM does not support TMM"); ++ return -ENODEV; ++ } ++ ++ for (cfg = 0; cfg < TMM_MAX_CFG; cfg++) { ++ ret = tmm_configure_one(tmm_guest, cfg, &error_abort); ++ if (ret) { ++ return ret; ++ } ++ } ++ ++ ret = tmm_create_rd(&error_abort); ++ if (ret) { ++ return ret; ++ } ++ ++ qemu_add_vm_change_state_handler(tmm_vm_state_change, NULL); ++ return 0; ++} ++ ++static void tmm_get_sve_vl(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ TmmGuest *guest = TMM_GUEST(obj); ++ ++ visit_type_uint32(v, name, &guest->sve_vl, errp); ++} ++ ++static void tmm_set_sve_vl(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ TmmGuest *guest = TMM_GUEST(obj); ++ uint32_t value; ++ ++ if (!visit_type_uint32(v, name, &value, errp)) { ++ return; ++ } ++ ++ if (value & 0x7f || value >= ARM_MAX_VQ * 128) { ++ error_setg(errp, "invalid SVE vector length"); ++ return; ++ } ++ ++ guest->sve_vl = value; ++} ++ ++static void tmm_get_num_pmu_cntrs(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ TmmGuest *guest = TMM_GUEST(obj); ++ ++ visit_type_uint32(v, name, &guest->num_pmu_cntrs, errp); ++} ++ ++static void tmm_set_num_pmu_cntrs(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ TmmGuest *guest = TMM_GUEST(obj); ++ uint32_t value; ++ ++ if (!visit_type_uint32(v, name, &value, errp)) { ++ return; ++ } ++ ++ if (value >= TMM_MAX_PMU_CTRS) { ++ error_setg(errp, "invalid number of PMU counters"); ++ return; ++ } ++ ++ guest->num_pmu_cntrs = value; ++} ++ ++static int tmm_get_measurement_algo(Object *obj, Error **errp G_GNUC_UNUSED) ++{ ++ TmmGuest *guest = TMM_GUEST(obj); ++ ++ return guest->measurement_algo; ++} ++ ++static void tmm_set_measurement_algo(Object *obj, int algo, Error **errp G_GNUC_UNUSED) ++{ ++ TmmGuest *guest = TMM_GUEST(obj); ++ ++ guest->measurement_algo = algo; ++} ++ ++static void tmm_guest_class_init(ObjectClass *oc, void *data) ++{ ++ object_class_property_add_enum(oc, "measurement-algo", ++ "TmmGuestMeasurementAlgo", ++ &TmmGuestMeasurementAlgo_lookup, ++ tmm_get_measurement_algo, ++ tmm_set_measurement_algo); ++ object_class_property_set_description(oc, "measurement-algo", ++ "cvm measurement algorithm ('sha256', 'sha512')"); ++ /* ++ * This is not ideal. Normally SVE parameters are given to -cpu, but the ++ * cvm parameters are needed much earlier than CPU initialization. We also ++ * don't have a way to discover what is supported at the moment, the idea is ++ * that the user knows exactly what hardware it is running on because these ++ * parameters are part of the measurement and play in the attestation. ++ */ ++ object_class_property_add(oc, "sve-vector-length", "uint32", tmm_get_sve_vl, ++ tmm_set_sve_vl, NULL, NULL); ++ object_class_property_set_description(oc, "sve-vector-length", ++ "SVE vector length. 0 disables SVE (the default)"); ++ object_class_property_add(oc, "num-pmu-counters", "uint32", ++ tmm_get_num_pmu_cntrs, tmm_set_num_pmu_cntrs, ++ NULL, NULL); ++ object_class_property_set_description(oc, "num-pmu-counters", ++ "Number of PMU counters"); ++} ++ ++static void tmm_guest_instance_init(Object *obj) ++{ ++ if (tmm_guest) { ++ error_report("a single instance of TmmGuest is supported"); ++ exit(1); ++ } ++ tmm_guest = TMM_GUEST(obj); ++} ++ ++static const TypeInfo tmm_guest_info = { ++ .parent = TYPE_CONFIDENTIAL_GUEST_SUPPORT, ++ .name = TYPE_TMM_GUEST, ++ .instance_size = sizeof(struct TmmGuest), ++ .instance_init = tmm_guest_instance_init, ++ .class_init = tmm_guest_class_init, ++ .interfaces = (InterfaceInfo[]) { ++ { TYPE_USER_CREATABLE }, ++ { } ++ } ++}; ++ ++static void tmm_register_types(void) ++{ ++ type_register_static(&tmm_guest_info); ++} ++type_init(tmm_register_types); +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 1ceb72a1c1..ee5ba68305 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -613,6 +613,10 @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level) + continue; + } + ++ if (virtcca_cvm_enabled() && regidx == KVM_REG_ARM_TIMER_CNT) { ++ continue; ++ } ++ + switch (regidx & KVM_REG_SIZE_MASK) { + case KVM_REG_SIZE_U32: + v32 = cpu->cpreg_values[i]; +@@ -1212,7 +1216,7 @@ int kvm_arch_msi_data_to_gsi(uint32_t data) + + bool kvm_arch_cpu_check_are_resettable(void) + { +- return true; ++ return !virtcca_cvm_enabled(); + } + + static void kvm_arch_get_eager_split_size(Object *obj, Visitor *v, +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index 8f01d485b0..b099287ed0 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -584,6 +584,11 @@ static int kvm_arm_sve_set_vls(CPUState *cs) + + assert(cpu->sve_max_vq <= KVM_ARM64_SVE_VQ_MAX); + ++ if (virtcca_cvm_enabled()) { ++ /* Already set through tmm config */ ++ return 0; ++ } ++ + return kvm_set_one_reg(cs, KVM_REG_ARM64_SVE_VLS, &vls[0]); + } + +diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h +index bf4df54c96..d6c7139f4a 100644 +--- a/target/arm/kvm_arm.h ++++ b/target/arm/kvm_arm.h +@@ -388,6 +388,11 @@ void kvm_arm_pvtime_init(CPUState *cs, uint64_t ipa); + + int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level); + ++void tmm_add_ram_region(hwaddr base1, hwaddr len1, hwaddr base2, hwaddr len2, bool populate); ++ ++int kvm_arm_tmm_init(ConfidentialGuestSupport *cgs, Error **errp); ++bool kvm_arm_tmm_enabled(void); ++ + /** + * kvm_arm_set_smccc_filter + * @func: funcion +@@ -475,6 +480,17 @@ static inline int kvm_arm_set_smccc_filter(uint64_t func, uint8_t faction) + { + g_assert_not_reached(); + } ++ ++static inline int kvm_arm_tmm_init(ConfidentialGuestSupport *cgs, Error **errp G_GNUC_UNUSED) ++{ ++ g_assert_not_reached(); ++} ++ ++static inline void tmm_add_ram_region(hwaddr base1, hwaddr len1, hwaddr base2, ++ hwaddr len2, bool populate) ++{ ++ g_assert_not_reached(); ++} + #endif + + /** +diff --git a/target/arm/meson.build b/target/arm/meson.build +index d1dd4932ed..389ee54658 100644 +--- a/target/arm/meson.build ++++ b/target/arm/meson.build +@@ -10,6 +10,7 @@ arm_ss.add(zlib) + + arm_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c')) + arm_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c')) ++arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c', 'kvm-tmm.c'), if_false: files('kvm-stub.c')) + + arm_ss.add(when: 'TARGET_AARCH64', if_true: files( + 'cpu64.c', +-- +2.41.0.windows.1 + diff --git a/aspeed-smc-Fix-possible-integer-overflow.patch b/aspeed-smc-Fix-possible-integer-overflow.patch new file mode 100644 index 0000000..dbe327d --- /dev/null +++ b/aspeed-smc-Fix-possible-integer-overflow.patch @@ -0,0 +1,45 @@ +From 041c319f2f91c85aeb4ed0cefa6afa76773fe960 Mon Sep 17 00:00:00 2001 +From: qihao +Date: Thu, 25 Jul 2024 09:57:01 +0800 +Subject: [PATCH] aspeed/smc: Fix possible integer overflow +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from 13951ccfcdf0f31902a93859506ccf8c0ef66583 + +Coverity reports a possible integer overflow because routine +aspeeed_smc_hclk_divisor() has a codepath returning 0, which could +lead to an integer overflow when computing variable 'hclk_shift' in +the caller aspeed_smc_dma_calibration(). + +The value passed to aspeed_smc_hclk_divisor() is always between 0 and +15 and, in this case, there is always a matching hclk divisor. Remove +the return 0 and use g_assert_not_reached() instead. + +Fixes: Coverity CID 1547822 +Suggested-by: Peter Maydell +Signed-off-by: Cédric Le Goater +Reviewed-by: Peter Maydell +Signed-off-by: qihao_yewu +--- + hw/ssi/aspeed_smc.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c +index 2a4001b774..8af919a970 100644 +--- a/hw/ssi/aspeed_smc.c ++++ b/hw/ssi/aspeed_smc.c +@@ -764,8 +764,7 @@ static uint8_t aspeed_smc_hclk_divisor(uint8_t hclk_mask) + } + } + +- aspeed_smc_error("invalid HCLK mask %x", hclk_mask); +- return 0; ++ g_assert_not_reached(); + } + + /* +-- +2.41.0.windows.1 + diff --git a/crypto-Introduce-SM4-symmetric-cipher-algorithm.patch b/crypto-Introduce-SM4-symmetric-cipher-algorithm.patch new file mode 100644 index 0000000..a7e40b8 --- /dev/null +++ b/crypto-Introduce-SM4-symmetric-cipher-algorithm.patch @@ -0,0 +1,306 @@ +From f402887e0c3e97dcbd6d1929ca9908ec57e2bb1f Mon Sep 17 00:00:00 2001 +From: Hyman Huang +Date: Thu, 7 Dec 2023 23:47:35 +0800 +Subject: [PATCH] crypto: Introduce SM4 symmetric cipher algorithm +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Introduce the SM4 cipher algorithms (OSCCA GB/T 32907-2016). + +SM4 (GBT.32907-2016) is a cryptographic standard issued by the +Organization of State Commercial Administration of China (OSCCA) +as an authorized cryptographic algorithms for the use within China. + +Detect the SM4 cipher algorithms and enable the feature silently +if it is available. + +Signed-off-by: Hyman Huang +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Daniel P. Berrangé +Signed-off-by: Daniel P. Berrangé +Signed-off-by: cheliequan +--- + crypto/block-luks.c | 11 ++++++++ + crypto/cipher-gcrypt.c.inc | 8 ++++++ + crypto/cipher-nettle.c.inc | 49 +++++++++++++++++++++++++++++++++ + crypto/cipher.c | 6 ++++ + meson.build | 26 +++++++++++++++++ + qapi/crypto.json | 5 +++- + tests/unit/test-crypto-cipher.c | 13 +++++++++ + 7 files changed, 117 insertions(+), 1 deletion(-) + +diff --git a/crypto/block-luks.c b/crypto/block-luks.c +index fb01ec38bb..f0813d69b4 100644 +--- a/crypto/block-luks.c ++++ b/crypto/block-luks.c +@@ -95,12 +95,23 @@ qcrypto_block_luks_cipher_size_map_twofish[] = { + { 0, 0 }, + }; + ++#ifdef CONFIG_CRYPTO_SM4 ++static const QCryptoBlockLUKSCipherSizeMap ++qcrypto_block_luks_cipher_size_map_sm4[] = { ++ { 16, QCRYPTO_CIPHER_ALG_SM4}, ++ { 0, 0 }, ++}; ++#endif ++ + static const QCryptoBlockLUKSCipherNameMap + qcrypto_block_luks_cipher_name_map[] = { + { "aes", qcrypto_block_luks_cipher_size_map_aes }, + { "cast5", qcrypto_block_luks_cipher_size_map_cast5 }, + { "serpent", qcrypto_block_luks_cipher_size_map_serpent }, + { "twofish", qcrypto_block_luks_cipher_size_map_twofish }, ++#ifdef CONFIG_CRYPTO_SM4 ++ { "sm4", qcrypto_block_luks_cipher_size_map_sm4}, ++#endif + }; + + QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSKeySlot) != 48); +diff --git a/crypto/cipher-gcrypt.c.inc b/crypto/cipher-gcrypt.c.inc +index a6a0117717..1377cbaf14 100644 +--- a/crypto/cipher-gcrypt.c.inc ++++ b/crypto/cipher-gcrypt.c.inc +@@ -35,6 +35,9 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, + case QCRYPTO_CIPHER_ALG_SERPENT_256: + case QCRYPTO_CIPHER_ALG_TWOFISH_128: + case QCRYPTO_CIPHER_ALG_TWOFISH_256: ++#ifdef CONFIG_CRYPTO_SM4 ++ case QCRYPTO_CIPHER_ALG_SM4: ++#endif + break; + default: + return false; +@@ -219,6 +222,11 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, + case QCRYPTO_CIPHER_ALG_TWOFISH_256: + gcryalg = GCRY_CIPHER_TWOFISH; + break; ++#ifdef CONFIG_CRYPTO_SM4 ++ case QCRYPTO_CIPHER_ALG_SM4: ++ gcryalg = GCRY_CIPHER_SM4; ++ break; ++#endif + default: + error_setg(errp, "Unsupported cipher algorithm %s", + QCryptoCipherAlgorithm_str(alg)); +diff --git a/crypto/cipher-nettle.c.inc b/crypto/cipher-nettle.c.inc +index 24cc61f87b..42b39e18a2 100644 +--- a/crypto/cipher-nettle.c.inc ++++ b/crypto/cipher-nettle.c.inc +@@ -33,6 +33,9 @@ + #ifndef CONFIG_QEMU_PRIVATE_XTS + #include + #endif ++#ifdef CONFIG_CRYPTO_SM4 ++#include ++#endif + + static inline bool qcrypto_length_check(size_t len, size_t blocksize, + Error **errp) +@@ -426,6 +429,30 @@ DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_twofish, + QCryptoNettleTwofish, TWOFISH_BLOCK_SIZE, + twofish_encrypt_native, twofish_decrypt_native) + ++#ifdef CONFIG_CRYPTO_SM4 ++typedef struct QCryptoNettleSm4 { ++ QCryptoCipher base; ++ struct sm4_ctx key[2]; ++} QCryptoNettleSm4; ++ ++static void sm4_encrypt_native(void *ctx, size_t length, ++ uint8_t *dst, const uint8_t *src) ++{ ++ struct sm4_ctx *keys = ctx; ++ sm4_crypt(&keys[0], length, dst, src); ++} ++ ++static void sm4_decrypt_native(void *ctx, size_t length, ++ uint8_t *dst, const uint8_t *src) ++{ ++ struct sm4_ctx *keys = ctx; ++ sm4_crypt(&keys[1], length, dst, src); ++} ++ ++DEFINE_ECB(qcrypto_nettle_sm4, ++ QCryptoNettleSm4, SM4_BLOCK_SIZE, ++ sm4_encrypt_native, sm4_decrypt_native) ++#endif + + bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, + QCryptoCipherMode mode) +@@ -443,6 +470,9 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, + case QCRYPTO_CIPHER_ALG_TWOFISH_128: + case QCRYPTO_CIPHER_ALG_TWOFISH_192: + case QCRYPTO_CIPHER_ALG_TWOFISH_256: ++#ifdef CONFIG_CRYPTO_SM4 ++ case QCRYPTO_CIPHER_ALG_SM4: ++#endif + break; + default: + return false; +@@ -701,6 +731,25 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, + + return &ctx->base; + } ++#ifdef CONFIG_CRYPTO_SM4 ++ case QCRYPTO_CIPHER_ALG_SM4: ++ { ++ QCryptoNettleSm4 *ctx = g_new0(QCryptoNettleSm4, 1); ++ ++ switch (mode) { ++ case QCRYPTO_CIPHER_MODE_ECB: ++ ctx->base.driver = &qcrypto_nettle_sm4_driver_ecb; ++ break; ++ default: ++ goto bad_cipher_mode; ++ } ++ ++ sm4_set_encrypt_key(&ctx->key[0], key); ++ sm4_set_decrypt_key(&ctx->key[1], key); ++ ++ return &ctx->base; ++ } ++#endif + + default: + error_setg(errp, "Unsupported cipher algorithm %s", +diff --git a/crypto/cipher.c b/crypto/cipher.c +index 74b09a5b26..5f512768ea 100644 +--- a/crypto/cipher.c ++++ b/crypto/cipher.c +@@ -38,6 +38,9 @@ static const size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = { + [QCRYPTO_CIPHER_ALG_TWOFISH_128] = 16, + [QCRYPTO_CIPHER_ALG_TWOFISH_192] = 24, + [QCRYPTO_CIPHER_ALG_TWOFISH_256] = 32, ++#ifdef CONFIG_CRYPTO_SM4 ++ [QCRYPTO_CIPHER_ALG_SM4] = 16, ++#endif + }; + + static const size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = { +@@ -53,6 +56,9 @@ static const size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = { + [QCRYPTO_CIPHER_ALG_TWOFISH_128] = 16, + [QCRYPTO_CIPHER_ALG_TWOFISH_192] = 16, + [QCRYPTO_CIPHER_ALG_TWOFISH_256] = 16, ++#ifdef CONFIG_CRYPTO_SM4 ++ [QCRYPTO_CIPHER_ALG_SM4] = 16, ++#endif + }; + + static const bool mode_need_iv[QCRYPTO_CIPHER_MODE__MAX] = { +diff --git a/meson.build b/meson.build +index 0c62b4156d..089f45d386 100644 +--- a/meson.build ++++ b/meson.build +@@ -1485,6 +1485,7 @@ endif + gcrypt = not_found + nettle = not_found + hogweed = not_found ++crypto_sm4 = not_found + xts = 'none' + + if get_option('nettle').enabled() and get_option('gcrypt').enabled() +@@ -1510,6 +1511,17 @@ if not gnutls_crypto.found() + cc.find_library('gpg-error', required: true)], + version: gcrypt.version()) + endif ++ crypto_sm4 = gcrypt ++ # SM4 ALG is available in libgcrypt >= 1.9 ++ if gcrypt.found() and not cc.links(''' ++ #include ++ int main(void) { ++ gcry_cipher_hd_t handler; ++ gcry_cipher_open(&handler, GCRY_CIPHER_SM4, GCRY_CIPHER_MODE_ECB, 0); ++ return 0; ++ }''', dependencies: gcrypt) ++ crypto_sm4 = not_found ++ endif + endif + if (not get_option('nettle').auto() or have_system) and not gcrypt.found() + nettle = dependency('nettle', version: '>=3.4', +@@ -1518,6 +1530,18 @@ if not gnutls_crypto.found() + if nettle.found() and not cc.has_header('nettle/xts.h', dependencies: nettle) + xts = 'private' + endif ++ crypto_sm4 = nettle ++ # SM4 ALG is available in nettle >= 3.9 ++ if nettle.found() and not cc.links(''' ++ #include ++ int main(void) { ++ struct sm4_ctx ctx; ++ unsigned char key[16] = {0}; ++ sm4_set_encrypt_key(&ctx, key); ++ return 0; ++ }''', dependencies: nettle) ++ crypto_sm4 = not_found ++ endif + endif + endif + +@@ -2204,6 +2228,7 @@ config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found()) + config_host_data.set('CONFIG_TASN1', tasn1.found()) + config_host_data.set('CONFIG_GCRYPT', gcrypt.found()) + config_host_data.set('CONFIG_NETTLE', nettle.found()) ++config_host_data.set('CONFIG_CRYPTO_SM4', crypto_sm4.found()) + config_host_data.set('CONFIG_HOGWEED', hogweed.found()) + config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private') + config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim) +@@ -4280,6 +4305,7 @@ summary_info += {'nettle': nettle} + if nettle.found() + summary_info += {' XTS': xts != 'private'} + endif ++summary_info += {'SM4 ALG support': crypto_sm4} + summary_info += {'AF_ALG support': have_afalg} + summary_info += {'rng-none': get_option('rng_none')} + summary_info += {'Linux keyring': have_keyring} +diff --git a/qapi/crypto.json b/qapi/crypto.json +index fd3d46ebd1..2f2aeff5fd 100644 +--- a/qapi/crypto.json ++++ b/qapi/crypto.json +@@ -94,6 +94,8 @@ + # + # @twofish-256: Twofish with 256 bit / 32 byte keys + # ++# @sm4: SM4 with 128 bit / 16 byte keys (since 9.0) ++# + # Since: 2.6 + ## + { 'enum': 'QCryptoCipherAlgorithm', +@@ -102,7 +104,8 @@ + 'des', '3des', + 'cast5-128', + 'serpent-128', 'serpent-192', 'serpent-256', +- 'twofish-128', 'twofish-192', 'twofish-256']} ++ 'twofish-128', 'twofish-192', 'twofish-256', ++ 'sm4']} + + ## + # @QCryptoCipherMode: +diff --git a/tests/unit/test-crypto-cipher.c b/tests/unit/test-crypto-cipher.c +index d9d9d078ff..11ab1a54fc 100644 +--- a/tests/unit/test-crypto-cipher.c ++++ b/tests/unit/test-crypto-cipher.c +@@ -382,6 +382,19 @@ static QCryptoCipherTestData test_data[] = { + .plaintext = "90afe91bb288544f2c32dc239b2635e6", + .ciphertext = "6cb4561c40bf0a9705931cb6d408e7fa", + }, ++#ifdef CONFIG_CRYPTO_SM4 ++ { ++ /* SM4, GB/T 32907-2016, Appendix A.1 */ ++ .path = "/crypto/cipher/sm4", ++ .alg = QCRYPTO_CIPHER_ALG_SM4, ++ .mode = QCRYPTO_CIPHER_MODE_ECB, ++ .key = "0123456789abcdeffedcba9876543210", ++ .plaintext = ++ "0123456789abcdeffedcba9876543210", ++ .ciphertext = ++ "681edf34d206965e86b3e94f536e4246", ++ }, ++#endif + { + /* #1 32 byte key, 32 byte PTX */ + .path = "/crypto/cipher/aes-xts-128-1", +-- +2.41.0.windows.1 + diff --git a/cvm-bug-fix-for-incorrect-device-name-check-for-vhos.patch b/cvm-bug-fix-for-incorrect-device-name-check-for-vhos.patch new file mode 100644 index 0000000..f923717 --- /dev/null +++ b/cvm-bug-fix-for-incorrect-device-name-check-for-vhos.patch @@ -0,0 +1,34 @@ +From 282d63f9b5915f0529e9d0ae54b47c0ceacc58c3 Mon Sep 17 00:00:00 2001 +From: liupingwei +Date: Mon, 19 Aug 2024 15:38:23 +0800 +Subject: [PATCH] cvm : bug-fix for incorrect device name check for + vhost-user-fs + +The 'vhost-user-fs' was being parsed as 'virtio-user-fs' during the +compilation and this caused the device to erroneously trigger the error +branch. + +Fixes: 5db954cb188d3775aec053fad8a39bf4c26a2b92("Add support for the +virtcca cvm feature.) + +Signed-off-by: liupingwei +--- + hw/virtio/virtio-bus.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c +index 7e750d073d..4f16e7ef77 100644 +--- a/hw/virtio/virtio-bus.c ++++ b/hw/virtio/virtio-bus.c +@@ -83,7 +83,7 @@ void virtio_bus_device_plugged(VirtIODevice *vdev, Error **errp) + if (has_iommu) { + vdev_has_iommu = virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); + +- if (virtcca_cvm_enabled() && (strcmp(vdev->name, "vhost-user-fs") == 0)) { ++ if (virtcca_cvm_enabled() && (strcmp(vdev->name, "virtio-user-fs") == 0)) { + vdev_has_iommu = true; + } + +-- +2.41.0.windows.1 + diff --git a/cvm-bug-fix-for-undefined-reference-to-virtcca_cvm_a.patch b/cvm-bug-fix-for-undefined-reference-to-virtcca_cvm_a.patch new file mode 100644 index 0000000..87f5186 --- /dev/null +++ b/cvm-bug-fix-for-undefined-reference-to-virtcca_cvm_a.patch @@ -0,0 +1,30 @@ +From 87dfbca72fe11b7a8d3f1afce52a7925be0e0b01 Mon Sep 17 00:00:00 2001 +From: liupingwei +Date: Wed, 4 Sep 2024 14:29:02 +0800 +Subject: [PATCH] cvm : bug fix for undefined reference to + 'virtcca_cvm_allowed' while compiling. + +Fixes a linking error due to an undefined reference to +'virtcca_cvm_allowed' when KVM is not enabled. + +Signed-off-by: liupingwei +--- + accel/stubs/kvm-stub.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c +index 1b37d9a302..ad39a434c4 100644 +--- a/accel/stubs/kvm-stub.c ++++ b/accel/stubs/kvm-stub.c +@@ -25,6 +25,8 @@ bool kvm_allowed; + bool kvm_readonly_mem_allowed; + bool kvm_msi_use_devid; + ++bool virtcca_cvm_allowed; ++ + void kvm_flush_coalesced_mmio_buffer(void) + { + } +-- +2.41.0.windows.1 + diff --git a/hvf-arm-Do-not-advance-PC-when-raising-an-exception.patch b/hvf-arm-Do-not-advance-PC-when-raising-an-exception.patch new file mode 100644 index 0000000..a0970ce --- /dev/null +++ b/hvf-arm-Do-not-advance-PC-when-raising-an-exception.patch @@ -0,0 +1,39 @@ +From 550d304465b366a116e02d2cb006475ea453a98a Mon Sep 17 00:00:00 2001 +From: guping +Date: Mon, 22 Jul 2024 00:37:30 +0000 +Subject: [PATCH] hvf: arm: Do not advance PC when raising an exception + cherry-pick from 30a1690f2402e6c1582d5b3ebcf7940bfe2fad4b + +hvf did not advance PC when raising an exception for most unhandled +system registers, but it mistakenly advanced PC when raising an +exception for GICv3 registers. + +Cc: qemu-stable@nongnu.org +Fixes: a2260983 + + ("hvf: arm: Add support for GICv3") +Signed-off-by: default avatarAkihiko Odaki +Message-id: 20240716-pmu-v3-4-8c7c1858a227@daynix.com +Reviewed-by: default avatarPeter Maydell +Signed-off-by: default avatarPeter Maydell + +Signed-off-by: guping +--- + target/arm/hvf/hvf.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c +index 757e13b0f9..b4e98a99e2 100644 +--- a/target/arm/hvf/hvf.c ++++ b/target/arm/hvf/hvf.c +@@ -1272,6 +1272,7 @@ static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint32_t rt) + /* Call the TCG sysreg handler. This is only safe for GICv3 regs. */ + if (!hvf_sysreg_read_cp(cpu, reg, &val)) { + hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized()); ++ return 1; + } + break; + case SYSREG_DBGBVR0_EL1: +-- +2.41.0.windows.1 + diff --git a/hw-display-bcm2835_fb-fix-fb_use_offsets-condition.patch b/hw-display-bcm2835_fb-fix-fb_use_offsets-condition.patch new file mode 100644 index 0000000..0c23976 --- /dev/null +++ b/hw-display-bcm2835_fb-fix-fb_use_offsets-condition.patch @@ -0,0 +1,51 @@ +From 1d3ea28fd7da9a23e278be70c7e028fbd2b69bf3 Mon Sep 17 00:00:00 2001 +From: qihao +Date: Thu, 25 Jul 2024 10:29:20 +0800 +Subject: [PATCH] hw/display/bcm2835_fb: fix fb_use_offsets condition +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from 345acc443905eda8008a1d328dd89b73c4a3f89e + +It is common practice when implementing double-buffering on VideoCore +to do so by multiplying the height of the virtual buffer by the +number of virtual screens desired (i.e., two - in the case of +double-bufferring). + +At present, this won't work in QEMU because the logic in +fb_use_offsets require that both the virtual width and height exceed +their physical counterparts. + +This appears to be unintentional/a typo and indeed the comment +states; "Experimentally, the hardware seems to do this only if the +viewport size is larger than the physical screen". The +viewport/virtual size would be larger than the physical size if +either virtual dimension were larger than their physical counterparts +and not necessarily both. + +Signed-off-by: SamJakob +Message-id: 20240713160353.62410-1-me@samjakob.com +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Peter Maydell +Signed-off-by: qihao_yewu +--- + hw/display/bcm2835_fb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c +index a05277674f..c45da149d9 100644 +--- a/hw/display/bcm2835_fb.c ++++ b/hw/display/bcm2835_fb.c +@@ -145,7 +145,7 @@ static bool fb_use_offsets(BCM2835FBConfig *config) + * viewport size is larger than the physical screen. (It doesn't + * prevent the guest setting this silly viewport setting, though...) + */ +- return config->xres_virtual > config->xres && ++ return config->xres_virtual > config->xres || + config->yres_virtual > config->yres; + } + +-- +2.41.0.windows.1 + diff --git a/hw-nvme-fix-memory-leak-in-nvme_dsm.patch b/hw-nvme-fix-memory-leak-in-nvme_dsm.patch new file mode 100644 index 0000000..7cc00c1 --- /dev/null +++ b/hw-nvme-fix-memory-leak-in-nvme_dsm.patch @@ -0,0 +1,49 @@ +From 0c23d22ea9f160a8e0e0e48b6cb400d7964ae868 Mon Sep 17 00:00:00 2001 +From: qihao +Date: Tue, 23 Jul 2024 21:06:08 +0800 +Subject: [PATCH] hw/nvme: fix memory leak in nvme_dsm + +cheery-pick from c510fe78f1b7c966524489d6ba752107423b20c8 + +The allocated memory to hold LBA ranges leaks in the nvme_dsm function. This +happens because the allocated memory for iocb->range is not freed in all +error handling paths. + +Fix this by adding a free to ensure that the allocated memory is properly freed. + +ASAN log: +==3075137==ERROR: LeakSanitizer: detected memory leaks + +Direct leak of 480 byte(s) in 6 object(s) allocated from: + #0 0x55f1f8a0eddd in malloc llvm/compiler-rt/lib/asan/asan_malloc_linux.cpp:129:3 + #1 0x7f531e0f6738 in g_malloc (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x5e738) + #2 0x55f1faf1f091 in blk_aio_get block/block-backend.c:2583:12 + #3 0x55f1f945c74b in nvme_dsm hw/nvme/ctrl.c:2609:30 + #4 0x55f1f945831b in nvme_io_cmd hw/nvme/ctrl.c:4470:16 + #5 0x55f1f94561b7 in nvme_process_sq hw/nvme/ctrl.c:7039:29 + +Cc: qemu-stable@nongnu.org +Fixes: d7d1474fd85d ("hw/nvme: reimplement dsm to allow cancellation") +Signed-off-by: Zheyu Ma +Reviewed-by: Klaus Jensen +Signed-off-by: Klaus Jensen +Signed-off-by: qihao_yewu +--- + hw/nvme/ctrl.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c +index 237b5c8871..dd1c962f93 100644 +--- a/hw/nvme/ctrl.c ++++ b/hw/nvme/ctrl.c +@@ -2592,6 +2592,7 @@ next: + done: + iocb->aiocb = NULL; + iocb->common.cb(iocb->common.opaque, iocb->ret); ++ g_free(iocb->range); + qemu_aio_unref(iocb); + } + +-- +2.41.0.windows.1 + diff --git a/hw-nvme-fix-number-of-PIDs-for-FDP-RUH-update.patch b/hw-nvme-fix-number-of-PIDs-for-FDP-RUH-update.patch new file mode 100644 index 0000000..285c70e --- /dev/null +++ b/hw-nvme-fix-number-of-PIDs-for-FDP-RUH-update.patch @@ -0,0 +1,35 @@ +From 3696b12c582440669de12d127701187828c5598f Mon Sep 17 00:00:00 2001 +From: Xu Zheng +Date: Fri, 19 Jul 2024 22:11:17 +0800 +Subject: [PATCH] hw/nvme: fix number of PIDs for FDP RUH update + +The number of PIDs is in the upper 16 bits of cdw10. So we need to +right-shift by 16 bits instead of only a single bit. + +Fixes: 73064edfb864 ("hw/nvme: flexible data placement emulation") + +cherry-pick from 3936bbdf9a2e9233875f850c7576c79d06add261 +Signed-off-by: Vincent Fu +Signed-off-by: Klaus Jensen +Signed-off-by: Michael Tokarev +Signed-off-by: Xu Zheng +--- + hw/nvme/ctrl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c +index 237b5c8871..d7e83c3d55 100644 +--- a/hw/nvme/ctrl.c ++++ b/hw/nvme/ctrl.c +@@ -4352,7 +4352,7 @@ static uint16_t nvme_io_mgmt_send_ruh_update(NvmeCtrl *n, NvmeRequest *req) + NvmeNamespace *ns = req->ns; + uint32_t cdw10 = le32_to_cpu(cmd->cdw10); + uint16_t ret = NVME_SUCCESS; +- uint32_t npid = (cdw10 >> 1) + 1; ++ uint32_t npid = (cdw10 >> 16) + 1; + unsigned int i = 0; + g_autofree uint16_t *pids = NULL; + uint32_t maxnpid; +-- +2.41.0.windows.1 + diff --git a/physmem-Bail-out-qemu_ram_block_from_host-for-invali.patch b/physmem-Bail-out-qemu_ram_block_from_host-for-invali.patch new file mode 100644 index 0000000..280e6ae --- /dev/null +++ b/physmem-Bail-out-qemu_ram_block_from_host-for-invali.patch @@ -0,0 +1,40 @@ +From 39eae397a6b573505c0e84cc808cd9765a950908 Mon Sep 17 00:00:00 2001 +From: guping +Date: Mon, 15 Jul 2024 00:54:12 +0000 +Subject: [PATCH] physmem: Bail out qemu_ram_block_from_host() for invalid ram + addrs cherry-pick from 596ccccdbfa124adb42be8c2faf0c74f4849c7a6 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Bail out in qemu_ram_block_from_host() when +xen_ram_addr_from_mapcache() does not find an existing +mapping. + +Signed-off-by: default avatarEdgar E. Iglesias +Reviewed-by: default avatarAlex Bennée +Reviewed-by: default avatarStefano Stabellini + +Signed-off-by: guping +--- + system/physmem.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/system/physmem.c b/system/physmem.c +index cbe838f203..0c629233bd 100644 +--- a/system/physmem.c ++++ b/system/physmem.c +@@ -2263,6 +2263,10 @@ RAMBlock *qemu_ram_block_from_host(void *ptr, bool round_offset, + ram_addr_t ram_addr; + RCU_READ_LOCK_GUARD(); + ram_addr = xen_ram_addr_from_mapcache(ptr); ++ if (ram_addr == RAM_ADDR_INVALID) { ++ return NULL; ++ } ++ + block = qemu_get_ram_block(ram_addr); + if (block) { + *offset = ram_addr - block->offset; +-- +2.41.0.windows.1 + diff --git a/ppc-vof-Fix-unaligned-FDT-property-access.patch b/ppc-vof-Fix-unaligned-FDT-property-access.patch new file mode 100644 index 0000000..9fc20c5 --- /dev/null +++ b/ppc-vof-Fix-unaligned-FDT-property-access.patch @@ -0,0 +1,34 @@ +From ad1d68502c41ff6a966ae89ae5ac008050602e2a Mon Sep 17 00:00:00 2001 +From: qihao +Date: Mon, 29 Jul 2024 10:38:46 +0800 +Subject: [PATCH] ppc/vof: Fix unaligned FDT property access + +cheery-pick from 785c8637f9d2362a8addf4ded853d975955a9d6b + +FDT properties are aligned by 4 bytes, not 8 bytes. + +Signed-off-by: Akihiko Odaki +Reviewed-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Nicholas Piggin +Signed-off-by: qihao_yewu +--- + hw/ppc/vof.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/ppc/vof.c b/hw/ppc/vof.c +index e3b430a81f..b5b6514d79 100644 +--- a/hw/ppc/vof.c ++++ b/hw/ppc/vof.c +@@ -646,7 +646,7 @@ static void vof_dt_memory_available(void *fdt, GArray *claimed, uint64_t base) + mem0_reg = fdt_getprop(fdt, offset, "reg", &proplen); + g_assert(mem0_reg && proplen == sizeof(uint32_t) * (ac + sc)); + if (sc == 2) { +- mem0_end = be64_to_cpu(*(uint64_t *)(mem0_reg + sizeof(uint32_t) * ac)); ++ mem0_end = ldq_be_p(mem0_reg + sizeof(uint32_t) * ac); + } else { + mem0_end = be32_to_cpu(*(uint32_t *)(mem0_reg + sizeof(uint32_t) * ac)); + } +-- +2.41.0.windows.1 + diff --git a/qemu.spec b/qemu.spec index 7f8d3e9..9c93ce5 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 8.2.0 -Release: 16 +Release: 17 Epoch: 11 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -287,6 +287,21 @@ Patch0270: nbd-server-Plumb-in-new-args-to-nbd_client_add.patch Patch0271: nbd-server-CVE-2024-7409-Cap-default-max-connections.patch Patch0272: nbd-server-CVE-2024-7409-Drop-non-negotiating-client.patch Patch0273: nbd-server-CVE-2024-7409-Close-stray-clients-at-serv.patch +Patch0274: physmem-Bail-out-qemu_ram_block_from_host-for-invali.patch +Patch0275: hvf-arm-Do-not-advance-PC-when-raising-an-exception.patch +Patch0276: hw-nvme-fix-memory-leak-in-nvme_dsm.patch +Patch0277: hw-nvme-fix-number-of-PIDs-for-FDP-RUH-update.patch +Patch0278: aspeed-smc-Fix-possible-integer-overflow.patch +Patch0279: hw-display-bcm2835_fb-fix-fb_use_offsets-condition.patch +Patch0280: vl-fix-type-is-NULL-in-vga-help.patch +Patch0281: ppc-vof-Fix-unaligned-FDT-property-access.patch +Patch0282: crypto-Introduce-SM4-symmetric-cipher-algorithm.patch +Patch0283: target-sparc-use-signed-denominator-in-sdiv-helper.patch +Patch0284: Add-support-for-the-virtcca-cvm-feature.patch +Patch0285: target-i386-add-support-for-LAM-in-CPUID-enumeration.patch +Patch0286: target-i386-add-control-bits-support-for-LAM.patch +Patch0287: cvm-bug-fix-for-incorrect-device-name-check-for-vhos.patch +Patch0288: cvm-bug-fix-for-undefined-reference-to-virtcca_cvm_a.patch BuildRequires: flex BuildRequires: gcc @@ -884,6 +899,23 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Thu Sep 5 2024 Jiabo Feng - 11:8.2.0-17 +- cvm : bug fix for undefined reference to 'virtcca_cvm_allowed' while compiling +- cvm : bug-fix for incorrect device name check for vhost-user-fs +- target/i386: add control bits support for LAM +- target/i386: add support for LAM in CPUID enumeration +- Add support for the virtcca cvm feature. +- target/sparc: use signed denominator in sdiv helper +- crypto: Introduce SM4 symmetric cipher algorithm +- ppc/vof: Fix unaligned FDT property access +- vl: fix "type is NULL" in -vga help +- hw/display/bcm2835_fb: fix fb_use_offsets condition +- aspeed/smc: Fix possible integer overflow +- hw/nvme: fix number of PIDs for FDP RUH update +- hw/nvme: fix memory leak in nvme_dsm +- hvf: arm: Do not advance PC when raising an exception +- physmem: Bail out qemu_ram_block_from_host() for invalid ram addrs + * Tue Aug 13 2024 Jiabo Feng - 11:8.2.0-16 - nbd/server: CVE-2024-7409: Close stray clients at server-stop - nbd/server: CVE-2024-7409: Drop non-negotiating clients diff --git a/target-i386-add-control-bits-support-for-LAM.patch b/target-i386-add-control-bits-support-for-LAM.patch new file mode 100644 index 0000000..d2a3974 --- /dev/null +++ b/target-i386-add-control-bits-support-for-LAM.patch @@ -0,0 +1,99 @@ +From 03e73f225c44daa067ff1c57845dcd4678897a49 Mon Sep 17 00:00:00 2001 +From: Binbin Wu +Date: Fri, 12 Jan 2024 14:00:42 +0800 +Subject: [PATCH] target/i386: add control bits support for LAM + +commit 0117067131f99acaab4f4d2cca0290c5510e37cf upstream. + +LAM uses CR3[61] and CR3[62] to configure/enable LAM on user pointers. +LAM uses CR4[28] to configure/enable LAM on supervisor pointers. + +For CR3 LAM bits, no additional handling needed: +- TCG + LAM is not supported for TCG of target-i386. helper_write_crN() and + helper_vmrun() check max physical address bits before calling + cpu_x86_update_cr3(), no change needed, i.e. CR3 LAM bits are not allowed + to be set in TCG. +- gdbstub + x86_cpu_gdb_write_register() will call cpu_x86_update_cr3() to update cr3. + Allow gdb to set the LAM bit(s) to CR3, if vcpu doesn't support LAM, + KVM_SET_SREGS will fail as other reserved bits. + +For CR4 LAM bit, its reservation depends on vcpu supporting LAM feature or +not. +- TCG + LAM is not supported for TCG of target-i386. helper_write_crN() and + helper_vmrun() check CR4 reserved bit before calling cpu_x86_update_cr4(), + i.e. CR4 LAM bit is not allowed to be set in TCG. +- gdbstub + x86_cpu_gdb_write_register() will call cpu_x86_update_cr4() to update cr4. + Mask out LAM bit on CR4 if vcpu doesn't support LAM. +- x86_cpu_reset_hold() doesn't need special handling. + +Intel-SIG: commit 0117067131f9 target/i386: add control bits support for +LAM +Backport Qemu Linear Address Masking (LAM) support. + +Signed-off-by: Binbin Wu +Tested-by: Xuelian Guo +Reviewed-by: Xiaoyao Li +Reviewed-by: Zhao Liu +Message-ID: <20240112060042.19925-3-binbin.wu@linux.intel.com> +Signed-off-by: Paolo Bonzini +[ Zhiquan Li: amend commit log ] +Signed-off-by: Zhiquan Li +--- + target/i386/cpu.h | 7 ++++++- + target/i386/helper.c | 4 ++++ + 2 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 8dbcb4a35f..b0666167d2 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -262,6 +262,7 @@ typedef enum X86Seg { + #define CR4_SMAP_MASK (1U << 21) + #define CR4_PKE_MASK (1U << 22) + #define CR4_PKS_MASK (1U << 24) ++#define CR4_LAM_SUP_MASK (1U << 28) + + #define CR4_RESERVED_MASK \ + (~(target_ulong)(CR4_VME_MASK | CR4_PVI_MASK | CR4_TSD_MASK \ +@@ -270,7 +271,8 @@ typedef enum X86Seg { + | CR4_OSFXSR_MASK | CR4_OSXMMEXCPT_MASK | CR4_UMIP_MASK \ + | CR4_LA57_MASK \ + | CR4_FSGSBASE_MASK | CR4_PCIDE_MASK | CR4_OSXSAVE_MASK \ +- | CR4_SMEP_MASK | CR4_SMAP_MASK | CR4_PKE_MASK | CR4_PKS_MASK)) ++ | CR4_SMEP_MASK | CR4_SMAP_MASK | CR4_PKE_MASK | CR4_PKS_MASK \ ++ | CR4_LAM_SUP_MASK)) + + #define DR6_BD (1 << 13) + #define DR6_BS (1 << 14) +@@ -2527,6 +2529,9 @@ static inline uint64_t cr4_reserved_bits(CPUX86State *env) + if (!(env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_PKS)) { + reserved_bits |= CR4_PKS_MASK; + } ++ if (!(env->features[FEAT_7_1_EAX] & CPUID_7_1_EAX_LAM)) { ++ reserved_bits |= CR4_LAM_SUP_MASK; ++ } + return reserved_bits; + } + +diff --git a/target/i386/helper.c b/target/i386/helper.c +index 2070dd0dda..1da7a7d315 100644 +--- a/target/i386/helper.c ++++ b/target/i386/helper.c +@@ -219,6 +219,10 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4) + new_cr4 &= ~CR4_PKS_MASK; + } + ++ if (!(env->features[FEAT_7_1_EAX] & CPUID_7_1_EAX_LAM)) { ++ new_cr4 &= ~CR4_LAM_SUP_MASK; ++ } ++ + env->cr[4] = new_cr4; + env->hflags = hflags; + +-- +2.41.0.windows.1 + diff --git a/target-i386-add-support-for-LAM-in-CPUID-enumeration.patch b/target-i386-add-support-for-LAM-in-CPUID-enumeration.patch new file mode 100644 index 0000000..cbe303d --- /dev/null +++ b/target-i386-add-support-for-LAM-in-CPUID-enumeration.patch @@ -0,0 +1,69 @@ +From 8bc3dd094a9daa348d49436dc4d0867b7b514ba7 Mon Sep 17 00:00:00 2001 +From: Robert Hoo +Date: Fri, 12 Jan 2024 14:00:41 +0800 +Subject: [PATCH] target/i386: add support for LAM in CPUID enumeration + +commit ba6780905943696d790cc880c8e5684b51f027fe upstream. + +Linear Address Masking (LAM) is a new Intel CPU feature, which allows +software to use of the untranslated address bits for metadata. + +The bit definition: +CPUID.(EAX=7,ECX=1):EAX[26] + +Add CPUID definition for LAM. + +Note LAM feature is not supported for TCG of target-i386, LAM CPIUD bit +will not be added to TCG_7_1_EAX_FEATURES. + +More info can be found in Intel ISE Chapter "LINEAR ADDRESS MASKING(LAM)" +https://cdrdv2.intel.com/v1/dl/getContent/671368 + +Intel-SIG: commit ba6780905943 target/i386: add support for LAM in CPUID +enumeration +Backport Qemu Linear Address Masking (LAM) support. + +Signed-off-by: Robert Hoo +Co-developed-by: Binbin Wu +Signed-off-by: Binbin Wu +Tested-by: Xuelian Guo +Reviewed-by: Xiaoyao Li +Reviewed-by: Zhao Liu +Message-ID: <20240112060042.19925-2-binbin.wu@linux.intel.com> +Signed-off-by: Paolo Bonzini +[ Zhiquan Li: amend commit log ] +Signed-off-by: Zhiquan Li +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 711370d9b8..19ebd49e8c 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -967,7 +967,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + "fsrc", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, "amx-fp16", NULL, "avx-ifma", +- NULL, NULL, NULL, NULL, ++ NULL, NULL, "lam", NULL, + NULL, NULL, NULL, NULL, + }, + .cpuid = { +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 6993552cd9..8dbcb4a35f 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -926,6 +926,8 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, + #define CPUID_7_1_EAX_AMX_FP16 (1U << 21) + /* Support for VPMADD52[H,L]UQ */ + #define CPUID_7_1_EAX_AVX_IFMA (1U << 23) ++/* Linear Address Masking */ ++#define CPUID_7_1_EAX_LAM (1U << 26) + + /* Support for VPDPB[SU,UU,SS]D[,S] */ + #define CPUID_7_1_EDX_AVX_VNNI_INT8 (1U << 4) +-- +2.41.0.windows.1 + diff --git a/target-sparc-use-signed-denominator-in-sdiv-helper.patch b/target-sparc-use-signed-denominator-in-sdiv-helper.patch new file mode 100644 index 0000000..50ab7ee --- /dev/null +++ b/target-sparc-use-signed-denominator-in-sdiv-helper.patch @@ -0,0 +1,41 @@ +From a222f9c1eea20db470c55f534d85987df27a1654 Mon Sep 17 00:00:00 2001 +From: Xu Zheng +Date: Fri, 19 Jul 2024 22:45:21 +0800 +Subject: [PATCH] target/sparc: use signed denominator in sdiv helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The result has to be done with the signed denominator (b32) instead of +the unsigned value passed in argument (b). + +cherry-pick from 6b4965373e561b77f91cfbdf41353635c9661358 +Fixes: 1326010322d6 ("target/sparc: Remove CC_OP_DIV") +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2319 +Signed-off-by: Clément Chigot +Reviewed-by: Richard Henderson +Message-Id: <20240606144331.698361-1-chigot@adacore.com> +Signed-off-by: Richard Henderson +(cherry picked from commit 6b4965373e561b77f91cfbdf41353635c9661358) +Signed-off-by: Michael Tokarev +Signed-off-by: Xu Zheng +--- + target/sparc/helper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/sparc/helper.c b/target/sparc/helper.c +index bd10b60e4b..8820c59e7c 100644 +--- a/target/sparc/helper.c ++++ b/target/sparc/helper.c +@@ -121,7 +121,7 @@ uint64_t helper_sdiv(CPUSPARCState *env, target_ulong a, target_ulong b) + return (uint32_t)(b32 < 0 ? INT32_MAX : INT32_MIN) | (-1ull << 32); + } + +- a64 /= b; ++ a64 /= b32; + r = a64; + if (unlikely(r != a64)) { + return (uint32_t)(a64 < 0 ? INT32_MIN : INT32_MAX) | (-1ull << 32); +-- +2.41.0.windows.1 + diff --git a/vl-fix-type-is-NULL-in-vga-help.patch b/vl-fix-type-is-NULL-in-vga-help.patch new file mode 100644 index 0000000..9215ef8 --- /dev/null +++ b/vl-fix-type-is-NULL-in-vga-help.patch @@ -0,0 +1,49 @@ +From ef42d79d805e430e24df57d46c156f9a7e3e1bed Mon Sep 17 00:00:00 2001 +From: qihao +Date: Thu, 25 Jul 2024 14:11:12 +0800 +Subject: [PATCH] vl: fix "type is NULL" in -vga help +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from a99dc9cd611cbaf10edee6260272e299626d0871 + +Don't pass NULL to module_object_class_by_name(), when the interface is +unavailable. + +Signed-off-by: Marc-André Lureau +Reviewed-by: Philippe Mathieu-Daudé +Message-ID: <20240715114420.2062870-1-marcandre.lureau@redhat.com> +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: qihao_yewu +--- + system/vl.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/system/vl.c b/system/vl.c +index 165c3cae8a..8e3357c578 100644 +--- a/system/vl.c ++++ b/system/vl.c +@@ -994,9 +994,16 @@ static bool vga_interface_available(VGAInterfaceType t) + const VGAInterfaceInfo *ti = &vga_interfaces[t]; + + assert(t < VGA_TYPE_MAX); +- return !ti->class_names[0] || +- module_object_class_by_name(ti->class_names[0]) || +- module_object_class_by_name(ti->class_names[1]); ++ ++ if (!ti->class_names[0] || module_object_class_by_name(ti->class_names[0])) { ++ return true; ++ } ++ ++ if (ti->class_names[1] && module_object_class_by_name(ti->class_names[1])) { ++ return true; ++ } ++ ++ return false; + } + + static const char * +-- +2.41.0.windows.1 + -- Gitee