分享

APIC – 高级可编程中断控制器

 waston 2022-08-20 发布于上海


x86架构的中断类型以及实现方式上有很多种。从中断控制器模块上分,x86中有8259中断控制器、Local APIC 以及 I/O APIC ,另外在PCI/PCIE中的存在MSI中断。从类型上来分,有硬件中断和软件中断之分,有可屏蔽中断和不可屏蔽中断之分。这部分的分类,前者是按照中断源来分的,可以是软件主动触发(通过INT等指令),也可以是模块内部或者外部硬件触发的;后者主要根据针对中断是否要被处理(大部分中断都可以通过设置来配置成可屏蔽或不可屏蔽)。从实现上来分,有IDT(InterruptDescriptor Table)和IVT(Interrupt Vector Table)之分。这部分的分类主要是根据x86模式来分的,IVT主要用于实模式,而IDT主要用于保护模式及之后的模式。IVT一般放在系统地址从0x0开始的4K空间,且一个Vector到实现代码之间的连接是比较直接的,Vector指针直接指向代码段。而IDT表中的项还有一些转换才指向到代码,这也跟保护模式相适应。IVT或者IDT都可以通过IDTR寄存器来获取,而通过指令LIDT/SIDT可以读写IDTR寄存器。

1.x86 中断

目前为止 x86的中断控制器常用的为APIC(高级可编程中断控制器),而8259中断控制器随着Intel处理器的发展已经渐渐的被淘汰了,所以我们在这里也就不讨论了。

我们在说明中断控制器的时候,我们首先先来了解一下x86的中断处理过程,我们从CPU内部从里向外看,首先中断的处理的整体过程就是当发生了一个中断或者异常的时候,CPU去调用中断处理函数,而我们在进行中断初始化的时候,会提供中断向量表,正是由于这个表项的存在CPU才能依据表来查询那个中断对应那个中断服务函数,那么x86架构的CPU是如何获得这个中断服务函数的地址呢,是通过 IDT (中断描述符表) 。中断描述符表(IDT)为每一个异常或中断向量对应的例程或任务分配了一个门描述符。由于只有256个中断或异常向量,所以IDT的表项也就256个,每一个中断向量对应一个描述符。所以我们通过中断描述符IDT就可以得到我们的中断服务函数的地址,而IDT表的基地址则是存放在IDTR寄存器中的,通过 IDTR 寄存器找到 IDT 表,在通过 IDT表查到中断服务函数的入口地址,整个过程的整体如下图:

在这里插入图片描述
这样系统就通过 IDT 得到了中断服务函数的入口地址,但是IDT有256个表项,我们是如何知道哪一个发生的呢,我们将中断的处理过程在向外扩一层,CPU如何确定当前中断或者异常是256个表项的哪一个呢,是通过 vector ,通过中断消息来告知处理器当前的中断的信息,而APIC接收的中断消息来源有三个(先不说MSI):来自内部的本地中断;来自其他CPU或者自己发送的IPI消息;从 I/O APIC 获取的外部中断,具体的细分法如下:

本地中断:
APIC Timer 产生的中断(APIC timer generated interrupts);

温度监控产生的中断(Thermal Sensor interrupts);

APIC检测内部错误错误时而产生的中断(APIC internal error interrupts);

本地直连 IO 设备 (Locally connected I/O devices) 通过 LINT0 和 LINT1 引脚发来的中断;

指定性能计数器在溢出时产生的中断(Performance monitoring counter interrupts);

CPU的核间中断(IPI):
其他CPU或者自身,调用ICR寄存器发送的 IPI 消息;

外部中断:
通过I/O APIC传出的外部设备的中断(例如:键盘。鼠标产生的中断等);

其实我们可以将这三种类别的中断当做是三种不同的消息格式,其目的是为了告诉CPU我的等待被处理的中断信息(例如中断号是什么,中断的类型是什么,边沿触发的还是电平触发,上升沿触发还是下降沿触发等)。而以上三种不同的中断类型也对应了三种不同的消息格式(虽然说是三种类型的中断消息,当其实内容是大致一样的)。本地中断使用本地向量表(LVT)来产生消息,五个寄存器分别对应五种本地中断;CPU的核间中断使用的是ICR寄存器产生消息;外部中断通过 I/O APIC中的 IOREDTBL[0:23] 产生,当I/OAPIC某个管脚接收到中断信号后,会根据该管脚对应的RTE,格式化出一条中断消息,发送给某个CPU的LAPIC。每一种消息类型的格式如下图所示:

