LWN: 模拟实现iopl()

news/2024/7/24 11:02:16
点击上方蓝色“ Linux News搬运工”关注我们~

Emulated iopl()

By Jonathan Corbet
November 8, 2019

原文来自:https://lwn.net/Articles/804143/

无论是操作系统,还是计算机硬件,都背负着很多历史负担。x86 I/O-port机制就是其中一个,近20年来设计的硬件都很少使用这个机制了,不过我们仍然需要保留对他的支持。不过,这并不意味着我们也不能对它进行清理和改进了,尤其是当这些旧的机制看起来不太合适的时候。这里就有一个例子,来自于Thomas Gleixner的the iopl() patch set。

在大多数体系结构上,I/O都是按照memory-mapped I/O(MMIO)区域来处理的。每个外设都会有一组寄存器可供访问,看起来就像一片内存区域一样,这些区域就会被映射到处理器的地址空间之中。设备驱动程序也就能通过对这些寄存器进行普通内存访问(或者某些类似的方式)来读写,从而跟外设交互。这个机制很有弹性,例如可以把一组寄存器直接映射到某个user-space进程去,如果有需要的话。很多user-space驱动程序都会依赖这个特性。

在x86体系结构的早期,情况跟现在有些不同。当时创建了一个独立的地址空间用来支持65536个I/O端口,需要使用特殊的指令来访问这些I/O端口。哪怕有些设备可以进行内存映射,也是为了其他目的的,至于控制接口还是需要使用I/O端口来访问。用来访问I/O端口的指令都必须是特权级的,因此user-space代码一般不能使用这些指令。

不过前面提过,有时候确实需要在user space来操作外设。为了支持这个功能,x86设计者就创建了两种独立的方式来供对非特权进程来访问I/O端口:

  • I/O privilege level (IOPL) 是2个bit的变量,用来控制哪些特权级别的进程可以访问I/O端口。通常这个寄存器设置为0,也就是说只有在kernel mode的代码才能够访问I/O port。如果设置成3的话,就能让普通的user-space进程来访问I/O端口了。这样一来,我们可以通过针对某个特定进程来设置IOPL(可以通过iopl()系统调用来修改),从而让这个进程可以访问所有I/O端口。

  • 在task state segment (TSS)里面存储的I/O port permission bitmap可以用来允许对某个特定Port的操作权限。如果对应某个port的相应bit是0,那么在运行的进程就可以访问这个port。可以使用ioperm()系统调用来操作这个bitmap。

特权进程可以利用iopl()或者ioperm()来获得对I/O端口的访问权限。调用ioperm()的话会增加进程的上下文切换时间,因为8KB bitmap在每次上下文切换的时候都需要进行一次copy。因此,不少程序会使用iopl,尽管它其实并不需要访问那么多的端口。

不过,使用iopl()的话还有其他一个小问题:如果提升I/O privilege level的话,也会允许当前进程打开或者关闭中断。Gleixner认为这个不太好,因为一个恶意程序就能轻松把CPU锁死,只要关掉中断然后做死循环即可。不过真正的问题是,大家设计的时候根本没有考虑过user space会可能关闭中断。kernel开发者一般都假设user space在运行的时候中断都是打开的,而IOPL特升特权的进程其实会违背这个假设,因此进程如果真的去关闭中断的话会有各种未知的问题出现,而目前IOPL方案就有这个问题。

Gleixner认为最好的解决方案就是彻底把iopl()拿掉。不过现在还有不少应用程序是依赖这个功能的,所以不能这么粗暴的拿掉。不过,可能还有一个方案:利用bitmap来模拟iopl()功能。如果某个进程使用I/O privilege bitmap并且清空所有bit,那么就可以访问所有的I/O端口,就跟利用IOPL提升权限是一样的效果,不过就不再能关闭中断了。

如果这么做的话,可能会导致此前一些通过这种方式来实现user space关闭中断的进程无法正常工作。Gleixner搜索了一下是不是有这中程序,唯一找到的一个是一个非常古老的X服务器解决方案,这套代码完全无法在当前系统上运行了,因此不用担心。希望他的搜索结果没有太大遗漏。

