From patchwork Fri Aug 11 16:14:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anatoly Burakov X-Patchwork-Id: 130171 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 3233843036; Fri, 11 Aug 2023 18:15:11 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id B23974325A; Fri, 11 Aug 2023 18:14:58 +0200 (CEST) Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.136]) by mails.dpdk.org (Postfix) with ESMTP id 883444325A for ; Fri, 11 Aug 2023 18:14:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1691770496; x=1723306496; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=vQTH2B6xZeu4yWp0eoIE5VpqT9F8OxJgmRz4cr7MQsY=; b=ln7ffY1DXktlTllFfyANCHtJaJXwvMHPM4j5zpmM8B3+kjDvmMWViFIw 2ArNajUlC9VOyK3amTATMBdDTm9NyRFd6MtltFuDOKZNavNroE9YHjvKw nTbXMRl5tAlMjFiUQszhGo26/Lm6pSbuvJQn7p6UWyCIU352AM/KalfVs L0Y0BAddFR771AtwTfecz9LCel43PgtvHMkOZkQk6GnpjIDNlR8B4O4o4 +aQYrUps6zpMUt+p4r3YQ7tUEEZ9Opj2DChv5LTahethFdQGMkIdJq0sI 6WtKwjeFsNwHmkkYJft6UwFzRcK6bXY36VW3LecFGrg7u3wnCWrL7SNlI Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10799"; a="351312964" X-IronPort-AV: E=Sophos;i="6.01,166,1684825200"; d="scan'208";a="351312964" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Aug 2023 09:14:56 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10799"; a="906499515" X-IronPort-AV: E=Sophos;i="6.01,166,1684825200"; d="scan'208";a="906499515" Received: from silpixa00401191.ir.intel.com ([10.55.128.139]) by orsmga005.jf.intel.com with ESMTP; 11 Aug 2023 09:14:54 -0700 From: Anatoly Burakov To: dev@dpdk.org, Bruce Richardson , Kevin Laatz Cc: Vladimir Medvedkin Subject: [PATCH v1 3/3] dma/idxd: add API to create and attach to window Date: Fri, 11 Aug 2023 16:14:46 +0000 Message-Id: X-Mailer: git-send-email 2.37.2 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org This commit implements functions necessary to use inter-domain operations with idxd driver. The process is as follows: 1. Process A that wishes to share its memory with others, shall call `rte_idxd_window_create()`, which will return a file descriptor 2. Process A is to send above mentioned file descriptor to any recipient process (usually over kernel IPC) that wishes to attach to that window 3. Process B, after receiving above mentioned file descriptor from process A over IPC, shall call `rte_idxd_window_attach()` and receive an inter-pasid handle 4. Process B shall use this handle as an argument for inter-domain operations using DMA device API Signed-off-by: Vladimir Medvedkin Signed-off-by: Anatoly Burakov --- doc/guides/dmadevs/idxd.rst | 52 ++++++++ drivers/dma/idxd/idxd_inter_dom.c | 166 ++++++++++++++++++++++++++ drivers/dma/idxd/meson.build | 7 +- drivers/dma/idxd/rte_idxd_inter_dom.h | 79 ++++++++++++ drivers/dma/idxd/version.map | 11 ++ 5 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 drivers/dma/idxd/idxd_inter_dom.c create mode 100644 drivers/dma/idxd/rte_idxd_inter_dom.h create mode 100644 drivers/dma/idxd/version.map diff --git a/doc/guides/dmadevs/idxd.rst b/doc/guides/dmadevs/idxd.rst index cb8f1fe729..b0439377f8 100644 --- a/doc/guides/dmadevs/idxd.rst +++ b/doc/guides/dmadevs/idxd.rst @@ -225,3 +225,55 @@ which operation failed and kick off the device to continue processing operations if (error){ status_count = rte_dma_completed_status(dev_id, vchan, COMP_BURST_SZ, &idx, status); } + +Performing Inter-Domain operations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Refer to the :ref:`Enqueue / Dequeue APIs ` section of the dmadev library +documentation for details on operation enqueue, submission and completion API usage. + +Refer to the :ref:`Inter-domain operations ` section of the dmadev library +documentation for details on inter-domain operations. + +Intel(R) IDXD currently supports the following inter-domain operations: + +* Copy operation +* Fill operation + +To use these operations with the IDXD driver, the following program flow should +be adhered to: + +* Process A that wishes to share its memory with others, shall call + ``rte_idxd_window_create()``, which will return a file descriptor +* Process A is to send above mentioned file descriptor to any recipient process + (usually over IPC) that wishes to attach to that window +* Process B, after receiving above mentioned file descriptor from process A over + IPC, shall call ``rte_idxd_window_attach()`` and receive an inter-pasid handle +* Process B shall use this handle as an argument for inter-domain operations + using DMA device API + +The controller ID parameter for create/attach functions in this case would be +the controller ID of configured DSA2 devices (located under ``rte_dma_info`` +structure), but which can also be read from ``accel-config`` tool, or from the +DSA2 work queue name (e.g. work queue ``wq0.3`` would have ``0`` as its +controller ID). + +The ``rte_idxd_window_create()`` call will accept a ``flags`` argument, which +can contain the following bits: + +* ``RTE_IDXD_WIN_FLAGS_PROT_READ`` - allow other process to read from memory + region to be shared + - In this case, the remote process will be using the resulting inter-pasid + handle as source handle for inter-domain DMA operations (and set the + ``RTE_DMA_OP_FLAG_SRC_HANDLE`` DMA operation flag) +* ``RTE_IDXD_WIN_FLAGS_PROT_WRITE`` - allow other process to write into memory + region to be shared + - In this case, the remote process will be using the resulting inter-pasid + handle as destination handle for inter-domain DMA operations (and set the + ``RTE_DMA_OP_FLAG_DST_HANDLE`` DMA operation flag) +* ``RTE_IDXD_WIN_FLAGS_WIN_CHECK`` - if this flag is not set, the remote process + will be allowed unrestricted access to entire memory space of the owner + process +* ``RTE_IDXD_WIN_FLAGS_OFFSET_MODE`` - addresses for DMA operations will have to + be specified as offsets from base address of the memory region to be shared +* ``RTE_IDXD_WIN_FLAGS_TYPE_SAMS`` - enable multi-submitter mode. diff --git a/drivers/dma/idxd/idxd_inter_dom.c b/drivers/dma/idxd/idxd_inter_dom.c new file mode 100644 index 0000000000..21dcd6980d --- /dev/null +++ b/drivers/dma/idxd/idxd_inter_dom.c @@ -0,0 +1,166 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "idxd_internal.h" + +#define IDXD_TYPE ('d') +#define IDXD_IOC_BASE 100 +#define IDXD_WIN_BASE 200 + +enum idxd_win_type { + IDXD_WIN_TYPE_SA_SS = 0, + IDXD_WIN_TYPE_SA_MS, +}; + +#define IDXD_WIN_FLAGS_MASK (RTE_IDXD_WIN_FLAGS_PROT_READ | RTE_IDXD_WIN_FLAGS_PROT_WRITE |\ + RTE_IDXD_WIN_FLAGS_WIN_CHECK | RTE_IDXD_WIN_FLAGS_OFFSET_MODE|\ + RTE_IDXD_WIN_FLAGS_TYPE_SAMS) + +struct idxd_win_param { + uint64_t base; /* Window base */ + uint64_t size; /* Window size */ + uint32_t type; /* Window type, see enum idxd_win_type */ + uint16_t flags; /* See IDXD windows flags */ + uint16_t handle; /* Window handle returned by driver */ +} __attribute__((packed)); + +struct idxd_win_attach { + uint32_t fd; /* Window file descriptor returned by IDXD_WIN_CREATE */ + uint16_t handle; /* Window handle returned by driver */ +} __attribute__((packed)); + +struct idxd_win_fault { + uint64_t offset; /* Window offset of faulting address */ + uint64_t len; /* Faulting range */ + uint32_t write_fault; /* Fault generated on write */ +} __attribute__((packed)); + +#define IDXD_WIN_CREATE _IOWR(IDXD_TYPE, IDXD_IOC_BASE + 1, struct idxd_win_param) +#define IDXD_WIN_ATTACH _IOR(IDXD_TYPE, IDXD_IOC_BASE + 2, struct idxd_win_attach) +#define IDXD_WIN_FAULT _IOR(IDXD_TYPE, IDXD_WIN_BASE + 1, struct idxd_win_fault) +#define DSA_DEV_PATH "/dev/dsa" + +static inline const char * +dsa_get_dev_path(void) +{ + const char *path = getenv("DSA_DEV_PATH"); + return path ? path : DSA_DEV_PATH; +} + +static int +dsa_find_work_queue(int controller_id) +{ + char dev_templ[PATH_MAX], path_templ[PATH_MAX]; + const char *path = dsa_get_dev_path(); + struct dirent *wq; + DIR *dev_dir; + int fd = -1; + + /* construct work queue path template */ + snprintf(dev_templ, sizeof(dev_templ), "wq%d.", controller_id); + + /* open the DSA device directory */ + dev_dir = opendir(path); + if (dev_dir == NULL) + return -1; + + /* find any available work queue */ + while ((wq = readdir(dev_dir)) != NULL) { + /* skip things that aren't work queues */ + if (strncmp(wq->d_name, dev_templ, strlen(dev_templ)) != 0) + continue; + + /* try this work queue */ + snprintf(path_templ, sizeof(path_templ), "%s/%s", path, wq->d_name); + + fd = open(path_templ, O_RDWR); + if (fd < 0) + continue; + + break; + } + + return fd; +} + +int +rte_idxd_window_create(int controller_id, void *win_addr, + unsigned int win_len, int flags) +{ + struct idxd_win_param param = {0}; + int idpte_fd, fd; + + fd = dsa_find_work_queue(controller_id); + + /* did we find anything? */ + if (fd < 0) { + IDXD_PMD_ERR("%s(): creatomg idpt window failed", __func__); + return -1; + } + + /* create a wormhole into a parallel reality... */ + param.base = (uint64_t)win_addr; + param.size = win_len; + param.flags = flags & IDXD_WIN_FLAGS_MASK; + param.type = (flags & RTE_IDXD_WIN_FLAGS_TYPE_SAMS) ? + IDXD_WIN_TYPE_SA_MS : IDXD_WIN_TYPE_SA_SS; + + idpte_fd = ioctl(fd, IDXD_WIN_CREATE, ¶m); + + close(fd); + + if (idpte_fd < 0) + rte_errno = idpte_fd; + + return idpte_fd; +} + +int +rte_idxd_window_attach(int controller_id, int idpte_fd, + uint16_t *handle) +{ + + struct idxd_win_attach win_attach = {0}; + int ret, fd; + + if (handle == NULL) { + rte_errno = EINVAL; + return -1; + } + + fd = dsa_find_work_queue(controller_id); + + /* did we find anything? */ + if (fd < 0) { + IDXD_PMD_ERR("%s(): creatomg idpt window failed", __func__); + rte_errno = ENOENT; + return -1; + } + + /* get access to someone else's wormhole */ + win_attach.fd = idpte_fd; + + ret = ioctl(fd, IDXD_WIN_ATTACH, &win_attach); + if (ret != 0) { + IDXD_PMD_ERR("%s(): attaching idpt window failed: %s", + __func__, strerror(ret)); + rte_errno = ret; + return -1; + } + + *handle = win_attach.handle; + + return 0; +} diff --git a/drivers/dma/idxd/meson.build b/drivers/dma/idxd/meson.build index c5403b431c..da73ab340c 100644 --- a/drivers/dma/idxd/meson.build +++ b/drivers/dma/idxd/meson.build @@ -22,5 +22,10 @@ sources = files( ) if is_linux - sources += files('idxd_bus.c') + sources += files( + 'idxd_bus.c', + 'idxd_inter_dom.c', +) endif + +headers = files('rte_idxd_inter_dom.h') diff --git a/drivers/dma/idxd/rte_idxd_inter_dom.h b/drivers/dma/idxd/rte_idxd_inter_dom.h new file mode 100644 index 0000000000..c31f3777c9 --- /dev/null +++ b/drivers/dma/idxd/rte_idxd_inter_dom.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Intel Corporation + */ + +#ifndef _RTE_IDXD_INTER_DOM_H_ +#define _RTE_IDXD_INTER_DOM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +/** Allow reading from address space. */ +#define RTE_IDXD_WIN_FLAGS_PROT_READ 0x0001 +/** Allow writing to address space. */ +#define RTE_IDXD_WIN_FLAGS_PROT_WRITE 0x0002 +/** If this flag not set, the entire address space will be accessible. */ +#define RTE_IDXD_WIN_FLAGS_WIN_CHECK 0x0004 +/** Destination addresses are offsets from window base address. */ +#define RTE_IDXD_WIN_FLAGS_OFFSET_MODE 0x0008 +/* multiple submitter flag. If not set - single submitter type will be used. */ +#define RTE_IDXD_WIN_FLAGS_TYPE_SAMS 0x0010 + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Create an inter-pasid window to allow another process to access this process' + * memory. This function returns a file descriptor for the window, that can be + * used by another process to access this window. + * + * @param controller_id + * IDXD controller device ID. + * @param win_addr + * Base address of memory chunk being shared (ignored if + * `RTE_IDXD_WIN_FLAGS_WIN_CHECK` is not set). + * @param win_len + * Length of memory chunk being shared (ignored if + * `RTE_IDXD_WIN_FLAGS_WIN_CHECK` is not set). + * @param flags + * Flags to configure the window. + * @return + * Non-negative on success. + * Negative on error. + */ +__rte_experimental +int rte_idxd_window_create(int controller_id, void *win_addr, + unsigned int win_len, int flags); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Attach to an inter-pasid window of another process. This function expects a + * file descriptor returned by `rte_idxd_window_create()`, and will set the + * value pointed to by `handle`. This handle can then be used to perform + * inter-domain DMA operations. + * + * @param controller_id + * IDXD controller device ID. + * @param idpte_fd + * File descriptor for another process's window + * @param handle + * Pointer to a variable to receive the handle. + * @return + * 0 on success. + * Negative on error. + */ +__rte_experimental +int rte_idxd_window_attach(int controller_id, int idpte_fd, uint16_t *handle); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_IDXD_INTER_DOM_H_ */ diff --git a/drivers/dma/idxd/version.map b/drivers/dma/idxd/version.map new file mode 100644 index 0000000000..e091bb7c09 --- /dev/null +++ b/drivers/dma/idxd/version.map @@ -0,0 +1,11 @@ +DPDK_23 { + local: *; +}; + + +EXPERIMENTAL { + global: + + rte_idxd_window_create; + rte_idxd_window_attach; +};