【x86架构】中断基础介绍

说明

本文讲的是Intel的x86架构下的中断。

参考的文档主要如下所示:

《64-ia-32-architectures-software-developer-manual.pdf》

《PCI Express体系结构导读》

《x86/x64体系探索及编程》

《82093AA I/O ADVANCED PROGRAMMABLE INTERRUPT CONTROLLER (IOAPIC).pdf》

《MultiProcess Specification.pdf》

《PCI.Local.Bus.Specification.Revision.3.0.pdf》

《PCI_Express_Base_Specification_Revision_3.0.pdf》

参考的代码主要来自EDKII源码(https://github.com/tianocore/edk2)。

因水平和篇幅有限,对中断的理解并非完全,如有错误,实属无奈......

分类

x86架构的中断类型和实现方式有很多种,这里做一个大致的分类。

从模块上来分,x86中有8259中断控制器Local APICI/O APIC,另外在PCI /PCIE中还存在MSI中断

对于这种分类,8259和APIC两者是旧和新的区分;Local APIC和I/O APIC是系统位置上的区分,前者属于CPU的一部分,后者属于Chipset的一部分(当然对于SoC来说区分就没有这么明显了);而MSI和前面这几个基本属于两个体系的东西,不过MSI的实现还是需要依赖于APIC,这个在后续会说明。

从类型上来分,有硬件中断和软件中断之分,有可屏蔽中断和不可屏蔽中断之分。

这部分的分类,前者是按照中断源来分的,可以是软件主动触发(通过INT等指令(存疑,这个不是很理解,比如int13h是用来表示读写硬盘的,但是参考文档中描述的是SIMD exception,根本是两回事儿,感觉两者并不是同一个东西...)),也可以是模块内部或者外部硬件触发的;

后者主要根据针对中断是否要被处理(大部分中断都可以通过设置来配置成可屏蔽或不可屏蔽)。

从实现上来分,有IDT(Interrupt Descriptor Table)和IVT(Interrupt Vector Table)之分。

这部分的分类主要是根据x86模式来分的,IVT主要用于实模式,而IDT主要用于保护模式及之后的模式。

IVT一般放在系统地址从0x0开始的4K空间,且一个Vector到实现代码之间的连接是比较直接的,Vector指针直接指向代码段。而IDT表中的项还有一些转换才指向到代码,这也跟保护模式相适应。

IVT或者IDT都可以通过IDTR寄存器来获取,而通过指令LIDT/SIDT可以读写IDTR寄存器,下面是IDTR到IDT的对应:

上图是在保护模式下,当在实模式下时对应的应该是IVT,IDTR中的Base Address在系统初始化的时候值为0,所以IVT才会放在0x0这个地址:

下面是IVT的基本配置:

上图也是在保护模式下的IDT表的说明,在保护模式下Intel将前面的32个中断作为自已保留使用的中断了。

因此从实模式转换到保护模式的时候,原本的中断也会向后移动(比如移动到0x20之后的位置)。

之后的介绍主要是按照模块来分。

8259中断控制器

8259控制器在系统中的布局大致如下:

实际的使用中,一般会使用两片8259芯片级联,一个主一个从。每一片有8个中断引脚,由于级联的关系,从片的INTR引脚会连到主片的一个中断引脚(IRQ2)中,所以实际的中断就是15个,分别是第一片上的IRQ0,IRQ1,IRQ3-IRQ7,和第二片的IRQ8-IRQ15。

这些中断引脚基本上的用法都固定,并且对应也都是一些比较老的设备。

8259控制器中对中断的响应优先级是有规定的,一般号越小优先级越高,不过IRQ8-IRQ15都是接在IRQ2上的,所以它们的优先级都当成2来看,所以优先级也比较高。

8259控制器(包括之后介绍的Local APIC)中,有几个比较重要的寄存器:

IRR:Interrupt Request Register,用来标志对应IRQ上发出了中断请求,它是一个8位的寄存器,刚好对应8个中断引脚,中断一次可以有多个,即可以有多个bit可以被置位;

ISR:Interrupt Service Register,用来记录IRQ的中断服务状态,它也是一个8位的寄存器,如果某个bit被置位,就表示中断请求正在被执行;

IMR:Interrupt Mask Register,用来屏蔽对应的中断请求,对应bit被置位表示屏蔽;

上述的寄存器并不能直接的读写。8259控制器在系统空间中使用I/O映射,对应的端口是20h,21h和A0h、A1h,分别对应主片和从片(这些值是硬件确定的软件配置的?)。

通过读写这些寄存器来访问和初始化控制器,写寄存器的值被称为ICW或者OCW,前者全称Initialization Command Word,用来初始化8259控制器,后者全称Operational Control Word,通过它就可以用来读写上述的寄存器以及其它的一些东西。

初始化

前面已经讲到了ICW,而8259控制器的初始化就是通过写ICW来实现的,大致的流程如下:

具体的初始化代码,在EDKII中可以参考8259.inf模块。

Interrupt8259SetVectorBase()函数就是一个初始化的过程。

这里需要注意的是寄存器的使用,写ICW1使用的是x0h这个端口,写ICW2-ICW4使用的是x1h这个端口。(x的值是2或者A)

此外,Interrupt8259WriteMask()函数设置了Mask和触发方式等。

对于触发方式还涉及到寄存器ELCR1和ELCR2,对应的I/O分别是4D0h和4D1h,两个寄存器都是8位的,共16位位对应到16个IRQ,0表示边沿触发1表示电平触发。

另外还安装了一个EFI_LEGACY_8259_PROTOCOL,通过它就可以获取对应的中断向量,并为此设置中断处理函数。下面是8254Timer.inf模块中的示例:

  //
  // Get the interrupt vector number corresponding to IRQ0 from the 8259 driver
  //
  TimerVector = 0;
  Status      = mLegacy8259->GetVector (mLegacy8259, Efi8259Irq0, (UINT8 *) &TimerVector);
  ASSERT_EFI_ERROR (Status);

  //
  // Install interrupt handler for 8254 Timer #0 (ISA IRQ0)
  //
  Status = mCpu->RegisterInterruptHandler (mCpu, TimerVector, TimerInterruptHandler);
  ASSERT_EFI_ERROR (Status);

上述代码为计时器提供了IRQ0处理函数,就是使IRQ0对应的中断向量指向了处理函数。

在中断发生后,经过一系列的处理,最终8259控制器向处理器发送一个中断向量,CPU在IDT表中找到这个向量对应的函数并执行。

需要说明的是,CPU检测中断,加载中断处理程序,从中断处理程序返回,这些动作都是硬件上的,软件并不参与,软件只需要设置中断向量,并配置中断处理函数,当然中断处理函数本身也是软件代码......

具体的CPU处理中断的过程可以参考http://www.cppblog.com/aaxron/archive/2011/11/16/160280.html

以上是一个简介,8259芯片的具体介绍可以参考https://pdos.csail.mit.edu/6.828/2010/readings/hardware/8259A.pdf

Local APIC

APIC的全称是Advanced Programmable Interrupt Controller,它算是8259控制器的升级版本。

引入它可以适应多处理器环境。

APIC包括了Local APIC和I/O APIC两部分内容,Local APIC是总的控制器,位于CPU内部;I/O APIC主要用于处理外部设备的中断。

下面是APIC在处理器中的逻辑框图:

上面的处理器单元在多线程处理器中指的是逻辑处理器,每个逻辑处理器都有自己的Local APIC,每个Local APIC都对应一组寄存器。这组寄存器可以是映射到系统地址(MMIO方式)中,也可以是在MSR寄存器中,这取决于Local APIC的模式,目前一般有xAPIC和x2APIC两种模式,后者使用MSR寄存器。

Local APIC寄存器介绍

下面首先了解这组寄存器:

上面的寄存器是以MMIO的形式展现。对于MSR形式的,是从0x802开始的一系列MSR,这里不再配图。

这些寄存器的位数存在32位、64位和256位几种情况。

其中256位的寄存器是以下的几个:

ISR:In-Service Register;

TMR:Trigger Mode Register;

IRR:Interrupt Request Register;

这些寄存器是跟中断个数对应的,系统中最多有256个中断,而上述寄存器中的每一个位都表示一个中断的状态。

当一个中断触发之后,对应的IRR位就被置位,不过此时中断并没有被CPU处理,只是在排队中,直到CPU要开始处理这个中断时,该位清零,而对应ISR位被设置,表示CPU开始处理这个中断了。当中断处理完成之后,会写EOI(End Of Interrupt)寄存器(也在上面的表中),这样Local APIC就会清零ISR对应的位。

TMR寄存器表示中断的触发方式。

另外还有几个需要详细介绍的寄存器:

Local APIC ID寄存器

Local APIC ID寄存器里面保存着APIC ID,它是逻辑处理器在系统中的唯一标识,这个APIC ID在多线程处理器下是很有用的。

Local APIC ID寄存器在xAPIC模式和x2APIC模式下略有不同:

xAPIC和x2APIC在表示Local APIC ID的位数上有差别。

另外,这些位还有一些细分,总共可以分为Cluster ID / Package ID / Core ID / SMT ID,这四层从高位到低位,而在系统中范围是从大到小的。Cluster是一组物理处理器,Package表示一个物理处理器,Core表示处理器中的一个核,SMT表示一个逻辑处理器。

这四层的架构其实包含了Intel多线程处理器中的两大个特性,即Hyper-Threading(又叫Simultaneous Multi-Threading,SMT)和Multi-Core。前者表示的是单个核里面里面有两个执行单元(线程),而后者表示一个处理器里面有多个核。所以提到Intel的处理器说4核8线程,就是应用了上述两者技术的结果,即一个处理器里面有4个核,每个核有两个线程。

参考《64-ia-32-architectures-software-developer-manual.pdf》中的说明会更清楚一些:

• Cluster — Some multi-threading environments consists of multiple clusters of multi-processor systems. The
CLUSTER_ID sub-field is usually supported by vendor firmware to distinguish different clusters. For non
clustered systems, CLUSTER_ID is usually 0 and system topology is reduced to three levels of hierarchy.
• Package — A multi-processor system consists of two or more sockets, each mates with a physical processor
package. The PACKAGE_ID sub-field distinguishes different physical packages within a cluster.
• Core — A physical processor package consists of one or more processor cores. The CORE_ID sub-field distin
guishes processor cores in a package. For a single-core processor, the width of this bit field is 0.
• SMT — A processor core provides one or more logical processors sharing execution resources. The SMT_ID
sub-field distinguishes logical processors in a core. The width of this bit field is non-zero if a processor core
provides more than one logical processors. 

下面是上述概念的对应的MP架构拓扑图:

包含两个Package的可以看成是一个Cluster。

至于为什么要有这个Cluster的概念,并不是很清楚......

Local  APIC版本寄存器

这是一个只读寄存器,它反映了Local APIC的特性,比如说是哪种模式的APIC(并不是xAPIC还是x2APIC,只有内部和外部APIC之分),比如支持对多多少个LVT(LVT后面会介绍)。

下面是它的具体信息:

LVT寄存器

Local APIC版本寄存器中确定了LVT的个数,目前的CPU一般支持7个LVT寄存器。LVT全称Local Vector Table,这些寄存器可以接收(主要是LINT0和LINT1)和产生本地中断源。

下面就是这些寄存器的图示:

需要说明的是LINT0和LINT1这两个寄存器,它们对应到Local APIC模块的INTR和NMI引脚,外部的中断会引发这两个寄存器的中断发起

对于具体位的说明如下:

1. Vector(bit0-bit7):就是中断号,通过它在IDT中寻找对应的中断描述符,进而找到中断处理函数;

2. Delivery Mode(bit8-bit10):交付模式,有以下可取的值:

    1)Fixed模式(000b),就是根据Vector找到中断处理函数并执行;

    2)SMI模式(010b),触发的是SMI中断,这个时候Vector的值需要是00h;

    3)NMI模式(100b),触发的是NMI中断,就不需要管Vector的值了;

    4)INIT模式(101b),处理器执行INIT(不清楚处理器具体做了什么);

    5)ExtINT模式(111b),表示中断源来自外部,比如8259控制器;

    其它都是reserved。

    典型的,可以将LINT0和LINT1配置成ExtINT和NMI交付模式。

