SMMU介绍

1. 什么是SMMU

        SMMU是System Memory Management Unit的缩写,中文名是内存管理单元。它是一种负责处理中央处理器(CPU)的内存访问请求的计算机硬件。它的功能包括虚拟地址到物理地址的转换(即虚拟内存管理)、内存保护、中央处理器高速缓存的控制。它在系统的位置如下图:

        概况来说,SMMU提供如下功能:

  1. 地址转换功能,虚拟内存到物理内存转换,提供1级页表和2级页表的能力;
  2. 地址读写权限属性、cache属性;
  3.  存储空间扩展功能,比如设备需要地址空间大于物理内存空间;

1.1 名词缩写

  1. ASID:Address Space ID   地址空间标识符
  2. CD:Context Descriptor;  上下文描述符;
  3. CTP:Context-table pointer   上下文表指针
  4. EPT:Extended Page Table 扩展页表
  5. GPA:Guest Phyical Address   客人的实际地址
  6. GVA:Guest Virtual Address   访客虚拟地址
  7. HPA:Host Phyical Address    主机物理地址
  8. IOVA:IO Virtual Address space   IO虚拟地址空间
  9. IPA:Intermediate Phyical Address    中间物理地址
  10. NPT:Nested Page Table   嵌套页表
  11. PCID:Process context identifier 进程上下文标识符
  12. PMCG:Performance Monitor Counter Groups 性能监控计数器组
  13. S2TTB:Stage 2 Translate Table Base  第二阶段翻译表库
  14. VT-d:Virtualization Technology for Direct I/O 直接I/O虚拟化技术

2. 为什么需要SMMU

       在linux中,用户态使用的内存是虚拟地址(Virtual Address,VA),实际硬件内存称为物理地址(Physical Address,PA)。用户访问内存看到的是VA,内核转化成PA操作实际物理地址。实际MMU硬件支持2层转化,PA->IPA->VA,但是linux bypass了IPA,简化了流程。        

        kernel运行在EL1,只能做VA->IPA, IPA->PA的操作是在EL2做的,也就是hypervisor,是为了给不同VM使用的,比如系统中有audio 的adsp,可以通过hypassign接口把一段内存从kernel 这个VM 的S2映射去掉,而assign给adsp,这时候如果kernel想访问的话需要调用hyp_assign来重新建立kernel所在的VM使用的S2的页表,否则kernel会报SEA错误,如果打开hyp的log可以看到有S2缺页的log。

        对用户体现虚拟地址,一方面可以起到安全作用(防止直接访问物理地址,查看我们存储的数据),另一方面减少用户对物理内存设备的关注,用户只要关注申请、读写、释放等使用内存操作即可

         了解SMMU出现的背景,需要知道系统中的两个概念:DMA和虚拟化。

2.1 DMA

        操作系统中,内存的使用非常频繁,小到一个进程任务分配堆栈、申请内存,大到设备访问内存(读写等操作)。根据上述SMMU功能介绍,这些内存使用都需要经过CPU从VA到PA的互相转化。而CPU的总线固定,一旦访问过多,访问有快有慢等,势必造成总线拥堵,影响性能。此时加入DMA (Direct Memory Access,直接内存存取)硬件,它与外设和内存连接,是一种外部设备不通过CPU而直接与系统内存交换数据的接口技术 。外设可以通过DMA,将数据批量传输到内存,然后再发送一个中断通知CPU取,其传输过程并不经过CPU, 减轻了CPU的负担。但由于DMA不能像CPU一样通过MMU操作虚拟地址,所以DMA需要连续的物理地址,通过SMMU,IO设备DMA的物理地址也可以不连续

2.2 虚拟化

        在虚拟化场景, 所有的VM都运行在中间层hypervisor上,每一个VM独立运行自己的OS(guest OS),Hypervisor完成硬件资源的共享, 隔离和切换。

        SMMU可以在支持虚拟化的系统中提供安全的内存隔离。通过为每个虚拟机配置独立的映射表,SMMU确保多个虚拟机之间和与宿主系统之间的内存访问相互隔离。这样,虚拟机之间无法互相窥探数据,也能够防止不同虚拟机之间的攻击。

        但对于Hypervisor + GuestOS的虚拟化系统来说, guest VM使用的物理地址是GPA,并非实际的物理地址(也就是HPA),因此Guest OS无法正常的将连续的物理地址分给硬件