可以通过把iopl()替换成bitmap方式来解决中断问题,不过前面提到的性能问题还是没法解决。这个patch set里面实现了一些优化来改善。大多数进程都根本不会用这个bitmap,因此并不需要为他们专门把bitfile设成全1,只要修改一下指向TSS中bitmap的那个指针,改为无效值即可,这样所有访问I/O端口的操作都会被拒绝。在上下文切换的时候,如果切换的这两个进程都在用bitmap,那么也只需要把清0的bit复制过去即可,这样就能大大加快速度。最终效果上来说,模拟iopl()的方案引入的开销是有的,不过也非常接近于0了。

Linus Torvalds指出,可以继续改善性能,不需要去管那个I/O bitmap,直到不得不需要修改的时候再改。这个优化主要是针对那些只有一个进程需要访问I/O端口的场景,其实这个场景占比非常高。Gleixner打算去照此实现。

Willy Tarreau建议再进一步,针对所有调用ioperm()的进程,都使用一个全0的bitmap。这样的缺点是,目前一些进程只打开了某些特定端口的访问权限,这么改过之后会导致它能访问所有端口了。他说,既然调用者进程本来就有权能获取那些端口的访问权限,那么这种改法并不会引入什么安全风险。Eric Biederman则指出DOSEMU其实会依赖ioperm()管控好只有申请过的端口才能访问,因此这个方案不现实。

目前对这个patch set整体来说没有什么反对意见,预计很快会在修改后合入。今后的kernel就能改善这个古老方案的一个缺点了,非常好。

全文完

LWN文章遵循CC BY-SA 4.0许可协议。

极度欢迎将文章分享到朋友圈 
热烈欢迎转载以及基于现有协议修改再创作~

长按下面二维码关注:Linux News搬运工,希望每周的深度文章以及开源社区的各种新近言论,能够让大家满意~


http://www.niftyadmin.cn/n/733966.html

相关文章

Maven灵活构建(转载)

https://blog.csdn.net/sin90lzc/article/details/7552033转载于:https://www.cnblogs.com/Andrew520/p/10521550.html

LWN: 2019 自动化测试峰会

点击上方蓝色“Linux News搬运工”关注我们~The 2019 Automated Testing SummitBy Jake EdgeNovember 13, 2019ATS原文来自:https://lwn.net/Articles/804050/ Automated Testing Summit(ATS)今年的会议是第二次,并且是首次对外公开的,去年的…

分布式快照

分布式快照 Distributed Snapshots: Determining Global States of Distributed Systems 这篇论文是Chandy和Lamport大神的作品,理论性非常强,没有具体应用的例子,读起来非常吃力。 我的能力有限,同时阅读这篇文章为了找到一种分布…

python 下载文件

2019独角兽企业重金招聘Python工程师标准>>> #!/usr/bin/env python3 # -*- coding: utf-8 -*-import urllib.request print(Beginning file download with urllib2...) filename"razorback.mp3" url http://www.futurecrew.com/skaven/song_files/mp3/f…

LWN: 对内核开发中的所有邮件进行分析!

点击上方蓝色“Linux News搬运工”关注我们~Analyzing kernel emailBy Jake EdgeNovember 13, 2019ELCE原文来自:https://lwn.net/Articles/804511/过去几年,有不少针对kernel开发过程中的email进行分析,因为email是Linux kernel开发流程的基…

Percolator 2PC模型

介绍 Percolator 用于Google的检索系统。Google爬取的网页建立的索引,通过Percolator系统建立索引。 Google的检索系统维护了上千台机器,有数十PB数据。 Percolator优化了增量处理(incremental processing)的问题: 很多网页是已经爬取过的,爬…

小程序--页面添加水印

记录经过?小功能点 简介 小程序页面增加水印 效果 因为所有页面都要加水印,所以肯定是要用自定义组件实现。 思考路程 第一种 最开始考虑的是canvas生成图片,转换成base64做一张背景图,然后才了解到水印不能直接在元素上作为背景作为页面的最…

LWN: Linux 5.4系列kernel正式发布

点击上方蓝色“Linux News搬运工”关注我们~The 5.4 kernel has been released[Kernel] Posted Nov 25, 2019 3:28 UTC (Mon) by corbet在2019年11月25日的时候,Linus宣布5.4 kernel正式发布了,他本人的评论是:“上个礼拜没有太多事情发生&am…