Linux内核4.14版本——drm框架分析(7)——用户态和内核态间的交互

这篇具有很好参考价值的文章主要介绍了Linux内核4.14版本——drm框架分析(7)——用户态和内核态间的交互。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

         驱动会注册一个支持KMS的DRM设备时,会在/dev/drm/下创建一个card%d文件,用户态可以通过打开该文件,并对文件描述符做相应的操作实现相应的功能。该文件描述符对应的文件操作回调函数(filesystem_operations)位于drm_driver中,并由驱动程序填充。典型如下:

static const struct file_operations rockchip_drm_driver_fops = {
	.owner = THIS_MODULE,
	.open = drm_open,
	.mmap = rockchip_gem_mmap,
	.poll = drm_poll,
	.read = drm_read,
	.unlocked_ioctl = drm_ioctl,
	.compat_ioctl = drm_compat_ioctl,
	.release = drm_release,
};
 
long drm_ioctl(struct file *filp,
	      unsigned int cmd, unsigned long arg)
{
	struct drm_file *file_priv = filp->private_data;
	struct drm_device *dev;
	const struct drm_ioctl_desc *ioctl = NULL;
	drm_ioctl_t *func;
	unsigned int nr = DRM_IOCTL_NR(cmd);
	int retcode = -EINVAL;
	char stack_kdata[128];
	char *kdata = NULL;
	unsigned int in_size, out_size, drv_size, ksize;
	bool is_driver_ioctl;
 
	dev = file_priv->minor->dev;
 
	if (drm_dev_is_unplugged(dev))
		return -ENODEV;
 
	is_driver_ioctl = nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END;
 
	if (is_driver_ioctl) {
		/* driver ioctl */
		unsigned int index = nr - DRM_COMMAND_BASE;
 
		if (index >= dev->driver->num_ioctls)
			goto err_i1;
		index = array_index_nospec(index, dev->driver->num_ioctls);
		ioctl = &dev->driver->ioctls[index];
	} else {
		/* core ioctl */
		if (nr >= DRM_CORE_IOCTL_COUNT)
			goto err_i1;
		nr = array_index_nospec(nr, DRM_CORE_IOCTL_COUNT);
		ioctl = &drm_ioctls[nr];
	}
 
	drv_size = _IOC_SIZE(ioctl->cmd);
	out_size = in_size = _IOC_SIZE(cmd);
	if ((cmd & ioctl->cmd & IOC_IN) == 0)
		in_size = 0;
	if ((cmd & ioctl->cmd & IOC_OUT) == 0)
		out_size = 0;
	ksize = max(max(in_size, out_size), drv_size);
 
	DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
		  task_pid_nr(current),
		  (long)old_encode_dev(file_priv->minor->kdev->devt),
		  file_priv->authenticated, ioctl->name);
 
	/* Do not trust userspace, use our own definition */
	func = ioctl->func;
 
	if (unlikely(!func)) {
		DRM_DEBUG("no function\n");
		retcode = -EINVAL;
		goto err_i1;
	}
 
	if (ksize <= sizeof(stack_kdata)) {
		kdata = stack_kdata;
	} else {
		kdata = kmalloc(ksize, GFP_KERNEL);
		if (!kdata) {
			retcode = -ENOMEM;
			goto err_i1;
		}
	}
 
	if (copy_from_user(kdata, (void __user *)arg, in_size) != 0) {
		retcode = -EFAULT;
		goto err_i1;
	}
 
	if (ksize > in_size)
		memset(kdata + in_size, 0, ksize - in_size);
 
	retcode = drm_ioctl_kernel(filp, func, kdata, ioctl->flags);
	if (copy_to_user((void __user *)arg, kdata, out_size) != 0)
		retcode = -EFAULT;
 
      err_i1:
	if (!ioctl)
		DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
			  task_pid_nr(current),
			  (long)old_encode_dev(file_priv->minor->kdev->devt),
			  file_priv->authenticated, cmd, nr);
 
	if (kdata != stack_kdata)
		kfree(kdata);
	if (retcode)
		DRM_DEBUG("pid=%d, ret = %d\n", task_pid_nr(current), retcode);
	return retcode;
}

        drm上层是如何调用的呢,我们使用以下命令跟踪。

strace -o 1.txt ./modetest -M mali-dp -P 27@34:1280x720@RG16 

其结果摘抄了一部分使用如下。