2.3 硬件加速器访问的内存隔离

        SMMU可以针对硬件加速器的访问进行地址映射和隔离。通过配置映射表,SMMU可以确保硬件加速器只能访问特定的内存区域,而不能访问其他应用程序或操作系统的敏感数据。这种内存隔离保护了系统中的关键数据不受硬件加速器访问的影响。

2.4 访问非连续的地址

        现在系统中很少再预留连续的memory,如果Master需要很多memory,可以通过SMMU把一些非连续的PA映射到连续的VA,例如给DMA,VPU,DPU使用。

2.5 32位转换成64位

        现在很多系统是64位的,但是有些Master还是32位的,只能访问低4GB空间,如果访问更大的地址空间需要软硬件参与交换memory,实现起来比较复杂,也可以通过SMMU来解决,Master发出来的32位的地址,通过SMMU转换成64位,就很容易访问高地址空间。

2.6 限制Master的访问空间

        Master理论上可以访问所有的地址空间,可以通过SMMU来对Master的访问进行过滤,只让Master访问受限的区域,那这个区域也可以通过CPU对SMMU建立页表时动态控制。

2.7 用户态驱动

        现在我们也看到很多系统把设备驱动做在用户态,调用驱动时不需要在切换到内核态,但是存在一些安全隐患,就是用户态直接控制驱动,有可能访问到内核空间,这种情况下也可以用SMMU来实现限制设备的访问空间

        因此,为了支持I/O透传机制中的DMA设备传输,而引入了IOMMU技术(ARM称作SMMU)。总而言之,SMMU可以为ARM架构下实现虚拟化扩展提供支持。它可以和MMU一样,提供stage1转换(VA->PA), 或者stage2转换(IPA->PA),或者stage1 + stage2转换(VA->IPA->PA)的灵活配置。

*[VA:虚拟地址;IPA: 中间物理地址;PA:物理地址]

3. SMMU常用概念

3.1 StreamID

        一个平台上可以有多个SMMU设备,每个SMMU设备下面可能连接着多个Endpoint, 多个设备互相之间可能不会复用同一个页表,需要加以区分,SMMU用StreamID来做这个区分( SubstreamID的概念和PCIe PASID是等效的)。每个设备对应一个streamID,并对应一个STE表。

3.2 STE Stream Table Entry

        STE包含stage1初始化信息、CD表指针(CD中包含stage1的页表基地址和相关转换信息)、stage2的页表基地址以及相关转换信息(如果使能stage2的话)。

        Linear Stream Table方式每个streamID对应一个STE,参考

StreamID is of IMPLEMENTATION DEFINED size, between 0 and 32 bits.
The StreamID is used to select a Stream Table Entry (STE) in a Stream table, which contains per-device configuration. The maximum size of in-memory configuration structures relates to the maximum StreamID span (see 3.3 below), with a maximum of 2^StreamIDSize entries in the Stream table.
Another property, SubstreamID, might optionally be provided to an SMMU implementing stage 1 translation. The SubstreamID is of IMPLEMENTATION DEFINED size, between 0 and 20 bits, and differentiates streams of traffic originating from the same logical block in order to associate different application address translations to each

        可知,streamID最大是2^32,SubstreamID最大2^20.

        2-level Stream Table方式StreamID不同bit指向不同STE

• StreamIDs 0-1023 (4 × 8-bit level 2 tables) are represented, though not all are valid.
• StreamIDs 0-255 are configured by the array of STEs at 0x1000 (each of which separately enables the relevant StreamID).
• StreamIDs 256-259 are configured by the array of STEs at 0x2F20.
• StreamIDs 512-767 are all invalid.
• The STE of StreamID 768 is at 0x4000.

