Chinaunix

标题: 关于386CPU使用64TB虚拟内存的解释的另一种方法! [打印本页]

作者: rawa99999    时间: 2009-09-25 16:44
标题: 关于386CPU使用64TB虚拟内存的解释的另一种方法!
名词解释:

段描述符--80386下的段具有三个属性:段基址,段界限,段属
            性,通常描述段的称作段描述符(Segment Descriptor)
段描述符表--存放段描述符(Segment Descriptor)的表 GDT IDT               LDT
段选择子--用来查找段描述符表中的段描述符(Segment Descriptor)

          段选择子的结构:
          15___________________2bit__1bit_____0bit   
              INDEX(13bit)   TI(1bit)   RPL(2bit)
           其中RPL(请求特权级--Requested Privilege Level)2位,
       TI(TABLE INDICATOR)1位
       INDEX(索引)13位


64T的解释:
    在整个系统中全局段描述符表GDT和中断描述符表只有一张,局部段描述符
表LDT可以由若干张,每个段描述符表都形成一个特殊的16位数据段(段限
--段的大小),由于段选择子中索引(INDEX)的限制这样的GDT和LDT中都最
多最多可以有2^13=8192个段描述符。
    LDT的描述符和IDT的描述符都存放在GDT中,注意GDT中还可以存放段描述符,
这三者长度都是64bit长,都存放在GDT中,所以更正一下GDT存放段描述符的
数量是8192-LDT表的数量-1(IDT表)的结果。这一点很重要。
    为了好理解讨论一个极端情况只有一个LDT,并且这个任务需要64TB内存,系
统首先加载GDT(在物理内存的某个位置),然后生成LDT,分配虚拟内存,由于需求
很大所以分配了最大的段数8192个4G空间=32T,不够,又请求使用GDT分配段最大
段数8190(8192-1个LDT-1个IDT)个4G空间约为32T(1TB=1000GB所以少了8G忽
略不计)这样系统共分配了64TB的虚拟内存。
---------------------------------
这件事使我联想起两件事,我去龙芯论坛了。
作者: mik    时间: 2009-09-26 00:12
看你这娃,又可怜又可笑

见你多看点 intel/amd 手册,是为你好! Y 的你却和我较劲。

你就这么的不思长进,还在扯住这个话题,还是那么的错误百出!



我大人有大量,给你上一堂课吧,也不需要你的感激了


1、 descriptor(描述符)


分两类:segment descriptor(段描述符)和 system descriptor(系统描述符)


(1)segment descriptor 描述一个段的相关信息,包括这个段的 base、limit 以及 attribute 信息

      分为:code segment descriptor 和 data segment descriptor 两类

  code segment descriptor 和 data segment descriptor 的区别在于 bit11,=1 时是 code segment descriptor
   = 0 时是 data segment descritor



(2) system descriptor(系统描述符),凡是 bit12 = 0 都可以称为 system descriptor

  
    system descriptor 是用来描述特殊的一块区域。包括两大类:

第一:LDT descriptor 和 TSS descriptor  

第二:gate descriptor(包括 call gate、interrupt gate 、trap gate 以及 task gate)



(3)descriptor 放在哪?

第一:所有的 segment descriptor 都放在 GDT / LDT 中

第二:call gate descriptor 放在 GDT / LDT 中

第三:LDT descriptor 和 TSS 只能放在 GDT 中

第四:Interrupt gate descriptor 和 trap gate descriptor 只能放在 IDT 中

第五:task gate descriptor 放在 GDT / LDT 和 IDT 中





2、selector (选择子)

  selector 的作用是用来查找相应的 descriptors,只有一种特殊情况下不需要 selector 进行查找 descriptor。

  就是:进行中断调用,或发生异常时。


(1)selector 的结构

selector[1:0]     ---->    RPL (requestor privilege level): 00 ~ 11
selector[2]        ---->    TI (table indicator):0 or 1
selector[15:3]    ---->    SI(selector index):0 ~ 8191



(2)关于 RPL、DPL  以及 CPL

RPL:    当用 selector 来查找 descriptor 时,selector[1:0] 才称为 RPL,即:RPL 是被用来以此权限来请求访问。

