1.深入了解iommu系列二:iommu 工作原理解析之dma remapping
2.Linux内核源码解析---EPOLL实现4之唤醒等待进程与惊群问题
3.Linux内核:内存管理——DMA
4.Linuxçlinuxçmemory
5.内核dma保护会不会降低性能
深入了解iommu系列二:iommu 工作原理解析之dma remapping
深入了解iommu系列二:iommu工作原理解析之dma remapping
序言
上一篇文章主要介绍了iommu硬件架构以及驱动层的内核初始化流程,本文将深入探讨iommu在虚拟化和非虚拟化场景下dma remapping的码内工作原理。
非虚拟化场景
非虚拟化场景下,核源除非在cmdline中明确设置iommu为disabled,代码否则一般默认启用iommu硬件。内核iommu=pt的码内picasso源码分析设置会提前建立静态映射。我们将通过内核代码片段分析iommu的核源dma工作机制。
取自内核e网卡驱动的代码代码片段,核心逻辑是内核将skb地址进行dma映射,以便硬件直接进行dma操作。码内pci_map_single函数最终调用intel_map_page。核源当iommu硬件存在(以intel iommu为例)时,代码它会引导到intel_map_page函数。内核
我们深入分析这个函数的码内核心逻辑。首先判断是核源否为iommu_no_mapping,如果是,则直接返回paddr(物理地址)。接着查看iommu_no_mapping函数的具体实现。从实现来看,首先判断iommu_identity_mapping是否为空(在iommut=pt的情况下不为空)。如果为空则返回false。debian 源码编译在不为空的情况下,函数走到identity_mapping,实现如下:
函数首先判断iommu_identity_mapping是否为空,iommut=pt时非空。接着检查设备的domain是否为si_domain,答案肯定。函数返回true,然后走到iommu_should_identity_map(dev, 0),主要判断如下:如果返回false,则从si_domain中删除设备的映射;反之,直接返回物理地址。总结,iommu=pt场景下,由于静态映射的存在,直接返回paddr。为什么直接返回物理地址而不是iova?我们详细解释。
在iommu=pt且硬件支持paasthrough翻译模式下,硬件的DMA到iommu后无需走页表翻译,直接与memory controller交互。但问题来了,kvm源码编译iommu硬件如何区分哪些设备的DMA需要页表转换,哪些不需要?为了解决这个问题,我们回顾一下DMA页表的确定过程。
通过分析,iommu通过contex_entry的TT字段来区分。TT为b表示不需要页表转换,从而iommu通过此字段进行区分。
iommu=pt、hw为true的情况已经解释,如果hw为false,逻辑从init_dmars函数开始。在这种情况下,不会提前创建si_domain(即提前做好iova映射)。设备在DMA映射时创建,逻辑在__intel_map_single函数中,部分核心逻辑如下。
虚拟化场景
iommu在虚拟化场景中扮演重要角色,尤其在设备直通场景。虚拟机中没有iommu,guest中使用的libev源码 csdndma_ops走noiommu。当guest使用dma_map等API时,返回gpa。在完全模拟设备(如virtio-net或virtio-blk)场景下,内存转换还在mmu层。但在直通设备场景,外设无法直接dma gpa,需要一层转换。接下来我们分析虚拟化场景下iommu的工作。
设置iommu=pt和intel_iommu=on,将vf或pf从原驱动unbind,bind到vfio_pci,初始化vfio层面,对guest内存vfio_dma_map。iommu=pt已解释,我们关注设备unbind和bind到vfio_pci的相关操作。
设备从原驱动unbind时,如果已有si_domain(pt场景下的静态映射),则从si_domain中移除设备。将设备bind到vfio-pci driver时,核心逻辑在vfio_pci_probe函数中。vncserver 源码 linux
qemu侧的vfio设备初始化函数vfio_realize,核心逻辑涉及设备所属的vfio_group和container的创建与关联。
vfio_realize中完成与vm dma相关数据结构初始化,并处理dma页表初始化。qemu通过注册memory region listener callback将vm内存映射起来,具体调用逻辑如下。
总结
结合分析,回答了非虚拟化场景下iommu=pt与disabled的区别,虚拟机中dma如何进行,以及不同intel iommu硬件下两个pci设备如何实现直通给同一vm的问题。
Linux内核源码解析---EPOLL实现4之唤醒等待进程与惊群问题
在Linux内核源码的EPOLL实现中,第四部分着重探讨了数据到来时如何唤醒等待进程以及惊群问题。当网卡接收到数据,DMA技术将数据复制到内存RingBuffer,通过硬中断通知CPU,然后由ksoftirqd线程处理,最终数据会进入socket接收队列。虽然ksoftirqd的创建过程不在本节讨论,但核心是理解数据如何从协议层传递到socket buffer。
在tcp_ipv4.c中,当接收到socket buffer时,会首先在连接表和监听表中寻找对应的socket。一旦找到,进入tcp_rcv_established函数,这里会检查socket是否准备好接收数据,通过调用sock_data_ready,其初始值为sock_def_readable,进而进入wake_up函数,唤醒之前挂上的wait_queue_t节点。
在wake_up方法中,会遍历链表并回调ep_poll_callback,这个函数是epoll的核心逻辑。然而,如果epoll的设置没有启用WQ_FLAG_EXCLUSIVE,就会导致惊群效应,即唤醒所有阻塞在当前epoll的进程。这在default_wake_function函数中体现,如果没有特殊标记,进程会立即被唤醒并进入调度。
总结来说,epoll的唤醒过程涉及socket buffer、协议层处理、链表操作以及回调函数,其中惊群问题与默认的唤醒策略密切相关。理解这些细节,有助于深入理解Linux内核中EPOLL的异步操作机制。
Linux内核:内存管理——DMA
Linux内核的内存管理中,DMA(Direct Memory Access)是关键组件之一。DMA用于在内存和I/O设备之间直接传输数据,简化了操作系统和硬件之间的通信。
在DMA中,有两种映射类型:一致性DMA映射(Consistent DMA mappings)和流式DMA映射(streaming DMA mapping)。一致性映射用于长时间使用的区域,它确保CPU和DMA controller在映射区域内不受缓存影响。流式映射则用于一次性DMA传输,传输完成后映射会释放。
为指定DMA设备的寻址范围,可以查阅include/linux/dma-mapping.h。
Linux内核提供了两种DMA映射接口:一致性DMA接口和流式DMA接口。一致性接口用于分配较大DMA缓冲区,而流式接口则涉及页面映射,返回DMA映射错误,映射scatterlist,并执行sync操作。
若欲深入了解Linux内核的DMA接口,推荐阅读反光的文章“linux DMA接口”。该文章可提供详尽的指导和示例,帮助你更好地理解和使用DMA接口。
为了提高学习效率,推荐加入Linux内核技术交流群。群内汇集了各类学习资源,包括精选学习书籍、视频教程、实战项目及代码。通过进群私聊群管理,即可获取内核资料包,包括视频教程、电子书、实战项目及代码。
如需深入了解Linux内核源码技术学习路线、视频教程及代码资料,可参考“Linux内核源码技术学习路线+视频教程代码资料”学习直通车。该资源覆盖Linux内核源码、内存调优、文件系统、进程管理、设备驱动、网络协议栈等多个关键领域,为你提供一站式学习解决方案。
Linuxçlinuxçmemory
linuxdmaåçï¼è®¡ç®æºç»æåçä¸çDMA
以å¾çI/O设å¤å主å交æ¢ä¿¡æ¯é½è¦ç»è¿CPUçæä½ãä¸è®ºæ¯ææ©ç轮询æ¹å¼ï¼è¿æ¯æ们å¦è¿çä¸ææ¹å¼ãè½ç¶ä¸ææ¹å¼ç¸æ¯è½®è¯¢æ¹å¼å·²ç»èçäºå¤§éçCPUèµæºãä½æ¯å¨å¤ç大éçæ°æ®æ¶ï¼DMAç¸æ¯ä¸ææ¹å¼è¿ä¸æ¥è§£æ¾äºCPUã
DMAå°±æ¯DirectMemoryAccessï¼æææ¯I/O设å¤ç´æ¥åå¨å¨è®¿é®ï¼å ä¹ä¸æ¶èCPUçèµæºãå¨I/O设å¤å主åä¼ éæ°æ®çæ¶åï¼CPUå¯ä»¥å¤çå ¶ä»äºã
linuxå æ ¸æ åæ件ä¸æ®éçELFæ件æä»ä¹åºå«ï¼
å ¶å®å æ¬shell以åmakeåºçä¸ç³»åæ件*.o*.soçä½æ¯*.aä¸æ¯
Linuxå æ ¸æå¤ç§æ ¼å¼çéåï¼å æ¬vmlinuxãImageãzImageãbzImageãuImageãxipImageãbootpImageç.
vmlinuzæ¯å¯å¼å¯¼çãå¯å缩çå æ ¸éåï¼vm代表VirtualMemory.Linuxæ¯æèæå åï¼å æ¤å¾åvm.å®æ¯ç±ç¨æ·å¯¹å æ ¸æºç ç¼è¯å¾å°ï¼å®è´¨æ¯elfæ ¼å¼çæ件.ä¹å°±æ¯è¯´ï¼vmlinuxæ¯ç¼è¯åºæ¥çæåå§çå æ ¸æ件ï¼æªå缩.è¿ç§æ ¼å¼çéåæ件å¤åæ¾å¨PCæºä¸.
èImageæ¯ç»è¿objcopyå¤ççåªå å«äºè¿å¶æ°æ®çå æ ¸ä»£ç ï¼å®å·²ç»ä¸æ¯elfæ ¼å¼äºï¼ä½è¿ç§æ ¼å¼çå æ ¸éåè¿æ²¡æç»è¿å缩.
å ¶ä»ç±»åçæ件就æ´ä¸æ¯äº
åªè½è¯´Linuxå æ ¸éåæä¸ç§æ¯elfæ ¼å¼çï¼å 为elfé常é½æ¯è¢«ç¼è¯çæçï¼æ以linuxå æ ¸æ åæ件ä¸æ®éçELFæ件å®ç°çåè½ä¸åé¿
Linuxç³»ç»ä¸çå åæ¸ çåéæ¾å½ä»¤å½çº³ï¼
#æ¸ çæ¥éª¤
#æ¸ çåå å使ç¨æ åµ
代ç å¦ä¸:
free-m
#å¼å§æ¸ ç
代ç å¦ä¸:
echo1/proc/sys/vm/drop_caches
#æ¸ çåå å使ç¨æ åµ
代ç å¦ä¸:
free-m
å®æ!
å¤å¶ä»£ç
代ç å¦ä¸:
dmidecode|grep-AMemoryDevice$
Tofreepagecache:
echo1/proc/sys/vm/drop_caches
Tofreedentriesandinodes:
echo2/proc/sys/vm/drop_caches
Tofreepagecache,dentriesandinodes:
echo3/proc/sys/vm/drop_caches
sync
#éæ¾åæ好syncä¸ä¸ï¼é²æ¢ä¸¢æ°æ®ãå 为LINUXçå æ ¸æºå¶ï¼ä¸è¬æ åµä¸ä¸éè¦ç¹æå»éæ¾å·²ç»ä½¿ç¨çcacheãè¿äºcacheèµ·æ¥çå 容å¯ä»¥å¢å æ件以åç读åé度ã
linuxcached为ä»ä¹ä¸ç´ä¸éæ¾ï¼
å½è¯»åæ件çæ¶åï¼Linuxå æ ¸ä¸ºäºæé«è¯»åæçä¸é度ï¼ä¼å°æ件å¨å åä¸è¿è¡ç¼åï¼è¿é¨åå åå°±æ¯CacheMemory(ç¼åå å)ãå³ä½¿ä½ çç¨åºè¿è¡ç»æåï¼CacheMemoryä¹ä¸ä¼èªå¨éæ¾ãç¼åå å(CacheMemory)å¨ä½ éè¦ä½¿ç¨å åçæ¶åä¼èªå¨éæ¾ï¼æ以ä¸å¿ æ å¿æ²¡æå åå¯ç¨ãå½ç¶ä¹å¯ä»¥æå¨éæ¾ï¼
echo1>/proc/sys/vm/drop_caches
echo2>/proc/sys/vm/drop_caches
echo3>/proc/sys/vm/drop_caches
注æï¼ç产ç¯å¢è¯·è°¨æ æä½ã
linuxæ±ç¼ï¼ldtoupper.o-lc-dynamic-linker/lib/ld-linux.so.2æ§è¡a.outåºç°memoryfaultæ±æ大ç¥ï¼
ä½ æºå¨æ¯ä½cpuå§ï¼ä½ æä½æ±ç¼ææä¸çä¾åï¼ä½æºå¨ä¸ç´æ¥è·ä¸æ¦æ¶åå°å åå°åå¿ ç¶ä¼æ¥æ®µé误çãä½æºå¨ä¸å½æ°è°ç¨æ¹æ³ä¹åä½ä¸åäºï¼å³ä½¿ä¸æ¯å°å åå°åï¼ä½ çç¨åºä¹æ²¡æ³è¾¾å°ç®ççã
内核dma保护会不会降低性能
内核DMA(Direct Memory Access,直接内存访问)保护是一种用于保护系统内存免受意外访问和恶意程序攻击的技术。它可以通过限制对内存的直接访问来增强系统的安全性。因此,虽然内核DMA保护可能会引入一些额外的开销,但它在提高系统安全性方面具有重要的作用。
由于内核DMA保护限制了对内存的直接访问,因此可能对系统的性能产生一定的影响。具体影响的程度取决于实施内核DMA保护的方式和技术。一般来说,当系统需要频繁进行大量的内存传输时,如数据包处理或大规模数据处理时,内核DMA保护可能会导致性能降低。
然而,现代的硬件和软件设计通常会在内核DMA保护和性能之间做出平衡,以最大限度地减少性能影响。例如,可以通过使用更高效的DMA控制器、采用硬件加速技术或优化内核代码来减少性能下降。
总的来说,内核DMA保护在一定程度上可能会对系统性能产生一些影响,但它是保障系统安全的重要手段。了解具体应用场景和系统需求,同时采用恰当的技术和优化措施,可以最大程度地减少性能降低的影响。