3.3 CD Context Descriptor

        上下文描述符,是一个特定格式的数据结构,包含了指向stage1地址翻译表的基地址指针和相关转换信息。SMMU检查STE表,STE.Config决定是否进行stage1转换,如果是,则(结合SubStreamID)根据S1ContextPtr指向对应CD表,CD表中包含stage1页表和转换的信息。

        由上可知每个SubStreamID对应一个CD表,SubStreamID对应每个用户态空间地址,换句话说,每个涉及对应外设的进程,都对应一个SubStreamID。SMMU根据S2TTB(如果配置的话),查找stage2页表和转换信息。

         S1ContextPtr指向的一个Context Descriptor的目录结构,arm中,如果没有虚拟机参与的话,无论是cpu还是smmu地址翻译都是从va->pa/iova->pa,我们称之为stage1,也就是不涉及虚拟,只是一阶段翻译而已。

        重要的CD表,读到这里,你是不是会问一个问题,在smmu中我们为何要使用CD表呢?原因是这样的,一个smmu可以管理很多设备,所以用STE表来区分每个设备的数据结构,每个设备一个STE表。那如果每个设备上跑了多个任务,这些任务又同时使用了不同的page table 的话,那咋管理呢?对不对?所以smmu 采用了CD(Context Descriptor) 表来管理每个page table;

        看一看cd(Context Descriptor) 表的查找规则:

        先说另外一个重要的概念:SubstreamID(pasid),这个叫substreamid又称之为pasid,也是非常简单的概念,既然有表了,那也得有id来协助查找啊,所以就出来了这个id,从这里也可以看出来,道理都一样,用了表了就有id 啊!

        CD表,在smmu中也是可以是线性的或者两级的,这个都是在smmu 寄存器中配置好了的,由smmu驱动来读去,进行按对应的位进行分级,和STE表一样的原理;

3.4 TLB(Translation Lookaside Buffer)

        Translation Lookaside Buffer可翻译为“地址转换后缓冲器”,也可简称为“快表”。用于存放页表转换关系的cache,其中存储了当前最可能被访问到的页表项,其内容是部分页表项的一个副本。只有在TLB无法完成地址翻译任务时,才会到内存中查询页表,这样就减少了页表查询导致的处理器性能下降,提高页表转换的效率。

        TLB miss:在TLB中没有找到需要查找的页表,需要到配置中查找;

        TLB hit:在TLB中找到所需页表;

        PTW:Page Table Walk,页表查找过程;

4. SMMU数据结构查找

        SMMU翻译过程需要使用多种数据结构,如STE, CD,PTW等。

4.1 SID查找STE

        Stream Table是存放在内存中的一张表,在SMMU驱动初始化时由驱动程序创建好。Stream table有两种格式,一种是Linear Stream Table, 一种是2-level Stream Table。

4.1.1. Linear Stream Table

        Linear Stream Table是将整个stream table在内存中线性展开成一个数组, 用Stream Id作为索引进行查找。Linear Stream Table 实现简单,只需要一次索引,速度快;但是平台上外设较少时,浪费连续的内存空间

4.1.2 2-level Stream Table

        2-level Stream Table,包含2级table, 第一级table是STD,包含了指向二级STE的基地址。第二级STE是Linear stream Table。2-level Stream Table的优点是更加节省内存

        SMMU根据寄存器配置的STRTAB_BASE地址找到STE, STRTAB_BASE定义了STE的基地值, Stream id定义了STE的偏移。

        如果使用linear 查找, 通过STRTAB_BASE + sid * 64(一个STE的大小为64B)找到对应的STE;

        若使用2-level查找, 则先通过sid的高位找到对应的L1_STD(STRTAB_BASE + sid[9:8] * 8, 一个L1_STD的大小为8B), L1_STD定义了下一级查找的基地址,然后通过sid 找到具体对应的STE(l2ptr + sid[7:0] * 64)。

        最终找到的STE如下所示,表中的信息包含属性相关信息, 翻译模式信息(是否 stream bypass, 若否,选择stage1, stage2或者stage1 + stage2翻译模式)。找到STE后可以进一步开始S1翻译或S2翻译。

4.2 SSID查找CD

        CD包含了指向stage1地址翻译表的基地址指针。如下图所示, STE指明了CD数据结构在DDR中的基地址S1ContextPTR, SSID(substream id)指明了CD数据结构的偏移,如果SMMU选择进行linear, 则使用S1ContextPTR + 64 * ssid 找到CD。如果SMMU选择2-level, 则使用ssid进行二级查找获得CD(与上节STE的方式一致)。

        最终找到的CD如下所示:

        表中信息包含memory属性,翻译控制信息,异常控制信息以及Page table walk(PTW)的起始地址TTB0, TTB1, 找到TTBx后,就可以PTW了。

5. SMMU地址转换

