软件初始化代码为0xFFFFFFF0H

问题描述 投票:5回答:3

英特尔表示,复位后处理器处于实模式,软件初始化代码从0xFFFFFFF0H开始。我的问题:

  • 如果处理器处于实模式,它如何访问内存> 1MB(0xFFFFFFF0H)
  • 如何发生这种情况或当RAM <4GB(比如2GB)时会发生什么
  • 如果BIOS映射到0x000FFFFFH,为什么处理器开始在0xFFFFFFF0H执行

请帮我解决这些问题。谢谢。

operating-system x86 computer-architecture bios
3个回答
6
投票

我终于在Coreboot documentation找到了答案:

每当x86 CPU在复位后唤醒时,它都会在实模式下执行。此模式仅限于1MiB地址空间和64k偏移量,原始8086/88的复位向量位于0xFFFF0。

由于即使我们运行像P3这样的当前处理器也没有变化,这些较新的CPU也感觉它们在复位后从0xF000:0xFFF0开始。但他们没有。复位后代码段寄存器的基址为0xFFFF0000,因此CPU为芯片组生成物理地址0xFFFFFFF0。芯片组负责将此区域转发到引导ROM。令人困惑的是:CPU“认为”它运行代码为0xF000:0xFFF0,但它使用的代码为0xFFFFFFF0。当他们将这种设计实现为芯片时,开发人员必须陷入困境。

因此,英特尔文档似乎谈到了“在线上”使用的物理地址,即访问真实总线时。这与CPU模式无关(总线不知道或不关心CPU模式,转换这些东西是CPU的责任)。


3
投票

要查看您的问题,您需要一个硬件调试器。适当的文档来自英特尔,引用:http://download.intel.com/design/processor/manuals/253668.pdf,第9.1.4节:

在硬件复位后获取并执行的第一条指令位于物理地址FFFFFFF0H。该地址比处理器的最高物理地址低16个字节。包含软件初始化代码的EPROM必须位于此地址。

这意味着BIOS ROM,FYI,而不是您的正常RAM,即内容是硬连线的。请记住,在这个阶段,RAM内存甚至没有设置,VGA内存(与RAM不同)甚至不可用并初始化。

在实地址模式下,地址FFFFFFF0H超出处理器的1 MB可寻址范围。处理器初始化为该起始地址如下。 CS寄存器有两部分:可见段选择器部分和隐藏的基址部分。在实地址模式中,基址通常是通过将16位段选择器值向左移位4位以产生20位基址来形成的。但是,在硬件复位期间,CS寄存器中的段选择器加载F000H,基址加载FFFF0000H。因此,通过将基址添加到EIP寄存器中的值(即,FFFF0000 + FFF0H = FFFFFFF0H)来形成起始地址。在硬件复位后CS寄存器第一次加载新值时,处理器将遵循实地址模式下的地址转换的常规规则(即,[CS基地址= CS段选择器* 16])。为了确保CS寄存器中的基址在基于EPROM的软件初始化代码完成之前保持不变,代码不得包含远跳或远程调用或允许中断发生(这将导致CS选择器值被更改) )

在此期间,BIOS本质上是初始化硬件和内存本身,同时仍然以实模式执行。最后,VGA BIOS(存在于您的VGA卡中,可在0xc700处寻址)执行等等。但这超出了当前的问题。但上面引用的评论基本上回答了你的问题。


2
投票

如果处理器处于实模式,它如何访问内存> 1MB(0xFFFFFFF0H)

CPU内部几乎没有任何关心“CPU模式”。执行正常指令时;实际上重要的是默认代码大小,段基数,段限制,段类型等,并且CPU模式无关紧要。它只是段寄存器加载和中断处理程序之类的东西,其中CPU模式很重要(事实上,除了分页之外,如果关注CPU模式的唯一事情是在微代码中实现的话,我也不会感到惊讶)。

因为CPU模式与正常指令大多无关(因为默认代码大小,段基数,段限制,段类型等等是唯一真正重要的事情);在上电或复位CPU时,可以将“异常”值(CPU模式通常不可能的值)设置为段寄存器,其余的CPU不关心。特别;它可以做“CS.base_address = 0xFFFF0000”(这对于CS段寄存器加载会执行“CS.base_address = 16_bit_CS.value << 4”的实模式是不可能的)。

最终结果是所有涉及CS(并通过段限制检查)的内存访问最终都会转到(线性)地址“0xFFFF0000 + offset”,即使CPU处于“实模式”,即使这通常不可能实模式。

请注意,在实模式下,地址不限于1 MiB。例如,如果将0xFFFF加载到段寄存器中,则CPU会将该段寄存器的隐藏信息设置为“segment.base = 0x000FFFF0”,使用该段的地址将以0x000FFFF0到0x0010FFEF的(线性)地址结束。这就是为什么(当80286发布时)我们需要“A20门”以与古老软件兼容(在没有CPU知道的情况下强制第20个地址位为零)。

另请注意,虽然“CS.base_address = 0xFFFF0000”对于实模式不正常;软件可以切换到保护模式并将“代码大小= 16位,段限制64 KiB,段基= 0xFFFF000”描述符加载到CS中;然后切换回实模式而不重新加载CS。最终结果将是CPU在上电或复位时设置的“异常CS基础”。

当然(无论异常值如何进入CS.base)在实模式下执行的任何正常CS段寄存器加载都会导致“CS.base”被设置为正常值;所以固件必须确保在异常地址处以“实模式”执行时不会发生CS段寄存器加载。

如何发生这种情况或当RAM <4GB(比如2GB)时会发生什么

物理地址空间用于RAM,ROM和内存映射设备。 ROM(而不是RAM)将位于“4 GiB”地址的正下方。例如,如果ROM是2 MiB,那么它将处于从0xFFE00000到0xFFFFFFFF的物理地址范围内。请注意,在开机固件时无法使用RAM(必须确定安装的内存模块的类型和大小,并配置内存控制器以适应,然后才能使RAM​​工作)。

如果BIOS映射到0x000FFFFFH,为什么处理器开始在0xFFFFFFF0H执行

最初(80286和更旧的CPU)BIOS实际上映射为0x000FFFFF。对于(某些)80386及更高版本的CPU,仅出于兼容性原因进行模拟。代替;固件将一小部分自身从ROM(在物理地址0xFFFFFFFF结束的区域)复制到RAM(在物理地址0x000FFFFF结尾的区域);然后配置内存控制器,以便忽略对此RAM区域的写入(以便内存控制器不会将这些写入转发到RAM芯片)。

请注意,对于“纯UEFI”系统(不包括“混合BIOS + UEFI”系统),固件没有理由设置以物理地址0x000FFFFF结尾的“传统BIOS区域”;此区域中的RAM可以是可用的RAM(在存储器控制器中配置为“允许写入”等)。同样,“纯UEFI”也不需要其他传统区域(用于VGA和设备ROM);并且在理论上(对于具有2 GiB或更少RAM的计算机)没有理由(除了SMM窃取一点)你不能只有从0x00000000到0x7FFFFFFF的正常RAM的单个连续区域。

© www.soinside.com 2019 - 2024. All rights reserved.