1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
// 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);
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
* @size: pointer to store VRAM BAR size
*
* Opens the VRAM BAR file descriptor for the specified device and retrieves
* its size by using fstat().
*
* Return: 0 on success, or negative value on failure.
*/
int intel_vram_bar_size(int pf_fd, unsigned int vf_num, uint64_t *size)
{
int fd, ret = 0;
struct stat st;
if (!size)
return -EINVAL;
fd = intel_vram_open_bar(pf_fd, vf_num, O_RDONLY);
if (fd < 0)
return fd;
if (fstat(fd, &st))
ret = -errno;
else
*size = (uint64_t)st.st_size;
close(fd);
return ret;
}
/**
* intel_vram_mmap - Map VRAM BAR region
* @pf_fd: PF device file descriptor
* @vf_num: VF number (1-based), or 0 for the PF
* @offset: Offset (in bytes) within the BAR to begin the mapping
* @length: Number of bytes to map
* @prot: Memory protection flags
* @map: pointer to vram_mapping struct to store address and size of the mapping
*
* Maps a PF or VF VRAM BAR into user space using mmap(). On error, it sets the
* mapping address to NULL and the mapping size to 0.
*
* Return: 0 on success, or negative value on failure.
*/
int intel_vram_mmap(int pf_fd, unsigned int vf_num, uint64_t offset, size_t length,
int prot, struct vram_mapping *map)
{
uint64_t bar_size, end;
int fd, ret = 0;
void *addr;
if (!map)
return -EINVAL;
map->addr = NULL;
map->size = 0;
if (!length)
return 0;
ret = intel_vram_bar_size(pf_fd, vf_num, &bar_size);
if (ret)
return ret;
end = offset + length;
if (end < offset || end > bar_size)
return -EINVAL;
fd = intel_vram_open_bar(pf_fd, vf_num, (prot & PROT_WRITE) ? O_RDWR : O_RDONLY);
if (fd < 0)
return fd;
addr = mmap(NULL, length, prot, MAP_SHARED, fd, (off_t)offset);
if (addr == MAP_FAILED) {
ret = -errno;
goto end;
}
map->addr = addr;
map->size = length;
end:
close(fd);
return ret;
}
/**
* 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(const 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(const 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(const struct vram_mapping *m, size_t offset, uint8_t value)
{
intel_vram_write8(m, offset, value);
return intel_vram_read8(m, offset);
}
|