中断虚拟化硬件基础

文章目录

  • GIC
    • 总体结构
    • 中断类型
    • 生命周期
    • 模拟GIC
  • IOAPIC
    • 总体结构
    • 原理简介
    • 模拟IOAPIC
  • LAPIC
    • 总体结构
    • 工作流程
    • 优先级
    • 寄存器
    • 模拟LAPIC

GIC

总体结构

  • 下图是GIC(Generic Interrupt Controller)总体结构图,它的位置介于外部设备与cpu核中间,它连接外部设备的中断引脚,将中断信号投递到cpu interface,GICv2是比较老的规范,它只能处理8个cpu,扩展性不好,不能用于大的系统,因此高级的ARM平台用的都是GICv3规范实现的芯片,从上图也能看到,GIC连接了8个cpu。因为都可以deliver中断给cpu,所以从这点上,可以把GIC想象成Intel的LAPIC。
    中断虚拟化硬件基础_第1张图片

中断类型

  • GICv2处理的中断有四类,这个在GICv2规范文档的1.4小节有介绍
  1. PPI(Private Peripheral Interrupt )外部中断,针对每个cpu都有一个输入,GIC的分发器不会对它进行分发
  2. SPI(Shared Peripheral Interrupt )外部中断,一个输入引脚可以通过GIC分发器分发到不同的CPU上
  3. SGI(Software-generated interrupt )软件产生中断,这是用户软件编程可以产生的中断
  4. Virtual interrupt 虚拟中断,可以在虚拟化场景下将中断发到VMM或者VM
  • 四种中断类型,我们只关注前三个,其中SGI和PPI的中断号在前32个,由于GICv2结构简单,SGI和PPI直连到每个CPU上,看上面的结构图,每个PPI和SGI都对应一个CPU,因此这种情况可以认为,中断号就是CPU的向量号,但在更高级的中断控制器(Intel IOAPIC/LAPIC),向量号是操作系统的概念,中断号已经没有实际的硬件意义。这一点必须明确。简单说,ARM GICv2的规范中,前32个中断号是不需要路由的,它直接就对应了每个CPU。
  • 除了SGI和PPI,还有一个SPI,这类外部中断占据了中断号的大部分,32-1019,这类中断因为硬件上不针对任何特定CPU,就是这类中断哪个CPU都可以去,因此在中断deliver时它需要GIC的Distributor路由一下,让Distributor告诉它,应该去哪个CPU,而Distributor是基于它维护的路由表来决定分发到哪个CPU,路由表又是可以编程配置的,所以这种方式比较灵活,并且可以让各个均匀的分摊中断的处理,达到负载均衡。由于只有SPI需要中断路由,因此KVM中维护的路由表只针对SPI,这个在路由表的建立中会提到。

生命周期

  • 首先弄清楚GIC规范中描述的中断生命周期,这里选取GICv3规范来讲解。生命周期在GICv3规范文档的4.1小节有介绍,其生命周周期如下
    中断虚拟化硬件基础_第2张图片
  1. Generate interrupt. An interrupt is generated either by the peripheral or by software.
    中断发起,外设或软件可以触发中断
  2. Distribute. The IRI performs interrupt grouping, interrupt prioritization, and controls the forwarding of interrupts to the CPU interfaces.
    分发,中断到了GIC之后,GIC中的IRI(Interrupt Routing Infrastructure)组件判断优先级,路由中断信号到目标CPU,GICv3规范中由于新增了一种中断(LPI,一种基于message实现的中断)和一个组件ITS(Interrupt translation service,用于将Message-based interrupt翻译成LPI),Distributor和ITS一起,被称为了IRI模块
  3. Deliver. A physical CPU interface delivers interrupts to the corresponding PE.
    投递,中断信号从GIC的CPU interface投递到CPU
  4. Activate. When software running on a PE acknowledges an interrupt, the GIC sets the highest active priority
    to that of the activated interrupt, and for SPIs, SGIs, and PPIs the interrupt becomes active.
    处理,当CPU响应投递的中断后,GIC会将该中断设置成active,表示中断正在被处理
  5. Priority drop. Software running on the PE signals to the GIC that the highest priority interrupt has been
    handled to the point where the priority can be dropped to the priority that the interrupt had before being
    handled. This is the point where the end of interrupt is indicated by the interrupt handler. The end of the
    interrupt can be configured to also perform deactivation of the interrupt.
    完成,当CPU处理完中断之后,向GIC发送信号通知中断结束(EOI)
  6. Deactivation. Deactivation clears the active state of the interrupt, and thereby allows the interrupt, when it is
    pending, to be taken again. Deactivation is not required for LPIs. Deactivation can be configured to occur at
    the same time as the priority drop, or it can be configured to occur later as the result of an explicit interrupt
    deactivation operation. This latter approach allows for software architectures where there is an advantage to
    separating interrupt handling into initial handling and scheduled handling.
    Deactivation的操作用户可显示配置,也可以默认配置,默认配置是当CPU发送EOI之后,GIC设置Priority drop的同时也设置Deactivation状态,显示配置允许用户将Deactivation操作放在Priority drop之后
  • 中断的生命周期暗含了中断的状态,下面是GICv2对中断状态的解释,1.4.1小节
  1. Inactive
    An interrupt that is not active or pending.
  2. Pending
    An interrupt from a source to the GIC that is recognized as asserted in hardware, or generated by software, and is waiting to be serviced by a target processor.
  3. Active
    An interrupt from a source to the GIC that has been acknowledged by a processor, and is being serviced but has not completed.
  4. Active and pending
    A processor is servicing the interrupt and the GIC has a pending interrupt from the same source.
  • GICv3中详细画出了针对SPI/PPI/SGI的中断状态处理状态机图,同时给了解释,比较明白。
    中断虚拟化硬件基础_第3张图片
    中断虚拟化硬件基础_第4张图片

