drm study
学习过程
0319:
-
对于任何驱动来说,buffer是最重要的,知道了buffer的创建使用这个驱动就会一半了;
-
现在感觉是一个无头苍蝇,感觉非常复杂:数据结构非常多,之间的关系也非常复杂;
-
不过没关系,先研究buffer通路;
-
![alt text]()
- 可以看见应用层对mmap写入的
hello world,驱动中vkms_obj->vaddr正是; - 对应的pa又是怎么来的呢?
- 可以看见应用层对mmap写入的
-
突然有个疑问:应用层是通过remap_pfn_range映射vma和一个pa,如果使用了smmu,这个pa就会变成iova,这时候vma和这个iova是如何映射的呢?
-
实验方法:
- crc_enabled设置为1:cat /sys/kernel/debug/dri/1/crtc-0/crc/data &
- vkms_vblank_simulate:./modeset-single-buffer
-
几个疑问:
- 这个
drm_gem_object应该是与物理内存有关 - vkms_gem_vmap的调用在mmap和fault之后,我理解是mmap只分配了vma,在fault应该会填入物理地址(好像是分配了page),vkms_gem_vmap中又在分配page,这是为啥呢?
- 细节非常复杂,先从输入输出入手,大致知晓数据结构关系,重要的是关键回调的调用关系,vkms_gem_vmap;
- 这个
vgem_test
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
struct vgem_bo {
uint32_t handle;
uint32_t width, height;
uint32_t bpp, pitch;
uint64_t size;
};
struct local_vgem_fence_signal {
uint32_t fence;
uint32_t flags;
};
struct local_vgem_fence_attach {
uint32_t handle;
uint32_t flags;
uint32_t out_fence;
uint32_t pad;
};
#define LOCAL_VGEM_FENCE_ATTACH 0x1
#define LOCAL_VGEM_FENCE_SIGNAL 0x2
#define VGEM_FENCE_WRITE 0x1
#define WIP_VGEM_FENCE_NOTIMEOUT 0x2
#define LOCAL_IOCTL_VGEM_FENCE_SIGNAL DRM_IOW( DRM_COMMAND_BASE + LOCAL_VGEM_FENCE_SIGNAL, struct local_vgem_fence_signal)
#define LOCAL_IOCTL_VGEM_FENCE_ATTACH DRM_IOWR( DRM_COMMAND_BASE + LOCAL_VGEM_FENCE_ATTACH, struct local_vgem_fence_attach)
int __vgem_create(int fd, struct vgem_bo *bo)
{
struct drm_mode_create_dumb arg;
memset(&arg, 0, sizeof(arg));
arg.width = bo->width;
arg.height = bo->height;
arg.bpp = bo->bpp;
if (drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg))
return -errno;
bo->handle = arg.handle;
bo->pitch = arg.pitch;
bo->size = arg.size;
return 0;
}
void vgem_create(int fd, struct vgem_bo *bo)
{
__vgem_create(fd, bo);
}
int prime_handle_to_fd(int fd, uint32_t handle)
{
struct drm_prime_handle args;
memset(&args, 0, sizeof(args));
args.handle = handle;
args.flags = DRM_CLOEXEC;
args.fd = -1;
ioctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
return args.fd;
}
static int __vgem_fence_attach(int fd, struct local_vgem_fence_attach *arg)
{
int err = 0;
if (ioctl(fd, LOCAL_IOCTL_VGEM_FENCE_ATTACH, arg))
err = -errno;
errno = 0;
return err;
}
uint32_t vgem_fence_attach(int fd, struct vgem_bo *bo, unsigned flags)
{
struct local_vgem_fence_attach arg;
memset(&arg, 0, sizeof(arg));
arg.handle = bo->handle;
arg.flags = flags;
__vgem_fence_attach(fd, &arg);
return arg.out_fence;
}
static bool prime_busy(int fd, bool excl)
{
struct pollfd pfd = { .fd = fd, .events = excl ? POLLOUT : POLLIN };
return poll(&pfd, 1, 0) == 0;
}
static int ioctl_vgem_fence_signal(int fd, struct local_vgem_fence_signal *arg)
{
int err = 0;
if (ioctl(fd, LOCAL_IOCTL_VGEM_FENCE_SIGNAL, arg))
err = -errno;
errno = 0;
return err;
}
int __vgem_fence_signal(int fd, uint32_t fence)
{
struct local_vgem_fence_signal arg;
memset(&arg, 0, sizeof(arg));
arg.fence = fence;
return ioctl_vgem_fence_signal(fd, &arg);
}
void vgem_fence_signal(int fd, uint32_t fence)
{
__vgem_fence_signal(fd, fence);
}
void gem_close(int fd, uint32_t handle)
{
struct drm_gem_close close_bo;
memset(&close_bo, 0, sizeof(close_bo));
close_bo.handle = handle;
ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close_bo);
}
static void test_dmabuf_fence(int fd)
{
struct vgem_bo bo;
int dmabuf;
uint32_t fence;
bo.width = 1024;
bo.height = 1;
bo.bpp = 32;
vgem_create(fd, &bo);
/* export, then fence */
dmabuf = prime_handle_to_fd(fd, bo.handle); /* 得到dmabuf的fd */
fence = vgem_fence_attach(fd, &bo, 0);
prime_busy(dmabuf, false);
prime_busy(dmabuf, true);
vgem_fence_signal(fd, fence);
prime_busy(dmabuf, false);
prime_busy(dmabuf, true);
fence = vgem_fence_attach(fd, &bo, VGEM_FENCE_WRITE);
prime_busy(dmabuf, false);
prime_busy(dmabuf, true);
vgem_fence_signal(fd, fence);
prime_busy(dmabuf, false);
prime_busy(dmabuf, true);
close(dmabuf);
gem_close(fd, bo.handle);
}
int main(int argc, char **argv)
{
int fd;
fd = open("/dev/dri/card0", O_RDWR);
test_dmabuf_fence(fd);
close(fd);
return 0;
}
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
struct buffer_object {
uint32_t width;
uint32_t height;
uint32_t pitch;
uint32_t handle;
uint32_t size;
uint8_t *vaddr;
uint32_t fb_id;
};
struct buffer_object buf;
static int modeset_create_fb(int fd, struct buffer_object *bo)
{
struct drm_mode_create_dumb create = {};
struct drm_mode_map_dumb map = {};
int i = 0;
/* create a dumb-buffer, the pixel format is XRGB888 */
create.width = bo->width;
create.height = bo->height;
create.bpp = 32;
drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
/* bind the dumb-buffer to an FB object */
bo->pitch = create.pitch;
bo->size = create.size;
bo->handle = create.handle;
drmModeAddFB(fd, bo->width, bo->height, 24, 32, bo->pitch,
bo->handle, &bo->fb_id);
/* map the dumb-buffer to userspace */
map.handle = create.handle;
drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map);
bo->vaddr = mmap(0, create.size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, map.offset);
printf("vaddr %p\n", bo->vaddr);
/* initialize the dumb-buffer with white-color */
for(i = 0; i < bo->size; i+= sizeof("hello world"))
memcpy(&bo->vaddr[i], "hello world", sizeof("hello world"));
// memset(bo->vaddr, 0xff, bo->size);
return 0;
}
static void modeset_destroy_fb(int fd, struct buffer_object *bo)
{
struct drm_mode_destroy_dumb destroy = {};
drmModeRmFB(fd, bo->fb_id);
munmap(bo->vaddr, bo->size);
destroy.handle = bo->handle;
drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy);
}
int main(int argc, char **argv)
{
int fd;
drmModeConnector *conn;
drmModeRes *res;
uint32_t conn_id;
uint32_t crtc_id;
int i;
printf("%s %d\n", __func__, __LINE__);
fd = open("/dev/dri/card1", O_RDWR | O_CLOEXEC);
printf("%s %d\n", __func__, __LINE__);
res = drmModeGetResources(fd);
printf("%s %d\n", __func__, __LINE__);
printf("%s %d\n", __func__, __LINE__);
crtc_id = res->crtcs[0];
conn_id = res->connectors[0];
printf("%s %d, %d\n", __func__, __LINE__, conn_id);
conn = drmModeGetConnector(fd, conn_id);
printf("%s %d\n", __func__, __LINE__);
buf.width = conn->modes[0].hdisplay;
buf.height = conn->modes[0].vdisplay;
modeset_create_fb(fd, &buf);
printf("%s %d\n", __func__, __LINE__);
drmModeSetCrtc(fd, crtc_id, buf.fb_id,
0, 0, &conn_id, 1, &conn->modes[0]);
printf("mmap data\n");
for(i = 0; i < buf.size; i+= sizeof("hello world"))
printf("%x", ((int *)(buf.vaddr))[i]);
printf("%s %d\n", __func__, __LINE__);
// getchar();
printf("%s %d\n", __func__, __LINE__);
modeset_destroy_fb(fd, &buf);
printf("%s %d\n", __func__, __LINE__);
drmModeFreeConnector(conn);
printf("%s %d\n", __func__, __LINE__);
drmModeFreeResources(res);
printf("%s %d\n", __func__, __LINE__);
close(fd);
return 0;
}


浙公网安备 33010602011771号