5.1 单stage的地址转换

  1. SMMU根据寄存器配置找到STRTAB_BASE地址;
  2. linear 查找时, 通过STRTAB_BASE + sid * 64(一个STE的大小为64B)找到对应的STE;使用2-level查找, 则先通过sid的高位找到对应的L1_STD(STRTAB_BASE + sid[9:8] * 8, 一个L1_STD的大小为8B), L1_STD定义了下一级查找的基地址,然后通过sid 找到具体对应的STE(l2ptr + sid[7:0] * 64)
  3. STE的内容包括有一个ContextPtr,然后根据ContextPtr可以从内存空间中获得上下文描述符Context Descriptor(CD)数据结构在DDR中的基地址S1ContextPTR, SSID(substream id);
  4. 如果选择linear, 则使用S1ContextPTR + 64 * ssid 找到CD。如果SMMU选择2-level, 则使用ssid进行二级查找获得CD(与上节STE的方式一致)。
  5. 通过CD获取实际用于地址翻译的内存空间id(ASID, address space identifier)和Page table walk(PTW)的页表基地址TTB0(translation table base), TTB1
  6. TTB 和 VA[47:39]组成获取Level0页表的地址PA;
  7. Level0页表中的next-level table address 和 VA[38:30]组成获取Level1的页表地址PA;
  8. Level1页表中的next-level table address 和 VA[29:21]组成获取Level2的页表地址PA;
  9. Level2页表中的next-level table address 和 VA[20:12]组成获取Leve3的页表地址PA;
  10. level3页表中的output address和va[12:0]组成获取最后的转换地址

        在stage1地址翻译阶段:硬件先通过StreamID索引到STE,然后用SubstreamID索引到CD, CD里面包含了stage1地址翻译(把进程的GVA/IOVA翻译成IPA)过程中需要的页表基地址信息、per-stream的配置信息以及ASID。在stage1翻译的过程中,多个CD对应着多个stage1的地址翻译,通过Substream去确定对应的stage1地址翻译页表。所以,Stage1地址翻译其实是一个(RequestID, PASID) => GPA的映射查找过程。

5.2 stage1+stage2的地址转换

        在使能SMMU两阶段地址翻译的情况下,stage1负责将设备DMA请求发出的VA翻译为IPA并作为stage2的输入, stage2则利用stage1输出的IPA再次进行翻译得到PA,从而DMA请求正确地访问到Guest的要操作的地址空间上。

        在stage2地址翻译阶段:STE里面包含了stage2地址翻译的页表基地址(IPA->HPA)和VMID信息。如果多个设备被直通给同一个虚拟机,那么意味着他们共享同一个stage2地址翻译页表。

        在两阶段地址翻译场景下, 地址转换流程步骤:

  1. Guest驱动发起DMA请求,这个DMA请求包含VA + SID前缀
  2. DMA请求到达SMMU,SMMU提取DMA请求中的SID就知道这个请求是哪个设备发来的,然后去StreamTable索引对应的STE
  3.  从对应的STE表中查找到对应的CD,然后用ssid到CD中进行索引找到对应的S1 Page Table
  4.  IOMMU进行S1 Page Table Walk,将VA翻译成IPA并作为S2的输入
  5.  IOMMU执行S2 Page Table Walk,将IPA翻译成PA,地址转化结束。

6. SMMU command queue 与 event queue

        系统软件通过Command Queue和Event Queue来和SMMU打交道,这2个Queue都是循环队列。

        Command queue:用于软件与SMMU的硬件交互,软件写命令到command queue, SMMU从command queue中读取命令处理。

        Event Queue:用于SMMU发生软件配置错误的状态信息记录,SMMU将配置错误信息写到Event queue中,软件通过读取Event queue获得配置错误信息并进行配置错误处理。

7. SMMU IP情况

7.1 CoreLink MMU-700 features

  • SMMUv3.2 compliant IO-MMU compatible with Arm v8.4 and Arm v9 based CPUs.
  • Key Arm architecture features enabled: Secure-EL2, range invalidate, MPAM.
  • Support for advanced PCIe and CXL ATS functionality.
  • Built to support PCIe Gen5 bandwidth for wide range of I/O applications.
  • Introduces AMBA-LTI for translations as a look-aside function.
  • Enables the PCIe-PRI feature for on-die accelerators without the need for ATS flow.

