[PATCH i-g-t 2/4] lib/intel_vram: Add library for VRAM accesses
Lukasz Laguna
lukasz.laguna at intel.com
Thu Jul 17 09:08:10 UTC 2025
Prepare a library with helpers to map and unmap VRAM BAR region and
perform read/write operations.
Signed-off-by: Lukasz Laguna <lukasz.laguna at intel.com>
---
lib/intel_vram.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++
lib/intel_vram.h | 22 ++++++
lib/meson.build | 1 +
3 files changed, 206 insertions(+)
create mode 100644 lib/intel_vram.c
create mode 100644 lib/intel_vram.h
diff --git a/lib/intel_vram.c b/lib/intel_vram.c
new file mode 100644
index 000000000..38e2ccf36
--- /dev/null
+++ b/lib/intel_vram.c
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2025 Intel Corporation
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include "igt_core.h"
+#include "igt_sriov_device.h"
+#include "intel_vram.h"
+
+static int intel_vram_open_bar(int pf_fd, unsigned int vf_num, int mode)
+{
+ int sysfs, fd;
+
+ sysfs = igt_sriov_device_sysfs_open(pf_fd, vf_num);
+ if (sysfs < 0) {
+ igt_debug("Failed to open sysfs for VF%d: %s\n", vf_num, strerror(errno));
+ return -1;
+ }
+
+ fd = openat(sysfs, "resource2", mode | O_SYNC);
+ if (fd < 0)
+ igt_debug("Failed to open resource2 for VF%d: %s\n", vf_num, strerror(errno));
+
+ close(sysfs);
+
+ return fd;
+}
+
+/**
+ * intel_vram_bar_size - Get the size of the VRAM BAR
+ * @pf_fd: PF device file descriptor
+ * @vf_num: VF number (1-based), or 0 for the PF
+ *
+ * Opens the VRAM BAR file descriptor for the specified device and retrieves
+ * its size by using fstat().
+ *
+ * Return: The size of the VRAM BAR in bytes on success,
+ * or negative value on failure.
+ */
+ssize_t intel_vram_bar_size(int pf_fd, unsigned int vf_num)
+{
+ int fd;
+ struct stat st;
+
+ fd = intel_vram_open_bar(pf_fd, vf_num, O_RDONLY);
+ if (fd < 0)
+ return fd;
+
+ if (fstat(fd, &st)) {
+ igt_debug("Failed to stat resource2 for VF%u: %s\n", vf_num, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+
+ return st.st_size;
+}
+
+/**
+ * intel_vram_mmap - Map VRAM BAR region
+ * @pf_fd: PF device file descriptor
+ * @vf_num: VF number (1-based), or 0 for the PF
+ * @length: Number of bytes to map
+ * @prot: Memory protection flags
+ * @offset: Offset (in bytes) within the BAR to begin the mapping
+ *
+ * Maps a PF or VF VRAM BAR into user space using mmap().
+ *
+ * Return: A vram_mapping struct with the mapped address and size on success,
+ * or NULL address and zero size on failure.
+ */
+struct vram_mapping intel_vram_mmap(int pf_fd, unsigned int vf_num, size_t length, int prot,
+ off_t offset)
+{
+ int open_flags = ((prot & PROT_WRITE) != 0) ? O_RDWR : O_RDONLY;
+ struct vram_mapping m = { .addr = NULL, .size = 0 };
+ ssize_t vram_bar_size;
+ int vram_bar_fd;
+ void *addr;
+
+ vram_bar_size = intel_vram_bar_size(pf_fd, vf_num);
+ if (vram_bar_size < 0) {
+ igt_debug("Failed to get VRAM BAR size for VF%u: %s\n", vf_num, strerror(errno));
+ return m;
+ }
+
+ if (vram_bar_size < length) {
+ igt_debug("Mapping length (%zu) exceeds VRAM BAR size (%" PRIu64 ")\n",
+ length, (uint64_t)vram_bar_size);
+ return m;
+ }
+
+ vram_bar_fd = intel_vram_open_bar(pf_fd, vf_num, open_flags);
+ if (vram_bar_fd < 0) {
+ igt_debug("Failed to open VRAM BAR file for VF%u: %s\n", vf_num, strerror(errno));
+ return m;
+ }
+
+ addr = mmap(NULL, length, prot, MAP_SHARED, vram_bar_fd, offset);
+ close(vram_bar_fd);
+ if (addr == MAP_FAILED) {
+ igt_debug("Failed to map VRAM BAR for VF%u: %s\n", vf_num, strerror(errno));
+ return m;
+ }
+
+ m.addr = addr;
+ m.size = length;
+ return m;
+}
+
+/**
+ * intel_vram_munmap - Unmap previously mapped VRAM region
+ * @m: Pointer to a vram_mapping struct representing the mapped region
+ *
+ * Unmaps the user-space memory region previously mapped by intel_vram_mmap().
+ *
+ * Return: 0 on success, or negative value on failure.
+ */
+int intel_vram_munmap(struct vram_mapping *m)
+{
+ int ret;
+
+ ret = munmap(m->addr, m->size);
+ if (ret < 0)
+ igt_debug("Failed munmap %p: %s\n", m->addr, strerror(errno));
+
+ return ret;
+}
+
+/**
+ * intel_vram_read8 - Read 8-bit value from a mapped VRAM region
+ * @m: Pointer to a vram_mapping struct representing the mapped region
+ * @offset: Offset (in bytes) to read from
+ *
+ * Reads a single 8-bit value from the specified offset in the mapped VRAM.
+ *
+ * Return: The 8-bit value read from the given offset.
+ */
+uint8_t intel_vram_read8(struct vram_mapping *m, size_t offset)
+{
+ igt_assert(offset < m->size);
+
+ return READ_ONCE(*((uint8_t *)m->addr + offset));
+}
+
+/**
+ * intel_vram_write8 - Write 8-bit value to a mapped VRAM region
+ * @m: Pointer to a vram_mapping struct representing the mapped region
+ * @offset: Offset (in bytes) to write to
+ * @value: The 8-bit value to write
+ *
+ * Writes a single 8-bit value to the specified offset in the mapped VRAM.
+ */
+void intel_vram_write8(struct vram_mapping *m, size_t offset, uint8_t value)
+{
+ igt_assert(offset < m->size);
+
+ WRITE_ONCE(*((uint8_t *)m->addr + offset), value);
+}
+
+/**
+ * intel_vram_write_readback8 - Write and then read back an 8-bit value
+ * @m: Pointer to a vram_mapping struct representing the mapped region
+ * @offset: Offset (in bytes) to write to and read from
+ * @value: The 8-bit value to write
+ *
+ * Writes an 8-bit value to the specified offset in the mapped VRAM and
+ * reads it back to verify if the write was successful.
+ *
+ * Return: The 8-bit value read back from the given offset.
+ */
+uint8_t intel_vram_write_readback8(struct vram_mapping *m, size_t offset, uint8_t value)
+{
+ intel_vram_write8(m, offset, value);
+ return intel_vram_read8(m, offset);
+}
diff --git a/lib/intel_vram.h b/lib/intel_vram.h
new file mode 100644
index 000000000..b93f915e9
--- /dev/null
+++ b/lib/intel_vram.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2025 Intel Corporation
+ */
+
+#ifndef __INTEL_VRAM_H__
+#define __INTEL_VRAM_H__
+
+struct vram_mapping {
+ void *addr; /* Pointer to the mapped VRAM */
+ size_t size; /* Size of the mapped VRAM region */
+};
+
+ssize_t intel_vram_bar_size(int pf_fd, unsigned int vf_num);
+struct vram_mapping intel_vram_mmap(int pf_fd, unsigned int vf_num, size_t length, int prot,
+ off_t offset);
+int intel_vram_munmap(struct vram_mapping *m);
+uint8_t intel_vram_read8(struct vram_mapping *m, size_t offset);
+void intel_vram_write8(struct vram_mapping *m, size_t offset, uint8_t value);
+uint8_t intel_vram_write_readback8(struct vram_mapping *m, size_t offset, uint8_t value);
+
+#endif /* INTEL_VRAM_H */
diff --git a/lib/meson.build b/lib/meson.build
index 2eaca42a4..25c68011d 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -70,6 +70,7 @@ lib_sources = [
'intel_mocs.c',
'igt_multigpu.c',
'intel_pat.c',
+ 'intel_vram.c',
'ioctl_wrappers.c',
'media_spin.c',
'media_fill.c',
--
2.40.0
More information about the igt-dev
mailing list