ioctl(3, DRM_IOCTL_VERSION, 0x4213f0)   = 0
ioctl(3, DRM_IOCTL_VERSION, 0x4213f0)   = 0
ioctl(3, DRM_IOCTL_GET_UNIQUE, 0x7fd60bb870) = 0
ioctl(3, DRM_IOCTL_GET_UNIQUE, 0x7fd60bb870) = 0
ioctl(3, DRM_IOCTL_SET_CLIENT_CAP, 0x7fd60bbb40) = 0
ioctl(3, DRM_IOCTL_MODE_GETRESOURCES, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETRESOURCES, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETCRTC, 0x7fd60bbae8) = 0
ioctl(3, DRM_IOCTL_MODE_GETENCODER, 0x7fd60bbb38) = 0
ioctl(3, DRM_IOCTL_MODE_GETCONNECTOR, 0x7fd60bbb00) = 0
ioctl(3, DRM_IOCTL_MODE_GETCONNECTOR, 0x7fd60bbb00) = 0
ioctl(3, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPLANERESOURCES, 0x7fd60bbb40) = 0
ioctl(3, DRM_IOCTL_MODE_GETPLANERESOURCES, 0x7fd60bbb40) = 0
ioctl(3, DRM_IOCTL_MODE_GETPLANE, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_GETPLANE, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_GETPLANE, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_GETPLANE, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_GETPLANE, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_GETPLANE, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_GETPLANE, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_GETPLANE, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, 0x7fd60bbb30) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_MODE_GETPROPERTY, 0x7fd60bbb10) = 0
ioctl(3, DRM_IOCTL_GET_CAP, 0x7fd60bbb40) = 0
ioctl(3, DRM_IOCTL_MODE_CREATE_DUMB, 0x7fd60bb980) = 0
ioctl(3, DRM_IOCTL_MODE_MAP_DUMB, 0x7fd60bb980) = 0
mmap(NULL, 8294400, PROT_READ|PROT_WRITE, MAP_SHARED, 3, 0x100e10000) = 0x7f9d4c0000
munmap(0x7f9d4c0000, 8294400)           = 0
ioctl(3, DRM_IOCTL_MODE_ADDFB2, 0x7fd60bb918) = 0
fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(0x5, 0x1), ...}) = 0
ioctl(1, TCGETS, {B115200 opost isig icanon echo ...}) = 0
write(1, "setting mode 1920x1080-75.00Hz o"..., 57) = 57
ioctl(3, DRM_IOCTL_MODE_SETCRTC, 0x7fd60bb9d8) = 0
ioctl(3, DRM_IOCTL_MODE_DIRTYFB, 0x7fd60bba28) = -1 ENOSYS (Function not implemented)
ioctl(3, DRM_IOCTL_MODE_OBJ_SETPROPERTY, 0x7fd60bab88) = 0
ioctl(3, DRM_IOCTL_MODE_OBJ_SETPROPERTY, 0x7fd60bab88) = 0
fstat(0, {st_mode=S_IFCHR|0600, st_rdev=makedev(0x5, 0x1), ...}) = 0
ioctl(0, TCGETS, {B115200 opost isig icanon echo ...}) = 0
read(0, "\n", 4096)                     = 1
ioctl(3, DRM_IOCTL_MODE_RMFB, 0x7fd60bbb4c) = 0
ioctl(3, DRM_IOCTL_MODE_DESTROY_DUMB, 0x7fd60bbb48) = 0
fstat(3, {st_mode=S_IFCHR|0660, st_rdev=makedev(0xe2, 0), ...}) = 0
fstat(3, {st_mode=S_IFCHR|0660, st_rdev=makedev(0xe2, 0), ...}) = 0
close(3)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

我们从上面简单分析,基本上按以下的ioctl调用顺序,进行调用的。

DRM_IOCTL_MODE_GETRESOURCES     // 获得资源

DRM_IOCTL_MODE_GETCRTC                  // 获得crtc

DRM_IOCTL_MODE_GETENCODER          // 获得encoder

DRM_IOCTL_MODE_GETCONNECTOR                   // 获得connector

DRM_IOCTL_MODE_OBJ_GETPROPERTIES          // 获得参数变量

DRM_IOCTL_MODE_GETPROPERTY                       // 获得参数变量

DRM_IOCTL_MODE_GETPLANERESOURCES        // 获得plane资源

DRM_IOCTL_MODE_GETPLANE                               // 获得plane

DRM_IOCTL_MODE_CREATE_DUMB                       // 获得gem

DRM_IOCTL_MODE_MAP_DUMB                              // map

mmap(NULL, 8294400, PROT_READ|PROT_WRITE, MAP_SHARED, 3, 0x100e10000) = 0x7f9d4c0000

DRM_IOCTL_MODE_ADDFB2                                   //填充fb

DRM_IOCTL_MODE_SETCRTC                                // 设置crtc

DRM_IOCTL_MODE_DIRTYFB

DRM_IOCTL_MODE_RMFB

后面我们会挑选一部分进行分析。文章来源地址https://www.toymoban.com/news/detail-493903.html