7.2 CoreLink MMU-600AE features

  • Meets automotive safety requirements for building high-performance ASIL B to ASIL D systems.
  • Software compatible with MMU-600 with Arm v8.2 compliant RAS reporting interface.
  • Efficient functional logic duplication, ECC and address protection for SRAM.
  • AMBA extensions for interface protection.
  • Fault management unit to simplify error reporting, testing and integration.

7.3 CoreLink MMU-600 features

  • Enhances CoreLink MMU-500 feature set by incorporating SMMUv3.1 specification to support Armv8.2 CPUs.
  • Expands the number of contexts supported to millions.
  • Implements AMBA-DTI to interface TBU and TCU to improve scalability.
  • Multi-level TLB and Walk Cache improves system address translation hit rates.
  • Improved write buffer depth and parallel translations.

7.4 CoreLink MMU-500 Features

  • Builds on top of MMU-400 features by implementing SMMUv2 architecture adding support for Armv8 CPUs.
  • Supports Stage 1, Stage 2, and Stage1 followed by Stage 2 address translation for up to 128 active device contexts.
  • Implements a distributed Translation Buffer Unit (TBU) micro-architecture with direct point-to-point connections between each TBU and the centralized Translation Control Unit (TCU) for Page Table Walks (PTWs).
  • Supports up to 128 entries per TLB which is further backed by TCU cache up to 2K entries.

7.5 CoreLink MMU-401 Features

  • Supports SMMUv1 architecture for Armv7 CPUs and Arm v8 for 64KB page sizes.
  • Performs stage2 translation only for hypervisor support.
  • Implements a single TBU micro-architecture with connection to a single TCU for page table walks

8. 操作系统分页式存储管理

        连续分配方式会形成许多“碎片”,虽然可通过“紧凑”方法将许多碎片拼接成可用的大块空间,但须为之付出很大开销。如果允许将一个进程直接分散地装入到许多不相邻接的分区中,则无须再进行“紧凑”。基于这一思想而产生了离散分配方式。如果离散分配的基本单位是页,则称为分页存储管理方式;如果离散分配的基本单位是段,则称为分段存储管理方式。

        在分页存储管理方式中,如果不具备页面对换功能,则称为基本的分页存储管理方式,或称为纯分页存储管理方式,它不具有支持实现虚拟存储器的功能,它要求把每个作业全部装入内存后方能运行。

        页式存储器管理操作系统中十分重要的内容,这也正是虚拟存储关键技术之一如果没有理解页式管理段式管理段页式管理,那么对操作系统中的虚拟内存理解也只有十之一二,因为操作系统中的各个概念都是密不可分的,你中有我,我中有你。本文将讲述内容包括一级页表快表二级页表多级页表

8.1 页面与页表

8.1.1 页面

8.1.1.1 页面和物理块

        分页存储管理是将一个进程的逻辑地址空间分成若干个大小相等的片,称为页面或页,并为各页加以编号,从 0 开始,如第 0 页、第 1 页等。相应地,也把内存空间分成与页面相同大小的若干个存储块,称为(物理)块或页框(frame),也同样为它们加以编号,如 0#块、1#块等等。在为进程分配内存时,以块为单位将进程中的若干个页分别装入到多个可以不相邻接的物理块中。由于进程的最后一页经常装不满一块而形成了不可利用的碎片,称之为“页内碎片”。

1. 页

        相对物理块来说,页是逻辑地址空间(虚拟内存空间)的划分,是逻辑地址空间顺序等分而成的一段逻辑空间,并依次连续编号。页的大小一般为 512B~8KB。

        例如:一个 32 位的操作系统,页的大小设为 2^12=4Kb,那么就有页号从 0 编到 2^20 的那么多页逻辑空间。

2. 物理块

        物理块则是相对于虚拟内存对物理内存按顺序等大小的划分。物理块的大小需要与页的大小一致。

        例如:2^31=2Gb 的物理内存,按照 4Kb/页的大小划分,可以划分成物理块号从 0 到 2^19 的那么多块的物理内存空间。

3. 页面大小

        在分页系统中的页面其大小应适中。页面若太小,一方面虽然可使内存碎片减小,从而减少了内存碎片的总空间,有利于提高内存利用率,但另一方面也会使每个进程占用较多的页面,从而导致进程的页表过长,占用大量内存;此外,还会降低页面换进换出的效率。然而,如果选择的页面较大,虽然可以减少页表的长度,提高页面换进换出的速度,但却又会使页内碎片增大。因此,页面的大小应选择适中,且页面大小应是 2 的幂,通常为 512 B~8 KB。

