[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