linux kernel的中断子系统之(四):High level irq event handler作者:linuxer 发布于:2014-8-28 20:00 分类:中断子系统 一、前言 当外设触发一次中断后,一个大概的处理过程是: 1、具体CPU architecture相关的模块会进行现场保护,然后调用machine driver对应的中断处理handler 2、machine driver对应的中断处理handler中会根据硬件的信息获取HW interrupt ID,并且通过irq domain模块翻译成IRQ number 3、调用该IRQ number对应的high level irq event handler,在这个high level的handler中,会通过和interupt controller交互,进行中断处理的flow control(处理中断的嵌套、抢占等),当然最终会遍历该中断描述符的IRQ action list,调用外设的specific handler来处理该中断 4、具体CPU architecture相关的模块会进行现场恢复。 上面的1、4这两个步骤在linux kernel的中断子系统之(六):ARM中断处理过程中已经有了较为细致的描述,步骤2在linux kernel的中断子系统之(二):irq domain介绍中介绍,本文主要描述步骤3,也就是linux中断子系统的high level irq event handler。
注:这份文档充满了猜测和空想,很多地方描述可能是有问题的,不过我还是把它发出来,抛砖引玉,希望可以引发大家讨论。
一、如何进入high level irq event handler 1、从具体CPU architecture的中断处理到machine相关的处理模块 说到具体的CPU,我们还是用ARM为例好了。对于ARM,我们在ARM中断处理文档中已经有了较为细致的描述。这里我们看看如何从从具体CPU的中断处理到machine相关的处理模块 ,其具体代码如下:
其实,直接从CPU的中断处理跳转到通用中断处理模块是不可能的,中断处理不可能越过interrupt controller这个层次。一般而言,通用中断处理模块会提供一些通用的中断代码处理库,然后由interrupt controller这个层次的代码调用这些通用中断处理的完成整个的中断处理过程。“interrupt controller这个层次的代码”是和硬件中断系统设计相关的,例如:系统中有多少个interrupt contrller,每个interrupt controller是如何控制的?它们是如何级联的?我们称这些相关的驱动模块为machine interrupt driver。 在上面的代码中,如果配置了MULTI_IRQ_HANDLER的话,ARM中断处理则直接跳转到一个叫做handle_arch_irq函数,如果系统中只有一个类型的interrupt controller(可能是多个interrupt controller,例如使用两个级联的GIC),那么handle_arch_irq可以在interrupt controller初始化的时候设定。代码如下:
gic_nr是GIC的编号,linux kernel初始化过程中,每发现一个GIC,都是会指向GIC driver的初始化函数的,不过对于第一个GIC,gic_nr等于0,对于第二个GIC,gic_nr等于1。当然handle_arch_irq这个函数指针不是per CPU的变量,是全部CPU共享的,因此,初始化一次就OK了。 当使用多种类型的interrupt controller的时候(例如HW 系统使用了S3C2451这样的SOC,这时候,系统有两种interrupt controller,一种是GPIO type,另外一种是SOC上的interrupt controller),则不适合在interrupt controller中进行设定,这时候,可以考虑在machine driver中设定。在这种情况下,handle_arch_irq 这个函数是在setup_arch函数中根据machine driver设定,具体如下:
关于MULTI_IRQ_HANDLER这个配置项,我们可以再多说几句。当然,其实这个配置项的名字已经出卖它了。multi irq handler就是说系统中有多个irq handler,可以在run time的时候指定。为何要run time的时候,从多个handler中选择一个呢?HW interrupt block难道不是固定的吗?我的理解(猜想)是:一个kernel的image支持多个HW platform,对于不同的HW platform,在运行时检查HW platform的类型,设定不同的irq handler。 2、interrupt controller相关的代码 我们还是以2个级联的GIC为例来描述interrupt controller相关的代码。代码如下:
更多关于GIC相关的信息,请参考linux kernel的中断子系统之(七):GIC代码分析。对于ARM处理器,handle_IRQ代码如下:
3、调用high level handler 调用high level handler的代码逻辑非常简单,如下:
二、理解high level irq event handler需要的知识准备 1、自动探测IRQ 一个硬件驱动可以通过下面的方法进行自动探测它使用的IRQ:
如果能够自动探测到IRQ,上面程序中的irq(probe_irq_off的返回值)就是自动探测的结果。后续程序可以通过request_threaded_irq申请该IRQ。probe_irq_on函数主要的目的是返回一个32 bit的掩码,通过该掩码可以知道可能使用的IRQ number有哪些,具体代码如下:
(1)那些能自动探测IRQ的中断描述符需要具体两个条件: a、该中断描述符还没有通过request_threaded_irq或者其他方式申请该IRQ的specific handler(也就是irqaction数据结构) b、该中断描述符允许自动探测(不能设定IRQ_NOPROBE) (2)如果满足上面的条件,那么该中断描述符属于备选描述符。设定其internal state为IRQS_AUTODETECT | IRQS_WAITING。IRQS_AUTODETECT表示本IRQ正处于自动探测中。 (3)在等待过程中,系统仍然允许,各种中断依然会触发。在各种high level irq event handler中,总会有如下的代码:
这里会清除IRQS_WAITING状态。 (4)这时候,我们还没有控制那个想要自动探测IRQ的硬件产生中断,因此处于自动探测中,并且IRQS_WAITING并清除的一定不是我们期待的IRQ(可能是spurious interrupts导致的),这时候,clear IRQS_AUTODETECT,shutdown该IRQ。 (5)最大探测的IRQ是31(mask是一个32 bit的value),mask返回的是可能的irq掩码。 我们再来看看probe_irq_off的代码:
因为在调用probe_irq_off已经触发了自动探测IRQ的那个硬件中断,因此在该中断的high level handler的执行过程中,该硬件对应的中断描述符的IRQS_WAITING标致应该已经被清除,因此probe_irq_off函数scan中断描述符DB,找到处于auto probe中,而且IRQS_WAITING标致被清除的那个IRQ。如果找到一个,那么探测OK,返回该IRQ number,如果找到多个,说明探测失败,返回负的IRQ个数信息,没有找到的话,返回0。
一个ARM SOC总是有很多的GPIO,有些GPIO可以提供中断功能,这些GPIO的中断可以配置成level trigger或者edge trigger。一般而言,大家都更喜欢用level trigger的中断。有的SOC只能是有限个数的GPIO可以配置成电平中断,因此,在项目初期进行pin define的时候,大家都在争抢电平触发的GPIO。 电平触发的中断有什么好处呢?电平触发的中断很简单、直接,只要硬件检测到硬件事件(例如有数据到来),其assert指定的电平信号,CPU ack该中断后,电平信号消失。但是对于边缘触发的中断,它是用一个上升沿或者下降沿告知硬件的状态,这个状态不是一个持续的状态,如果软件处理不好,容易丢失中断。 什么时候会resend一个中断呢?我们考虑一个简单的例子: (1)CPU A上正在处理x外设的中断 (2)x外设的中断再次到来(CPU A已经ack该IRQ,因此x外设的中断可以再次触发),这时候其他CPU会处理它(mask and ack),并设置该中断描述符是pending状态,并委托CPU A处理该pending状态的中断。需要注意的是CPU已经ack了该中断,因此该中断的硬件状态已经不是pending状态,无法触发中断了,这里的pending状态是指中断描述符的软件状态。 (3)CPU B上由于同步的需求,disable了x外设的IRQ,这时候,CPU A没有处理pending状态的x外设中断就离开了中断处理过程。 (4)当enable x外设的IRQ的时候,需要检测pending状态以便resend该中断,否则,该中断会丢失的 具体代码如下:
在各种high level irq event handler中,总会有如下的代码:
这里会清除IRQS_REPLAY状态,表示该中断已经被retrigger,一次resend interrupt的过程结束。
3、unhandled interrupt和spurious interrupt 在中断处理的最后,总会有一段代码如下:
note_interrupt就是进行unhandled interrupt和spurious interrupt处理的。对于这类中断,linux kernel有一套复杂的机制来处理,你可以通过command line参数(noirqdebug)来控制开关该功能。 当发生了一个中断,但是没有被处理(有两种可能,一种是根本没有注册的specific handler,第二种是有handler,但是handler否认是自己对应的设备触发的中断),怎么办?毫无疑问这是一个异常状况,那么kernel是否要立刻采取措施将该IRQ disable呢?也不太合适,毕竟interrupt request信号线是允许共享的,直接disable该IRQ有可能会下手太狠,kernel采取了这样的策略:如果该IRQ触发了100,000次,但是99,900次没有处理,在这种条件下,我们就是disable这个interrupt request line。多么有情有义的策略啊!相关的控制数据在中断描述符中,如下:
irq_count和irqs_unhandled都是比较直观的,为何要记录unhandled interrupt发生的时间呢?我们来看具体的代码。具体的相关代码位于note_interrupt中,如下:
(1)是否是一次有效的unhandled interrupt还要根据时间来判断。一般而言,当硬件处于异常状态的时候往往是非常短的时间触发非常多次的中断,如果距离上次unhandled interrupt的时间超过了10秒(HZ=100),那么我们要把irqs_unhandled重新计数。如果不这么处理的话,随着时间的累计,最终irqs_unhandled可能会达到99900次的,从而把这个IRQ错误的推上了审判台。 (2)irq_count每次都会加一,记录IRQ被触发的次数。但只要大于100000才启动 step (3)中的检查。一旦启动检查,irq_count会清零,irqs_unhandled也会清零,进入下一个检查周期。 (3)如果满足条件(IRQ触发了100,000次,但是99,900次没有处理),disable该IRQ。 (4)启动timer,轮询整个系统中的handler来处理这个中断(轮询啊,绝对是真爱啊)。这个timer的callback函数定义如下:
三、和high level irq event handler相关的硬件描述 1、CPU layer和Interrupt controller之间的接口 从逻辑层面上看,CPU和interrupt controller之间的接口包括: (1)触发中断的signal。一般而言,这个(些)信号是电平触发的。对于ARM CPU,它是nIRQ和nFIQ信号线,对于X86,它是INT和NMI信号线,对于PowerPC,这些信号线包括MC(machine check)、CRIT(critical interrupt)和NON-CRIT(Non critical interrupt)。对于linux kernel的中断子系统,我们只使用其中一个信号线(例如对于ARM而言,我们只使用nIRQ这个信号线)。这样,从CPU层面看,其逻辑动作非常的简单,不区分优先级,触发中断的那个信号线一旦assert,并且CPU没有mask中断,那么软件就会转到一个异常向量执行,完毕后返回现场。 (2)Ack中断的signal。这个signal可能是物理上的一个连接CPU和interrupt controller的铜线,也可能不是。对于X86+8259这样的结构,Ack中断的signal就是nINTA信号线,对于ARM+GIC而言,这个信号就是总线上的一次访问(读Interrupt Acknowledge Register寄存器)。CPU ack中断标识cpu开启启动中断服务程序(specific handler)去处理该中断。对于X86而言,ack中断可以让8259将interrupt vector数据送到数据总线上,从而让CPU获取了足够的处理该中断的信息。对于ARM而言,ack中断的同时也就是获取了发生中断的HW interrupt ID,总而言之,ack中断后,CPU获取了足够开启执行中断处理的信息。 (3)结束中断(EOI,end of interrupt)的signal。这个signal用来标识CPU已经完成了对该中断的处理(specific handler或者ISR,interrupt serivce routine执行完毕)。实际的物理形态这里就不描述了,和ack中断signal是类似的。 (4)控制总线和数据总线接口。通过这些接口,CPU可以访问(读写)interrupt controller的寄存器。
2、Interrupt controller和Peripheral device之间的接口 所有的系统中,Interrupt controller和Peripheral device之间的接口都是一个Interrupt Request信号线。外设通过这个信号线上的电平或者边缘向CPU(实际上是通过interrupt controller)申请中断服务。
四、几种典型的high level irq event handler 本章主要介绍几种典型的high level irq event handler,在进行high level irq event handler的设定的时候需要注意,不是外设使用电平触发就选用handle_level_irq,选用什么样的high level irq event handler是和Interrupt controller的行为以及外设电平触发方式决定的。介绍每个典型的handler之前,我会简单的描述该handler要求的硬件行为,如果该外设的中断系统符合这个硬件行为,那么可以选择该handler为该中断的high level irq event handler。 1、边缘触发的handler。 使用handle_edge_irq这个handler的硬件中断系统行为如下: 我们以上升沿为例描述边缘中断的处理过程(下降沿的触发是类似的)。当interrupt controller检测到了上升沿信号,会将该上升沿状态(pending)锁存在寄存器中,并通过中断的signal向CPU触发中断。需要注意:这时候,外设和interrupt controller之间的interrupt request信号线会保持高电平,这也就意味着interrupt controller不可能检测到新的中断信号(本身是高电平,无法形成上升沿)。这个高电平信号会一直保持到软件ack该中断(调用irq chip的irq_ack callback函数)。ack之后,中断控制器才有可能继续探测上升沿,触发下一次中断。 ARM+GIC组成的系统不符合这个类型。虽然GIC提供了IAR(Interrupt Acknowledge Register)寄存器来让ARM来ack中断,但是,在调用high level handler之前,中断处理程序需要通过读取IAR寄存器获得HW interrpt ID并转换成IRQ number,因此实际上,对于GIC的irq chip,它是无法提供本场景中的irq_ack函数的。很多GPIO type的interrupt controller符合上面的条件,它们会提供pending状态寄存器,读可以获取pending状态,而向pending状态寄存器写1可以ack该中断,让interrupt controller可以继续触发下一次中断。 handle_edge_irq代码如下:
(0) 这时候,中断仍然是关闭的,因此不会有来自本CPU的并发,使用raw spin lock就防止其他CPU上对该IRQ的中断描述符的访问。针对该spin lock,我们直观的感觉是raw_spin_lock和(7)中的raw_spin_unlock是成对的,实际上并不是,handle_irq_event中的代码是这样的:
实际上,由于在handle_irq_event中处理action list的耗时还是比较长的,因此处理具体的action list的时候并没有持有中断描述符的spin lock。在如果那样的话,其他CPU在对中断描述符进行操作的时候需要spin的时间会很长的。 (1)判断是否需要执行下面的action list的处理。这里分成几种情况: a、该中断事件已经被其他的CPU处理了 b、该中断被其他的CPU disable了 c、该中断描述符没有注册specific handler。这个比较简单,如果没有irqaction,根本没有必要调用action list的处理 如果该中断事件已经被其他的CPU处理了,那么我们仅仅是设定pending状态(为了委托正在处理的该中断的那个CPU进行处理),mask_ack_irq该中断并退出就OK了,并不做具体的处理。另外正在处理该中断的CPU会检查pending状态,并进行处理的。同样的,如果该中断被其他的CPU disable了,本就不应该继续执行该中断的specific handler,我们也是设定pending状态,mask and ack中断就退出了。当其他CPU的代码离开临界区,enable 该中断的时候,软件会检测pending状态并resend该中断。 这里的irq_check_poll代码如下:
IRQS_POLL_INPROGRESS标识了该IRQ正在被polling(上一章有描述),如果没有被轮询,那么返回false,进行正常的设定pending标记、mask and ack中断。如果正在被轮询,那么需要等待poll结束。 (2)ack该中断。对于中断控制器,一旦被ack,表示该外设的中断被enable,硬件上已经准备好触发下一次中断了。再次触发的中断会被调度到其他的CPU上。现在,我们可以再次回到步骤(1)中,为什么这里用mask and ack而不是单纯的ack呢?如果单纯的ack则意味着后续中断还是会触发,这时候怎么处理?在pending+in progress的情况下,我们要怎么处理?记录pending的次数,有意义吗?由于中断是完全异步的,也有可能pending的标记可能在另外的CPU上已经修改为replay的标记,这时候怎么办?当事情变得复杂的时候,那一定是本来方向就错了,因此,mask and ack就是最好的策略,我已经记录了pending状态,不再考虑pending嵌套的情况。 (3)在调用specific handler处理具体的中断的时候,由于不持有中断描述符的spin lock,因此其他CPU上有可能会注销其specific handler,因此do while循环之后,desc->action有可能是NULL,如果是这样,那么mask irq,然后退出就OK了 (4)如果中断描述符处于pending状态,那么一定是其他CPU上又触发了该interrupt source的中断,并设定了pending状态,“委托”本CPU进行处理,这时候,需要把之前mask住的中断进行unmask的操作。一旦unmask了该interrupt source,后续的中断可以继续触发,由其他的CPU处理(仍然是设定中断描述符的pending状态,委托当前正在处理该中断请求的那个CPU进行处理)。 (5)处理该中断请求事件
(6)只要有pending标记,就说明该中断还在pending状态,需要继续处理。当然,如果有其他的CPU disable了该interrupt source,那么本次中断结束处理。
2、电平触发的handler 使用handle_level_irq这个handler的硬件中断系统行为如下: 我们以高电平触发为例。当interrupt controller检测到了高电平信号,并通过中断的signal向CPU触发中断。这时候,对中断控制器进行ack并不能改变interrupt request signal上的电平状态,一直要等到执行具体的中断服务程序(specific handler),对外设进行ack的时候,电平信号才会恢复成低电平。在对外设ack之前,中断状态一直是pending的,如果没有mask中断,那么中断控制器就会assert CPU。 handle_level_irq的代码如下:
(1)考虑CPU<------>interrupt controller<------>device这样的连接方式中,我们认为high level handler主要是和interrupt controller交互,而specific handler(request_irq注册的那个)是和device进行交互。Level类型的中断的特点就是只要外设interrupt request line的电平状态是有效状态,对于interrupt controller,该外设的interrupt总是active的。由于外设检测到了事件(比如数据到来了),因此assert了指定的电平信号,这个电平信号会一直保持,直到软件清除了外设的状态寄存器。但是,high level irq event handler这个层面只能操作Interrupt controller,不能操作具体外设的寄存器(那应该属于具体外设的specific interrupt handler处理内容,该handler会挂入中断描述符中的IRQ action list)。直到在具体的中断服务程序(specific handler中)操作具体外设的寄存器,才能让这个asserted电平信号消息。 正是因为level trigger的这个特点,因此,在high level handler中首先mask并ack该IRQ。这一点和边缘触发的high level handler有显著的不同,在handle_edge_irq中,我们仅仅是ack了中断,并没有mask,因为边缘触发的中断稍纵即逝,一旦mask了该中断,容易造成中断丢失。而对于电平中断,我们不得不mask住该中断,如果不mask住,只要CPU ack中断,中断控制器将持续的assert CPU中断(因为有效电平状态一直保持)。如果我们mask住该中断,中断控制器将不再转发该interrupt source来的中断,因此,所有的CPU都不会感知到该中断,直到软件unmask。这里的ack是针对interrupt controller的ack,本身ack就是为了clear interrupt controller对该IRQ的状态寄存器,不过由于外部的电平仍然是有效信号,其实未必能清除interrupt controller的中断状态,不过这是和中断控制器硬件实现相关的。 (2)对于电平触发的high level handler,我们一开始就mask并ack了中断,因此后续specific handler因该是串行化执行的,为何要判断in progress标记呢?不要忘记spurious interrupt,那里会直接调用handler来处理spurious interrupt。 (3)这里有两个场景 a、没有注册specific handler。如果没有注册handler,那么保持mask并设定pending标记(这个pending标记有什么作用还没有想明白)。 b、该中断被其他的CPU disable了。如果该中断被其他的CPU disable了,本就不应该继续执行该中断的specific handler,我们也是设定pending状态,mask and ack中断就退出了。当其他CPU的代码离开临界区,enable 该中断的时候,软件会检测pending状态并resend该中断。 (4)为何是有条件的unmask该IRQ?正常的话当然是umask就OK了,不过有些threaded interrupt(这个概念在下一份文档中描述)要求是one shot的(首次中断,specific handler中开了一枪,wakeup了irq handler thread,如果允许中断嵌套,那么在specific handler会多次开枪,这也就不是one shot了,有些IRQ的handler thread要求是one shot,也就是不能嵌套specific handler)。
3、支持EOI的handler TODO 原创文章,转发请注明出处。蜗窝科技。http://www./linux_kenrel/High_level_irq_event_handler.html 标签: 中断处理 评论:
heziq
2015-03-23 10:19 @linuxer:
请教几个问题: 1.有没有同时支持上升沿和下降沿的中断控制器?当然我觉得不可能有同时支持高电平和低电平出发的中断控制器。 2.gpio type 中断,如果是上升沿中断,是不是要使用下拉电阻或者根本不使用上下拉?如果使用了上拉电阻会怎么样? 3.gpio type 中断,如果是高电平,我觉得肯定要使用下拉电阻,将电平钳制在低电平。 3.gpio type 中断,如果是下降沿,是不是要使用上拉电阻,或者不使用。如果使用了下拉电阻会怎么样? 4.gpio type 中断,如果是低电平,我觉得肯定要使用上拉电阻,将电平钳制在高电平。 5.如果gpio中断内部使用了上拉电阻,如果外部在使用上拉电阻,会出现什么副作用吗。我觉得有,两个上拉电源之间会互相影响。 5.如果gpio中断内部使用了下拉电阻,如果外部在使用下拉电阻,会使pin脚的输入电阻变低,有可能高电平信号拉不起来。 6.如果外设使用边沿触发。比如上升沿,那么它的高电平维持时间有要求吗,由高电平变低电平,是外设自己拉低的?还是interrupt controler控制? 这都是我在工作中碰到的疑问。有些设置不好,会造成中断触发失败,有些会造成功耗过大。在这里想和大家交流一下。
RobinHsiang
2015-03-26 17:29 @linuxer:一般所说GPIO导致漏电,是什么导致的?是比如GPIO设置,或者类似中断类型GPIO错误的上下拉导致的吗?
而漏电的方向是从CPU漏到device还是反过来漏?这个主要看电源域吗? 一般怎么样去查证项目中有没有GPIO上面的漏电呢?
linuxer
2015-03-28 22:22 @RobinHsiang:多谢你的问题,让我仔细思考了一番(好的问题总是有这样的特性),因此延迟到今天才回复。
一般而言,漏电(leakage current)是一个芯片的DC参数之一,例如Iozl和Iozh这两个参数,分别表示引脚处于高阻(High-Impedance)状态时,外加高电平和低电平的电流值。由于是高阻状态,因此这时候的leakage current应该是很小的(例如1uA)。当然,我想你这里说的不是这种漏电。 我们调试嵌入式设备总是从功能开始,然后性能,特别是功耗,例如待机或者关机电流,我们都是希望能够满足功能的情况下越小越好。当大刀阔斧的针对各个HW block的的检查过后,最后往往会纠缠在GPIO状态的调整上,正确的GPIO设定往往能节省几个毫安的电流(例如如果一个GPIO的状态的错误设定可能导致0.1mA的电流,那么精细的调整10个GPIO可以节省1个mA) 具体电流是source(用你的描述就是从CPU漏到device)还是sink(从device漏到CPU)是和实际的电路连接、cpu pin的特性以及外设芯片引脚的特性相关。例如CPU的一个GPIO是tri state,假设在CPU处于suspend的时候,将该pin设定为high-impedance状态,如果对端连接的是外设芯片的enable引脚(低电平有效),为了稳定的电路状态,可能需要连接一个上拉电阻,确保外设芯片处于disable状态,以便节省功耗。如果CPU处于suspend的时候,将该pin设定为低电平,那么上拉电阻上将有一个不小的电流消耗(假设上拉到3V,上拉电阻是10k,那么CPU在该GPIO上的sink current大约要0.3mA)。如果调整输出成高电平,也不会有这个sink current。 具体的电路形形色色,这里无法每一个都描述了。
Rocky
2015-03-18 17:23 a、没有注册specific handler。如果没有注册handler,那么保持mask并设定pending标记(这个pending标记有什么作用还没有想明白)。
@linuxer 应该没有特别的作用,就是代码简洁吧?!要不是为了mark一下IRQS_PENDING,表明此中断曾经来过?? if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {-----(3) if(desc->action)//啰嗦吧?! desc->istate |= IRQS_PENDING; goto out_unlock; } ps:写的真的挺好的,看第二遍就理解很清楚了!
linuxer
2015-03-23 23:21 @Rocky:多谢!有机会的话可以考虑出中断子系统version 2,这次写的很多文档有些自己也没有搞明白,因此很难让读者明白。有些自己明白,写出来又不是那么明白。总之,这次的中断系统的文档就当是爱因斯坦的第一个小板凳吧,虽然粗糙,但是有些板凳的形状,需要后续不断的打磨。
linuxer
2014-08-29 19:33 补充两句,实际上这份文档我是写不下去了,我准备从具体的中断控制器驱动开始,把各种中断控制器的代码理清楚的话,在回头review这份文档,也许这份文档也是注定要打上“废弃”的标签
linuxer
2014-09-01 12:18 @forion:我写的也很累啊,哈哈
这种抽象层的东西就是理解起来比较困难,因此实际的系统是千奇百怪的,因此,要要足够的底层知识的累积才可以悟到上层逻辑的精妙。
linuxer 2014-09-01 18:21 @linuxer:因此实际的系统是千奇百怪的--->因为实际的系统是千奇百怪的
------------------------------- 这里没有精确的表达我的意思,本来我想说的是:目前我还不掌握足够的底层知识,需要积累到一定程度才能领会上层逻辑的精妙。因此,我准备先潜心研究一下具体的中断控制器再回头看看怎么修改这份文档。目前考虑先看看ARM+GIC系统,X86+Multi APIC系统和PowerPC+MPIC系统 |
|