8.1.2 地址结构

        分页地址中的地址结构如下:

        这是一个 32 位的逻辑地址,它含有两部分:前一部分为页号 P,后一部分为位移量 W(或称为页内地址)。图中的地址长度为 32 位,其中 0~11 位为页内地址,即每页的大小为 4 KB;12~31 位为页号,地址空间最多允许有 1 M 页。对于某特定机器,其地址结构是一定的。

8.1.3 页表

        在分页系统中,允许将进程的各个页离散地存储在内存不同的物理块中,但系统应能保证进程的正确运行,即能在内存中找到每个页面所对应的物理块。为此,系统又为每个进程建立了一张页面映像表,简称页表。在进程地址空间内的所有页(0~n),依次在页表中有一页表项,其中记录了相应页在内存中对应的物理块号,见下图的中间部分。在配置了页表后,进程执行时,通过查找该表,即可找到每页在内存中的物理块号。可见,页表的作用是实现从页号到物理块号的地址映射。

        页表是记录逻辑空间(虚拟内存)中每一页在内存中对应的物理块号。但并非每一页逻辑空间都会实际对应着一个物理块,只有实际驻留在物理内存空间中的页才会对应着物理块。页表是需要一直驻留在物理内存中的(多级页表除外),另外页表的起址和长度存放在 PCB(Process Control Block)进程控制结构体中。

        即使在简单的分页系统中,也常在页表的表项中设置一存取控制字段,用于对该存储块中的内容加以保护。当存取控制字段仅有一位时,可用来规定该存储块中的内容是允许读/写,还是只读;若存取控制字段为二位,则可规定为读/写、只读和只执行等存取方式。如果有一进程试图去写一个只允许读的存储块时,将引起操作系统的一次中断。如果要利用分页系统去实现虚拟存储器,则还须增设一数据项。

8.2 地址变换

        为了能将用户地址空间中的逻辑地址变换为内存空间中的物理地址,在系统中必须设置地址变换机构。该机构的基本任务是实现从逻辑地址到物理地址的转换。由于页内地址和物理地址是一一对应的(例如,对于页面大小是 1 KB 的页内地址是 0~1023,其相应的物理块内的地址也是 0~1023,无须再进行转换),因此,地址变换机构的任务实际上只是将逻辑地址中的页号,转换为内存中的物理块号。又因为页面映射表的作用就是用于实现从页号到物理块号的变换,因此,地址变换任务是借助于页表来完成的。

8.2.1 基本的地址变换机构

        页表的功能可以由一组专门的寄存器来实现。一个页表项用一个寄存器。寄存器具有较高的访问速度,因而有利于提高地址变换的速度;但由于寄存器成本较高,且大多数现代计算机的页表又可能很大,使页表项的总数可达几千甚至几十万个,显然这些页表项不可能都用寄存器来实现,因此,页表大多驻留在内存中。在系统中只设置一个页表寄存器 PTR(Page-Table Register),在其中存放页表在内存的起始地址和页表的长度。平时,进程未执行时,页表的起始地址和页表长度存放在本进程的 PCB 中。当调度程序调度到某进程时,才将这两个数据装入页表寄存器中。因此,在单处理机环境下,虽然系统中可以运行多个进程,但只需一个页表寄存器

        当进程要访问某个逻辑地址中的数据时,分页地址变换机构会自动地将有效地址(相对地址)分为页号和页内地址两部分,再以页号为索引去检索页表。查找操作由硬件执行。在执行检索之前,先将页号与页表长度进行比较,如果页号大于或等于页表长度,则表示本次所访问的地址已超越进程的地址空间。于是,这一错误将被系统发现并产生一地址越界中断。若未出现越界错误,则将页表始址与页号和页表项长度的乘积相加,便得到该表项在页表中的位置,于是可从中得到该页的物理块号,将之装入物理地址寄存器中。与此同时,再将有效地址寄存器中的页内地址送入物理地址寄存器的块内地址字段中。这样便完成了从逻辑地址到物理地址的变换。下图为分页系统的地址变换机构。

        页表转换过程:

  1. 进程访问某个逻辑地址时,分页地址机构自动将逻辑地址分为页号和页内地址
  2. 页号大于页表长度,越界错误
  3. 页表项的地址 p = 页表起始地址 F + 页号 P * 表项大小 S,从而得到对应的物理块号 B
  4. 页和物理块的大小是一致的,所以 页内地址=块内地址
  5. 然后 物理地址 = 物理块号 B * 页大小 L + 页内地址
  6. 根据物理地址读取数据

        例:某系统采用分页式存储管理,页大小为 2KB。已知进程 A 的逻辑地址空间为 4 个页,内存分配如下页表所示,求逻辑地址 4832 的物理地址。(所有数据都是十进制)

        解:

        2KB=2048B

        页号 P=逻辑地址/页大小=4832/2048=2

        页内地址 F=逻辑地址%页大小=4832%2048=736

        根据页表查得 2 号页对应着 25 号物理块

        物理地址 A=物理块号*页大小 + 页内地址=25*2048+736=51936