本地中断使用本地向量表(LVT)来产生消息
在这里插入图片描述
IPI使用ICR寄存器产生消息
在这里插入图片描述
外部中断通过 I/O APIC格式化一条类似LVT的消息在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们可以看出,这三种中断消息寄存器产生的消息,大体内容和格式相同(三者也有差异,例如 IPI 和
外部中断都可能涉及不同的LAPIC,所以需要在寄存器中指明LAPIC的地址。以及地址的解析方法,故
这两个种都为64位的寄存器)。

这样我们就了解了三种中断消息的类型和格式,也就是说,我们CPU在接收到的中断可能来自于自己本地,也可能来自于其他CPU,也可能是外设外部的中断,这些中断在发送到处理器后,Local APIC会通过中断消息中包含的中断向量(Vector,三种消息的第八位表示Vector)来判定中断的优先级,最后将优先级最高的那个中断消息送如CPU,接着CPU会经过如下的过程来判定是否接受这个中断:
在这里插入图片描述
当该中断被CPU接受了,就会进入前面所说的通过消息中包含的Vector 去IDT中断描述符来查询当前中断对应的中断服务函数的地址,然后就去处理。

这样x86整体的中断处理过程我们就分析完了,总结一下:通过中断消息来告知处理器有中断(这个消息来自于本地中断、IPI核间中断、I/O APIC的外部中断中的其中一种),然后在本地APIC中去对这个消息进行判定(中断优先级、是否是特殊的中断(NMI / SMI / INIT / ExINT)等),当确定好一个中断消息送入CPU后,就会通过这个消息获取这个中断的属性(例如:触发模式、中断向量、空闲模式等),通过获取的中断向量在IDT表中通过基址加偏移的方式去获得最终的中断服务函数的地址,之后去处理。

2.Local APIC

对于APIC来说,分为两个,一个为Local APIC,一个为I/O APIC,在 Intel Xeon 系列的处理器上,二者的关系如下图所示

在这里插入图片描述
其中Local APIC与 I/O APIC之间采用的是系统总线进行通信。

而对于 P6 家族的处理器来说,二者的关系则如下图所示:

在这里插入图片描述
其中Local APIC与 I/O APIC之间采用的是3线的APIC总线进行通信。

每个本地APIC都由一组APIC寄存器和相关联的硬件组成,这些硬件控制中断向处理器内核的传递以及IPI消息的生成。 APIC寄存器是存储器映射的,可以使用MOV指令进行读写。上面的处理器单元在多线程处理器中指的是逻辑处理器,每个逻辑处理器都有自己的Local APIC,每个Local APIC都对应一组寄存器。这组寄存器可以是映射到系统地址(MMIO方式)中,也可以是在MSR寄存器中,这取决于Local APIC的模式,目前一般有xAPIC和x2APIC两种模式,后者使用MSR寄存器。对于奔腾4以及Intel 至强处理器使用的是xAPIC体系,而P6系列的处理器则是使用的APIC体系,XAPIC体系的local APIC与 I/O APIC之间通过系统总线通信,而APIC体系则是通过APIC总线通信,我们可以认为XAPIC是APIC体系的扩展,而为了提高处理器的可寻址性还有X2APIC ,而X2APIC 又是对XAPIC的扩展 , x2APIC体系结构为xAPIC体系结构提供了向后兼容性,并为将来的英特尔平台创新提供了向前的可扩展性。
下面我们先说Local APIC,Local APIC可以从以下来源接收中断:

·本地连接的I / O设备 — 这些中断是由直接连接到处理器的本地中断引脚(LINT0和LINT1)的I / O设备声明的边沿或电平而产生的。 I / O设备也可以连接到8259型中断控制器,该控制器又通过本地中断引脚之一连接到处理器。

