Commit 8ee24758 authored by Huang Shijie's avatar Huang Shijie Committed by Jim Harris
Browse files

vfio_user: fix the errors in 64K page kernel



We will meet the followings errors in 64K page kernel:
    " vfio_user.c:4454:nvmf_vfio_user_listen: *ERROR*: /tmp/nvme-vfio-user: error to mmap file /tmp/nvme-vfio-user/bar0: Invalid argument."
    " vfio_user.c:3088:vfio_user_log: *ERROR*: /tmp/nvme-vfio-user: migration registers cannot be memory mapped"

Fix them by
    0.)
        0.1) Add a new field @bar0 in nvmf_vfio_user_endpoint{} to store
             the mmap result.

        0.2) Pass 0 to mmap's offset parameter.
	     The doorbell offset is fixed at 0x1000 (kernel NVME driver uses it too).
             But mmap requires the offset must be a multiple of the page size
	     as returned by sysconf(_SC_PAGE_SIZE).

             In 64K page size kernel will meet the failure.
	     So set 0 to mmap's offset, and then change to doorbell
	     offset manually.

    1.) convert the hardcode to PAGE_SIZE.

Tested this patch with cloud-hypervisor in :
  (64K page size kernel) + (4K page size kernel).

Change-Id: Ibf0a61e4773cff6a3b7887315b50a686f7c237dc
Signed-off-by: default avatarHuang Shijie <shijie@os.amperecomputing.com>
Reviewed-on: https://review.spdk.io/c/spdk/spdk/+/18627


Reviewed-by: default avatarJohn Levon <levon@movementarian.org>
Reviewed-by: default avatarJim Harris <jim.harris@nvidia.com>
Reviewed-by: default avatarBen Walker <ben@nvidia.com>
Tested-by: default avatarSPDK Automated Test System <spdkbot@gmail.com>
Reviewed-by: default avatarGangCao <gang.cao@intel.com>
parent 4487b377
Loading
Loading
Loading
Loading
+18 −7
Original line number Diff line number Diff line
@@ -501,6 +501,7 @@ struct nvmf_vfio_user_endpoint {
	int					accept_intr_fd;
	struct spdk_interrupt			*accept_intr;

	volatile uint32_t			*bar0;
	volatile uint32_t			*bar0_doorbells;

	int					migr_fd;
@@ -1198,8 +1199,10 @@ nvmf_vfio_user_destroy_endpoint(struct nvmf_vfio_user_endpoint *endpoint)
	spdk_interrupt_unregister(&endpoint->accept_intr);
	spdk_poller_unregister(&endpoint->accept_poller);

	if (endpoint->bar0_doorbells) {
		munmap((void *)endpoint->bar0_doorbells, NVMF_VFIO_USER_DOORBELLS_SIZE);
	if (endpoint->bar0) {
		munmap((void *)endpoint->bar0, NVME_REG_BAR0_SIZE);
		endpoint->bar0 = NULL;
		endpoint->bar0_doorbells = NULL;
	}

	if (endpoint->devmem_fd > 0) {
@@ -4259,7 +4262,7 @@ vfio_user_dev_info_fill(struct nvmf_vfio_user_transport *vu_transport,

	vfu_setup_device_quiesce_cb(vfu_ctx, vfio_user_dev_quiesce_cb);

	migr_sparse_mmap.iov_base = (void *)4096;
	migr_sparse_mmap.iov_base = (void *)PAGE_SIZE;
	migr_sparse_mmap.iov_len = vfio_user_migr_data_len();
	ret = vfu_setup_region(vfu_ctx, VFU_PCI_DEV_MIGR_REGION_IDX,
			       vfu_get_migr_register_area_size() + vfio_user_migr_data_len(),
@@ -4504,14 +4507,22 @@ nvmf_vfio_user_listen(struct spdk_nvmf_transport *transport,
		goto out;
	}

	endpoint->bar0_doorbells = mmap(NULL, NVMF_VFIO_USER_DOORBELLS_SIZE,
					PROT_READ | PROT_WRITE, MAP_SHARED, endpoint->devmem_fd, NVME_DOORBELLS_OFFSET);
	if (endpoint->bar0_doorbells == MAP_FAILED) {
	/*
	 * The doorbell offset is fixed at 0x1000.
	 * But mmap requires the offset must be a multiple of the page size as returned by
	 * sysconf(_SC_PAGE_SIZE).
	 * In order to avoid the mmap failure in non-4K page size kernel,
	 * set 0 to mmap's offset, and then change to doorbell offset manually.
	 */
	endpoint->bar0 = mmap(NULL, NVME_REG_BAR0_SIZE, PROT_READ | PROT_WRITE,
			      MAP_SHARED, endpoint->devmem_fd, 0);
	if (endpoint->bar0 == MAP_FAILED) {
		SPDK_ERRLOG("%s: error to mmap file %s: %s.\n", endpoint_id(endpoint), path, spdk_strerror(errno));
		endpoint->bar0_doorbells = NULL;
		endpoint->bar0 = NULL;
		ret = -1;
		goto out;
	}
	endpoint->bar0_doorbells = (uint32_t *)(((unsigned long)endpoint->bar0) + NVME_DOORBELLS_OFFSET);

	ret = snprintf(path, PATH_MAX, "%s/migr", endpoint_id(endpoint));
	if (ret < 0 || ret >= PATH_MAX) {