8.2.2 具有快表的地址变换机构

        由于页表是存放在内存中的,这使 CPU 在每存取一个数据时,都要两次访问内存。第一次是访问内存中的页表,从中找到指定页的物理块号,再将块号与页内偏移量 W 拼接,以形成物理地址。第二次访问内存时,才是从第一次所得地址中获得所需数据(或向此地址中写入数据)。因此,采用这种方式将使计算机的处理速度降低近 1/2。可见,以此高昂代价来换取存储器空间利用率的提高,是得不偿失的。

        为了提高地址变换速度,可在地址变换机构中增设一个具有并行查寻能力的特殊高速缓冲寄存器,又称为“联想寄存器”(Associative Memory),或称为“快表”,在 IBM 系统中又取名为 TLB(Translation Lookaside Buffer),用以存放当前访问的那些页表项。此时的地址变换过程是:在 CPU 给出有效地址后,由地址变换机构自动地将页号 P 送入高速缓冲寄存器,并将此页号与高速缓存中的所有页号进行比较,若其中有与此相匹配的页号,便表示所要访问的页表项在快表中。于是,可直接从快表中读出该页所对应的物理块号,并送到物理地址寄存器中。如在块表中未找到对应的页表项,则还须再访问内存中的页表,找到后,把从页表项中读出的物理块号送地址寄存器;同时,再将此页表项存入快表的一个寄存器单元中,亦即,重新修改快表。但如果联想寄存器已满,则 OS 必须找到一个老的且已被认为不再需要的页表项,将它换出。因为高速缓冲存储器的访问速度要比内存的访问速度快很多,因此使用可以大大加快虚拟地址转换成物理地址。根据统计,快表的命中率可以达到 90%以上。下图为具有快表的地址变换机构。

        由于成本的关系,快表不可能做得很大,通常只存放 16~512 个页表项,这对中、小型作业来说,已有可能把全部页表项放在快表中,但对于大型作业,则只能将其一部分页表项放入其中。由于对程序和数据的访问往往带有局限性,因此,据统计,从快表中能找到所需页表项的机率可达 90%以上。这样,由于增加了地址变换机构而造成的速度损失,可减少到 10%以下,达到了可接受的程度。

8.3 页表结构

        现代的大多数计算机系统,都支持非常大的逻辑地址空间。在这样的环境下,页表就变得非常大,要占用相当大的内存空间。例如,对于一个具有 32 位逻辑地址空间的分页系统,规定页面大小为 4 KB ,则在每个进程页表中的页表项可达 1 兆个之多。又因为每个页表项占用一个字节,故每个进程仅仅其页表就要占用 1 MB 的内存空间,而且还要求是连续的。显然这是不现实的,我们可以采用下述两个方法来解决这一问题:

  • 采用离散分配方式来解决难以找到一块连续的大内存空间的问题;
  • 只将当前需要的部分页表项调入内存,其余的页表项仍驻留在磁盘上,需要时再调入。

8.3.1 一级页表的缺陷

        由于页表必须连续存放,并且需要常驻物理内存,当逻辑地址空间很大时,导致页表占用内存空间很大。例如,地址长度 32 位,可以得到最大空间为 4GB,页大小 4KB,最多包含 4G/4K=1M 个页。若每个页表项占用 4 个字节,则页表最大长度为 4MB,即要求内存划分出连续 4MB 的空间来装载页表;若地址程度为 64 位时,就需要恐怖的 4*2^52Byte 空间来存储页表了。而且页表采用的是连续分配,不是分页分配。

        采用离散分配方式的管理页表,将当前需要的部分页表项调入内存,其余的页表项仍驻留在磁盘上,需要时再调入。