3. Delivery Status(bit12),0表示当前没有中断交付或者中断已经交付给CPU处理,1表示中断已交付但是CPU还未处理;

4. Interrupt Input Pin Polarity(bit13),它只用于LINT0和LINT1,用于设置触发模式,0表示高电平触发1表示低电平触发;

5. Remote IRR Flag(bit14),它只用于LINT0和LINT1,使用在Fixed,电平触发模式中,1表示Local APIC接收并处理由INTR和NMI交付的中断,0表示接收到EOI命令;

6. Trigger Mode(bit15):它只用于LINT0和LINT1,0表示边沿触发,1表示电平触发;

7. Mask(bit16):1表示屏蔽中断响应;

8. Timer Mode(bit17-bit18):它只用于LVT Timer寄存器,用来设置Timer Count的计数模式。00b表示一次计数,01h表示循环计数,10表示指定TSC值计数;

LVT寄存器在上电和复位之后的值都是0x00010000。

CMCI寄存器、Thermal Monitor寄存器和Performance Monitor寄存器只能使用Fixed、SMI或NMI交付模式;

LINT0和LINT1寄存器只能使用Fixed、ExtINT或NMI交付模式;

ICR寄存器

ICR全称Interrupt Command Register,它用于逻辑处理器之间的通信,使用的中断称为IPI(Inter-Processor Interrupt)。

