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

当CPU需要高于0xC0000000的地址时,如何执行地址转换(virt->;phy)?,c,linux,memory,operating-system,linux-kernel,C,Linux,Memory,Operating System,Linux Kernel,我提出这个问题是因为我不明白地址转换是如何在内核区域执行的 据我所知,要翻译上面的任何地址0xc000000,我们只需要用PAGE\u OFFSET减去这个地址(内核初始化过程除外,这里我们需要一个8MB范围的页表)。但如果CPU执行的指令要求地址在,比如说0xF0000020,而系统只有256MB RAM,那么这就没有意义了 出于上述原因,我认为内核确实有一个页表,允许MMU将上面的虚拟地址0xc000000转换为物理地址。因此,在什么情况下我们可以直接减去PAGE\u偏移量,在什么情况下我们

我提出这个问题是因为我不明白地址转换是如何在内核区域执行的

据我所知,要翻译上面的任何地址
0xc000000
,我们只需要用
PAGE\u OFFSET
减去这个地址(内核初始化过程除外,这里我们需要一个8MB范围的页表)。但如果CPU执行的指令要求地址在,比如说
0xF0000020
,而系统只有256MB RAM,那么这就没有意义了

出于上述原因,我认为内核确实有一个页表,允许MMU将上面的虚拟地址
0xc000000
转换为物理地址。因此,在什么情况下我们可以直接减去
PAGE\u偏移量
,在什么情况下我们需要内核页表

我一开始可能会出错,请改正


编辑

从>,它说内核页表存在。现在,更困惑的是

3.6内核页面表

当系统第一次启动时,由于页表未启用,因此不会启用分页 神奇地初始化自己。每个体系结构都以不同的方式实现这一点 只讨论x86案例。页表初始化分为两部分 阶段。引导阶段只为8Mb设置页面表,以便分页 可以启用该单元第二阶段初始化页面表的其余部分。我们 在以下章节中讨论这两个阶段

3.6.1自举

3.6.2定稿

负责完成页表的函数称为paging_init()。这个 x86上此函数的调用图如图3.4所示。

函数首先调用pagetable_init()来初始化所需的页表 要引用分区\ DMA和分区\正常中的所有物理内存。记得吗 无法直接引用区域_HIGHMEM中的高内存,并且该映射 是为它临时设置的。对于内核使用的每个pgd t,启动内存 调用分配器(参见第5章)为PGD和PSE分配页面 如果可以使用4MiB TLB条目而不是4KiB条目,则将设置位。如果PSE 位不受支持,将为每个pmd t分配PTE页。如果CPU 支持PGE标志,它也将被设置为使页表条目是全局的 并且对所有进程都可见

接下来,pagetable_init()调用fixrange_init()来设置固定地址 从FIXADDR\u START开始的虚拟地址空间末尾的空间映射。 这些映射用于本地高级可编程 中断控制器(APIC)和FIX_KMAP_BEGIN之间的原子映射 并修复KMAP_atomic()所需的\u KMAP_END。最后,函数调用 fixrang_init()初始化正常高内存所需的页表项 使用kmap()的映射

返回pagetable_init()后,内核空间的页表现在已完全打开 已初始化,因此静态PGD(swapper_pg_dir)加载到CR3寄存器中 分页单元现在正在使用静态表

分页_init()的下一个任务负责调用kmap_init()以 使用PAGE_内核保护标志初始化每个PTE。最后的任务是 调用zone_size_init(),它初始化所有使用的区域结构


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

虽然线性映射对人类来说可能很特殊,但它(通常)在MMU配置方面并不特殊


正如你所说,要将虚拟地址从3G转换为3G+900MB,我们可以直接减去这些地址的PAGE_偏移量。这是否意味着内核不需要任何页面表

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

但这在CPU执行需要地址为(比如0xF0000020)的指令时没有意义

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

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

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


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

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


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

所以正如你所说,要将虚拟地址从3G转换为3G+900MB,我们可以直接减去这些地址的页偏移量。这是否意味着内核不需要任何页面表?但是,它确实存在,所以我不明白是什么服务
virtual addr --> MMU --> physical addr