为什么细分不能完全禁用? [英] Why segmentation cannot be completely disable?

查看:83
本文介绍了为什么细分不能完全禁用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据AMD manual的细分不能被禁用. 我的问题是为什么,为什么不可能? 另一个问题是说64位将其禁用,这是什么意思?在64位模式下是否完全禁用了分段?

According to AMD manual segmentation can not be disabled. My question is why, why it's impossible? Another question, it says that 64-bit disables it, what does that mean? Is segmentation completly disabled on 64-bit mode?

AMD手册: https://s7.postimg.cc/hk15o6swr/Capture.png

推荐答案

简介

在64位模式下,每当将非空的段选择器加载到任何段寄存器中时,处理器都会自动将相应的段描述符加载到段寄存器的隐藏部分中,就像在保护/兼容模式下一样.但是,完全忽略了DS,ES或SS选择器选择的段描述符. FS和GS选择器选择的段描述符的限制和属性字段也将被忽略.

Introduction

In 64-bit mode, whenever a non-null segment selector is loaded into any of the segment registers, the processor automatically loads the corresponding segment descriptor in the hidden part of the segment register, just like in protected/compatibility mode. However, the segment descriptors selected by the DS, ES, or SS selectors are completely ignored. Also the limit and attribute fields of the segment descriptors selected by the FS and GS selectors are ignored.

英特尔手册V3 3.4.4:

Intel Manual V3 3.4.4:

由于在64位模式下未使用ES,DS和SS段寄存器, 段描述符中其字段(基础,限制和属性) 寄存器被忽略.段加载指令的某些形式是 也无效(例如LDS,POP ES).地址计算 引用ES,DS或SS段,就好像该段 底数为零.

Because ES, DS, and SS segment registers are not used in 64-bit mode, their fields (base, limit, and attribute) in segment descriptor registers are ignored. Some forms of segment load instructions are also invalid (for example, LDS, POP ES). Address calculations that reference the ES, DS, or SS segments are treated as if the segment base is zero.

...

在64位模式下,使用FS段和GS段的内存访问 不会检查覆盖是否有运行时限制,也不会受到覆盖 属性检查.

In 64-bit mode, memory accesses using FS-segment and GS-segment overrides are not checked for a runtime limit nor subjected to attribute-checking.

除此之外,假定每个段的基地址为0,长度为2 64 .但是,由CS,FS或GS选择器选择的段描述符的某些部分仍然有效.特别是,使用了在各自的描述符中指定的FS和GS的基地址.

Other than that, it's assumed that the base address of each of these segments to be 0 and the length to be 264. However, some parts of the segment descriptors selected by the CS, FS, or GS selectors still take effect. In particular, the base addresses of FS and GS specified in their respective descriptors are used.

英特尔手册V3 3.4.4:

Intel Manual V3 3.4.4:

在64位模式下使用FS和GS段替代时,它们的 相应的基址用于线性地址计算.

When FS and GS segment overrides are used in 64-bit mode, their respective base addresses are used in the linear address calculation.

此外,使用CS描述符的以下字段:D(默认位),L(64位子模式位),AVL(OS位),P(当前位),DPL(特权级位) ),S(系统位),D/C(数据/代码位)和C(合格位).注意,CS的基地址固定为0,CS,FS和GS的长度都固定为2 64 .正如彼得在其评论中指出的那样,要求CS描述符的L和D位能够在长模式的不同子模式之间进行切换. CS的其他活动字段也很有用.支持FS和GS的不同基址对于诸如线程本地存储之类的事情很有用.

In addition, the following fields of the CS descriptor are used: D (default bit), L (64-bit sub-mode bit), AVL (OS bits), P (present bit), DPL (privilege level bits), S (system bit), D/C (data/code bit), and C (conforming bit). Note that the base address of CS is fixed at 0 and the lengths of CS, FS, and GS are all fixed at 264. As Peter indicated in his comment, the L and D bits of the CS descriptor are required to be able to switch between the different sub-modes of the long mode. The other active fields of CS are also useful. Supporting different base addresses for FS and GS is useful for things like thread-local storage.

英特尔手册V3 5.2.1:

Intel Manual V3 5.2.1:

代码段继续以64位模式存在,即使对于 地址计算时,段基数被视为零.一些 代码段(CS)描述符内容(基地址和限制 字段)被忽略;其余字段正常运行(除了 类型字段中的可读位).