DPL:    在所有 descriptor 的 DPL 属性里,用来设置访问这个 descriptor 所描述的目标的权限级别

如:   code segment descriptor 的 DPL 设置访问目标 code segment 的权限
        gate descriptor 的 DPL 设置访问这个 gate 的权限

CPL:  当通过相关的权限检查后, 相应的 descriptor 被加载到相应的 registers 后,selector[1:0] 被称为 CPL。
   CPL 会被设为 DPL,即 CPL = DPL

典型的:
   code segment descriptor 被加载到 cs 寄存器后,cs.selector.RPL 成为 CPL

   实际上,CPL 就是等于 cs.selector.RPL

   同样 ss.selector.RPL 也将成为 CPL,即 cs.selector.RPL = ss.selector.RPL = CPL

   processor 会自动检查 cs.selector.RPL 是否等于 ss.selector.RPL。在一系列的检查并加载过程中,processor 会始终保持 cs.selector.RPL = ss.selector.RPL。

   但是,有一种例外,执行 syscall 指令时,processor 不会自动设 ss.selector.RPL 等于 cs.selector.RPL,这时需要自己设定 ss.selector.RPL = cs.selector.RPL



(3)关于 null selector

当任何 registers 被加载为 0,此是 selector = 00,这个 selector 被会为 NULL selector,

NULL selector 表示: selector.SI = 00
                            selector.TI = 0
                            selector.RPL = 00

即,仅在 GDT 中才存在  NULL selector,NULL selector 是不合法的 selector,会才产 #GP 异常




3、descriptor table(描述符表)

descriptor table 是用来存放 descriptor 的一个表格(数据结构),包括:GDT、LDT 和 IDT


(1)descriptor table 的基址

GDT、LDT 和 IDT 的基址分别存放在 GDTR.base、LDTR.base 和 IDTR.base


(2)descriptor table 基址的获取

  GDTR 和 IDTR 的结构是完全一样的,只能通过指令 lgdt 和 lidt 设置。其操作数是所有内存寻址操作数,

也就是:
  GDTR.limit、GDTR.base  在内存中获取
  IDTR.limit 、IDTR.base  在内存中获取


  LDTR 的结构与所有的 segment registers(CS、DS 等) 一样。LDT 需要在 GDT 中获取 LDT descriptor 来定位。


(3)limit 与 base

descriptor table 的 limit 是 16 位 64 K 大小,可容纳 8192 个 descriptors

descriptor base 是 base 是 64 位,可在任何 2^64 线性地址空间定位。32 位保护模式下使用低 32 位,高 32 清 0,64 位模式下使用 full 64 位的线性地址

[ 本帖最后由 mik 于 2009-9-26 01:46 编辑 ]
作者: mik    时间: 2009-09-26 01:12
原帖由 rawa99999 于 2009-9-25 16:44 发表
段描述符--80386下的段具有三个属性:段基址,段界限,段属
            性,通常描述段的称作段描述符(Segment Descriptor)
段描述符表--存放段描述符(Segment Descriptor)的表 GDT IDT               LDT
段选择子--用来查找段描述符表中的段描述符(Segment Descriptor)

          段选择子的结构:
          15___________________2bit__1bit_____0bit   
              INDEX(13bit)   TI(1bit)   RPL(2bit)
           其中RPL(请求特权级--Requested Privilege Level)2位,
       TI(TABLE INDICATOR)1位
       INDEX(索引)13位


64T的解释:
    在整个系统中全局段描述符表GDT和中断描述符表只有一张,局部段描述符
表LDT可以由若干张,每个段描述符表都形成一个特殊的16位数据段(段限
--段的大小),由于段选择子中索引(INDEX)的限制这样的GDT和LDT中都最
多最多可以有2^13=8192个段描述符。
    LDT的描述符和IDT的描述符都存放在GDT中,注意GDT中还可以存放段描述符,
这三者长度都是64bit长,都存放在GDT中,所以更正一下GDT存放段描述符的
数量是8192-LDT表的数量-1(IDT表)的结果
。这一点很重要。
    为了好理解讨论一个极端情况只有一个LDT,并且这个任务需要64TB内存,系
