IA64 Linux 外部中断处理机制(转)

本文详细解析了Intel IA64架构下Linux系统的SAPIC(Streamlined Advanced Programmable Interrupt Controller)中断处理机制。重点介绍了SAPIC的特点及其在IA64 Linux 2.4.21内核中的实现,包括中断架构、中断处理流程和技术细节。

IA64 Linux 外部中断处理机制

developerWorks
文档选项
将打印机的版面设置成横向打印模式

打印本页

将此页作为电子邮件发送

将此页作为电子邮件发送


本文分析和介绍了 Intel IA64 体系结构中新型的中断处理方式 ―― SAPIC(Streamlined Advanced Programmable Interrupt Controller),通过分析 IA64 Linux 2.4.21 内核的外部中断处理过程,着重讨论了 IA64 Linux 对 SAPIC 的支持,为 IA64 Linux 系统开发人员实现 SAPIC 的中断处理提供技术参考。

一、IA64 中断处理架构


Intel 公司的 IA64 体系结构采用了一种全新的中断处理架构 SAPIC(Streamlined Advanced Programmable Interrupt Controller),它与传统的 8259 和 APIC(Advanced Programmable Interrupt Controller)中断架构不同,具有良好的可扩展性和高效的中断处理性能。与传统的 8259 相比,SAPIC 架构将基于引腿的中断机制转变为基于消息的中断机制。采用基于引腿的方式,当需要增加中断源时,就必须增加引腿数目,中断架构的可扩展性较差;而采用基于消息的中断机制,总线上中断源的数目是没有限制的。SAPIC 用系统总线中断发送机制比 APIC 用专用串行总线的实现更高效,中断处理能力可以随着处理器系统总线的速度扩展,外部 I/O 中断通过 I/O 总线发送,并可快速发送到系统总线上。此外,SAPIC 在运行中断服务程序时可一次性处理同一优先级中的所有等待中断,减少了现场切换次数,提高了系统性能。

SAPIC 通常是指整个中断架构,具体实现时将它分为两部分:本地 CPU 部分和 IO 部分,前者简称为 LSAPIC,后者简称为 IOSAPIC。如图所示。

图1典型 Intel 安腾多处理器平台中断架构





回页首


CPU 内部中断


IA64 中断架构由一个 8 位的中断向量构成,用于标识中断源,每个 CPU 最多可以支持 256 种不同的中断源。前 16 个向量(0-15)是预留的,有特殊用途,如:非屏蔽中断的中断向量号为 2,野中断的中断向量号为 15。剩下的 240 个向量没有固定的含义,操作系统可以根据自己的需要定义和使用,中断向量的优先级是由中断向量号决定的,中断向量号越大中断优先级越高,如 IA64 Linux 中时钟中断的中断向量号为 0xef(include/asm-ia64/hw_irq.h 中定义的)。

IA64 中断架构中,除了基于优先级的特点外,还可以通过屏蔽处理器状态寄存器 psr.i 位和控制寄存器 tpr(任务优先级寄存器)进行控制。如 psr.i 清 0,则将屏蔽所有的外部中断(包括非屏蔽中断)。tpr 可以提供细粒度的中断屏蔽,该寄存器的格式如图所示。

图2控制寄存器 tpr 的布局

如果 mmi 置 1,则屏蔽除非屏蔽中断外的所有外部中断,如果 mmi 置 0,则 mic 域控制中断向量的屏蔽。256 个中断被分成 16 组,每组 16 个向量,向量 16-31 为第 1 组,32-47 为第 2 组,依次类推。向 mic 域写值n,则屏蔽从 1 到 n 组的所有中断,第 0 组(向量 0-15)不受 mic 值的影响。因此,如果 mic 置 0,则允许所有的外部中断;如 mic 置 15,则屏蔽除非屏蔽中断外的所有外部中断。

每个 IA64 CPU 自身有三个外部中断源:定时器、可修复故障检测和性能监控中断。此外,还提供外部设备直接连接 CPU 的中断引腿 LINT0 和 LINT1,但一般不使用。CPU 内部的每个中断源都有自己的控制寄存器用于存储 8 位中断向量,当定时器中断发生时,itv 寄存器存储定时器中断向量号,当发生一个可修复故障时,cmcv 寄存器存储可修复故障中断向量号,当发生性能监控中断时,pmv 寄存器存储性能监控中断向量号。