·外部连接的I / O设备 — 这些中断的产生是由连接到I / O APIC的中断输入引脚的I / O设备声明的边沿或电平。中断作为I / O中断消息从I / O APIC发送到系统中的一个或多个处理器。

·处理器间中断(IPI) — Intel 64或IA-32处理器可以使用IPI机制来中断系统总线上的另一个处理器或一组处理器。 IPI用于软件自中断,中断转发或抢先式调度。

·APIC计时器生成的中断 — 可以对本地APIC计时器进行编程,以在达到已编程的计数时将本地中断发送至与其关联的处理器。

·性能监视计数器中断 — 当性能监视计数器溢出时,P6家族,奔腾4和Intel Xeon处理器提供了向其关联的处理器发送中断的能力 )。

·热传感器中断 — 当内部热传感器跳闸时,奔腾4和Intel Xeon处理器提供了向自己发送中断的能力(请参见第14.7.2节“热监控器”)。

·APIC内部错误中断 — 当本地APIC中识别出错误情况(例如尝试访问未实现的寄存器)时,可以对APIC进行编程,以将中断发送到其关联的处理器。处理”)

在这7个中断当中,LINT0和LINT1的中断;APIC计时器生成的中断;性能监视计数器中断;热传感器中断;APIC内部错误中断这5个中断我们称为本地中断,在本地向量表中为每个本地中断源提供了一个单独的条目,该条目允许为每个中断源建立特定的中断传递协议。 例如,如果将LINT1引脚用作NMI引脚,则可以设置本地向量表中的LINT1条目,以将具有2号向量的中断(NMI中断)传递给处理器内核。
### 2.1 设置 Local APIC

从P6系统的处理器开始,我们可以使用 CPUD 指令来检测本地的APIC的存在与否 ,通过查阅《Intel软件开发手册 卷二 指令集参考》的CPUID指令可知,我们可以在EAX段寄存器中使用操作数 1h 执行CPUID指令,当我们在EAX设置为01H的情况下执行CPUID时,我们可以从EBX 和 EDX寄存器中获取一些关于Local APIC的消息

从EBX的高8字节获取的ID
在这里插入图片描述
从EDX的第九位获取 Local APIC 存在或不存在在这里插入图片描述

2.1.1 使能或禁止 Local APIC

《Intel软件开发手册》给出了两种方法来设计 Local APIC 。第一种为通过在IA32_APIC_BASE MSR寄存器中配置APIC全局启用/禁用标志来设置;第二种是使用伪中断向量(SVR)寄存器中的软件启用/禁用标志来配置APIC。

IA32_APIC_BASE MSR寄存器中配置
在这里插入图片描述
通过设置IA32_APIC_BASE MSR寄存器的第11位,我们可以使能或者禁止APIC。当IA32_APIC_BASE [11]为0时,该处理器在功能上等同于不带片上APIC的IA-32处理器。 APIC的CPUID功能标志也设置为0,并且当IA32_APIC_BASE [11]设置为0时,可能会丢失对APIC的先前初始化。

伪中断向量(SVR)寄存器中配置
在这里插入图片描述

通过设置伪中断向量(SVR)寄存器的第6位,我们可以使能或者禁止APIC。如果IA32_APIC_BASE [11]为1,则软件可以随时通过清除虚假中断向量寄存器中的APIC软件启用/禁用标志来临时禁用本地APIC,而当本地APIC处于软件禁用状态时,可以通过将APIC软件启用/禁用标志设置为1随时重新启用它。

2.1.2 重定位 Local APIC 寄存器基地址

奔腾4,英特尔至强和P6系列处理器通过修改IA32_APIC_BASE MSR的24位基址字段中的值,可以将APIC寄存器的起始地址从FEE00000H重定位到另一个物理地址。 提供APIC体系结构的扩展是为了帮助解决与现有系统的内存映射的冲突,并允许MP系统中的各个处理器将其APIC寄存器映射到物理内存中的不同位置。

2.2 Local APIC 寄存器