Local APIC初始化

Local APIC的初始化包括两个部分,一个上述寄存器的配置,一个是IDT表的配置。

在EDKII代码中,初始化在CpuDex.inf模块中:

  //
  // Setup IDT pointer, IDT and interrupt entry points
  //
  InitInterruptDescriptorTable ();

  //
  // Enable the local APIC for Virtual Wire Mode.
  //
  ProgramVirtualWireMode ();

ProgramVirtualWiredMode()函数主要配置了LINT0、LINT1和Spurious Interrupt Vector Register,最后一个寄存器是用来使能Local APIC的。 

这里的Virtual Wire Mode是多处理器系统的一种中断形式,Local APIC下的Virtual Wire Mode结构如下:

关于多处理器系统的介绍,可以参考http://download.intel.com/design/archives/processors/pro/docs/24201606.pdf

CpuDxe.inf并不会把所有的中断都配置好,这里更可以说是搭好了框架,后续不同模块根据其实现母的还会有中断配置和处理函数添加。

I/O APIC

前面已经讲过,APIC有两个部分,一个是Local APIC,一个是I/O APIC,前者位于CPU中,后者位于芯片组中,两者之间通过系统总线来通信。

相比8259控制器通过INTR引脚与处理器通信的方式,I/O APIC则直接通过它的MMIO来与CPU通信。

