mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
vfio: selftests: Introduce a sysfs lib
Introduce a sysfs library to handle the common reads/writes to the PCI sysfs files, for example, getting the total number of VFs supported by the device via /sys/bus/pci/devices/$BDF/sriov_totalvfs. The library will be used in the upcoming test patch to configure the VFs for a given PF device. Since readlink() is quite commonly used in the lib, introduce and use readlink_safe() to take care of potential buffer overrun errors and to safely terminate the buffer with '\0'. Opportunistically, move vfio_pci_get_group_from_dev() to this library as it falls under the same bucket. Rename it to sysfs_iommu_group_get() to align with other function names. Signed-off-by: Raghavendra Rao Ananta <rananta@google.com> Reviewed-by: Vipin Sharma <vipinsh@google.com> Reviewed-by: David Matlack <dmatlack@google.com> Tested-by: David Matlack <dmatlack@google.com> Link: https://lore.kernel.org/r/20260505212838.1698034-4-rananta@google.com Signed-off-by: Alex Williamson <alex@shazbot.org>
This commit is contained in:
parent
91ee1738a9
commit
c5db77a035
|
|
@ -5,6 +5,7 @@
|
|||
#include <libvfio/assert.h>
|
||||
#include <libvfio/iommu.h>
|
||||
#include <libvfio/iova_allocator.h>
|
||||
#include <libvfio/sysfs.h>
|
||||
#include <libvfio/vfio_pci_device.h>
|
||||
#include <libvfio/vfio_pci_driver.h>
|
||||
|
||||
|
|
|
|||
12
tools/testing/selftests/vfio/lib/include/libvfio/sysfs.h
Normal file
12
tools/testing/selftests/vfio/lib/include/libvfio/sysfs.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef SELFTESTS_VFIO_LIB_INCLUDE_LIBVFIO_SYSFS_H
|
||||
#define SELFTESTS_VFIO_LIB_INCLUDE_LIBVFIO_SYSFS_H
|
||||
|
||||
int sysfs_sriov_totalvfs_get(const char *bdf);
|
||||
int sysfs_sriov_numvfs_get(const char *bdf);
|
||||
void sysfs_sriov_numvfs_set(const char *bdf, int numvfs);
|
||||
char *sysfs_sriov_vf_bdf_get(const char *pf_bdf, int i);
|
||||
int sysfs_iommu_group_get(const char *bdf);
|
||||
char *sysfs_driver_get(const char *bdf);
|
||||
|
||||
#endif /* SELFTESTS_VFIO_LIB_INCLUDE_LIBVFIO_SYSFS_H */
|
||||
|
|
@ -6,6 +6,7 @@ LIBVFIO_SRCDIR := $(selfdir)/vfio/lib
|
|||
LIBVFIO_C := iommu.c
|
||||
LIBVFIO_C += iova_allocator.c
|
||||
LIBVFIO_C += libvfio.c
|
||||
LIBVFIO_C += sysfs.c
|
||||
LIBVFIO_C += vfio_pci_device.c
|
||||
LIBVFIO_C += vfio_pci_driver.c
|
||||
|
||||
|
|
|
|||
150
tools/testing/selftests/vfio/lib/sysfs.c
Normal file
150
tools/testing/selftests/vfio/lib/sysfs.c
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <linux/limits.h>
|
||||
|
||||
#include <libvfio.h>
|
||||
|
||||
#define readlink_safe(_path, _buf) ({ \
|
||||
int __ret; \
|
||||
\
|
||||
_Static_assert(!__builtin_types_compatible_p( \
|
||||
__typeof__(_buf), char *), \
|
||||
"readlink_safe: _buf must be an array, not a pointer"); \
|
||||
\
|
||||
__ret = readlink(_path, _buf, sizeof(_buf) - 1); \
|
||||
if (__ret != -1) \
|
||||
_buf[__ret] = 0; \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
static void readlink_base(const char *path, const char *data_fmt, void *out_data)
|
||||
{
|
||||
char rl_path[PATH_MAX];
|
||||
int ret;
|
||||
|
||||
ret = readlink_safe(path, rl_path);
|
||||
VFIO_ASSERT_NE(ret, -1);
|
||||
|
||||
ret = sscanf(basename(rl_path), data_fmt, out_data);
|
||||
VFIO_ASSERT_EQ(ret, 1);
|
||||
}
|
||||
|
||||
static int sysfs_val_get_int(const char *component, const char *name,
|
||||
const char *file)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char buf[32];
|
||||
int ret;
|
||||
int fd;
|
||||
|
||||
snprintf_assert(path, PATH_MAX, "/sys/bus/pci/%s/%s/%s", component, name, file);
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
VFIO_ASSERT_GT(read(fd, buf, ARRAY_SIZE(buf)), 0);
|
||||
VFIO_ASSERT_EQ(close(fd), 0);
|
||||
|
||||
errno = 0;
|
||||
ret = strtol(buf, NULL, 0);
|
||||
VFIO_ASSERT_EQ(errno, 0, "sysfs path \"%s\" is not an integer: \"%s\"\n", path, buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sysfs_val_set(const char *component, const char *name,
|
||||
const char *file, const char *val)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
int fd;
|
||||
|
||||
snprintf_assert(path, PATH_MAX, "/sys/bus/pci/%s/%s/%s", component, name, file);
|
||||
VFIO_ASSERT_GT(fd = open(path, O_WRONLY), 0);
|
||||
|
||||
VFIO_ASSERT_EQ(write(fd, val, strlen(val)), strlen(val));
|
||||
VFIO_ASSERT_EQ(close(fd), 0);
|
||||
}
|
||||
|
||||
static int sysfs_device_val_get(const char *bdf, const char *file)
|
||||
{
|
||||
return sysfs_val_get_int("devices", bdf, file);
|
||||
}
|
||||
|
||||
static void sysfs_device_val_set(const char *bdf, const char *file, const char *val)
|
||||
{
|
||||
sysfs_val_set("devices", bdf, file, val);
|
||||
}
|
||||
|
||||
static void sysfs_device_val_set_int(const char *bdf, const char *file, int val)
|
||||
{
|
||||
char val_str[32];
|
||||
|
||||
snprintf_assert(val_str, sizeof(val_str), "%d", val);
|
||||
sysfs_device_val_set(bdf, file, val_str);
|
||||
}
|
||||
|
||||
int sysfs_sriov_totalvfs_get(const char *bdf)
|
||||
{
|
||||
return sysfs_device_val_get(bdf, "sriov_totalvfs");
|
||||
}
|
||||
|
||||
int sysfs_sriov_numvfs_get(const char *bdf)
|
||||
{
|
||||
return sysfs_device_val_get(bdf, "sriov_numvfs");
|
||||
}
|
||||
|
||||
void sysfs_sriov_numvfs_set(const char *bdf, int numvfs)
|
||||
{
|
||||
sysfs_device_val_set_int(bdf, "sriov_numvfs", numvfs);
|
||||
}
|
||||
|
||||
char *sysfs_sriov_vf_bdf_get(const char *pf_bdf, int i)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char *out_vf_bdf;
|
||||
|
||||
/* Fit "0000:00:00.0" */
|
||||
out_vf_bdf = calloc(16, sizeof(char));
|
||||
VFIO_ASSERT_NOT_NULL(out_vf_bdf);
|
||||
|
||||
snprintf_assert(path, PATH_MAX, "/sys/bus/pci/devices/%s/virtfn%d", pf_bdf, i);
|
||||
readlink_base(path, "%s", out_vf_bdf);
|
||||
|
||||
return out_vf_bdf;
|
||||
}
|
||||
|
||||
int sysfs_iommu_group_get(const char *bdf)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
int group;
|
||||
|
||||
snprintf_assert(path, PATH_MAX, "/sys/bus/pci/devices/%s/iommu_group", bdf);
|
||||
readlink_base(path, "%d", &group);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
char *sysfs_driver_get(const char *bdf)
|
||||
{
|
||||
char driver_path[PATH_MAX];
|
||||
char path[PATH_MAX];
|
||||
char *out_driver;
|
||||
int ret;
|
||||
|
||||
snprintf_assert(path, PATH_MAX, "/sys/bus/pci/devices/%s/driver", bdf);
|
||||
ret = readlink_safe(path, driver_path);
|
||||
if (ret == -1) {
|
||||
if (errno == ENOENT)
|
||||
return NULL;
|
||||
|
||||
VFIO_FAIL("Failed to read %s\n", path);
|
||||
}
|
||||
|
||||
out_driver = strdup(basename(driver_path));
|
||||
VFIO_ASSERT_NOT_NULL(out_driver);
|
||||
|
||||
return out_driver;
|
||||
}
|
||||
|
|
@ -25,8 +25,6 @@
|
|||
#include "kselftest.h"
|
||||
#include <libvfio.h>
|
||||
|
||||
#define PCI_SYSFS_PATH "/sys/bus/pci/devices"
|
||||
|
||||
static void vfio_pci_irq_set(struct vfio_pci_device *device,
|
||||
u32 index, u32 vector, u32 count, int *fds)
|
||||
{
|
||||
|
|
@ -204,24 +202,6 @@ void vfio_pci_device_reset(struct vfio_pci_device *device)
|
|||
ioctl_assert(device->fd, VFIO_DEVICE_RESET, NULL);
|
||||
}
|
||||
|
||||
static unsigned int vfio_pci_get_group_from_dev(const char *bdf)
|
||||
{
|
||||
char dev_iommu_group_path[PATH_MAX] = {0};
|
||||
char sysfs_path[PATH_MAX] = {0};
|
||||
unsigned int group;
|
||||
int ret;
|
||||
|
||||
snprintf_assert(sysfs_path, PATH_MAX, "%s/%s/iommu_group", PCI_SYSFS_PATH, bdf);
|
||||
|
||||
ret = readlink(sysfs_path, dev_iommu_group_path, sizeof(dev_iommu_group_path));
|
||||
VFIO_ASSERT_NE(ret, -1, "Failed to get the IOMMU group for device: %s\n", bdf);
|
||||
|
||||
ret = sscanf(basename(dev_iommu_group_path), "%u", &group);
|
||||
VFIO_ASSERT_EQ(ret, 1, "Failed to get the IOMMU group for device: %s\n", bdf);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
static void vfio_pci_group_setup(struct vfio_pci_device *device, const char *bdf)
|
||||
{
|
||||
struct vfio_group_status group_status = {
|
||||
|
|
@ -230,7 +210,7 @@ static void vfio_pci_group_setup(struct vfio_pci_device *device, const char *bdf
|
|||
char group_path[32];
|
||||
int group;
|
||||
|
||||
group = vfio_pci_get_group_from_dev(bdf);
|
||||
group = sysfs_iommu_group_get(bdf);
|
||||
snprintf_assert(group_path, sizeof(group_path), "/dev/vfio/%d", group);
|
||||
|
||||
device->group_fd = open(group_path, O_RDWR);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user