段寄存器如何参与内存地址转换?
How are segment registers involved in memory address translation?
到目前为止我学到的关于细分的知识:
- 一个虚拟地址包含一个段选择符和一个偏移量
- 段选择符与GDTR配合使用,查找段描述符的线性地址
- 段描述符包含有关所选段的信息,包括其线性地址
所以,我的问题是:
根据我读到的内容,虚拟地址被加载到段寄存器中,然后以某种方式从那里继续进行翻译。将虚拟地址加载到段寄存器中以获得描述符后,段寄存器会发生什么?
据我了解,段寄存器还保存了描述符的缓存值。这在翻译过程中如何发挥作用?
考虑到一个段选择器最多可以有 2^13 个不同的值,而主寄存器只有六个,系统如何确定加载哪个段寄存器?
通常的翻译如下:
Logical address --> GDT --> Linear address --> Page tables --> Physical Address
(segment:offset) (segment base + offset)
\______________________________________________________/
Virtual address
(can be either logical or linear)
如果 运行 在 VMX 非 root 模式下(即在 VM 中)并且启用了 EPT,则:
Logical address --> GDT --> Linear address --> Page tables --> Guest Physical Address --> EPT --> (System) Physical Address
(segment:offset) (segment base + offset)
\______________________________________________________/ \__________________________________________________________/
Virtual address Physical address
(can be either logical or linear)
如果存在 IOMMU(如保护伞技术 VT-d):
Logical address --> GDT --> Linear address --> Page tables --> Guest Physical Address --> EPT --> (System) Physical Address --> 1 or 2 level translation --> (IO) Physical address
(segment:offset) (segment base + offset)
\______________________________________________________/ \___________________________________________________________________________________________________________________/
Virtual address Physical address
(can be either logical or linear)
MMIO甚至可以进行Guest Virtual Address或Guest Physical Address的转换(其目的之一是将应用程序的Virtual address具体化为硬件,简化过多地址的管理spaces 在翻译过程中遇到)。
注意正如Hadi Brais所指出的,术语"Virtual address"在Intel和AMD手册中仅指定线性地址。
我发现将逻辑地址和线性地址都标记为虚拟地址更有用,因为它们在页面转换步骤之前。
段寄存器保存一个段选择器,它索引一个段描述符,用于执行安全检查并获取段base 与逻辑地址.
的偏移部分相加
之后就大功告成了。
在指令级指定的每个地址都是一个逻辑地址 - 需要查找段描述符。
为了避免每次指令访问内存时都从内存中读取它,CPU 缓存它 - 否则会成为性能杀手。
OS 根据需要执行的操作设置段寄存器,但无论如何它很少需要超过四个段。
分段(在 PM 中)的主要目的是通过为每个程序定义非重叠分段来实现进程隔离。
一个程序通常只需要一个堆栈段、一个数据段和一个代码段——其他三个是为了避免 saving/restoring 当时的数据段,当时段最大大小为 64KiB(阅读:实模式。fs
和 gs
是后来添加的)。
今天 OSes 使用平面模型,其中只有两个部分(代码和 data/stack - 这是一种简化,需要其他部分)包含整个地址 space , 再加上 OS 特定段,例如 TLS 或 PEB/TEB.
所以六个段寄存器甚至超过了它的需要,GDT 的 8192 个条目在那里以备不时之需(如果甚至)需要。
第1题:
好吧,直到下一个 virtual/logical 地址被加载到段寄存器,当前选择器才会出现。(没有变化,保持相同的虚拟地址)。
第2题:
最初,发生分段过程(即将虚拟地址转换为 32 位线性地址)。
首先,16 位选择器将被加载到一个段寄存器中。这个 16 位选择器包含(13 位描述符编号,1 位 Table 索引,2 位 RPL[请求的特权级别])。
现在 GDT/LDT 的 32 位基地址(GDT 如果 TI=0)来自 GDTR/LDTR 与 13 位指针相加并指向相应 GDT 中的描述符? LDT.
描述符是一个 8 字节的条目,包含内存段的 32 位基地址、访问权限和内存段的 Limits/length/size。
现在上面提到的所有3个实体都被复制到所选段寄存器的程序员不可见缓存寄存器部分。
这个来自缓存的32位基地址与虚拟地址或逻辑地址的32位偏移量相加,形成线性地址。
如果禁用分页,这将用作物理地址,否则,将进行页面转换以获取内存段中某个段的物理地址。
第3题:
这真的无关紧要,因为描述符中 8 位访问权限中的位将内存段的使用指定为 code/data/stack/extra 段。
到目前为止我学到的关于细分的知识:
- 一个虚拟地址包含一个段选择符和一个偏移量
- 段选择符与GDTR配合使用,查找段描述符的线性地址
- 段描述符包含有关所选段的信息,包括其线性地址
所以,我的问题是:
根据我读到的内容,虚拟地址被加载到段寄存器中,然后以某种方式从那里继续进行翻译。将虚拟地址加载到段寄存器中以获得描述符后,段寄存器会发生什么?
据我了解,段寄存器还保存了描述符的缓存值。这在翻译过程中如何发挥作用?
考虑到一个段选择器最多可以有 2^13 个不同的值,而主寄存器只有六个,系统如何确定加载哪个段寄存器?
通常的翻译如下:
Logical address --> GDT --> Linear address --> Page tables --> Physical Address
(segment:offset) (segment base + offset)
\______________________________________________________/
Virtual address
(can be either logical or linear)
如果 运行 在 VMX 非 root 模式下(即在 VM 中)并且启用了 EPT,则:
Logical address --> GDT --> Linear address --> Page tables --> Guest Physical Address --> EPT --> (System) Physical Address
(segment:offset) (segment base + offset)
\______________________________________________________/ \__________________________________________________________/
Virtual address Physical address
(can be either logical or linear)
如果存在 IOMMU(如保护伞技术 VT-d):
Logical address --> GDT --> Linear address --> Page tables --> Guest Physical Address --> EPT --> (System) Physical Address --> 1 or 2 level translation --> (IO) Physical address
(segment:offset) (segment base + offset)
\______________________________________________________/ \___________________________________________________________________________________________________________________/
Virtual address Physical address
(can be either logical or linear)
MMIO甚至可以进行Guest Virtual Address或Guest Physical Address的转换(其目的之一是将应用程序的Virtual address具体化为硬件,简化过多地址的管理spaces 在翻译过程中遇到)。
注意正如Hadi Brais所指出的,术语"Virtual address"在Intel和AMD手册中仅指定线性地址。
我发现将逻辑地址和线性地址都标记为虚拟地址更有用,因为它们在页面转换步骤之前。
段寄存器保存一个段选择器,它索引一个段描述符,用于执行安全检查并获取段base 与逻辑地址.
的偏移部分相加
之后就大功告成了。
在指令级指定的每个地址都是一个逻辑地址 - 需要查找段描述符。
为了避免每次指令访问内存时都从内存中读取它,CPU 缓存它 - 否则会成为性能杀手。
OS 根据需要执行的操作设置段寄存器,但无论如何它很少需要超过四个段。
分段(在 PM 中)的主要目的是通过为每个程序定义非重叠分段来实现进程隔离。
一个程序通常只需要一个堆栈段、一个数据段和一个代码段——其他三个是为了避免 saving/restoring 当时的数据段,当时段最大大小为 64KiB(阅读:实模式。fs
和 gs
是后来添加的)。
今天 OSes 使用平面模型,其中只有两个部分(代码和 data/stack - 这是一种简化,需要其他部分)包含整个地址 space , 再加上 OS 特定段,例如 TLS 或 PEB/TEB.
所以六个段寄存器甚至超过了它的需要,GDT 的 8192 个条目在那里以备不时之需(如果甚至)需要。
第1题: 好吧,直到下一个 virtual/logical 地址被加载到段寄存器,当前选择器才会出现。(没有变化,保持相同的虚拟地址)。
第2题: 最初,发生分段过程(即将虚拟地址转换为 32 位线性地址)。
首先,16 位选择器将被加载到一个段寄存器中。这个 16 位选择器包含(13 位描述符编号,1 位 Table 索引,2 位 RPL[请求的特权级别])。
现在 GDT/LDT 的 32 位基地址(GDT 如果 TI=0)来自 GDTR/LDTR 与 13 位指针相加并指向相应 GDT 中的描述符? LDT.
描述符是一个 8 字节的条目,包含内存段的 32 位基地址、访问权限和内存段的 Limits/length/size。
现在上面提到的所有3个实体都被复制到所选段寄存器的程序员不可见缓存寄存器部分。
这个来自缓存的32位基地址与虚拟地址或逻辑地址的32位偏移量相加,形成线性地址。 如果禁用分页,这将用作物理地址,否则,将进行页面转换以获取内存段中某个段的物理地址。
第3题:
这真的无关紧要,因为描述符中 8 位访问权限中的位将内存段的使用指定为 code/data/stack/extra 段。