这通过“Local APIC初始化”那一章节中的Virtual Wire Mode配置图中就可看出来。

下面说明下通过MMIO访问的那些寄存器,它们分为两类,直接访问的寄存器和间接访问的寄存器。

直接访问的寄存器就是下面几个:

这里的xy的值需要另外确定,这个跟平台相关,一般就是00h。

间接方位寄存器有下面几个:

间接寄存器的访问需要通过直接寄存器来完成,可以看到直接寄存器两个分别是index和data,所以过程就是往index中写入需要读取的间接寄存器的偏移,然后通过data得到间接寄存器的值。下面是一个代码示例:

/**
  Read a 32-bit I/O APIC register.

  If Index is >= 0x100, then ASSERT().
  
  @param  Index  Specifies the I/O APIC register to read.

  @return  The 32-bit value read from the I/O APIC register specified by Index.
**/
UINT32
EFIAPI
IoApicRead (
  IN UINTN  Index
  )
{
  ASSERT (Index < 0x100);
  MmioWrite8 (PcdGet32 (PcdIoApicBaseAddress) + IOAPIC_INDEX_OFFSET, (UINT8)Index);
  return MmioRead32 (PcdGet32 (PcdIoApicBaseAddress) + IOAPIC_DATA_OFFSET);
}

间接寄存器跟Local APIC中的寄存器组形式类似。10-3Fh称为Redirection Table寄存器,跟Local APIC中的LVT类似。

RT寄存器一般有24个,每个占64位。

关于这些寄存器的说明,可以参考http://www.intel.com/design/chipsets/datashts/29056601.pdf

没有找到相关I/O APIC的初始化代码。不过有一个BaseIoApicLib.inf库有配置Redirection Table寄存器。

另外,对应有一个模块HpetTimerDxe.inf,里面有设置I/O APIC和添加中断处理函数的代码:

  //
  // Initialize I/O APIC entry for HPET Timer Interrupt
  // Fixed Delivery Mode, Level Triggered, Asserted Low
  //
  IoApicConfigureInterrupt (mTimerIrq, PcdGet8 (PcdHpetLocalApicVector), IO_APIC_DELIVERY_MODE_LOWEST_PRIORITY, TRUE, FALSE);

  // 中间代码省略  

  //
  // Install interrupt handler for selected HPET Timer
  //
  Status = mCpu->RegisterInterruptHandler (mCpu, PcdGet8 (PcdHpetLocalApicVector), TimerInterruptHandler);
  ASSERT_EFI_ERROR (Status);