8.3.2 二级页表

        对于要求连续的内存空间来存放页表的问题,可利用将页表进行分页,并离散地将各个页面分别存放在不同的物理块中的办法来加以解决,同样也要为离散分配的页表再建立一张页表,称为外层页表(Outer Page Table),在每个页表项中记录了页表页面的物理块号。下面我们仍以前面的 32 位逻辑地址空间为例来说明。当页面大小为 4 KB 时(12 位),若采用一级页表结构,应具有 20 位的页号,即页表项应有 1 兆个;在采用两级页表结构时,再对页表进行分页,使每页中包含 1024个页表项,最多允许有 1024个页表分页;或者说,外层页表中的外层页内地址 P2为 10 位,外层页号 P1也为 10 位。此时的逻辑地址结构可描述如下:

        下图为两级页表结构。由图可以看出,在页表的每个表项中存放的是进程的某页在内存中的物理块号,如第0#页存放在 1#物理块中;1#页存放在 4#物理块中。而在外层页表的每个页表项中,所存放的是某页表分页的首址,如第 0#页表是存放在第 1011#物理块中。我们可以利用外层页表和页表这两级页表,来实现从进程的逻辑地址到内存中物理地址间的变换。

        为了地址变换实现上的方便起见,在地址变换机构中同样需要增设一个外层页表寄存器,用于存放外层页表的始址,并利用逻辑地址中的外层页号,作为外层页表的索引,从中找到指定页表分页的始址,再利用 P2 作为指定页表分页的索引,找到指定的页表项,其中即含有该页在内存的物理块号,用该块号和页内地址 d 即可构成访问的内存物理地址。下图为两级页表时的地址变换机构。

        从上图而知,在二级页表管理中,逻辑地址分成了三部分:顶级页号、次级页号和页内地址。根据顶级页表起始地址和顶级页号从顶级页表中查到次级页表对应的物理块号,接着由该次级页表的物理块号结合次级页号得到对应页的物理块号,结合页内地址求得最终的物理地址。

        上述对页表施行离散分配的方法,虽然解决了对大页表无需大片存储空间的问题,但并未解决用较少的内存空间去存放大页表的问题。换言之,只用离散分配空间的办法并未减少页表所占用的内存空间。解决方法是把当前需要的一批页表项调入内存,以后再根据需要陆续调入。在采用两级页表结构的情况下,对于正在运行的进程,必须将其外层页表调入内存,而对页表则只需调入一页或几页。为了表征某页的页表是否已经调入内存,还应在外层页表项中增设一个状态位 S,其值若为 0,表示该页表分页尚未调入内存;否则,说明其分页已在内存中。进程运行时,地址变换机构根据逻辑地址中的 P1,去查找外层页表;若所找到的页表项中的状态位为 0,则产生一中断信号,请求 OS 将该页表分页调入内存。

8.3.3 多级页表    

        对于 32 位的机器,采用两级页表结构是合适的;但对于 64 位的机器,采用两级页表是否仍可适用的问题,须做以下简单分析。如果页面大小仍采用 4 KB ,那么还剩下 52 位,假定仍按物理块的大小4 KB来划分页表,则将余下的 42 位用于外层页号。此时在外层页表中可能有 4096 G 个页表项,要占用 16 384 GB 的连续内存空间。这样的结果显然是不能令人接受的,因此必须采用多级页表,将外层页表再进行分页,也就是将各分页离散地装入到不相邻接的物理块中,再利用第 2 级的外层页表来映射它们之间的关系。

        对于 64 位的计算机,如果要求它能支持 1 844 744 TB规模的物理存储空间,则即使是采用三级页表结构也是难以办到的;而在当前的实际应用中也无此必要。故在近两年推出的 64 位 OS 中,把可直接寻址的存储器空间减少为 45 位长度左右,这样便可利用三级页表结构来实现分页存储管理。

        多级页表和二级页表类似。多级页表和二级页表是为了节省物理内存空间。使得页表可以在内存中离散存储。(单级页表为了随机访问必须连续存储,如果虚拟内存空间很大,就需要很多页表项,就需要很大的连续内存空间,但是多级页表不需要。

  • 15
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值