From: Fabiano Rosas <farosas@suse.de>
To: Hao Xiang <hao.xiang@linux.dev>,
marcandre.lureau@redhat.com, peterx@redhat.com,
armbru@redhat.com, lvivier@redhat.com, qemu-devel@nongnu.org
Cc: Hao Xiang <hao.xiang@linux.dev>, Bryan Zhang <bryan.zhang@bytedance.com>
Subject: Re: [PATCH v4 03/14] util/dsa: Implement DSA device start and stop logic.
Date: Thu, 25 Apr 2024 18:22:13 -0300 [thread overview]
Message-ID: <871q6t87ei.fsf@suse.de> (raw)
In-Reply-To: <20240425022117.4035031-4-hao.xiang@linux.dev>
Hao Xiang <hao.xiang@linux.dev> writes:
> * DSA device open and close.
> * DSA group contains multiple DSA devices.
> * DSA group configure/start/stop/clean.
>
> Signed-off-by: Hao Xiang <hao.xiang@linux.dev>
> Signed-off-by: Bryan Zhang <bryan.zhang@bytedance.com>
> ---
> include/qemu/dsa.h | 72 +++++++++++
> util/dsa.c | 316 +++++++++++++++++++++++++++++++++++++++++++++
> util/meson.build | 1 +
> 3 files changed, 389 insertions(+)
> create mode 100644 include/qemu/dsa.h
> create mode 100644 util/dsa.c
>
> diff --git a/include/qemu/dsa.h b/include/qemu/dsa.h
> new file mode 100644
> index 0000000000..f15c05ee85
> --- /dev/null
> +++ b/include/qemu/dsa.h
> @@ -0,0 +1,72 @@
> +#ifndef QEMU_DSA_H
> +#define QEMU_DSA_H
> +
> +#include "qemu/error-report.h"
> +#include "qemu/thread.h"
> +#include "qemu/queue.h"
> +
> +#ifdef CONFIG_DSA_OPT
> +
> +#pragma GCC push_options
> +#pragma GCC target("enqcmd")
> +
> +#include <linux/idxd.h>
> +#include "x86intrin.h"
> +
> +/**
> + * @brief Initializes DSA devices.
> + *
> + * @param dsa_parameter A list of DSA device path from migration parameter.
> + *
> + * @return int Zero if successful, otherwise non zero.
> + */
> +int dsa_init(const char *dsa_parameter);
> +
> +/**
> + * @brief Start logic to enable using DSA.
> + */
> +void dsa_start(void);
> +
> +/**
> + * @brief Stop the device group and the completion thread.
> + */
> +void dsa_stop(void);
> +
> +/**
> + * @brief Clean up system resources created for DSA offloading.
> + */
> +void dsa_cleanup(void);
> +
> +/**
> + * @brief Check if DSA is running.
> + *
> + * @return True if DSA is running, otherwise false.
> + */
> +bool dsa_is_running(void);
> +
> +#else
> +
> +static inline bool dsa_is_running(void)
> +{
> + return false;
> +}
> +
> +static inline int dsa_init(const char *dsa_parameter)
> +{
> + if (dsa_parameter != NULL && strlen(dsa_parameter) != 0) {
> + error_report("DSA not supported.");
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static inline void dsa_start(void) {}
> +
> +static inline void dsa_stop(void) {}
> +
> +static inline void dsa_cleanup(void) {}
> +
> +#endif
> +
> +#endif
> diff --git a/util/dsa.c b/util/dsa.c
> new file mode 100644
> index 0000000000..05bbf8e31a
> --- /dev/null
> +++ b/util/dsa.c
> @@ -0,0 +1,316 @@
> +/*
> + * Use Intel Data Streaming Accelerator to offload certain background
> + * operations.
> + *
> + * Copyright (c) 2023 Hao Xiang <hao.xiang@bytedance.com>
> + * Bryan Zhang <bryan.zhang@bytedance.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/queue.h"
> +#include "qemu/memalign.h"
> +#include "qemu/lockable.h"
> +#include "qemu/cutils.h"
> +#include "qemu/dsa.h"
> +#include "qemu/bswap.h"
> +#include "qemu/error-report.h"
> +#include "qemu/rcu.h"
> +
> +#ifdef CONFIG_DSA_OPT
This should be done in meson.build. Here you're allowing an empty object
to be generated just so we can expose the struct batch_task to
multifd. In another patch I suggested we stop using it, then we can put
the whole dsa.c under CONFIG_DSA (we can drop the OPT as well) in
meson.build.
> +
> +#pragma GCC push_options
> +#pragma GCC target("enqcmd")
> +
> +#include <linux/idxd.h>
> +#include "x86intrin.h"
> +
> +#define DSA_WQ_SIZE 4096
> +#define MAX_DSA_DEVICES 16
> +
> +typedef QSIMPLEQ_HEAD(dsa_task_queue, dsa_batch_task) dsa_task_queue;
> +
> +struct dsa_device {
> + void *work_queue;
> +};
> +
> +struct dsa_device_group {
> + struct dsa_device *dsa_devices;
> + int num_dsa_devices;
> + /* The index of the next DSA device to be used. */
> + uint32_t device_allocator_index;
> + bool running;
> + QemuMutex task_queue_lock;
> + QemuCond task_queue_cond;
> + dsa_task_queue task_queue;
> +};
> +
> +uint64_t max_retry_count;
> +static struct dsa_device_group dsa_group;
> +
> +
> +/**
> + * @brief This function opens a DSA device's work queue and
> + * maps the DSA device memory into the current process.
> + *
> + * @param dsa_wq_path A pointer to the DSA device work queue's file path.
> + * @return A pointer to the mapped memory, or MAP_FAILED on failure.
> + */
> +static void *
> +map_dsa_device(const char *dsa_wq_path)
> +{
> + void *dsa_device;
> + int fd;
> +
> + fd = open(dsa_wq_path, O_RDWR);
> + if (fd < 0) {
> + error_report("Open %s failed with errno = %d.",
> + dsa_wq_path, errno);
> + return MAP_FAILED;
> + }
> + dsa_device = mmap(NULL, DSA_WQ_SIZE, PROT_WRITE,
> + MAP_SHARED | MAP_POPULATE, fd, 0);
> + close(fd);
> + if (dsa_device == MAP_FAILED) {
> + error_report("mmap failed with errno = %d.", errno);
> + return MAP_FAILED;
> + }
> + return dsa_device;
> +}
> +
> +/**
> + * @brief Initializes a DSA device structure.
> + *
> + * @param instance A pointer to the DSA device.
> + * @param work_queue A pointer to the DSA work queue.
> + */
> +static void
> +dsa_device_init(struct dsa_device *instance,
> + void *dsa_work_queue)
> +{
> + instance->work_queue = dsa_work_queue;
> +}
> +
> +/**
> + * @brief Cleans up a DSA device structure.
> + *
> + * @param instance A pointer to the DSA device to cleanup.
> + */
> +static void
> +dsa_device_cleanup(struct dsa_device *instance)
> +{
> + if (instance->work_queue != MAP_FAILED) {
> + munmap(instance->work_queue, DSA_WQ_SIZE);
> + }
> +}
> +
> +/**
> + * @brief Initializes a DSA device group.
> + *
> + * @param group A pointer to the DSA device group.
> + * @param dsa_parameter A list of DSA device path from are separated by space
> + * character migration parameter. Multiple DSA device path.
> + *
> + * @return Zero if successful, non-zero otherwise.
> + */
> +static int
> +dsa_device_group_init(struct dsa_device_group *group,
> + const char *dsa_parameter)
> +{
> + if (dsa_parameter == NULL || strlen(dsa_parameter) == 0) {
> + return 0;
> + }
> +
> + int ret = 0;
> + char *local_dsa_parameter = g_strdup(dsa_parameter);
> + const char *dsa_path[MAX_DSA_DEVICES];
> + int num_dsa_devices = 0;
> + char delim[2] = " ";
> +
> + char *current_dsa_path = strtok(local_dsa_parameter, delim);
> +
> + while (current_dsa_path != NULL) {
> + dsa_path[num_dsa_devices++] = current_dsa_path;
> + if (num_dsa_devices == MAX_DSA_DEVICES) {
> + break;
> + }
> + current_dsa_path = strtok(NULL, delim);
> + }
> +
> + group->dsa_devices =
> + g_new0(struct dsa_device, num_dsa_devices);
> + group->num_dsa_devices = num_dsa_devices;
> + group->device_allocator_index = 0;
> +
> + group->running = false;
> + qemu_mutex_init(&group->task_queue_lock);
> + qemu_cond_init(&group->task_queue_cond);
> + QSIMPLEQ_INIT(&group->task_queue);
> +
> + void *dsa_wq = MAP_FAILED;
> + for (int i = 0; i < num_dsa_devices; i++) {
> + dsa_wq = map_dsa_device(dsa_path[i]);
> + if (dsa_wq == MAP_FAILED) {
> + error_report("map_dsa_device failed MAP_FAILED.");
> + ret = -1;
> + goto exit;
> + }
> + dsa_device_init(&dsa_group.dsa_devices[i], dsa_wq);
> + }
> +
> +exit:
> + g_free(local_dsa_parameter);
> + return ret;
> +}
> +
> +/**
> + * @brief Starts a DSA device group.
> + *
> + * @param group A pointer to the DSA device group.
> + */
> +static void
> +dsa_device_group_start(struct dsa_device_group *group)
> +{
> + group->running = true;
> +}
> +
> +/**
> + * @brief Stops a DSA device group.
> + *
> + * @param group A pointer to the DSA device group.
> + */
> +__attribute__((unused))
> +static void
> +dsa_device_group_stop(struct dsa_device_group *group)
> +{
> + group->running = false;
> +}
> +
> +/**
> + * @brief Cleans up a DSA device group.
> + *
> + * @param group A pointer to the DSA device group.
> + */
> +static void
> +dsa_device_group_cleanup(struct dsa_device_group *group)
> +{
> + if (!group->dsa_devices) {
> + return;
> + }
> + for (int i = 0; i < group->num_dsa_devices; i++) {
> + dsa_device_cleanup(&group->dsa_devices[i]);
> + }
> + g_free(group->dsa_devices);
> + group->dsa_devices = NULL;
> +
> + qemu_mutex_destroy(&group->task_queue_lock);
> + qemu_cond_destroy(&group->task_queue_cond);
> +}
> +
> +/**
> + * @brief Returns the next available DSA device in the group.
> + *
> + * @param group A pointer to the DSA device group.
> + *
> + * @return struct dsa_device* A pointer to the next available DSA device
> + * in the group.
> + */
> +__attribute__((unused))
> +static struct dsa_device *
> +dsa_device_group_get_next_device(struct dsa_device_group *group)
> +{
> + if (group->num_dsa_devices == 0) {
> + return NULL;
> + }
> + uint32_t current = qatomic_fetch_inc(&group->device_allocator_index);
> + current %= group->num_dsa_devices;
> + return &group->dsa_devices[current];
> +}
> +
> +/**
> + * @brief Check if DSA is running.
> + *
> + * @return True if DSA is running, otherwise false.
> + */
> +bool dsa_is_running(void)
> +{
> + return false;
> +}
> +
> +static void
> +dsa_globals_init(void)
> +{
> + max_retry_count = UINT64_MAX;
> +}
> +
> +/**
> + * @brief Initializes DSA devices.
> + *
> + * @param dsa_parameter A list of DSA device path from migration parameter.
> + *
> + * @return int Zero if successful, otherwise non zero.
> + */
> +int dsa_init(const char *dsa_parameter)
> +{
> + dsa_globals_init();
> +
> + return dsa_device_group_init(&dsa_group, dsa_parameter);
> +}
> +
> +/**
> + * @brief Start logic to enable using DSA.
> + *
> + */
> +void dsa_start(void)
> +{
> + if (dsa_group.num_dsa_devices == 0) {
> + return;
> + }
> + if (dsa_group.running) {
> + return;
> + }
> + dsa_device_group_start(&dsa_group);
> +}
> +
> +/**
> + * @brief Stop the device group and the completion thread.
> + *
> + */
> +void dsa_stop(void)
> +{
> + struct dsa_device_group *group = &dsa_group;
> +
> + if (!group->running) {
> + return;
> + }
> +}
> +
> +/**
> + * @brief Clean up system resources created for DSA offloading.
> + *
> + */
> +void dsa_cleanup(void)
> +{
> + dsa_stop();
> + dsa_device_group_cleanup(&dsa_group);
> +}
> +
> +#endif
> +
> diff --git a/util/meson.build b/util/meson.build
> index 2ad57b10ba..144c6812e5 100644
> --- a/util/meson.build
> +++ b/util/meson.build
> @@ -88,6 +88,7 @@ if have_block or have_ga
> endif
> if have_block
> util_ss.add(files('aio-wait.c'))
> + util_ss.add(files('dsa.c'))
> util_ss.add(files('buffer.c'))
> util_ss.add(files('bufferiszero.c'))
> util_ss.add(files('hbitmap.c'))
next prev parent reply other threads:[~2024-04-25 21:23 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-25 2:21 [PATCH v4 00/14] Use Intel DSA accelerator to offload zero page checking in multifd live migration Hao Xiang
2024-04-25 2:21 ` [PATCH v4 01/14] meson: Introduce new instruction set enqcmd to the build system Hao Xiang
2024-04-25 18:50 ` Fabiano Rosas
2024-04-25 2:21 ` [PATCH v4 02/14] util/dsa: Add dependency idxd Hao Xiang
2024-04-25 20:33 ` Fabiano Rosas
2024-04-25 2:21 ` [PATCH v4 03/14] util/dsa: Implement DSA device start and stop logic Hao Xiang
2024-04-25 14:21 ` Daniel P. Berrangé
2024-04-25 14:25 ` Daniel P. Berrangé
2024-04-25 14:32 ` Daniel P. Berrangé
2024-04-25 21:22 ` Fabiano Rosas [this message]
2024-04-25 2:21 ` [PATCH v4 04/14] util/dsa: Implement DSA task enqueue and dequeue Hao Xiang
2024-04-25 20:55 ` Fabiano Rosas
2024-04-25 21:48 ` Fabiano Rosas
2024-04-25 2:21 ` [PATCH v4 05/14] util/dsa: Implement DSA task asynchronous completion thread model Hao Xiang
2024-04-25 2:21 ` [PATCH v4 06/14] util/dsa: Implement zero page checking in DSA task Hao Xiang
2024-04-25 2:21 ` [PATCH v4 07/14] util/dsa: Implement DSA task asynchronous submission and wait for completion Hao Xiang
2024-05-01 18:59 ` Peter Xu
2024-04-25 2:21 ` [PATCH v4 08/14] migration/multifd: Add new migration option for multifd DSA offloading Hao Xiang
2024-04-25 14:17 ` Daniel P. Berrangé
2024-04-26 9:16 ` Markus Armbruster
2024-04-25 2:21 ` [PATCH v4 09/14] migration/multifd: Prepare to introduce DSA acceleration on the multifd path Hao Xiang
2024-05-01 19:18 ` Peter Xu
2024-04-25 2:21 ` [PATCH v4 10/14] migration/multifd: Enable DSA offloading in multifd sender path Hao Xiang
2024-04-25 14:29 ` Daniel P. Berrangé
2024-04-25 15:39 ` Fabiano Rosas
2024-05-01 19:25 ` Peter Xu
2024-04-25 2:21 ` [PATCH v4 11/14] migration/multifd: Add migration option set packet size Hao Xiang
2024-05-01 19:36 ` Peter Xu
2024-04-25 2:21 ` [PATCH v4 12/14] migration/multifd: Enable set packet size migration option Hao Xiang
2024-04-25 2:21 ` [PATCH v4 13/14] util/dsa: Add unit test coverage for Intel DSA task submission and completion Hao Xiang
2024-04-25 2:21 ` [PATCH v4 14/14] migration/multifd: Add integration tests for multifd with Intel DSA offloading Hao Xiang
2024-05-01 19:54 ` [PATCH v4 00/14] Use Intel DSA accelerator to offload zero page checking in multifd live migration Peter Xu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=871q6t87ei.fsf@suse.de \
--to=farosas@suse.de \
--cc=armbru@redhat.com \
--cc=bryan.zhang@bytedance.com \
--cc=hao.xiang@linux.dev \
--cc=lvivier@redhat.com \
--cc=marcandre.lureau@redhat.com \
--cc=peterx@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.