上一章提到的IA32_APIC_BASE MSR的24位基址字段中存放的值就是我们Local APIC 寄存器的基地址,Local APIC 的寄存器的宽度为为32位,64位或256位。 全部在128位边界上对齐。 应该使用128位对齐的32位加载或存储访问所有32位寄存器。 一些处理器可能支持某些APIC寄存器的加载和少于32位的存储。 但是这个只是针对于一些特殊模型架构的,不能保证在所有处理器上都能正常工作。该寄存器的这段地址上电默认值为0xFEE00000,如果我们不去修改该值,那么Local APIC寄存器就是从这个地址开始。
在这里插入图片描述
在这里插入图片描述
这些寄存器的位数存在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寄存器表示中断的触发方式。

2.2.1 Local APIC ID 寄存器

Local APIC ID 寄存器中存储的值为APIC的ID号,它是逻辑处理器在系统中的唯一标识,而在不同的APIC模式下, Local APIC ID 寄存器也略有不同.
在这里插入图片描述
xAPIC和x2APIC在表示Local APIC ID的位数上有差别。

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

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

2.2.2 Local APIC版本寄存器

在这里插入图片描述
该寄存器反映了当前 Local APIC的特性,比如说是那种模式的(注意:这里所说的模式并不是指xAPIC或者x2APIC,而是指该APIC是内部的还是外部的),还有支持多少个LVT。

版本本地APIC的版本号:
0XH 82489DX离散APIC。
10H-15H 集成APIC。
其他值保留。
最大LVT输入显示减去1的LVT条目数。对于奔腾4和Intel Xeon处理器(具有 6个LVT条目),
“最大LVT”字段中 返回的值为5;否则为5。 对 于P6系列处理器(具有5个LVT条
目),返回的值为4; 对于奔 腾处 理器(具有4个LVT条目),返回的值为3。对于
基于英特尔 微体系结构代码名称Nehalem(具有7 个LVT条目)及以后的处理
器,返回的值为6。
禁止EOI广播指示软件是否可以通过将杂散中断向量寄存器的第12位设置来禁止广播EOI消息。

2.2.3 局部向量表(LVT)

本地向量表(LVT)允许软件将本地的中断传递到处理器它由以下32位APIC寄存器,每一个本地中断对应一个寄存器
在这里插入图片描述
这五个LVT寄存器分别如下:

· 温度监控器寄存器(FEE0 0330H)-指定温度传感器产生中断时的中断传送。该LVT条目是特定于实现的,而不是体系结构的。如果实现,它将始终位于基地址FEE0 0330H。

· 性能计数器寄存器(FEE0 0340H)-指定性能计数器在溢出时产生中断时的中断传送。该LVT条目是特定于实现的,而不是体系结构的。如果实现,则不能保证它位于基地址FEE0 0340H。

· LINT0寄存器(FEE0 0350H)—指定在LINT0引脚上发出中断信号时的中断传递。

· LINT1寄存器(FEE0 0360H)—指定在LINT1引脚上发出中断信号时的中断传递。

· 错误寄存器(FEE0 0370H)-当APIC检测到内部错误时指定中断传递。