模拟GIC

中断虚拟化硬件基础_第5张图片

IOAPIC

总体结构

  • IOAPIC属于外设,不在CPU核内,接收来自ISA设备或者其它pci设备的中断信号,通过它和LAPIC模块之间专用的APIC bus将中断信息传递给LAPIC。
    中断虚拟化硬件基础_第6张图片

原理简介

  • IOAPIC有24个中断信号输入引脚,因此可以处理24个中断信号并将其重定向到目标CPU,对每个引脚的输入信号,IOAPIC都有一个重定向的寄存器与之对应,这个寄存器是可写的,软件可编程,重定向寄存器决定了其对应引脚的中断可以发到哪个CPU。24个重定向寄存器组成的就是所为的IOAPIC重定向表。格式如下
    在这里插入图片描述

模拟IOAPIC

中断虚拟化硬件基础_第7张图片

LAPIC

总体结构

  • LAPIC位于CPU核心,不属于外设,它接收IOAPIC经Host桥发送来的中断信息,对其进行处理。物理位置如下,截图自Intel手册vol3-10.1
    中断虚拟化硬件基础_第8张图片

工作流程

  • IOAPIC发送的中断消息包含两个关键信息:中断要发到哪个CPU(APIC ID),中断向量是多少(VECTOR)。两个信息在IOAPIC中断重定向表项中可以设置,其低8位[0-7]存放中断向量(0-255),[56-63]存放APIC ID(0-255),截图自820933AA IOAPIC datasheet第3章
    在这里插入图片描述
    中断虚拟化硬件基础_第9张图片
  • LAPIC接收中断信息后的处理流程如下,截图自Intel手册vol3-10.8.1
    中断虚拟化硬件基础_第10张图片
  1. 解析中断信息中的APIC ID字段,和本身的ID(Local APIC ID Register)比较,确认自己关联的CPU是否为中断的目的CPU
  2. 如果确认中断目的地是本CPU,解析该中断信息的类型,NMI,SMI,INIT,ExtINT,SIPI这5类中断不需要经APIC处理,直接deliver到CPU
  3. 如果确认中断目的地是本CPU,中断类型不是以上5类,是固定向量的中断,取出其Vector的值,将其在IRR(Interrupt Request Register)上对应的bit设置为1,请求CPU进行处理。IRR共256bit(32字节),每1位对应一个中断向量。IRR中包含的是LAPIC已接受,但还没有被CPU处理的中断
  4. LAPIC检查当前IRR寄存器中优先级最高的中断,如果该中断对应的ISR为0,表示处理器空闲,该向量的上一次中断已经被CPU处理,LAPIC将IRR对应bit清0,ISR对应bit置1。CPU检查到ISR置1后就处理该中断(CPU只认ISR)
  5. CPU执行中断处理例程(Interrupt Service Routine)完成后,会写EOI(end-of-interrupt)Register标记当前中断处理已,LAPIC检查到EOI标记后将ISR对应bit清0,此时IRR和ISR都为0,LAPIC再接收到IOAPIC发来的中断,重复之前的步骤,设置IRR,清0 IRR并设置ISR,清0 ISR

