Пример #1
0
int
rte_ivshmem_metadata_cmdline_generate(char *buffer, unsigned size, const char *name)
{
	const struct memseg_cache_entry * ms_cache, *entry;
	struct ivshmem_config * config;
	char cmdline[IVSHMEM_QEMU_CMDLINE_BUFSIZE], *cmdline_ptr;
	char cfg_file_path[PATH_MAX];
	unsigned remaining_len, tmplen, iter;
	uint64_t shared_mem_size, zero_size, total_size;

	if (buffer == NULL || name == NULL)
		return -1;

	config = get_config_by_name(name);

	if (config == NULL) {
		RTE_LOG(ERR, EAL, "Config %s not found!\n", name);
		return -1;
	}

	rte_spinlock_lock(&config->sl);

	/* prepare metadata file path */
	snprintf(cfg_file_path, sizeof(cfg_file_path), IVSHMEM_CONFIG_FILE_FMT,
			config->metadata->name);

	ms_cache = config->memseg_cache;

	cmdline_ptr = cmdline;
	remaining_len = sizeof(cmdline);

	shared_mem_size = 0;
	iter = 0;

	while ((ms_cache[iter].len != 0) && (iter < RTE_DIM(config->metadata->entry))) {

		entry = &ms_cache[iter];

		/* Offset and sizes within the current pathname */
		tmplen = snprintf(cmdline_ptr, remaining_len, IVSHMEM_QEMU_CMD_FD_FMT,
				entry->filepath, entry->offset, entry->len);

		shared_mem_size += entry->len;

		cmdline_ptr = RTE_PTR_ADD(cmdline_ptr, tmplen);
		remaining_len -= tmplen;

		if (remaining_len == 0) {
			RTE_LOG(ERR, EAL, "Command line too long!\n");
			rte_spinlock_unlock(&config->sl);
			return -1;
		}

		iter++;
	}

	total_size = rte_align64pow2(shared_mem_size + METADATA_SIZE_ALIGNED);
	zero_size = total_size - shared_mem_size - METADATA_SIZE_ALIGNED;

	/* add /dev/zero to command-line to fill the space */
	tmplen = snprintf(cmdline_ptr, remaining_len, IVSHMEM_QEMU_CMD_FD_FMT,
			"/dev/zero",
			(uint64_t)0x0,
			zero_size);

	cmdline_ptr = RTE_PTR_ADD(cmdline_ptr, tmplen);
	remaining_len -= tmplen;

	if (remaining_len == 0) {
		RTE_LOG(ERR, EAL, "Command line too long!\n");
		rte_spinlock_unlock(&config->sl);
		return -1;
	}

	/* add metadata file to the end of command-line */
	tmplen = snprintf(cmdline_ptr, remaining_len, IVSHMEM_QEMU_CMD_FD_FMT,
			cfg_file_path,
			(uint64_t)0x0,
			METADATA_SIZE_ALIGNED);

	cmdline_ptr = RTE_PTR_ADD(cmdline_ptr, tmplen);
	remaining_len -= tmplen;

	if (remaining_len == 0) {
		RTE_LOG(ERR, EAL, "Command line too long!\n");
		rte_spinlock_unlock(&config->sl);
		return -1;
	}

	/* if current length of the command line is bigger than the buffer supplied
	 * by the user, or if command-line is bigger than what IVSHMEM accepts */
	if ((sizeof(cmdline) - remaining_len) > size) {
		RTE_LOG(ERR, EAL, "Buffer is too short!\n");
		rte_spinlock_unlock(&config->sl);
		return -1;
	}
	/* complete the command-line */
	snprintf(buffer, size,
			IVSHMEM_QEMU_CMD_LINE_HEADER_FMT,
			total_size >> 20,
			cmdline);

	rte_spinlock_unlock(&config->sl);

	return 0;
}
Пример #2
0
static int
vfio_spapr_dma_map(int vfio_container_fd)
{
	const struct rte_memseg *ms = rte_eal_get_physmem_layout();
	int i, ret;

	struct vfio_iommu_spapr_register_memory reg = {
		.argsz = sizeof(reg),
		.flags = 0
	};
	struct vfio_iommu_spapr_tce_info info = {
		.argsz = sizeof(info),
	};
	struct vfio_iommu_spapr_tce_create create = {
		.argsz = sizeof(create),
	};
	struct vfio_iommu_spapr_tce_remove remove = {
		.argsz = sizeof(remove),
	};

	/* query spapr iommu info */
	ret = ioctl(vfio_container_fd, VFIO_IOMMU_SPAPR_TCE_GET_INFO, &info);
	if (ret) {
		RTE_LOG(ERR, EAL, "  cannot get iommu info, "
				"error %i (%s)\n", errno, strerror(errno));
		return -1;
	}

	/* remove default DMA of 32 bit window */
	remove.start_addr = info.dma32_window_start;
	ret = ioctl(vfio_container_fd, VFIO_IOMMU_SPAPR_TCE_REMOVE, &remove);
	if (ret) {
		RTE_LOG(ERR, EAL, "  cannot remove default DMA window, "
				"error %i (%s)\n", errno, strerror(errno));
		return -1;
	}

	/* create DMA window from 0 to max(phys_addr + len) */
	for (i = 0; i < RTE_MAX_MEMSEG; i++) {
		if (ms[i].addr == NULL)
			break;

		create.window_size = RTE_MAX(create.window_size,
				ms[i].iova + ms[i].len);
	}

	/* sPAPR requires window size to be a power of 2 */
	create.window_size = rte_align64pow2(create.window_size);
	create.page_shift = __builtin_ctzll(ms->hugepage_sz);
	create.levels = 1;

	ret = ioctl(vfio_container_fd, VFIO_IOMMU_SPAPR_TCE_CREATE, &create);
	if (ret) {
		RTE_LOG(ERR, EAL, "  cannot create new DMA window, "
				"error %i (%s)\n", errno, strerror(errno));
		return -1;
	}

	if (create.start_addr != 0) {
		RTE_LOG(ERR, EAL, "  DMA window start address != 0\n");
		return -1;
	}

	/* map all DPDK segments for DMA. use 1:1 PA to IOVA mapping */
	for (i = 0; i < RTE_MAX_MEMSEG; i++) {
		struct vfio_iommu_type1_dma_map dma_map;

		if (ms[i].addr == NULL)
			break;

		reg.vaddr = (uintptr_t) ms[i].addr;
		reg.size = ms[i].len;
		ret = ioctl(vfio_container_fd,
			VFIO_IOMMU_SPAPR_REGISTER_MEMORY, &reg);
		if (ret) {
			RTE_LOG(ERR, EAL, "  cannot register vaddr for IOMMU, "
				"error %i (%s)\n", errno, strerror(errno));
			return -1;
		}

		memset(&dma_map, 0, sizeof(dma_map));
		dma_map.argsz = sizeof(struct vfio_iommu_type1_dma_map);
		dma_map.vaddr = ms[i].addr_64;
		dma_map.size = ms[i].len;
		dma_map.iova = ms[i].iova;
		dma_map.flags = VFIO_DMA_MAP_FLAG_READ |
				 VFIO_DMA_MAP_FLAG_WRITE;

		ret = ioctl(vfio_container_fd, VFIO_IOMMU_MAP_DMA, &dma_map);

		if (ret) {
			RTE_LOG(ERR, EAL, "  cannot set up DMA remapping, "
				"error %i (%s)\n", errno, strerror(errno));
			return -1;
		}

	}

	return 0;
}

static int
vfio_noiommu_dma_map(int __rte_unused vfio_container_fd)
{
	/* No-IOMMU mode does not need DMA mapping */
	return 0;
}

int
rte_vfio_noiommu_is_enabled(void)
{
	int fd, ret, cnt __rte_unused;
	char c;

	ret = -1;
	fd = open(VFIO_NOIOMMU_MODE, O_RDONLY);
	if (fd < 0)
		return -1;

	cnt = read(fd, &c, 1);
	if (c == 'Y')
		ret = 1;

	close(fd);
	return ret;
}