向量(0 ~ 7)中断向量号
模式(8 ~ 10)000(已修复)
提供向量字段中指定的中断。
010(SMI)
通过处理器的本地SMI信号路径向处理器内核提供SMI中断。使用此投放方式时,矢量字段应设置为00H以便将来兼容。
100(NMI)
向处理器提供NMI中断。矢量信息将被忽略。
101(初始)
向处理器内核发送INIT请求,这将导致处理器执行INIT。使用此传送模式时,矢量字段应设置为00H,以便将来兼容。 LVT CMCI寄存器,LVT热监控器寄存器或LVT性能计数器寄存器不支持。
110(保留)
任何LVT寄存器均不支持。
111(ExtINT)
使处理器响应该中断,就好像该中断源自外部连接(兼容8259A)的中断控制器一样。对应于ExtINT的特殊INTA总线 周期被路由到外部控制器。期望外部控制器提供矢量信息。 APIC体系结构仅支持系统中通常包含在兼容性桥中的一个ExtINT源。系统中只有一个处理器应具有配置为使用ExtINT交付模式的LVT条目。 LVT CMCI寄存器,LVT热监控器寄存器或LVT性能计数器寄存器不支持
传送状态(只读)(12)指示中断传递状态,如下所示:
0(空闲)
此中断源当前没有任何活动,或者该中断源的前一个中断已传送到处理器内核并被接受。
1(待发送)
指示来自此源的中断已传递到处理器内核,但尚未被接受(请参见第10.5.5节“本地中断接受”)。
中断输入引脚极性指定相应中断引脚的极性:(0)高电平有效或(1)低电平有效。
远程IRR标志(只读)对于固定模式,电平触发的中断; 当本地APIC接受服务中断时,将设置此标志;当从处理器接收到EOI命令时,将重置此标志。 对于边沿触发的中断和其他传送模式,此标志的含义未定义。
触发方式选择本地LINT0和LINT1引脚的触发模式:(0)边沿敏感和(1)电平敏感。 仅当传送模式为“固定”时才使用此标志。 当传送模式为NMI,SMI或INIT时,触发模式始终对边沿敏感。 当传送模式为ExtINT时,触发模式始终对电平敏感。 定时器和错误中断始终被视为边沿敏感。如果未将本地APIC与I / O APIC结合使用,并且选择了固定交付模式; Pentium 4,Intel Xeon和P6系列处理器将始终使用级别敏感的触发,而不管是否选择了边缘敏感的触发。软件应始终将LVT LINT1寄存器中的触发模式设置为0(对边沿敏感)。LINT1不支持电平敏感中断。
屏蔽位中断屏蔽:(0)允许接收中断,而(1)禁止接收中断。 当本地APIC处理性能监视计数器中断时,它会自动在LVT 性能计数器寄存器中设置掩码标志。 复位时该标志设置为1。 只能通过软件清除
定时器模式位18:17选择定时器模式:
(00b)使用倒计时值的单拍模式,
(01b)周期性模式重新加载倒计时值,
(10b)在IA32_TSC_DEADLINE MSR中使用绝对目标值的TSC截止模式,
(11b)被保留。

这5个寄存器会存在些许的差异,但是大体的信息都是一样的。

2.2.4 ICR寄存器

ICR全称Interrupt Command Register,它用于逻辑处理器之间的通信,使用的中断称为IPI(Inter Processor Interrupt)。
在这里插入图片描述
Local APIC 用于从软件发出处理器间中断(IPI),发出IPI主要需要Local APIC 寄存器组中的中断命令寄存器(ICR),ICR寄存器可用于以下功能:

·将中断发送到另一个处理器。

·允许处理器将其收到但未提供服务的中断转发给另一个处理器进行服务。

·指示处理器中断自身(执行自中断)。

·向其他处理器传递特殊IPI,例如启动IPI(SIPI)消息。

通过此功能生成的中断通过系统总线(用于Pentium 4和Intel Xeon处理器)或APIC总线(用于P6系列和Pentium处理器)传递到系统中的其他处理器。 处理器发送最低优先级IPI的这项功能是基于一些特殊情况下的,BIOS和操作系统软件应避免使用。

中断命令寄存器(ICR)是一个64位本地APIC寄存器,分为ICR_Low和ICR_High两部分,分别位于Base0x300(Low)和Base + 0x310(High),写入ICR_Low即可发送一个IPI,它允许处理器上运行的软件指定处理器间中断(IPI)并将其发送到系统中的其他处理器。 软件必须设置ICR来指示要发送的IPI消息的类型以及目标处理器。 (ICR的所有字段都是软件读写的,但传送状态字段是只读的。)写入ICR的低位双字的动作会导致IPI被发送。

Voctor : 正在发送的中断的向量号

Delivery Mode : 指定要发送的IPI的类型。该字段也称为IPI消息类型字段。

