diff --git a/1133-newfeature-hw-vfio-add-hct-device-based-mediated-use.patch b/1133-newfeature-hw-vfio-add-hct-device-based-mediated-use.patch new file mode 100644 index 0000000000000000000000000000000000000000..455bf827e6a17948fabd2f7ea85bd51d32b95397 --- /dev/null +++ b/1133-newfeature-hw-vfio-add-hct-device-based-mediated-use.patch @@ -0,0 +1,631 @@ +From c6da8933127e3c32a7ebdf276c40d7a68ae0aa01 Mon Sep 17 00:00:00 2001 +From: Yabin Li +Date: Fri, 4 Aug 2023 21:09:08 +0800 +Subject: [PATCH 1/1] [newfeature]hw/vfio: add hct device based mediated used + for ccp support. + +Change-Id: I0fa86e74996fe4e81abc65bdf506d06095c31abc +--- + hw/vfio/Kconfig | 6 + + hw/vfio/hct.c | 583 ++++++++++++++++++++++++++++++++++++++++++++ + hw/vfio/meson.build | 1 + + 3 files changed, 590 insertions(+) + create mode 100644 hw/vfio/hct.c + +diff --git a/hw/vfio/Kconfig b/hw/vfio/Kconfig +index 7cdba0560a..5f0d3c2d2b 100644 +--- a/hw/vfio/Kconfig ++++ b/hw/vfio/Kconfig +@@ -41,3 +41,9 @@ config VFIO_IGD + bool + default y if PC_PCI + depends on VFIO_PCI ++ ++config VFIO_HCT ++ bool ++ default y ++ select VFIO ++ depends on LINUX && PCI +diff --git a/hw/vfio/hct.c b/hw/vfio/hct.c +new file mode 100644 +index 0000000000..c31d315073 +--- /dev/null ++++ b/hw/vfio/hct.c +@@ -0,0 +1,583 @@ ++/* ++ * vfio based mediated ccp(hct) assignment support ++ * ++ * Copyright 2023 HYGON Corp. ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or (at ++ * your option) any later version. See the COPYING file in the top-level ++ * directory. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "qemu/osdep.h" ++#include "qemu/queue.h" ++#include "qemu/main-loop.h" ++#include "qemu-common.h" ++#include "qemu/log.h" ++#include "trace.h" ++#include "hw/pci/pci.h" ++#include "hw/vfio/pci.h" ++#include "qemu/range.h" ++#include "sysemu/kvm.h" ++#include "hw/pci/msi.h" ++#include "qemu/error-report.h" ++#include "qapi/error.h" ++#include "hw/qdev-properties.h" ++ ++#define MAX_CCP_CNT 16 ++#define PAGE_SIZE 4096 ++#define HCT_SHARED_MEMORY_SIZE (PAGE_SIZE * MAX_CCP_CNT) ++#define CCP_INDEX_BYTES 4 ++#define PATH_MAX 4096 ++#define TYPE_HCT_DEV "hct" ++#define PCI_HCT_DEV(obj) OBJECT_CHECK(HCTDevState, (obj), TYPE_HCT_DEV) ++#define HCT_MMIO_SIZE (1 << 20) ++#define HCT_MAX_PASID (1 << 8) ++ ++#define PCI_VENDOR_ID_HYGON_CCP 0x1d94 ++#define PCI_DEVICE_ID_HYGON_CCP 0x1468 ++ ++#define HCT_SHARE_DEV "/dev/hct_share" ++ ++#define HCT_VERSION_STRING "0.2" ++#define DEF_VERSION_STRING "0.1" ++#define VERSION_SIZE 16 ++ ++#define HCT_SHARE_IOC_TYPE 'C' ++#define HCT_SHARE_OP_TYPE 0x01 ++#define HCT_SHARE_OP _IOWR(HCT_SHARE_IOC_TYPE, \ ++ HCT_SHARE_OP_TYPE, \ ++ struct hct_dev_ctrl) ++#define HCT_SHARE_OP_DMA_MAP 0x01 ++#define HCT_SHARE_OP_GET_ID 0x03 ++#define HCT_SHARE_OP_GET_PASID 0x04 ++#define HCT_SHARE_OP_DMA_UNMAP 0x05 ++#define HCT_SHARE_OP_GET_VERSION 0x06 ++ ++/* BARS */ ++#define HCT_REG_BAR_IDX 2 ++#define HCT_SHARED_BAR_IDX 3 ++#define HCT_PASID_BAR_IDX 4 ++ ++#define PASID_OFFSET 40 ++ ++static volatile struct hct_data { ++ int init; ++ int hct_fd; ++ unsigned long pasid; ++ uint8_t *pasid_memory; ++ uint8_t *hct_shared_memory; ++ uint8_t ccp_index[MAX_CCP_CNT]; ++ uint8_t ccp_cnt; ++} hct_data; ++ ++typedef struct SharedDevice { ++ PCIDevice dev; ++ int shared_memory_offset; ++} SharedDevice; ++ ++typedef struct HctDevState { ++ SharedDevice sdev; ++ VFIODevice vdev; ++ MemoryRegion mmio; ++ MemoryRegion shared; ++ MemoryRegion pasid; ++ void *maps[PCI_NUM_REGIONS]; ++} HCTDevState; ++ ++struct hct_dev_ctrl { ++ unsigned char op; ++ unsigned char rsvd[3]; ++ union { ++ unsigned char version[VERSION_SIZE]; ++ struct { ++ unsigned long vaddr; ++ unsigned long iova; ++ unsigned long size; ++ }; ++ unsigned int id; ++ }; ++}; ++ ++static int pasid_get_and_init(HCTDevState *state) ++{ ++ struct hct_dev_ctrl ctrl; ++ int ret; ++ ++ ctrl.op = HCT_SHARE_OP_GET_PASID; ++ ctrl.id = -1; ++ ret = ioctl(hct_data.hct_fd, HCT_SHARE_OP, &ctrl); ++ if (ret < 0) { ++ ret = -errno; ++ error_report("GET_PASID fail: %d", -errno); ++ goto out; ++ } ++ ++ *hct_data.pasid_memory = ctrl.id; ++ hct_data.pasid = ctrl.id; ++ ++out: ++ return ret; ++} ++ ++static const MemoryRegionOps hct_mmio_ops = { ++ .endianness = DEVICE_NATIVE_ENDIAN, ++ .valid = { ++ .min_access_size = 4, ++ .max_access_size = 4, ++ }, ++}; ++ ++static void vfio_hct_put_device(HCTDevState *state) ++{ ++ g_free(state->vdev.name); ++ vfio_put_base_device(&state->vdev); ++ return; ++} ++ ++static void vfio_hct_exit(PCIDevice *dev) ++{ ++ HCTDevState *state = PCI_HCT_DEV(dev); ++ ++ vfio_hct_put_device(state); ++ vfio_put_group(state->vdev.group); ++ if (hct_data.hct_fd) { ++ qemu_close(hct_data.hct_fd); ++ hct_data.hct_fd = 0; ++ } ++} ++ ++static Property vfio_hct_properties[] = { ++ DEFINE_PROP_STRING("sysfsdev", HCTDevState, vdev.sysfsdev), ++ DEFINE_PROP_END_OF_LIST(), ++}; ++ ++static void vfio_ccp_compute_needs_reset(VFIODevice *vdev) ++{ ++ vdev->needs_reset = false; ++} ++ ++struct VFIODeviceOps vfio_ccp_ops = { ++ .vfio_compute_needs_reset = vfio_ccp_compute_needs_reset, ++}; ++ ++static void vfio_hct_get_device(VFIOGroup *group, HCTDevState *state, ++ Error **errp) ++{ ++ if (vfio_get_device(group, state->vdev.name, &state->vdev, errp)) ++ return; ++ ++ state->vdev.ops = &vfio_ccp_ops; ++ state->vdev.dev = &state->sdev.dev.qdev; ++ ++ return; ++} ++ ++static VFIOGroup *vfio_hct_get_group(HCTDevState *state, Error **errp) ++{ ++ char *tmp, group_path[PATH_MAX]; ++ ssize_t len; ++ int groupid; ++ ++ tmp = g_strdup_printf("%s/iommu_group", state->vdev.sysfsdev); ++ len = readlink(tmp, group_path, sizeof(group_path)); ++ g_free(tmp); ++ ++ if (len <= 0 || len >= sizeof(group_path)) { ++ error_setg(errp, "vfio: no iommu_group found"); ++ return NULL; ++ } ++ ++ group_path[len] = 0; ++ ++ if (sscanf(basename(group_path), "%d", &groupid) != 1) { ++ error_setg(errp, "vfio: failed to read %s", group_path); ++ return NULL; ++ } ++ ++ return vfio_get_group(groupid, &address_space_memory, errp); ++} ++ ++/* create BAR2, BAR3 and BAR4 space for the virtual machine. */ ++static int vfio_hct_region_mmap(HCTDevState *state) ++{ ++ int ret; ++ int i; ++ struct vfio_region_info *info; ++ ++ for (i = 0; i < PCI_ROM_SLOT; i++) { ++ ret = vfio_get_region_info(&state->vdev, i, &info); ++ if (ret) ++ goto out; ++ ++ if (info->size) { ++ state->maps[i] = mmap(NULL, info->size, ++ PROT_READ | PROT_WRITE, MAP_SHARED, ++ state->vdev.fd, info->offset); ++ if (state->maps[i] == MAP_FAILED) { ++ ret = -errno; ++ error_report("vfio mmap fail\n"); ++ goto out; ++ } ++ } ++ g_free(info); ++ } ++ ++ memory_region_init_io(&state->mmio, OBJECT(state), &hct_mmio_ops, ++ state, "hct mmio", HCT_MMIO_SIZE); ++ memory_region_init_ram_device_ptr(&state->mmio, OBJECT(state), ++ "hct mmio", HCT_MMIO_SIZE, ++ state->maps[HCT_REG_BAR_IDX]); ++ ++ memory_region_init_io(&state->shared, OBJECT(state), &hct_mmio_ops, ++ state, "hct shared memory", PAGE_SIZE); ++ memory_region_init_ram_device_ptr(&state->shared, OBJECT(state), ++ "hct shared memory", PAGE_SIZE, ++ (void *)hct_data.hct_shared_memory + ++ state->sdev.shared_memory_offset * ++ PAGE_SIZE); ++ ++ memory_region_init_io(&state->pasid, OBJECT(state), &hct_mmio_ops, ++ state, "hct pasid", PAGE_SIZE); ++ memory_region_init_ram_device_ptr(&state->pasid, OBJECT(state), ++ "hct pasid", PAGE_SIZE, ++ hct_data.pasid_memory); ++ ++ pci_register_bar(&state->sdev.dev, HCT_REG_BAR_IDX, ++ PCI_BASE_ADDRESS_SPACE_MEMORY, &state->mmio); ++ pci_register_bar(&state->sdev.dev, HCT_SHARED_BAR_IDX, ++ PCI_BASE_ADDRESS_SPACE_MEMORY, &state->shared); ++ pci_register_bar(&state->sdev.dev, HCT_PASID_BAR_IDX, ++ PCI_BASE_ADDRESS_SPACE_MEMORY, &state->pasid); ++out: ++ return ret; ++} ++ ++static int hct_check_duplicated_index(int index) ++{ ++ int cnt; ++ for (cnt = 0; cnt < hct_data.ccp_cnt; cnt++) { ++ if (hct_data.ccp_index[cnt] == index) { ++ error_report("many mdev shouldn't be mapped to one ccp in a virtual machine!\n"); ++ return 1; ++ } ++ } ++ ++ hct_data.ccp_index[hct_data.ccp_cnt++] = index; ++ return 0; ++} ++ ++static int hct_get_ccp_index(HCTDevState *state) ++{ ++ char path[PATH_MAX]; ++ char buf[CCP_INDEX_BYTES]; ++ int fd; ++ int ret; ++ int ccp_index; ++ ++ snprintf(path, PATH_MAX, "%s/vendor/id", state->vdev.sysfsdev); ++ fd = qemu_open_old(path, O_RDONLY); ++ if (fd < 0) { ++ error_report("open %s fail\n", path); ++ return -errno; ++ } ++ ++ ret = read(fd, buf, sizeof(buf)); ++ if (ret < 0) { ++ ret = -errno; ++ error_report("read %s fail\n", path); ++ goto out; ++ } ++ ++ if (1 != sscanf(buf, "%d", &ccp_index)) { ++ ret = -errno; ++ error_report("format addr %s fail\n", buf); ++ goto out; ++ } ++ ++ if (!hct_check_duplicated_index(ccp_index)) { ++ state->sdev.shared_memory_offset = ccp_index; ++ } else { ++ ret = -1; ++ } ++ ++out: ++ qemu_close(fd); ++ return ret; ++} ++ ++static int hct_api_version_check(void) ++{ ++ struct hct_dev_ctrl ctrl; ++ int ret; ++ ++ ctrl.op = HCT_SHARE_OP_GET_VERSION; ++ memcpy(ctrl.version, DEF_VERSION_STRING, sizeof(DEF_VERSION_STRING)); ++ ret = ioctl(hct_data.hct_fd, HCT_SHARE_OP, &ctrl); ++ if (ret < 0) { ++ error_report("ret %d, errno %d: fail to get hct.ko version, please update hct.ko to version 0.2.\n", ++ ret, errno); ++ return -1; ++ } else if (memcmp(ctrl.version, HCT_VERSION_STRING, sizeof(HCT_VERSION_STRING)) < 0) { ++ error_report("The API version %s is larger than hct.ko version %s, " ++ "please update hct.ko to version 0.2\n", HCT_VERSION_STRING, ctrl.version); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int hct_shared_memory_init(void) ++{ ++ int ret = 0; ++ ++ hct_data.hct_shared_memory = mmap(NULL, HCT_SHARED_MEMORY_SIZE, ++ PROT_READ | PROT_WRITE, MAP_SHARED, ++ hct_data.hct_fd, 0); ++ if (hct_data.hct_shared_memory == MAP_FAILED) { ++ ret = -errno; ++ error_report("map hct shared memory fail\n"); ++ goto out; ++ } ++ ++out: ++ return ret; ++} ++ ++static void hct_listener_region_add(MemoryListener *listener, ++ MemoryRegionSection *section) ++{ ++ struct hct_dev_ctrl ctrl; ++ hwaddr iova; ++ Int128 llend, llsize; ++ void *vaddr; ++ int ret; ++ ++ iova = REAL_HOST_PAGE_ALIGN(section->offset_within_address_space); ++ llend = int128_make64(section->offset_within_address_space); ++ llend = int128_add(llend, section->size); ++ llend = int128_add(llend, int128_exts64(qemu_real_host_page_mask)); ++ ++ if (int128_ge(int128_make64(iova), llend)) { ++ return; ++ } ++ ++ if(!section->mr->ram) { ++ return; ++ } ++ ++ vaddr = memory_region_get_ram_ptr(section->mr) + ++ section->offset_within_region + ++ (iova - section->offset_within_address_space); ++ llsize = int128_sub(llend, int128_make64(iova)); ++ ++ ctrl.op = HCT_SHARE_OP_DMA_MAP; ++ ctrl.iova = iova | (hct_data.pasid << PASID_OFFSET); ++ ctrl.vaddr = (uint64_t)vaddr; ++ ctrl.size = llsize; ++ ret = ioctl(hct_data.hct_fd, HCT_SHARE_OP, &ctrl); ++ if (ret < 0) ++ error_report("VIFO_MAP_DMA: %d, iova=%lx", -errno, iova); ++} ++ ++static void hct_listener_region_del(MemoryListener *listener, ++ MemoryRegionSection *section) ++{ ++ struct hct_dev_ctrl ctrl; ++ hwaddr iova; ++ Int128 llend, llsize; ++ int ret; ++ ++ iova = REAL_HOST_PAGE_ALIGN(section->offset_within_address_space); ++ llend = int128_make64(section->offset_within_address_space); ++ llend = int128_add(llend, section->size); ++ llend = int128_add(llend, int128_exts64(qemu_real_host_page_mask)); ++ ++ if (int128_ge(int128_make64(iova), llend)) { ++ return; ++ } ++ ++ if(!section->mr->ram) { ++ return; ++ } ++ ++ llsize = int128_sub(llend, int128_make64(iova)); ++ ++ ctrl.op = HCT_SHARE_OP_DMA_UNMAP; ++ ctrl.iova = iova | (hct_data.pasid << PASID_OFFSET); ++ ctrl.size = llsize; ++ ret = ioctl(hct_data.hct_fd, HCT_SHARE_OP, &ctrl); ++ if (ret < 0) ++ error_report("VIFO_UNMAP_DMA: %d", -errno); ++ ++} ++ ++static MemoryListener hct_memory_listener = { ++ .region_add = hct_listener_region_add, ++ .region_del = hct_listener_region_del, ++}; ++ ++static void hct_data_uninit(HCTDevState *state) ++{ ++ if (hct_data.hct_fd) { ++ qemu_close(hct_data.hct_fd); ++ hct_data.hct_fd = 0; ++ } ++ ++ if (hct_data.pasid) { ++ hct_data.pasid = 0; ++ } ++ ++ if (hct_data.pasid_memory) { ++ munmap(hct_data.pasid_memory, PAGE_SIZE); ++ hct_data.pasid_memory = NULL; ++ } ++ ++ if (hct_data.hct_shared_memory) { ++ munmap((void *)hct_data.hct_shared_memory, HCT_SHARED_MEMORY_SIZE); ++ hct_data.hct_shared_memory = NULL; ++ } ++ ++ memory_listener_unregister(&hct_memory_listener); ++} ++ ++static int hct_data_init(HCTDevState *state) ++{ ++ int ret; ++ ++ if (hct_data.init == 0) { ++ ++ hct_data.hct_fd = qemu_open_old(HCT_SHARE_DEV, O_RDWR); ++ if (hct_data.hct_fd < 0) { ++ error_report("fail to open %s, errno %d.", HCT_SHARE_DEV, errno); ++ ret = -errno; ++ goto out; ++ } ++ ++ /* The hct.ko version number needs not to be less than 0.2. */ ++ ret = hct_api_version_check(); ++ if (ret) ++ goto out; ++ ++ /* assign a page to the virtual BAR3 of each CCP. */ ++ ret = hct_shared_memory_init(); ++ if (ret) ++ goto out; ++ ++ hct_data.pasid_memory = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ++ if (hct_data.pasid_memory < 0) ++ goto unmap_shared_memory_exit; ++ ++ /* assign a unique pasid to each virtual machine. */ ++ ret = pasid_get_and_init(state); ++ if (ret < 0) ++ goto unmap_pasid_memory_exit; ++ ++ /* perform DMA_MAP and DMA_UNMAP operations on all memories of the virtual machine. */ ++ memory_listener_register(&hct_memory_listener, &address_space_memory); ++ ++ hct_data.init = 1; ++ } ++ ++ return hct_get_ccp_index(state); ++ ++unmap_pasid_memory_exit: ++ munmap(hct_data.pasid_memory, PAGE_SIZE); ++ ++unmap_shared_memory_exit: ++ munmap((void *)hct_data.hct_shared_memory, HCT_SHARED_MEMORY_SIZE); ++ ++out: ++ return ret; ++} ++ ++/* When device is loaded */ ++static void vfio_hct_realize(PCIDevice *pci_dev, Error **errp) ++{ ++ int ret; ++ char *mdevid; ++ Error *err = NULL; ++ VFIOGroup *group; ++ HCTDevState *state = PCI_HCT_DEV(pci_dev); ++ ++ /* parsing mdev device name from startup scripts */ ++ mdevid = g_path_get_basename(state->vdev.sysfsdev); ++ state->vdev.name = g_strdup_printf("%s", mdevid); ++ ++ ret = hct_data_init(state); ++ if (ret < 0) { ++ g_free(state->vdev.name); ++ goto out; ++ } ++ ++ group = vfio_hct_get_group(state, &err); ++ if (!group) { ++ g_free(state->vdev.name); ++ goto data_uninit_out; ++ } ++ ++ vfio_hct_get_device(group, state, &err); ++ if (err) { ++ goto put_group_out; ++ } ++ ++ ret = vfio_hct_region_mmap(state); ++ if (ret < 0) ++ goto put_device_out; ++ ++ return; ++ ++put_device_out: ++ vfio_hct_put_device(state); ++ ++put_group_out: ++ vfio_put_group(group); ++ ++data_uninit_out: ++ hct_data_uninit(state); ++ ++out: ++ return; ++} ++ ++static void hct_dev_class_init(ObjectClass *klass, void *data) ++{ ++ DeviceClass *dc = DEVICE_CLASS(klass); ++ PCIDeviceClass *pdc = PCI_DEVICE_CLASS(klass); ++ ++ dc->desc = "HCT Device"; ++ device_class_set_props(dc, vfio_hct_properties); ++ ++ pdc->realize = vfio_hct_realize; ++ pdc->exit = vfio_hct_exit; ++ pdc->vendor_id = PCI_VENDOR_ID_HYGON_CCP; ++ pdc->device_id = PCI_DEVICE_ID_HYGON_CCP; ++ pdc->class_id = PCI_CLASS_CRYPT_OTHER; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); ++ ++ return; ++} ++ ++static const TypeInfo pci_hct_info = { ++ .name = TYPE_HCT_DEV, ++ .parent = TYPE_PCI_DEVICE, ++ .instance_size = sizeof(HCTDevState), ++ .class_init = hct_dev_class_init, ++ .interfaces = (InterfaceInfo[]) { ++ { INTERFACE_CONVENTIONAL_PCI_DEVICE }, ++ { }, ++ }, ++}; ++ ++static void hct_register_types(void) ++{ ++ type_register_static(&pci_hct_info); ++} ++ ++type_init(hct_register_types); +diff --git a/hw/vfio/meson.build b/hw/vfio/meson.build +index da9af297a0..50e5631057 100644 +--- a/hw/vfio/meson.build ++++ b/hw/vfio/meson.build +@@ -15,5 +15,6 @@ vfio_ss.add(when: 'CONFIG_VFIO_XGMAC', if_true: files('calxeda-xgmac.c')) + vfio_ss.add(when: 'CONFIG_VFIO_AMD_XGBE', if_true: files('amd-xgbe.c')) + vfio_ss.add(when: 'CONFIG_VFIO_AP', if_true: files('ap.c')) + vfio_ss.add(when: 'CONFIG_VFIO_IGD', if_true: files('igd.c')) ++vfio_ss.add(when: 'CONFIG_VFIO_HCT', if_true: files('hct.c')) + + specific_ss.add_all(when: 'CONFIG_VFIO', if_true: vfio_ss) +-- +2.17.1 + diff --git a/1134-newfeature-hw-vfio-hct-Change-MAX_CCP_CNT-from-16-to.patch b/1134-newfeature-hw-vfio-hct-Change-MAX_CCP_CNT-from-16-to.patch new file mode 100644 index 0000000000000000000000000000000000000000..e84c627e5f5318c8bda4f5118cf356df09c9d190 --- /dev/null +++ b/1134-newfeature-hw-vfio-hct-Change-MAX_CCP_CNT-from-16-to.patch @@ -0,0 +1,52 @@ +From 388c7d9dc317b915a4316d08838d850eeb1c23ae Mon Sep 17 00:00:00 2001 +From: Yabin Li +Date: Tue, 23 Apr 2024 15:38:48 +0800 +Subject: [PATCH 2/5] [newfeature]hw/vfio/hct: Change MAX_CCP_CNT from 16 to + 48. + +Change-Id: I177ea5ea29c0ceaa3d0dfbbb5e6a594808280cb9 +--- + hw/vfio/hct.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/hw/vfio/hct.c b/hw/vfio/hct.c +index c31d315073..2b7a09c564 100644 +--- a/hw/vfio/hct.c ++++ b/hw/vfio/hct.c +@@ -29,7 +29,7 @@ + #include "qapi/error.h" + #include "hw/qdev-properties.h" + +-#define MAX_CCP_CNT 16 ++#define MAX_CCP_CNT 48 + #define PAGE_SIZE 4096 + #define HCT_SHARED_MEMORY_SIZE (PAGE_SIZE * MAX_CCP_CNT) + #define CCP_INDEX_BYTES 4 +@@ -44,7 +44,7 @@ + + #define HCT_SHARE_DEV "/dev/hct_share" + +-#define HCT_VERSION_STRING "0.2" ++#define HCT_VERSION_STRING "0.5" + #define DEF_VERSION_STRING "0.1" + #define VERSION_SIZE 16 + +@@ -320,12 +320,11 @@ static int hct_api_version_check(void) + memcpy(ctrl.version, DEF_VERSION_STRING, sizeof(DEF_VERSION_STRING)); + ret = ioctl(hct_data.hct_fd, HCT_SHARE_OP, &ctrl); + if (ret < 0) { +- error_report("ret %d, errno %d: fail to get hct.ko version, please update hct.ko to version 0.2.\n", +- ret, errno); ++ error_report("ret %d, errno %d: fail to get hct.ko version.\n", ret, errno); + return -1; + } else if (memcmp(ctrl.version, HCT_VERSION_STRING, sizeof(HCT_VERSION_STRING)) < 0) { +- error_report("The API version %s is larger than hct.ko version %s, " +- "please update hct.ko to version 0.2\n", HCT_VERSION_STRING, ctrl.version); ++ error_report("The hct.ko version is %s, please upgrade to version %s or higher.\n", ++ ctrl.version, HCT_VERSION_STRING); + return -1; + } + +-- +2.17.1 + diff --git a/1135-bugfix-hw-vfio-hct-fix-ccp-index-error-caused-by-uni.patch b/1135-bugfix-hw-vfio-hct-fix-ccp-index-error-caused-by-uni.patch new file mode 100644 index 0000000000000000000000000000000000000000..30a01d3b8e3cf49ef125c0f19434e9296577ed2a --- /dev/null +++ b/1135-bugfix-hw-vfio-hct-fix-ccp-index-error-caused-by-uni.patch @@ -0,0 +1,29 @@ +From 7efdb831fe471d431bdb0ea7301290d9c3396052 Mon Sep 17 00:00:00 2001 +From: yangdepei +Date: Tue, 27 Aug 2024 14:06:14 +0800 +Subject: [PATCH 3/5] [bugfix]hw/vfio/hct: fix ccp index error caused by + uninitialized buf + +Change-Id: I239aff462256930df696969c885799c0506f4f68 +--- + hw/vfio/hct.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/vfio/hct.c b/hw/vfio/hct.c +index 2b7a09c564..3b8d8e44ba 100644 +--- a/hw/vfio/hct.c ++++ b/hw/vfio/hct.c +@@ -274,8 +274,8 @@ static int hct_check_duplicated_index(int index) + + static int hct_get_ccp_index(HCTDevState *state) + { +- char path[PATH_MAX]; +- char buf[CCP_INDEX_BYTES]; ++ char path[PATH_MAX] = {0}; ++ char buf[CCP_INDEX_BYTES] = {0}; + int fd; + int ret; + int ccp_index; +-- +2.17.1 + diff --git a/1136-newfeature-hw-vfio-hct-sharing-CCP-resources-between.patch b/1136-newfeature-hw-vfio-hct-sharing-CCP-resources-between.patch new file mode 100644 index 0000000000000000000000000000000000000000..90cb499ca180ec639aab60b550c078449219b4cb --- /dev/null +++ b/1136-newfeature-hw-vfio-hct-sharing-CCP-resources-between.patch @@ -0,0 +1,268 @@ +From b5c95783ca208a45631bc78bfbe002619a4678f3 Mon Sep 17 00:00:00 2001 +From: Your Name +Date: Fri, 1 Nov 2024 11:36:04 +0800 +Subject: [PATCH 4/5] [newfeature]hw/vfio/hct: sharing CCP resources between + host and virtual machines. + +Change-Id: I24f0dd7db004a437c57e6f2efc0012c07cf99fce +--- + hw/vfio/hct.c | 156 ++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 106 insertions(+), 50 deletions(-) + +diff --git a/hw/vfio/hct.c b/hw/vfio/hct.c +index 3b8d8e44ba..a78973bebf 100644 +--- a/hw/vfio/hct.c ++++ b/hw/vfio/hct.c +@@ -30,6 +30,7 @@ + #include "hw/qdev-properties.h" + + #define MAX_CCP_CNT 48 ++#define DEF_CCP_CNT_MAX 16 + #define PAGE_SIZE 4096 + #define HCT_SHARED_MEMORY_SIZE (PAGE_SIZE * MAX_CCP_CNT) + #define CCP_INDEX_BYTES 4 +@@ -44,8 +45,10 @@ + + #define HCT_SHARE_DEV "/dev/hct_share" + +-#define HCT_VERSION_STRING "0.5" + #define DEF_VERSION_STRING "0.1" ++#define HCT_VERSION_STR_02 "0.2" ++#define HCT_VERSION_STR_05 "0.5" ++#define HCT_VERSION_STR_06 "0.6" + #define VERSION_SIZE 16 + + #define HCT_SHARE_IOC_TYPE 'C' +@@ -65,13 +68,16 @@ + #define HCT_PASID_BAR_IDX 4 + + #define PASID_OFFSET 40 ++#define HCT_PASID_MEM_GID_OFFSET 1024 + + static volatile struct hct_data { + int init; + int hct_fd; + unsigned long pasid; ++ unsigned long hct_shared_size; + uint8_t *pasid_memory; + uint8_t *hct_shared_memory; ++ uint8_t hct_version[VERSION_SIZE]; + uint8_t ccp_index[MAX_CCP_CNT]; + uint8_t ccp_cnt; + } hct_data; +@@ -91,35 +97,87 @@ typedef struct HctDevState { + } HCTDevState; + + struct hct_dev_ctrl { +- unsigned char op; +- unsigned char rsvd[3]; +- union { +- unsigned char version[VERSION_SIZE]; +- struct { +- unsigned long vaddr; +- unsigned long iova; +- unsigned long size; +- }; +- unsigned int id; +- }; ++ unsigned char op; ++ unsigned char rsvd[3]; ++ union { ++ unsigned char version[VERSION_SIZE]; ++ unsigned int id; ++ unsigned int pasid; ++ struct { ++ unsigned long vaddr; ++ unsigned long iova; ++ unsigned long size; ++ }; ++ }; + }; + ++enum MDEV_USED_TYPE { ++ MDEV_USED_FOR_HOST, ++ MDEV_USED_FOR_VM, ++ MDEV_USED_UNDEF ++}; ++ ++static int hct_get_sysfs_value(const char *path, int *val) ++{ ++ FILE *fp = NULL; ++ char buf[CCP_INDEX_BYTES] = {0}; ++ unsigned long v; ++ ++ fp = fopen(path, "r"); ++ if (!fp) { ++ error_report("fail to open %s, errno %d.\n", path, errno); ++ return -EINVAL; ++ } ++ ++ if (fgets(buf, sizeof(buf), fp) == NULL) { ++ fclose(fp); ++ return -EINVAL; ++ } ++ ++ if (1 != sscanf(buf, "%lu", &v)) { ++ fclose(fp); ++ return -EINVAL; ++ } ++ ++ *val = (int)v; ++ ++ fclose(fp); ++ return 0; ++} ++ ++/* ++ * the memory layout of pasid_memory is as follows: ++ * offset -- 0 1024 4096 ++ * a page -- |pasid(8B) --- |gid(8B) --- | ++ */ + static int pasid_get_and_init(HCTDevState *state) + { ++ void *base = (void *)hct_data.pasid_memory; + struct hct_dev_ctrl ctrl; ++ unsigned long *gid = NULL; + int ret; + + ctrl.op = HCT_SHARE_OP_GET_PASID; +- ctrl.id = -1; + ret = ioctl(hct_data.hct_fd, HCT_SHARE_OP, &ctrl); + if (ret < 0) { + ret = -errno; +- error_report("GET_PASID fail: %d", -errno); ++ error_report("get pasid fail, errno: %d.", errno); ++ goto out; ++ } ++ ++ hct_data.pasid = (unsigned long)ctrl.pasid; ++ *(unsigned long *)base = (unsigned long)ctrl.pasid; ++ ++ ctrl.op = HCT_SHARE_OP_GET_ID; ++ ret = ioctl(hct_data.hct_fd, HCT_SHARE_OP, &ctrl); ++ if (ret < 0) { ++ ret = -errno; ++ error_report("get gid fail, errno: %d", errno); + goto out; + } + +- *hct_data.pasid_memory = ctrl.id; +- hct_data.pasid = ctrl.id; ++ gid = (unsigned long *)((unsigned long)base + HCT_PASID_MEM_GID_OFFSET); ++ *(unsigned long *)gid = (unsigned long)ctrl.id; + + out: + return ret; +@@ -275,40 +333,32 @@ static int hct_check_duplicated_index(int index) + static int hct_get_ccp_index(HCTDevState *state) + { + char path[PATH_MAX] = {0}; +- char buf[CCP_INDEX_BYTES] = {0}; +- int fd; +- int ret; +- int ccp_index; +- +- snprintf(path, PATH_MAX, "%s/vendor/id", state->vdev.sysfsdev); +- fd = qemu_open_old(path, O_RDONLY); +- if (fd < 0) { +- error_report("open %s fail\n", path); +- return -errno; +- } +- +- ret = read(fd, buf, sizeof(buf)); +- if (ret < 0) { +- ret = -errno; +- error_report("read %s fail\n", path); +- goto out; ++ int mdev_used, index; ++ ++ if (memcmp((void *)hct_data.hct_version, HCT_VERSION_STR_06, ++ sizeof(HCT_VERSION_STR_06)) >= 0) { ++ snprintf(path, PATH_MAX, "%s/vendor/use", state->vdev.sysfsdev); ++ if (hct_get_sysfs_value(path, &mdev_used)) { ++ error_report("get %s sysfs value fail.\n", path); ++ return -1; ++ } else if (mdev_used != MDEV_USED_FOR_VM) { ++ error_report("The value of file node(%s) is %d, should be MDEV_USED_FOR_VM(%d), pls check.\n", ++ path, mdev_used, MDEV_USED_FOR_VM); ++ return -1; ++ } + } + +- if (1 != sscanf(buf, "%d", &ccp_index)) { +- ret = -errno; +- error_report("format addr %s fail\n", buf); +- goto out; ++ snprintf(path, PATH_MAX, "%s/vendor/id", state->vdev.sysfsdev); ++ if (hct_get_sysfs_value(path, &index)) { ++ error_report("get %s sysfs value fail.\n", path); ++ return -1; + } + +- if (!hct_check_duplicated_index(ccp_index)) { +- state->sdev.shared_memory_offset = ccp_index; +- } else { +- ret = -1; +- } ++ if (hct_check_duplicated_index(index)) ++ return -1; + +-out: +- qemu_close(fd); +- return ret; ++ state->sdev.shared_memory_offset = index; ++ return 0; + } + + static int hct_api_version_check(void) +@@ -322,12 +372,18 @@ static int hct_api_version_check(void) + if (ret < 0) { + error_report("ret %d, errno %d: fail to get hct.ko version.\n", ret, errno); + return -1; +- } else if (memcmp(ctrl.version, HCT_VERSION_STRING, sizeof(HCT_VERSION_STRING)) < 0) { ++ } else if (memcmp(ctrl.version, HCT_VERSION_STR_02, sizeof(HCT_VERSION_STR_02)) < 0) { + error_report("The hct.ko version is %s, please upgrade to version %s or higher.\n", +- ctrl.version, HCT_VERSION_STRING); ++ ctrl.version, HCT_VERSION_STR_02); + return -1; + } + ++ memcpy((void *)hct_data.hct_version, (void *)ctrl.version, sizeof(hct_data.hct_version)); ++ if (memcmp(ctrl.version, HCT_VERSION_STR_05, sizeof(HCT_VERSION_STR_05)) < 0) ++ hct_data.hct_shared_size = PAGE_SIZE * DEF_CCP_CNT_MAX; ++ else ++ hct_data.hct_shared_size = HCT_SHARED_MEMORY_SIZE; ++ + return 0; + } + +@@ -335,7 +391,7 @@ static int hct_shared_memory_init(void) + { + int ret = 0; + +- hct_data.hct_shared_memory = mmap(NULL, HCT_SHARED_MEMORY_SIZE, ++ hct_data.hct_shared_memory = mmap(NULL, hct_data.hct_shared_size, + PROT_READ | PROT_WRITE, MAP_SHARED, + hct_data.hct_fd, 0); + if (hct_data.hct_shared_memory == MAP_FAILED) { +@@ -438,7 +494,7 @@ static void hct_data_uninit(HCTDevState *state) + } + + if (hct_data.hct_shared_memory) { +- munmap((void *)hct_data.hct_shared_memory, HCT_SHARED_MEMORY_SIZE); ++ munmap((void *)hct_data.hct_shared_memory, hct_data.hct_shared_size); + hct_data.hct_shared_memory = NULL; + } + +@@ -490,7 +546,7 @@ unmap_pasid_memory_exit: + munmap(hct_data.pasid_memory, PAGE_SIZE); + + unmap_shared_memory_exit: +- munmap((void *)hct_data.hct_shared_memory, HCT_SHARED_MEMORY_SIZE); ++ munmap((void *)hct_data.hct_shared_memory, hct_data.hct_shared_size); + + out: + return ret; +-- +2.17.1 + diff --git a/1137-bugfix-hw-vfio-hct-exit-once-mdev-deivce-realize-fai.patch b/1137-bugfix-hw-vfio-hct-exit-once-mdev-deivce-realize-fai.patch new file mode 100644 index 0000000000000000000000000000000000000000..9ebbb44a99a3ce8c421118e6e970646304da3c56 --- /dev/null +++ b/1137-bugfix-hw-vfio-hct-exit-once-mdev-deivce-realize-fai.patch @@ -0,0 +1,49 @@ +From aa0b594c588f455cd4f7a41a621f620d0e0e8994 Mon Sep 17 00:00:00 2001 +From: yangdepei +Date: Tue, 21 Jan 2025 17:36:38 +0800 +Subject: [PATCH 5/5] [bugfix]hw/vfio/hct: exit once mdev deivce realize + failed. + +Change-Id: Ife5d1d519a0ea8011396d8c1147e352d175d41ca +--- + hw/vfio/hct.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/hw/vfio/hct.c b/hw/vfio/hct.c +index a78973bebf..f4531b05ed 100644 +--- a/hw/vfio/hct.c ++++ b/hw/vfio/hct.c +@@ -567,24 +567,30 @@ static void vfio_hct_realize(PCIDevice *pci_dev, Error **errp) + + ret = hct_data_init(state); + if (ret < 0) { ++ error_setg(errp, "hct data initialization failed."); + g_free(state->vdev.name); + goto out; + } + + group = vfio_hct_get_group(state, &err); + if (!group) { ++ error_setg(errp, "hct get vfio iommu_group failed."); + g_free(state->vdev.name); + goto data_uninit_out; + } + + vfio_hct_get_device(group, state, &err); + if (err) { ++ error_setg(errp, "hct get vfio device information failed."); + goto put_group_out; + } + + ret = vfio_hct_region_mmap(state); + if (ret < 0) ++ { ++ error_setg(errp, "hct vfio region mmap failed."); + goto put_device_out; ++ } + + return; + +-- +2.17.1 + diff --git a/1138-bugfix-hw-vfio-hct-build-hct-device-in-default.patch b/1138-bugfix-hw-vfio-hct-build-hct-device-in-default.patch new file mode 100644 index 0000000000000000000000000000000000000000..37cc3b4c87aad95d5248d38c5c2232e395f240b5 --- /dev/null +++ b/1138-bugfix-hw-vfio-hct-build-hct-device-in-default.patch @@ -0,0 +1,21 @@ +From e9a211ae29bdb2b7965d6386ecfd43ea0a1be6c3 Mon Sep 17 00:00:00 2001 +From: yangdepei +Date: Fri, 24 Jan 2025 10:14:24 +0800 +Subject: [PATCH] [bugfix]hw/vfio/hct: build hct device in default + +--- + configs/devices/x86_64-softmmu/x86_64-rh-devices.mak | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak b/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak +index 3a277d097..778af1dae 100644 +--- a/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak ++++ b/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak +@@ -104,3 +104,4 @@ CONFIG_TPM_PASSTHROUGH=y + CONFIG_SGX=y + CONFIG_CSV=y + CONFIG_PSP_DEV=y ++CONFIG_VFIO_HCT=y +-- +2.17.1 + diff --git a/qemu-kvm.spec b/qemu-kvm.spec index ac5d4712e68ed39237911d340f23882b1dfc184f..42a3950069ca712d6576d486ebef232ae758e146 100644 --- a/qemu-kvm.spec +++ b/qemu-kvm.spec @@ -1,4 +1,4 @@ -%define anolis_release .0.5 +%define anolis_release .0.6 %global SLOF_gittagdate 20191022 %global SLOF_gittagcommit 899d9883 @@ -1038,6 +1038,12 @@ Patch1129: 1129-Enable-CONFIG_PSP_DEV-for-x86_64.patch Patch1130: 1130-newfeature-hw-i386-add-mem2-option-for-qemu.patch Patch1131: 1131-newfeature-hw-misc-psp-support-tkm-use-mem2-memory.patch Patch1132: 1132-newfeature-hw-misc-psp-Pin-the-hugepage-memory-speci.patch +Patch1133: 1133-newfeature-hw-vfio-add-hct-device-based-mediated-use.patch +Patch1134: 1134-newfeature-hw-vfio-hct-Change-MAX_CCP_CNT-from-16-to.patch +Patch1135: 1135-bugfix-hw-vfio-hct-fix-ccp-index-error-caused-by-uni.patch +Patch1136: 1136-newfeature-hw-vfio-hct-sharing-CCP-resources-between.patch +Patch1137: 1137-bugfix-hw-vfio-hct-exit-once-mdev-deivce-realize-fai.patch +Patch1138: 1138-bugfix-hw-vfio-hct-build-hct-device-in-default.patch BuildRequires: wget BuildRequires: rpm-build @@ -1999,8 +2005,8 @@ popd # Install qemu-user-static mkdir -p $RPM_BUILD_ROOT%{_bindir}/ pushd %{static_builddir} -for src in qemu-*\.*; do - rm -rf $src +for src in qemu-*\.*; do + rm -rf $src done for src in qemu-*; do @@ -2276,6 +2282,15 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %endif %changelog +* Fri Feb 14 2025 yangdepei - 6.2.0-53.0.1.6 +- support Hygon CCP used in guest +- 1133-newfeature-hw-vfio-add-hct-device-based-mediated-use.patch +- 1134-newfeature-hw-vfio-hct-Change-MAX_CCP_CNT-from-16-to.patch +- 1135-bugfix-hw-vfio-hct-fix-ccp-index-error-caused-by-uni.patch +- 1136-newfeature-hw-vfio-hct-sharing-CCP-resources-between.patch +- 1137-bugfix-hw-vfio-hct-exit-once-mdev-deivce-realize-fai.patch +- 1138-bugfix-hw-vfio-hct-build-hct-device-in-default.patch + * Thu Feb 13 2025 xiongmengbiao - 6.2.0-53.0.1.5 - Support Hygon TKM run on CSV Guest - 1130-newfeature-hw-i386-add-mem2-option-for-qemu.patch @@ -4726,7 +4741,7 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : - Resolves: bz#1640044 (Disable CONFIG_I2C and CONFIG_IPMI in default-configs/ppc64-softmmu.mak) -* Tue Dec 11 2018 Danilo Cesar Lemes de Paula - qemu-kvm-2.12.0-46 +* Tue Dec 11 2018 Danilo Cesar Lemes de Paula - qemu-kvm-2.12.0-46 - kvm-qcow2-Give-the-refcount-cache-the-minimum-possible-s.patch [bz#1656507] - kvm-docs-Document-the-new-default-sizes-of-the-qcow2-cac.patch [bz#1656507] - kvm-qcow2-Fix-Coverity-warning-when-calculating-the-refc.patch [bz#1656507] @@ -4912,7 +4927,7 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : - Resolves: bz#1639374 (qemu-img map 'Aborted (core dumped)' when specifying a plain file) -* Tue Oct 16 2018 Danilo Cesar Lemes de Paula - +* Tue Oct 16 2018 Danilo Cesar Lemes de Paula - - kvm-linux-headers-update.patch [bz#1508142] - kvm-s390x-cpumodel-Set-up-CPU-model-for-AP-device-suppor.patch [bz#1508142] - kvm-s390x-kvm-enable-AP-instruction-interpretation-for-g.patch [bz#1508142]