回页首


平台中断


I/O 设备通常采用两种方式触发中断:电平或边缘触发方式,在现代计算机中大多采用电平方式,它具有多个 I/O 设备共享中断和能降低信号干扰等优势。所有外部的 I/O 引腿中断都需要通过 IOSAPIC 进行路由,IOSAPIC 负责将设备的中断请求转化为中断事务,通过其内部的 I/O RTE 表将一个输入中断信号转化为一个中断请求消息,然后该消息以一个内存写事务通过 I/O 总线。

系统桥控制器的中断发送实现是可选的。如果桥控制器中没有实现 XTP 寄存器,它将中断事务没有修改地发送到系统总线上,桥控制器不检查中断事务。如果实现了 XTP 寄存器,则系统总线桥控制器接收到中断事务时,它首先检测重定向提示信息位是否设置,然后将该中断事务发送到系统总线中最低优先级的处理器。桥控制器用芯片组中的 XTP 寄存器确定中断发送到哪个处理器,系统总线上的每个处理器都会对应一个 XTP 寄存器,用于反映最低优先级处理器,这些寄存器放置在平台中断发送的路径上,并用于将一个中断事务重定向到一个最低优先级的处理器。

在系统总线上,一个中断事务如同一个正常的读或写事务,除了发送的数据编码为中断向量号而不是内存地址。在多处理机系统中,由于多个 CPU 连接到系统总线,因此向某个 CPU 发送中断时需要在中断事务中标识该 CPU,中断事务中的 ID 和 EID 域可以唯一标识平台中的任意一个 CPU。在系统启动时,firmware 为每个 CPU 分配一个唯一的本地 ID,并将该 ID 写入一个特殊的 CPU 控制寄存器 lid,在进行中断事务处理时,目标 CPU 的 lid 与中断向量号一起进行编码。





回页首


处理器间中断


在多处理器系统中,操作系统需要在多个处理器间协调操作,这通常是通过机间中断(IPI)实现的。IA64 的 IPI 机制是以 LSAPIC 的处理器中断块形式实现的,该中断块在物理内存地址空间中占据 2MB,缺省情况下,它的基址为 0xfee00000,该中断块主要具有两个功能:(1)将中断消息发送到系统中的其它处理器,(2)可以设置本地 CPU 的 XTP 值。

与普通的设备中断一样,IPI 采用基于事务的中断方式。如果一个处理器向另一个处理器发送中断,则查询目标处理器的本地 ID,将该值与需要发送的中断向量号结合写入到处理器的中断块中。LSAPIC 在系统总线上产生一个中断消息,目标处理器以通常的方式处理到来的机间中断。

一个处理器可以发送 IPI 到任意一个处理器,包括它自己,这对延迟一个中断处理是非常有用的。如果操作系统在不合适时机接收到一个中断,则操作系统只简单记录发生的中断向量,继续其它处理。当操作系统可以处理该中断时,则通过 IPI 向自己发送先前被忽略的中断向量实现中断的接力。

不明确区分 IPI 与设备中断是非常有用的,例如,当一个处理器接收到一个中断时,如果发现另一个处理器处理该中断更加合理,则可以通过 IPI 机制将该中断传递到其它的处理器,可以实现处理器的负载平衡。





回页首


二、IA64 Linux 外部中断处理流程


图3 IA64 Linux 中断处理流程

IA64 Linux 的中断处理从 arch/ia64/kernel/ivt.S 开始。该文件定义了 CPU 使用的中断向量表,并不是一个中断向量表表项对应一个中断,可能有多个中断共用一个中断向量表表项。该文件共定义了 68 个表项,其中前 20 个表项中每个表项可以包含 64 条指令束(由于 IA64 采用 EPIC 架构,每条指令束可以同时有 3 条指令),因此可以将较短的中断处理函数嵌入在该表项中,这对需要快速中断处理是十分有效的,如与 TLB 失效相关的中断处理函数就嵌入在中断向量表中。后 48 个表项中每个表项只包含 16 条指令束,因此一般不能满足中断处理函数嵌入的需求,通常采用跳转函数。外部中断处理在中断向量表中位于 0x3000,是第 12 个表项,具体内容如下,