000 (Fixed)将向量字段中指定的中断传递给目标处理器。
001 (Lowest Priority)与Fixed模式相同,除了将中断传递给在目标字段中指定的一组处理器中以最低优先级执行的处理器。 处理器发送最低优先级IPI的能力是特定于模型的,BIOS和操作系统软件应避免这种能力。
010 (SMI)将SMI中断传递给目标处理器。 必须将向量字段编程为00H,以便将来兼容。
011 (Reserved)保留。
100 (NMI)将NMI中断传递给目标处理器,Voctor信息将被忽略。
101 (INIT)向一个或多个目标处理器交付INIT请求,让它们执行INIT。 作为此IPI消息的结果,所有目标处理器都执行INIT。 必须将向量字段编程为00H,以便将来兼容
101 (INIT Level De-assert)(Pentium 4和Intel Xeon处理器不支持。)向系统中的所有本地APIC发送同步消息,以将其仲裁ID(存储在其Arb ID寄存器中)设置为其APIC ID的值( 请参见第10.7节“系统和APIC总线仲裁”)。 对于此交付模式,必须将级别标志设置为0,将触发模式标志设置为1。无论目标字段或目标速记字段中的值如何,该IPI都将发送到所有处理器; 但是,软件应指定“包括自我在内的所有内容”的简写。
110 (Start-Up)将特殊的“启动” IPI(称为SIPI)发送到目标处理器。 该向量通常指向BIOS引导代码中的启动例程 如果源APIC无法传送以这种传送方式发送的IPI,则不会自动重试。 由软件决定是否成功交付SIPI,并在必要时重新发布SIPI。

Destination Mode : 选择物理(0)或逻辑(1)目标模式

Delivery Status : 指示IPI传递状态,如下所示:

​ 0(空闲)表示此本地APIC已完成发送所有以前的IPI。
​ 1(待发送)指示此本地APIC尚未完成发送最后一个IPI。

Level : 对于INIT级别取消声明传送模式,该标志必须设置为0;否则,该对于所有其他交付模式,必须将其设置为1。 (此标志在Pentium 4和Intel Xeon处理器中没有意义,并且始终以1.发出。)

Trigger Mode : 使用INIT级别取消断言传送模式时选择触发模式:边沿(0)或级别(1)。 对于所有其他交付模式,它将被忽略。 (此标志在Pentium 4和Intel Xeon处理器中没有意义,并且始终以0发出。)

Destination Shorthand : 指示是否使用速记符号来指定中断的目的地,以及如果是这样,则使用哪个速记。 目标速记用于代替8位目标字段,并且可以由软件通过一次写入ICR的低位双字来发送。 为以下情况定义了快捷方式:软件自中断,到系统中所有处理器(包括发送者)的IPI,到系统中所有处理器(不包括发送者)的IPI。

00: (No Shorthand)发出APIC是IPI的唯一目的地。 此目标速记允许软件中断正在其上执行的处理器。 APIC实现可以自由地在内部传递自中断消息,也可以将消息发布到总线并像其他任何IPI消息一样“监
10: (All Including Self)IPI被发送到系统中的所有处理器,包括发送IPI的处理器。APIC将广播一条IPI消息,其中Pentium和P6系列处理器的目标字段设置为FH,Pentium 4和Intel Xeon处理器的目标字段设置为FFH。
11: (All Excluding Self)除了处理器发送IPI之外,IPI被发送到系统中的所有处理器。APIC广播一条消息,其中Pentium和P6系列处理器的物理目标模式和目标字段设置为FH,对于Pentium 4和Intel Xeon处理器则设置为FFH。 结合最低优先级传递模式支持此目标速记是特定于型号的。 对于Pentium 4和Intel Xeon处理器,当将该速记与最低优先级交付模式一起使用时,IPI可能会重定向回发行方处理器.

Destination Field : 指定一个或多个目标处理器。 仅当目标速记字段设置为00B时,才使用此字段。 如果将目标模式设置为物理模式,则位56到59包含奔腾和P6系列处理器的目标处理器的APIC ID,位56到63包含奔腾4和Intel Xeon处理器的目标处理器的APIC ID。 如果将目标模式设置为逻辑模式,则对8位目标字段的解释取决于系统中所有进程中本地APIC的DFR和LDR寄存器的设置。

3. I/O APIC

在这里插入图片描述
I/O APIC负责接收来自外设的中断,例如键盘鼠标这中外部的中断,I/O APIC的寄存器没有在软件开发手册中说明,所以在此我们参考了82093 I/OAPIC的数据手册来说明I/OAPIC的寄存器和使用