MSI

MSI全称Message Signaled Interrupt,它是PCI/PCIE体系的一部分。

下面是引自《PCI Local Bus Specification》中的话,它也被《64-ia-32-architectures-software-developer-manual.pdf》所引用:

“Message signalled interrupts (MSI) is an optional feature that enables PCI devices to request
service by writing a system-specified message to a system-specified address (PCI DWORD memory
write transaction). The transaction address specifies the message destination while the transaction
data specifies the message. System software is expected to initialize the message destination and
message during device configuration, allocating one or more non-shared messages to each MSI
capable function.”

在PCI总线中,所有需要提交中断请求的设备,必须能够通过INTx引脚(这个引脚会连接到8259或者I/O APCI上)提交中断请求,而MSI机制是一种可选机制(说是可选,但是不确定在PCI上要怎么实现);

而在PCIE总线中,PCIE设备必须支持MSI或者MSI-X(MSI的升级版本)中断请求机制,而可以不支持INTx中断。目前一般的PCIE设备都使用MSI机制来提交中断。

MSI使用了MSI Capability结构来实现中断请求。PCIE设备在提交MSI请求时,总是想这种Capability结构中的Message Address的地址写Message Data,从而组成一个寄存器写TLP,向处理器提交中断请求。

MSI Capability的结构如下:

它有几种不同的类型,根据位数和是否带MASK来区分。

其中:

Capability ID:它的值是0x05,表示的是MSI的ID号;

Next Pointer:指向下一个Capability,这是PCIE配置结构的组成形式,这里可以不关注;

Message Control:状态和控制寄存器,具体位的意义如下:

Message Address/Message Upper Address:存放目的地址。

Message Data:用来存放MSI报文使用的数据。

关于Message Address/Data,在《64-ia-32-architectures-software-developer-manual.pdf》中有说明:

Mask Bits:一个PCIE设备使用MSI机制时,最多可以使用32个中断,对应到这里的32位,BIT置1时表示屏蔽中断。

Pending Bits:该部分只读,也是32位,对应到可用的32个中断。

Mask Bits和Pending Bits配合使用,当系统软件(中断为什么需要软件来触发,那硬件中断怎么办?)将Mask Bits的某一位从1改写为0,PCIE设备发送MSI报文想处理器提交中断请求,同事讲Pending Bits中对应的位清0(什么时候是1呢?)。

关于MSI的初始化,也可以参考HpetTimerDxe.inf这个模块,在这个模块中不仅可以使用I/O APIC,也可以使用MSI:

  if (FeaturePcdGet (PcdHpetMsiEnable) && MsiTimerIndex != HPET_INVALID_TIMER_INDEX) {
    //
    // Use MSI interrupt if supported
    //
    mTimerIndex  = MsiTimerIndex;

    //
    // Program MSI Address and MSI Data values in the selected HPET Timer
    //
    HpetTimerMsiRoute.Bits.Address = GetApicMsiAddress ();
    HpetTimerMsiRoute.Bits.Value   = (UINT32)GetApicMsiValue (PcdGet8 (PcdHpetLocalApicVector), LOCAL_APIC_DELIVERY_MODE_LOWEST_PRIORITY, FALSE, FALSE);
    HpetWrite (HPET_TIMER_MSI_ROUTE_OFFSET + mTimerIndex * HPET_TIMER_STRIDE, HpetTimerMsiRoute.Uint64);

    //
    // Read the HPET Timer Capabilities and Configuration register and initialize for MSI mode
    //   Clear LevelTriggeredInterrupt to use edge triggered interrupts when in MSI mode
    //
    mTimerConfiguration.Uint64 = HpetRead (HPET_TIMER_CONFIGURATION_OFFSET + mTimerIndex * HPET_TIMER_STRIDE);
    mTimerConfiguration.Bits.LevelTriggeredInterrupt = 0;
  }

需要注意的是,HPET并不是传统的PCI或者PCIE设备(并没有BDF号),不过它所在的系统空间中,会给每一个Timer留有一个类似MSI Capability的结构体,通过它可以设置MSI中断需要的参数。