优先级

  • 中断向量被写入IRR后,LAPIC还会对中断优先级进行判断,当中断优先级满足条件时,LAPIC才将其写入ISR并调度CPU进行中断处理。中断向量号是判断中断优先级的基础,Intel将中断向量的优先级分级,分别是1-15,向量号的高4位[7:4]表示中断处于哪一级,每一级有16个中断向量,向量的级数越高优先级越高,同级内向量号越大优先级越高。
  • TPR(Task-Priority Register),控制当前CPU需要处理的中断向量的阈值,当向量的优先级小于该TPR指定的优先级,当前CPU不会对中断进行处理。
  • PPR(Processor-Priority Register),指示当前CPU正在处理的中断向量的优先级,被LAPIC用来比较新接收的中断向量和CPU正在处理的中断向量的优先级,当新接收的中断向量优先级高于当前正在处理的中断向量优先级,LAPIC会立即调度CPU执行中断处理程序,可以实现中断的嵌套调用
  • 假设操作系统设置CPU 0 的TPR寄存器的值为51,下面是CPU 0的LAPIC处理中断的分析
    中断虚拟化硬件基础_第11张图片
  1. IOAPIC发送25号中断到CPU 0,LAPIC接收中断信息后首先判断自己是否是中断的目的CPU,确认本CPU是中断信号的目的CPU后,检查中断类型是固定向量号的中断,将其发到IRR中
  2. 检查当前CPU的PPR,由于没有正在处理的中断,PPR就是用户设置的TPR,对比IRR中存储的中断向量优先级,PPR指示CPU处理优先级的阈值是3级,中断向量优先级属于2级,因此LAPIC判断中断向量优先级低于处理器能够处理的中断的阈值,25号中断向量不会被处理
  3. IOAPIC发送129号中断到CPU 0,LAPIC检查PPR阈值为3级,中断向量优先级为8级,高于PPR,129号中断会被处理,LAPIC将129号向量在ISR中对应位置1,ISRV表示在ISR中优先级最高的向量,即当前正被CPU处理的最高优先级的中断向量,此时ISRV为129。PPR为128,PPR的取值来自ISRV或TPR,计算方法可以查看Intel手册vol3-10.8.3.1
  4. 在129号向量被CPU处理过程中,IOAPIC发来了156号向量,LAPIC处理后写入IRR,比较中断向量和PPR的优先级,新来中断比正在处理的中断优先级要高,需要优先被处理,CPU放下当前正在处理的中断,跳转到新中断(156)对应的处理例程执行中断处理,完成之后,CPU再回去执行(129)之前没有处理完的中断例程

寄存器

  • LAPIC处理中断的过程中涉及到具体的寄存器,下面一一介绍
  1. LAPIC接收到中断信息后,首先取出其目的字段的APIC ID,将其于LAPIC 中Local APIC ID Regsiter中记录的ID值比较,如果相同,表示中断信号的目的是本CPU,下面是Local APIC ID Regsiter的格式介绍,不同的CPU型号其格式不同,P6和Pentium处理器APIC ID占4bit,最多表示16个CPU,因此P6能支持的最大CPU个数也就16个,Xeon服务器CPU的APIC ID占8bit,最多表示256个CPU,因此Xeon最大能支持256个CPU
    中断虚拟化硬件基础_第12张图片
  2. LAPIC接收中断信号后,将其放入IRR中请求CPU处理,LAPIC判断中断向量的优先级达到条件并且ISR对应位为0,没有正在被CPU处理的该向量的中断,将ISR置1,并清0 IRR,CPU开始处理该中断,每个中断可以有边沿触发和水平触发两种方式,TMR用来指示当前申请的中断是哪种触发方式。下图就是这三个寄存器,每个寄存器的宽度都是256bit,可以表示256个中断向量
    中断虚拟化硬件基础_第13张图片
  3. CPU中断服务例程执行完后,向EOI寄存器中写入值表示中断处理完成,可以继续处理下一个中断,这里有一个EOI寄存器,其长度4字节32bit
  4. LAPIC在设置ISR前,先读取PPR的值,将其优先级和中断向量的优先级比较,当中断向量优先级高于PPR优先级,设置ISR,设置ISR之后,LAPIC会更新PPR,它的值来源有两个,一个是ISRV(ISR寄存器中中断优先级最高的向量),一个是TPR(用户软件设置的CPU处理的中断阈值),PPR的高4位去ISRV和TPR中的大值,低4位为0或取自TPR的低4位。算法和涉及的寄存器如下
    中断虚拟化硬件基础_第14张图片
    中断虚拟化硬件基础_第15张图片
    中断虚拟化硬件基础_第16张图片

模拟LAPIC

  • Intel平台每个cpu都包含一个lapic,KVM按照相同的情况进行模拟,其数据结构如下
    中断虚拟化硬件基础_第17张图片
    从上面看出,一个通用cpu是所有平台cpu实现的共性抽象,各平台的cpu具体实现由arch成员指向,x86平台上,cpu上包含各种寄存器,也包括lapic模块,lapic的regs成员存放lapic的所有寄存器的值

你可能感兴趣的:(中断虚拟化)