统首先加载GDT(在物理内存的某个位置),然后生成LDT,分配虚拟内存,由于需求
很大所以分配了最大的段数8192个4G空间=32T,不够,又请求使用GDT分配段最大
段数8190(8192-1个LDT-1个IDT)个4G空间约为32T(1TB=1000GB所以少了8G忽
略不计)这样系统共分配了64TB的虚拟内存。
---------------------------------
这件事使我联想起两件事,我去龙芯论坛了。  ...





看一看,短短的一段话,错误之多,可服了你



>> 段描述符表--存放段描述符(Segment Descriptor)的表 GDT IDT               LDT

(1)段描述符表 ----> 应使用“描述符表”一词,

(2)IDT 不能存放 segment descriptors



>> 段选择子--用来查找段描述符表中的段描述符(Segment Descriptor)
  
  也能说错误,不严谨,应使用“选择子”一词


>> 每个段描述符表都形成一个特殊的16位数据段

  描述混乱,limit 在 descriptor table register 的 limit 里



>>  LDT的描述符和IDT的描述符都存放在GDT中

  不存在 IDT 描述符,IDT 是从内存中获取




>> 所以更正一下GDT存放段描述符的数量是8192-LDT表的数量-1(IDT表)的结果

还更正一下

(1)  GDT 可存放 segment descriptor 和 system descriptor(LDT/TSS)以及 call gate descriptor

(2)  哪来的 IDT 表 ??

(3)  NULL selector  去哪了?




>> 并且这个任务需要64TB内存,系统首先加载GDT(在物理内存的某个位置),

(1) GDT 是放在 CPU 的线性地址空间,不是物理内存



>>  然后生成LDT,分配虚拟内存,由于需求很大所以分配了最大的段数8192个4G空间=32T

(1)LDT 从 GDT 处加载

(2)LDT 的加载和 32T 有什么关系 ???



>> 又请求使用GDT分配段最大
段数8190(8192-1个LDT-1个IDT)个4G空间约为32T(1TB=1000GB所以少了8G忽
略不计)这样系统共分配了64TB的虚拟内存。


(1)8190:犯前面所说错误
(2)1TB = 1024 GB






你怎么就老绕着 64T 想不开


1、告诉你吧,GDT 最多能容纳多少 segment descriptor(按你假设只有一个 LDT 的情形) ??

答案是: 8192 - 1(NULL selector) - 1(TSS selector)- 1(LDT selector)= 8189 个



2、假设全都用上 8189 个 segment descriptor,情况是怎样?

第1个 data segment descriptor 的 base 是 0,limit = 4G
第2个 data segment descriptor 的 base 是 0x40000000, limit = 3G(只能设为 3G)
第3个 data segment descriptor 的 base 是 0x80000000, limit = 2G(只能设为 2G)
第4个 data segment descriptor 的 base 是 0xC0000000, limit = 1G(只能设为 1G)
第5个 data segment descriptor 的 base 是 0x00000000, limit = 4G
第6个 code segment descriptor 的 base 是 0x00000000, limit = 4G

以此类推 ... ...

这些 segment descriptor 的空间绝大多数都是重叠在一起。全都在 4G 的线性空间之内

这些 segment 经过分段管理后,全部转为 4G 的线性地址的某一个地址。



你怎么就那么的想不开呢?
作者: mingyanguo    时间: 2009-09-26 08:48
终于忍不住了,你们两个可笑死我了………………
作者: mik    时间: 2009-09-26 08:54
原帖由 mingyanguo 于 2009-9-26 08:48 发表
终于忍不住了,你们两个可笑死我了………………


作者: rawa99999    时间: 2009-09-26 10:54
我描述的可能不够严格,这只是一种解释,但是虚拟地址空间最终转化为控制虚拟内存,还有很多办法,比如soft MMU(软件内存管理单元),CPU提供了这种寻址的能力,就一定能控制这么大的虚拟内存,况且64T虚拟内存是官方的描述(这一点很明显386CPU86年的那一款跟88年的那一款虚拟地址空间的差别)。
作者: sep    时间: 2009-09-26 12:17
mik真够耐心
作者: newIT666    时间: 2009-09-26 17:22
   两位高人还在PK