Code segments continue to exist in 64-bit mode even though, for address calculations, the segment base is treated as zero. Some code-segment (CS) descriptor content (the base address and limit fields) is ignored; the remaining fields function normally (except for the readable bit in the type field).

在IA-32e模式下需要代码段描述符和选择器以 建立处理器的操作模式和执行 特权级别.

Code segment descriptors and selectors are needed in IA-32e mode to establish the processor’s operating mode and execution privilege-level.

我认为在64位模式下,可读位和访问位都将被忽略.这些属性被分页结构中的相应属性替换.尽管我在Intel手册中找不到任何地方说访问的位被忽略了.但是AMD手册确实明确指出了这一点.

I think that both the readable bit and accessed bit are ignored in 64-bit mode. These attributes are replaced by the corresponding attributes in the paging structures. Although I couldn't find anywhere in the Intel manual that says that the accessed bit is ignored. But the AMD manual does state that clearly.

描述符表限制检查仍在执行.

Descriptor table limit checks are still performed.

Intel手册V3 5.3.1:

Intel Manual V3 5.3.1:

在64位模式下,处理器不执行运行时限制检查 在代码或数据段上.但是,处理器会检查 描述符表限制.

In 64-bit mode, the processor does not perform runtime limit checking on code or data segments. However, the processor does check descriptor-table limits.

因此,您可以说DS,ES和SS细分完全禁用了细分.但对于其他三个细分市场而言,却不完全相同.这就是segmentation cannot be completely disabled的意思.

So you could say that segmentation is completely disabled for the DS, ES, and SS segments. But not exactly for the other three segments. That's what segmentation cannot be completely disabled means.

我引用POP指令的描述.

I quote from the description of the POP instruction.

64位模式异常

64-Bit Mode Exceptions

#GP(0)如果内存地址为非规范形式.
#SS(0)如果堆栈地址为非规范形式.
#GP(selector)如果描述符超出描述符表限制.
如果正在加载FS或GS寄存器,并且指向的段不是数据段或可读代码段.
如果正在加载FS或GS寄存器,并且指向的段是 数据段或不合格代码段,但RPL和CPL均为 大于DPL.
#AC(0)如果在启用对齐检查的情况下进行了未对齐的内存引用.
#PF(故障代码)如果发生页面错误.
#NP 如果正在加载FS或GS寄存器,并且标记为指向的段不存在.
#UD如果使用LOCK前缀.

#GP(0) If the memory address is in a non-canonical form.
#SS(0) If the stack address is in a non-canonical form.
#GP(selector) If the descriptor is outside the descriptor table limit.
If the FS or GS register is being loaded and the segment pointed to is not a data or readable code segment.
If the FS or GS register is being loaded and the segment pointed to is a data or nonconforming code segment, but both the RPL and the CPL are greater than the DPL.
#AC(0) If an unaligned memory reference is made while alignment checking is enabled.
#PF(fault-code) If a page fault occurs.
#NP If the FS or GS register is being loaded and the segment pointed to is marked not present.
#UD If the LOCK prefix is used.

请注意,到DS,ES,SS的POP在64位模式下无效,并且没有POP CS.这就是为什么只谈论FS和GS的原因.尽管这意味着FS和GS选择的描述符的属性不会被完全忽略.

Note that POPs to DS, ES, SS are not valid in 64-bit mode, and there is no POP CS. That's why it only talks about FS and GS. Although this implies that the attributes of the descriptors selected by FS and GS are not completely ignored.

类似地,MOV指令的描述为:

Similarly, the description of the MOV instruction says:

64位模式异常

64-Bit Mode Exceptions

#GP(0)
如果内存地址为非规范形式.
如果尝试在使用NULL段选择器加载SS寄存器时 CPL =3.
如果尝试用NULL段加载SS寄存器 当CPL< 3,CPL≠RPL.
#GP(选择器)
如果段选择器索引超出描述符表的限制.如果对描述符表的内存访问为 非规范的.
如果正在加载SS寄存器和段 选择器的RPL和段描述符的DPL不等于 CPL.
如果正在加载SS寄存器并且该段指向 是不可写的数据段.
如果DS,ES,FS或GS寄存器是 正在加载并且指向的段不是数据或可读代码 细分.
如果正在加载DS,ES,FS或GS寄存器,并且 指向的段是数据段或不合格的代码段,但两者 RPL和CPL大于DPL.
#SS(0)如果堆栈地址为非规范形式.
#SS(selector)如果正在加载SS寄存器,并且所指向的段被标记为不存在.
#PF(故障代码)如果发生页面错误.
#AC(0)如果启用了对齐检查,并且在当前特权级别为3时进行了未对齐的内存引用.
#UD如果试图加载CS寄存器.如果使用LOCK前缀.

