当CPU要求地址高于0xC0000000时,如何执行地址转换(virt-> phy)?

时间:2012-03-28 20:01:05

标签: c linux memory operating-system linux-kernel

我想出了这个问题,因为我不明白在内核区域如何进行地址转换。

根据我的理解,要翻译0xC0000000以上的任何地址,我们只需要用PAGE_OFFSET减去此地址(除了内核初始化过程,我们需要一个8MB范围的页表)。但是,如果CPU执行需要地址的指令(例如0xF0000020),而系统只有256MB RAM,则没有意义。

由于上述原因,我认为内核确实有一个页表,允许MMU将0xC0000000以上的虚拟地址转换为物理地址。因此,在什么情况下我们可以直接减去PAGE_OFFSET,在什么情况下我们需要内核页表?

我可能在开始时出错,所以请更正。


编辑

来自<<了解Linux虚拟内存管理器>>,它表示存在内核页表。现在,更加困惑......

  

3.6内核页表

     

系统首次启动时,未启用分页,因为页表不会   神奇地初始化自己。每个架构都以不同的方式实现   只讨论x86案例。页表初始化分为两个   阶段。引导阶段仅为8MiB设置页表,以便进行分页   单位可以启用。 第二阶段初始化其余页面表。我们   在以下部分中讨论这两个阶段。

     

3.6.1引导

     

...

     

3.6.2完成

     

负责完成页表的函数叫做paging_init()。该   x86上此函数的调用图如图3.4所示。   enter image description here

     

该函数首先调用pagetable_init()来初始化必要的页表   引用ZONE_DMA和ZONE_NORMAL中的所有物理内存。记住这一点   ZONE_HIGHMEM中的高内存不能直接引用和映射   暂时设置它。对于内核使用的每个pgd,引导内存   调用allocator(参见第5章)为PGD和PSE分配页面   如果可以使用4MiB TLB条目而不是4KiB,则将设置位。如果是PSE   不支持bit,将为每个pmd t分配PTE的页面。如果是CPU   支持PGE标志,它也将被设置为使页表条目是全局的   并且对所有流程都可见。

     

接下来,pagetable_init()调用fixrange_init()来设置固定地址   从FIXADDR_START开始的虚拟地址空间末尾的空间映射。   这些映射用于诸如本地高级可编程之类的目的   中断控制器(APIC)和FIX_KMAP_BEGIN之间的原子kmappings   和kmap_atomic()所需的FIX_KMAP_END。最后,函数调用   fixrang_init()初始化正常高内存所需的页表条目   使用kmap()进行映射。

     

在pagetable_init()返回后,内核空间的页表现已完全显示   初始化,所以静态PGD(swapper_pg_dir)被加载到CR3寄存器中   现在,寻呼单元正在使用静态表。

     

paging_init()的下一个任务是负责调用kmap_init()   使用PAGE_KERNEL保护标志初始化每个PTE。最后的任务是   调用zone_sizes_init(),初始化所有使用的区域结构。

3 个答案:

答案 0 :(得分:0)

第一个900MB物理内存(如果存在)有一个线性映射,因此该内存的虚拟地址等于物理内存加PAGE_OFFSET。当然,如果内核想要将该内存用于其他目的,这并不会阻止相同的物理内存映射到进程的地址空间的其他位置。

答案 1 :(得分:0)

尽管线性映射对于人类来说似乎很特殊,但它(通常)在MMU配置方面并不特殊。

  

正如您所说,要将虚拟地址从3G转换为3G + 900MB,我们可以使用PAGE_OFFSET直接减去这些地址。这是否意味着内核不需要任何页表?

仍需要这些表来解释到MMU的特定(线性)映射。虽然有一些特殊情况,如MIPS R3000

  

但是,如果CPU执行需要地址的指令,例如0xF0000020

,这没有意义

我会问首先在该地址执行指令是否有意义。我的意思是,在具有256MB RAM的系统上,您不会仅仅遇到这样的请求(至少假设代码没有错误)。

让您感到困惑的一点是IMO:谁负责进行地址翻译?答案是(通常也是)MMU,用硬件实现。因此,页面表是MMU如何进行此类翻译的方式 - 这样做不是内核的责任。内核只需要配置MMU。

  

当CPU要求地址高于0xC0000000时,如何执行地址转换(virt-> phy)?

就像下面的地址一样。 This阅读可能会有所帮助。

答案 2 :(得分:0)

实际上,您的用户空间程序甚至内核都使用虚拟寻址。这意味着每个内存请求都通过MMU。如果它通过MMU,它使用页表(参见x86上的CR3寄存器)

virtual addr --> MMU --> physical addr 

当你访问lowmem时,内核并没有使用一些神奇的优化。是的,lowmem是直接映射的,这就是为什么从人类的角度来看,你可以通过简单的减法将lowmem的虚拟地址转换为物理,但CPU通过内核页表进行翻译。