3.1 I/O APIC寄存器

I/O APIC的寄存器分为两个类型的寄存器,第一种是用于访问 I/O APIC 寄存器的内存映射寄存器(Table 1所示),第二种是实际的 I/O APIC的寄存器(Table 2所示)
在这里插入图片描述
这两类的寄存器的用法为使用IOREGSEL寄存器中填入需要访问 Table 2 中的哪一个寄存器,之后在IOWIN寄存器对其进行访问,其读写特性由我们目标访问的寄存器决定

3.1.1 I/O APIC 寄存器的内存映射寄存器

我们可以查阅到在Linux中对于I/O APIC寄存器提供的读写方法
在这里插入图片描述

arch\x86\kenel\apic\io_apic.c
    
struct io_apic {
unsigned int index;
unsigned int unused[3];
unsigned int data;
unsigned int unused2[11];
unsigned int eoi;
};

unsigned int native_io_apic_read(unsigned int apic, unsigned int reg)
{
 	//获取I/O APIC寄存器的地址 将地址与上面的结构体io_apic绑定,就可以通过结构体来操作寄存器   
	struct io_apic __iomem *io_apic = io_apic_base(apic); 
	writel(reg, &io_apic->index);  //在IOREGSEL写入我们要读那个I/O APIC的寄存器
	return readl(&io_apic->data);  //在IOWIN读数据
}

static void io_apic_write(unsigned int apic, unsigned int reg,unsigned int value)
{
	struct io_apic __iomem *io_apic = io_apic_base(apic);
	writel(reg, &io_apic->index);  //在IOREGSEL写入我们要操作那个I/O APIC的寄存器
	writel(value, &io_apic->data); //在IOWIN写数据
}

在这段代码中,结构体 io_apic 实际上表示的就是IOREGSEL和IOWIN这组寄存器。其中index表示IOREGSEL,其偏移地址为00;data表示IOWIN,偏移为10,所以我们可以看到在下面两个读写函数中,首先完成的就是对于这个结构体首地址的绑定,该基地址的获取通过io_apic_base函数获取。而在后面的代码中,无论我们是读取还是写入都需先向 index 需要访问的I/O APIC的寄存器,然后才是具体的读写操作,结构体中的 unused 为填充,没有实际的意义。

3.1.2 IOAPICVER

在这里插入图片描述
IOAPIC版本寄存器标识APIC硬件版本。 软件可以使用它来提供不同的APIC实现及其版本之间的兼容
性。 此外,该寄存器提供了I / O重定向表中的最大条目数。

3.1.3 IOAPICARB

在这里插入图片描述

APICARB寄存器包含IOAPIC的总线仲裁优先级。 写入IOAPIC ID寄存器时,将加载该寄存器。 APIC使用单线仲裁来赢得总线所有权。 轮换优先级方案用于仲裁。 仲裁的胜者将成为最低优先级的代理,并假定仲裁ID为0。 除仲裁ID为15的代理外,所有其他代理将其仲裁ID递增1。 ID为15的代理获取获胜者的仲裁ID,并将其递增1。 仅对于成功传输的消息,更改(递增或假定)仲裁ID(除非是低优先级消息,即使消息未成功传输,仲裁ID也会更改)。 如果未报告该消息的校验和错误或接受错误,则消息发送成功。 在“级别触发具有断言的INIT”消息期间,APICARB寄存器始终装载有IOAPIC ID。

3.1.4 IOREDTBL寄存器组 [23:0]

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
APICARB注册器有24个I / O重定向表条目寄存器。每个寄存器是每个中断输入信号的专用条目。与8259A的IRQ引脚不同,中断优先级的概念与APIC上物理中断输入信号的位置完全无关。而是由软件确定每个相应中断输入信号的向量(并因此确定优先级)。对于每个中断信号,操作系统还可以指定信号极性(低有效或高有效),是否以边沿或电平形式通知中断,以及中断的目的地和传送模式。重定向表中的信息用于将相应的中断引脚信息转换为APIC间消息。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多