#GP(0)
If the memory address is in a non-canonical form.
If an attempt is made to load SS register with NULL segment selector when CPL = 3.
If an attempt is made to load SS register with NULL segment selector when CPL < 3 and CPL ≠ RPL.
#GP(selector)
If segment selector index is outside descriptor table limits. If the memory access to the descriptor table is non-canonical.
If the SS register is being loaded and the segment selector's RPL and the segment descriptor’s DPL are not equal to the CPL.
If the SS register is being loaded and the segment pointed to is a nonwritable data segment.
If the DS, ES, FS, or GS register is being loaded and the segment pointed to is not a data or readable code segment.
If the DS, ES, FS, or GS register is being loaded and the segment pointed to is a data or nonconforming code segment, but both the RPL and the CPL are greater than the DPL.
#SS(0) If the stack address is in a non-canonical form.
#SS(selector) If the SS register is being loaded and the segment pointed to is marked not present.
#PF(fault-code) If a page fault occurs.
#AC(0) If alignment checking is enabled and an unaligned memory reference is made while the current privilege level is 3.
#UD If attempt is made to load the CS register. If the LOCK prefix is used.

但是请注意,此处未出现#NP!这表明仅检查FS,GS,CS和SS的当前位(P),而不检查DS和ES. (但是我认为所有段都检查了P位.)这些引号也暗示着也使用了任何段寄存器的选择器的RPL部分.

But notice that #NP does not occur here! This suggests that the present bit (P) is only checked for FS, GS, CS, and SS, but not for DS and ES. (But I think that the P bit is checked for all of the segments.) These quotes also suggest that the RPL part of the selector of any segment register is also used.

空段选择器是一个值为0x0000、0x0001、0x0002或0x0003的选择器.对于处理器而言,所有这些值始终具有相同的效果.这些都选择相同的描述符,即GDT的条目0.

The null segment selector is a selector whose value is 0x0000, 0x0001, 0x0002, or 0x0003. To the processor, all of these values always have the same effect. These all select the same descriptor, entry 0 of GDT.

空段选择器不能以任何使用分段的模式(包括64位模式)加载到CS中,因为CS必须始终包含一个实际的选择器.尝试这样做会生成GP异常.

The null segment selector cannot be loaded into CS in any mode that uses segmentation (including 64-bit mode) because CS must contain an actual selector at all times. An attempt to do that generates a GP exception.