// 0x3000 Entry 12 (size 64 bundles) External Interrupt (4)
ENTRY(interrupt)
 DBG_FAULT(12)
 mov r31=pr  // prepare to save predicates
 ;;
 SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3
 ssm psr.ic | PSR_DEFAULT_BITS
 ;;
 adds r3=8,r2  // set up second base pointer for SAVE_REST
 srlz.i   // ensure everybody knows psr.ic is back on
 ;;
 SAVE_REST
 ;;
 alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group
 mov out0=cr.ivr  // pass cr.ivr as first arg
 add out1=16,sp  // pass pointer to pt_regs as second arg
 ;;
 srlz.d   // make  sure we see the effect of cr.ivr
 movl r14=ia64_leave_kernel
 ;;
 mov rp=r14
 br.call.sptk.many b6=ia64_handle_irq
END(interrupt)
                

从中断控制寄存器 ivr 中读取中断向量号,然后调用外部中断处理函数 ia64_handle_irq(),跳转到 C 函数写的处理程序中。该函数在 arch/ia64/kernel/irq_ia64.c 中定义,主要过程如下,

saved_tpr = ia64_get_tpr();
ia64_srlz_d();
while (vector != IA64_SPURIOUS_INT_VECTOR) {
  if (!IS_RESCHEDULE(vector)) {
   ia64_set_tpr(vector);
   ia64_srlz_d();
   do_IRQ(local_vector_to_irq(vector), regs);
   /*
    * Disable interrupts and send EOI:
    */
   local_irq_disable();
   ia64_set_tpr(saved_tpr);
  } else {
   kstat.irqs[smp_processor_id()][IA64_IPI_RESCHEDULE]++;
  }
  ia64_eoi();
  vector = ia64_get_ivr();
 }
 if (local_softirq_pending())
  do_softirq();
                

它利用 local_vector_to_irq() 将中断向量号映射到相应的 irq 号,并调用 do_IRQ 函数激活相应的设备中断处理函数(该设备中断处理函数在系统初始化时已注册到 irq 描述符的动作列表中)。当处理完该中断,内核须通过写 eoi 寄存器通知 CPU 当前中断已完成。中断处理函数重新读取 ivr,判断是否还有未处理的中断,如果没有,ivr 返回 15,则退出死循环;如果有,则返回新中断向量,重新处理该中断,处理流程与前面的一样。这种等待中断的批处理方式可以减少进入内核和退出内核的次数,从而提供效率。软中断的处理在 ia64_eoi()之后,因为只有内核在调用 ia64_eoi()之后才会产生新的中断。

IA64 外部中断是根据中断向量号排优先级的,中断向量号越大优先级越高。由于有 256 个中断向量,因此在同一个内核栈中有可能产生上百个嵌套中断,假设处理每个中断平均需要 1KB 的栈空间,则该内核栈需要 0.25 兆空间才能避免栈溢出。由于每个任务都需要有自己的内核栈,因此这么大的内核栈是不切合实际的。为了避免这个问题,Linux/ia64 用 tpr 寄存器控制嵌套深度。处理过程如上述程序所示,它将 tpr 的当前值保留在 saved_tpr 局部变量中,然后将当前中断的向量号写入 tpr。该写操作会屏蔽该组或低于该组的所有中断,在设备中断处理完成后,恢复原来的 tpr 值。由于只有全系统只有 16 个优先级组,因此 32KB 的内核栈就可以保证避免栈溢出。如果在 tpr 写入新值或在旧值恢复后发生另一个中断,则会导致刚才的嵌套深度机制失效,因此这时内核必须关闭处理器状态寄存器中的中断位(psr.i),在调用外部中断处理函数时该位必须关闭。在恢复 tpr 前,通过 local_irq_disable() 再次清除该位。这样确保内核的进入和退出路径都在屏蔽中断发送情况下进行的。有个例外,如果有等待的软中断,在调用 do_softirq() 时该函数会调用 local_irq_enable() 重新赋能中断发送,因此 do_softirq() 在执行前先检查当前嵌套中断的深度,如果深度超过 1,则立即返回。软中断只在深度为 1 的时候处理。

IA64 Linux 的中断处理过程充分利用 SAPIC 中断架构的特点,通过中断向量表中嵌入中断处理函数、中断优先级控制、中断屏蔽、等待中断的批处理等方式实现高效的中断处理。随着 SAPIC 中断架构的日趋成熟和壮大,IA64 Linux 的中断处理过程将具有重要的参考价值。


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值