看不懂,学习了.
作者: nizvoo    时间: 2009-09-26 19:05
学习学习
作者: cjaizss    时间: 2009-09-26 22:52
我来分析一下吧。
无论如何,当你使用地址这个概念的时候,最终都是要落到物理地址上去的。而物理地址就那么多,这是自然的,在这种意义下,
当一定要说到“虚拟存储”是多少的时候,这个问题很不好讲,因为这就涉及到什么是“虚拟存储”了。
软件比硬件强的一点就在于,软件的扩展性可以非常非常强,这是硬件所不能及的,也是我们使用软件的原因之所在。我们可以建立长长的软链表,树结构,我们可以把这样的数据结构存在内存乃至外存里,我们可以在内核中加入不断的存储切换机制,我们可以不断的把内存上的数据导入硬盘以及其他存储,也可以不断的把其他存储导入内存,我们可以利用软件不断的去修改CPU中的数据,而我们又不去计较它具体的可实施性的问题(比如效率)。
大家都还记得我们学习算法的时候会提到外排序吧,外排序的算法可以扩展到非常大的外存,假如我们暂时先不管它多久能够帮我们排出来的话。存储使用的算法甚至也可以扩展到类似的算法,于是切换中,我们就可以使用高的多的空间,于是,这样我们就仿佛可以用很多很多的独立存储。
虚拟内存也更应是一个软件概念,虽然考虑到别的因素,是需要有硬件支持的。
作者: accessory    时间: 2009-09-29 05:46
看了半天,我也引用下手册吧:
link:http://www.intel.com/Assets/PDF/manual/253665.pdf

PAGE 68, PAGE 71.

下面是2张图,一个是32BIT cpu的。一个是64BIT CPU的。 注意画红线的地方

[ 本帖最后由 accessory 于 2009-9-29 05:47 编辑 ]

intel1.gif (26.12 KB, 下载次数: 28)

intel1.gif

intel2.gif (23.86 KB, 下载次数: 16)

intel2.gif

作者: 好人家    时间: 2009-09-30 10:48
学习一下!虽然不知道说什么呢?
作者: drangon    时间: 2009-09-30 13:26
原帖由 rawa99999 于 2009-9-26 10:54 发表
我描述的可能不够严格,这只是一种解释,但是虚拟地址空间最终转化为控制虚拟内存,还有很多办法,比如soft MMU(软件内存管理单元),CPU提供了这种寻址的能力,就一定能控制这么大的虚拟内存,况且64T虚拟内存 ...


我觉得还是好好看看intel volume 3,system program guide里面的第三章,关于 logical address,linear address,physical address及其相互计算的流程,虚拟内存这个词太模糊了。

简单来说,程序中用的是logical address,通过段机制转换成linear address。

linear address只有4G(32位)!!!

logical address无论通过GDT、LDT的几千上万多种表达方式,但每种表达方式只能表达同一个linear address的4G(32位CPU)的一部分或全部。
这样对同一个线性地址的不同表达方式可以直接累加吗?

回到286年代,一共有64K个段,每个段有64K,(只不过每个段比前一个段偏移16字节而重叠),这样我们能说286能访问4G内存吗?实际上还是只有1M的寻址能力,EMS、XMS等不讨论。
作者: rawa99999    时间: 2009-10-09 08:10
呵呵,以楼上几位的意思,intel9000多个32位CPU的服务器也只能有4G内存了。
作者: rawa99999    时间: 2009-10-09 08:16
Ubuntu安装server的kernel,32位的系统可以使用4G以上的内存,最多能到64G。这还不是改写linux内核,针对大内存修改内核能支持更高的内存容量,这还不是虚拟内存管理,还仅仅是物理内存。
作者: saekil    时间: 2009-10-09 14:04
晕死,你们两还在PK啊
作者: qnxchina    时间: 2009-10-11 10:32
to rawa99999:
连手册都看不懂还来辩论??




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2