补充说明

本文主要介绍的是中断,但是对于异常(Exception),x86平台下的处理机制也是一样的。

目录 第一篇 x86 基础 第1 章数与数据类型2 1.1 数 2 1.1.1 数字 2 1.1.2 二进制数 3 1.1.3 二进制数的排列 3 1.1.4 十六进制数 5 1.1.5 八进制数与十进制数 5 1.2 数据类型 6 1.2.1 integer 数 6 1.2.2 floating-point 数. 9 1.2.3 real number(实数)与NaN(not a number) . 11 1.2.4 unsupported 编码值 14 1.2.5 浮点数精度的转换 15 1.2.6 浮点数的溢出 17 1.2.7 BCD 码 20 1.2.8 SIMD 数据 21 第2 章 x86/x64 编程基础 23 2.1 选择编译器 23 2.2 机器语言 24 2.3 Hello world 25 2.3.1 使用寄存器传递参数 26 2.3.2 调用过程 27 2.3.3 定义变量 27 2.4 16 位编程、32 位编程,以及64 位编程 28 2.4.1 通用寄存器 28 2.4.2 操作数大小 30 2.4.2 64 位模式下的内存地址 30 2.4.4 内存寻址模式 31 2.4.5 内存寻址范围 34 2.4.6 使用的指令限制 34 2.5 编程基础 34 2.5.1 操作数寻址 35 2.5.2 传送数据指令 39 2.5.3 位操作指令 45 2.5.4 算术指令 47 2.5.5 CALL 与RET 指令 48 2.5.6 跳转指令 48 2.6 编辑与编译、运行 48 第 3 章编写本书的实验例子 50 3.1 实验的运行环境 50 3.2 生成空白的映像文件 52 3.2.1 使用nasm 编译器生成 52 3.2.2 使用bximage 工具 52 3.3 设置bochs 配置文件. 53 3.4 源代码的基本结构 54 3.5 编译源代码55 3.6 映像文件内的组织 55 3.7 使用merge 工具 56 3.7.1 merge 的配置文件 57 3.7.2 执行merge 命令 57 3.8 使用U 盘启动真实机器 58 3.8.1 使用merge 工具写U 盘 58 3.8.2 使用hex 编辑软件写U 盘 59 3.9 编写boot 代码 60 3.9.1 LBA 转换为CHS 62 3.9.2 测试是否支持int 13h 扩展功能 63 3.9.3 使用int 13h 扩展读磁盘 64 3.9.4 最后看看load_module() 64 3.10 总结 66 第4 章处理器的身份 67 4.1 测试是否支持CPUID 指令 67 4.2 CPUID 指令的术语及表达 68 4.3 基本信息与扩展信息 68 4.4 处理器的型号(family,model 与stepping) 72 4.5 最大的物理地址和线性地址 73 4.6 处理器扩展状态信息74 4.6.1 探测Processor Extended State 子叶 75 4.6.2 Processor Extended State 子叶所需内存size 76 4.6.3 Processor Extended State 的保存 77 4.6.4 Processor Extended State 的恢复 78 4.7 处理器的特性 78 4.8 处理器的Cache 与TLB 信息 80 4.9 MONITOR/MWAIT 信息 83 4.10 处理器的long mode 84 第 5 章了解 Flags 85 5.1 Eflags 中的状态标志位 86 5.1.1 signed 数的运算 86 5.1.2 unsigned 数的运算 89 5.2 IOPL 标志位 90 5.3 TF 标志与RF 标志 93 5.4 NT 标志 95 5.5 AC 标志 96 5.6 VM 标志 98 5.7 eflags 寄存器的其他事项 99 第 6 章处理器的控制寄存器 101 6.1 CR8 102 6.2 CR3 103 6.3 CR0 104 6.3.1 保护模式位PE 104 6.3.2 x87 FPU 单元的执行环境 104 6.3.3 CR0.PG 控制位 108 6.3.4 CR0.CD 与CR0.NW 控制位 108 6.3.5 CR0.WP 控制位 110 6.3.6 CR0.AM 控制位 110 6.4 CR4 110 6.4.1 CR4.TSD 与CR4.PCE 控制位 110 6.4.2 CR4.DE 与CR4.MCD 控制位 111 6.4.3 CR4.OSFXSR 控制位 111 6.4.4 CR4.VMXE 与CR4.SMXE 控制位 111 6.4.5 CR4.PCIDE 与CR4.SMEP 控制位 112 6.4.6 CR4.OSXSAVE 控制位 113 6.4.7 CR4 中关于页的控制位 113 6.5 EFER 扩展功能寄存器 114 第 7 章 MSR. 116 7.1 MSR 的使用 116 7.2 MTRR 117 7.2.1 Fixed-range 区域的映射 118 7.2.2 MTRR 的功能寄存器 120 7.3 MSR 中对特殊指令的支持 124 7.3.1 支持sysenter/sysexit 指令的MSR 125 7.3.2 支持syscall/sysret 指令的MSR 126 7.3.3 支持swapgs 指令的MSR 127 7.3.4 支持monitor/mwait 指令的MSR 128 7.4 提供processor feature 管理 129 7.5 其他未列出来的MSR 129 7.6 关于MSR 一些后续说明 129 第二篇 处理器的工作模式 第8 章实地址模式 132 8.1 真实的地址 132 8.2 real mode 的编址 132 8.3 real mode 的状态 133 8.4 段基址的计算 134 8.5 第1 条执行的指令 134 8.6 实模式下的执行环境 135 8.7 实模式下的IVT 135 8.8 突破64K 段限 136 8.9 A20 地址线 137 第 9 章 SMM系统管理模式探索 138 9.1 进入SMM 138 9.2 SMM 的运行环境 141 9.2.1 SMRAM 区域 141 9.2.2 SMM 执行环境的初始化 143 9.2.3 SMM 下的operand 与address 144 9.2.4 SMM 下的CS 与EIP 144 9.2.5 SMM 下的SS 与ESP 145 9.3 SMM 里的中断 145 9.4 SMI 的Back-to-Back 响应 147 9.5 SMM 里开启保护模式 147 9.6 SMM 的版本 148 9.7 I/O 指令的重启及Halt 重启 151 9.8 SMM 的退出 152 9.9 SMBASE 的重定位. 153 9.10 SMI 处理程序的初始化 154 9.11 SMM 的安全 156 9.11.1 芯片组的控制 156 9.11.2 处理器对SMRAM 空间的限制 158 9.11.3 cache 的限制 160 9.12 测试SMI 处理程序 161 第 10 章 x86/x64 保护模式体系(上) 163 10.1 x86/x64 的权限 164 10.2 保护模式下的环境 164 10.2.1 段式管理所使用的资源 165 10.2.2 paging 分页机制所使用的资源 165 10.3 物理地址的产生 166 10.4 段式管理机制 167 10.4.1 段式内存管理 168 10.4.2 段式的保护措施 168 10.5 段式管理的数据结构 169 10.5.1 Segment Selector(段选择子) 169 10.5.2 Descriptor Table(描述符表) 172 10.5.3 Segment Selector Register(段寄存器) 174 10.5.4 Segment Descriptor(段描述符) 175 10.5.5 LDT 描述符与LDT 258 10.6 开启保护模式 259 10.6.1 初始化GDT 260 10.6.2 初始化IDT. 262 10.6.3 切换到保护模式 263 第11 章 x86/x64 保护模式体系(下) 265 11.1 物理页面 265 11.1.1 处理器的最高物理地址(MAXPHYADDR) 266 11.1.2 物理页面的大小 267 11.1.3 页转换模式(Paging Mode) 268 11.2 paging 机制下使用的资源 270 11.2.1 寄存器 270 11.2.2 CPUID 查询leaf 270 11.2.3 寄存器的控制位 271 11.2.4 页转换表资源 272 11.3 32 位paging 模式(non-PAE 模式) 273 11.3.1 CR3 结构 274 11.3.2 32 位paging 模式下的PDE 结构 275 11.3.3 使用32 位paging 279 11.4 PAE paging 模式. 282 11.4.1 在Intel64 下的CR3 与PDPTE 寄存器 283 11.4.2 在AMD64 下的CR3 285 11.4.3 PAE paging 模式里的PDPTE 结构 286 11.4.4 PAE paging 模式里的PDE 结构 286 11.4.5 PAE paging 模式里的PTE 结构 288 11.4.6 使用和测试PAE paging 模式 288 11.4.7 使用和测试Execution Disable 功能 292 11.5 IA-32e pagi
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值