到了这里,关于Linux内核4.14版本——drm框架分析(7)——用户态和内核态间的交互的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【操作系统】一篇文章带你快速搞懂用户态和内核态

    目录 一、指令划分 二、特权级别 三、操作系统需要两种CPU状态 四、CPU状态之间的转换 4.1 CPU状态转换的途径 4.2 CPU状态转化流程 4.3 什么情况会导致用户态到内核态切换 通常来说,以下三种情况会导致用户态到内核态的切换 1、系统调用 2、异常 3、外围设备的中断 五、为什

    2024年02月05日
    浏览(49)
  • linux-2.6.22.6内核nand flash框架分析

    内核启动时会在串口打印nand flash的相关信息,通过该信息可定位到内核自带的nand flash相关驱动代码。 例如串口打印S3C24XX NAND Driver,搜索该字符串可找到/home/book/work/linux/linux-2.6.22.6/drivers/mtd/nand/s3c2410.c这个文件,这个就是nand flash驱动代码文件。 从该文件的s3c2410_nand_init函数

    2024年02月11日
    浏览(35)
  • linux-2.6.22.6内核i2c驱动框架源码分析

    i2c是常见的通信协议,协议比较简单,只有数据和时钟两条线(SDA和SCL),i2c的通信分为主机和从机,主机一般占主导地位,从机可以有多个。 i2c通信的数据格式为(SDA上的数据):开始的7位里面指定了设备地址(因为有多个从机),第8位是读或写信号,表示此次传输是读还

    2024年02月11日
    浏览(52)
  • 4.14日网络编程学习

    IP地址:指互联网协议地址(Internet Protocol Address),俗称IP。 要想使网络中的计算机能够进行通信,必须为每台计算机指定一个标识号,通过这个标识号来指定接受数据的计算机或者发送数据的计算机。 在TCP/IP协议中,这个标识号就是IP地址,它可以唯一标识一台计算机,目

    2024年04月15日
    浏览(36)
  • 操作系统实验 2.3系统调用:linux-0.11-lab “为版本0内核增加一个系统调用getjiffies” 和 “在用户程序中使用新增的系统调用”

    打开 vscode ,在如图所示位置打开 ~/os/linux-0.11-lab/0 文件夹 1.定义getjiffies系统调用 题目中给的提示:进入到 unistd.h 文件中 阅读代码,可以发现上图划线处有个系统调用名为 getpid :返回当前进程号——这与我们期望实现的功能类似:通过系统调用返回jiffies值。 于是此时希望

    2023年04月08日
    浏览(98)
  • 《C++大学教程》4.14信用额度问题

    题目:

    2024年02月01日
    浏览(35)
  • 4.14 HTTPS 中 TLS 和 TCP 能同时握手吗?

    目录 实现HTTPS中TLS和TCP同时握手的前提: 什么是TCP Fast Open? TLS v1.3 TCP Fast Open + TLSv1.3 HTTPS都是基于TCP传输协议实现的,得先建立完可靠得TCP连接才能做TLS握手的事情。 1、客户端和服务端开启了TCP Fast Open,且TLS版本在1.3; 2、客户端和服务端已经完成过一次通信。 常规的T

    2024年02月11日
    浏览(30)
  • 【Linux内核解析-linux-5.14.10-内核源码注释】内核启动kernel_init解释

    static int __ref kernel_init(void *unused) : 声明一个静态整型函数 kernel_init() ,该函数不会被其他文件访问,使用 __ref 标记表示该函数是可重定位的,并且该函数不需要任何参数。 wait_for_completion(kthreadd_done); : 等待 kthreadd 线程完成初始化, wait_for_completion() 函数会阻塞当前进程,直到

    2024年02月02日
    浏览(70)
  • 【Linux内核解析-linux-5.14.10-内核源码注释】关于Linux同步机制知识点整理

    在Linux系统中,同步机制是操作系统中非常重要的一部分,以下是一些基本要点: 什么是同步机制?同步机制是一种操作系统提供的机制,用于协调多个进程或线程之间的访问共享资源,防止出现竞态条件和死锁等问题。 Linux中常用的同步机制有哪些?Linux中常用的同步机制

    2024年02月04日
    浏览(50)
  • CleanMyMac最新版4.14Mac清理软件下载安装使用教程

    苹果电脑是很多人喜欢使用的一种电脑,它有着优美的外观,流畅的操作系统,丰富的应用程序和高效的性能。但是,随着时间的推移,苹果电脑也会产生一些不必要的文件和数据,这些文件和数据就是我们常说的垃圾。那么,苹果电脑会自动清理垃圾吗?苹果电脑系统垃圾

    2024年02月10日
    浏览(63)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包