可以将空段选择器以64位模式(与其他模式相比)加载到SS中,但仅在某些情况下才可以.有关更多信息,请参阅英特尔手册V3 6.15的常规保护异常(#GP)"部分.

The null segment selector can be loaded into SS in 64-bit mode (in contrast to other modes), but only in certain situations. For more information, refer to the part "General Protection Exception (#GP)" of Intel Manual V3 6.15.

空段选择器可以加载到DS,ES,GS和FS中.

The null segment selector can be loaded into DS, ES, GS, and FS.

Intel手册V3 5.4.1.1:

Intel Manual V3 5.4.1.1:

在64位模式下,处理器不执行以下操作的运行时检查: 空段选择器.在以下情况下,处理器不会导致#GP故障 试图访问引用段所在的内存 寄存器具有NULL段选择器.

In 64-bit mode, the processor does not perform runtime checking on NULL segment selectors. The processor does not cause a #GP fault when an attempt is made to access memory where the referenced segment register has a NULL segment selector.

我觉得这很有趣,我将在后面解释. (我也发现,专门用于细分的第3章没有说明这一点很奇怪.)

I find this very interesting as I will explain later. (I also find it weird that Chapter 3, which is dedicated for segmentation, does not state that).

对于我来说,还不清楚处理器在使用null选择器加载时是否将内存中的null描述符加载到段寄存器的不可见部分中.

It's not perfectly clear to me whether the processor loads the null descriptor from memory into the invisible part of the segment register when loading it with the null selector.

英特尔手册V3 3.4.2:

Intel Manual V3 3.4.2:

处理器未使用GDT的第一个条目.

The first entry of the GDT is not used by the processor.

这是否意味着处理器将不会加载空描述符?或者,也许仅意味着不使用描述符的内容.后来在3.4.4中说:

Does this mean that the processor will not load the null descriptor? Or perhaps it only means that the contents of the descriptor are not used. Later it says in 3.4.4:

为了为应用程序设置兼容模式,请分段加载 指令(MOV到Sreg,POP Sreg)在64位模式下正常工作.一个 条目是从系统描述符表(GDT或LDT)中读取的,并且 加载到段寄存器的隐藏部分中.这 描述符寄存器的基数,限制和属性字段均已加载. 但是,数据和堆栈段选择器的内容以及 描述符寄存器将被忽略.

In order to set up compatibility mode for an application, segment-load instructions (MOV to Sreg, POP Sreg) work normally in 64-bit mode. An entry is read from the system descriptor table (GDT or LDT) and is loaded in the hidden portion of the segment register. The descriptor-register base, limit, and attribute fields are all loaded. However, the contents of the data and stack segment selector and the descriptor registers are ignored.

Intel手册V2中的POP指令说明如下:

The description of the POP instruction from the Intel Manual V2 says:

64位模式

64-BIT_MODE

如果IF FS或GS装有NULL选择器;
然后
SegmentRegister←段选择器;
SegmentRegister←段描述符;
FI;

IF FS, or GS is loaded with a NULL selector;
THEN
SegmentRegister ← segment selector;
SegmentRegister ← segment descriptor;
FI;

Intel手册V2中对MOV指令的描述为:

The description of the MOV instruction from the Intel Manual V2 says:

如果使用空选择器加载了DS,ES,FS或GS,则
然后
SegmentRegister←段选择器;
SegmentRegister←段描述符;
FI;

IF DS, ES, FS, or GS is loaded with NULL selector
THEN
SegmentRegister ← segment selector;
SegmentRegister ← segment descriptor;
FI;

这表明实际上已加载了空描述符,但其内容被忽略了. Linux内核将空描述符定义为所有位为零.我在许多文章和教科书中都读到,这是强制性的.但是,柯林斯,这是不必要的:

This suggests that the null descriptor does actually get loaded, but its contents are ignored. The Linux kernel defines the null descriptor to have all bits zero. I've read in many articles and textbooks that this is mandatory. However, Collins says that this is not necessary:

全局描述符表(GDT)中的第一个条目称为 空描述符. NULL描述符是GDT唯一的,因为它有一个 TI = 0,并且INDEX = 0.大多数印刷文档指出 描述符表项必须为0. 这个主题,永远不要说它不能用于什么.英特尔确实声明 第0个描述符表条目永远不会被 处理器.

The first entry in the Global Descriptor Table (GDT) is called the null descriptor. The NULL descriptor is unique to the GDT, as it has a TI=0, and INDEX=0. Most printed documentation states that this descriptor table entry must be 0. Even Intel is somewhat ambiguous on this subject, never saying what it CAN'T be used for. Intel does state that the 0'th descriptor table entry is never referenced by the processor.

AFAIK,Intel对空描述符的内容不加任何限制.所以我想柯林斯是对的.

AFAIK, Intel does not impose any restrictions on the contents of the null descriptor. So I guess Collins is right.

因为这意味着可以在64位模式下使用DS,ES,GS和GS来保存常量0x0000、0x0001、0x0002或0x0003.确保GDT至少包含空描述符,因此描述符表限制检查将通过(对于其他选择器可能不正确).此外,对这些段中任何一个的所有引用仍将成功执行. MOV指令可用于将值从段寄存器移至GPR,然后对其执行操作.

Because this means it's possible to use DS, ES, GS, and GS to hold any of the constants 0x0000, 0x0001, 0x0002, or 0x0003, in 64-bit mode. It's guaranteed that the GDT contains at least the null descriptor, so descriptor table limit check will pass (this may not be true with other selectors). In addition, all references to any of these segments will still be performed successfully. The MOV instruction can be used to move a value from a segment register to a GPR and then performing an operation on it.

要写.

这篇关于为什么细分不能完全禁用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