zoukankan      html  css  js  c++  java
  • 【原创】MIPS浅议之——中断系统之我见

    最近,准确的说应该是最近两个月的时间,我都在研究MIPS的异常与中断。或者可以说,最近这两个月,我才真正了解中断系统的整个结构和处理流程以及为什么要这样做?这段时间我最大的体会就是以前我们在“计算机组成原理”、“微机原理”等课程中背诵的东西真的很重要。我深刻感受到真的有很多内容都需要我们去思考为什么,而不能仅仅局限于会算、会背。
    看过很多本书,很多高校对MIPS中断处理的部分。当然,我看到的也只是冰山一角。我觉得对于中断的处理仅就我们本科生阶段还处在程序查询的阶段,然后在“微机原理”和“计算机组成原理”这些课程中我们讲述的都是向量化中断的方式。无论哪种方式,都是正确的。这两个月的学习和研究,直到今日我才觉得自己学到了些东西,和大家分享。希望会对也在研究者块的同学有帮助。
    以下内容参照MIPS32 24K Processor Core Family Software User′s Manual以及
    MIPS32 1004K CPU Family Software User′s Manual。
    首先,我想说的是我认为仅就《see mips run》(第二版)对这部分知识的侧重点属于程序查询方式。然而,MIPS体系结构共有三种不同方式的方式,虽然该书有提到,但是我曾经固执地觉得其他两种处理方式显然要比此种更具有优势,而且Intel采用的即是向量化中断,就是我们常算的IDT转化的那种方式。
    作者在5.3节叙述了他的理由,但是我曾经认为按照一级一级的查询,一定会浪费很多机器周期,仅就我自己写的中断嵌套代码也是如此。看过手册,我才发现原来其实并不是这样,MIPS在模式一中做了向量地址映射的简化,这一简化恰恰体现了RISC指令集的特点和价值。这个价值根本不是用多条精简指令代替复杂指令,这个说法太绝对了。
    以24K Family为例浅析。
    5.3.1 Interrupt Modes
    The 24K core includes support for three interrupt modes, as defined by Release 2 of the Architecture:
    ·Interrupt compatibility mode, which acts identically to that in an implementation of Release 1 of the Architec-ture.
    ·Vectored Interrupt (VI) mode, which adds the ability to prioritize and vector interrupts to a handler dedicated to that interrupt, and to assign a GPR shadow set for use during interrupt processing. The presence of this mode is denoted by the VInt bit in the Config3 register. This mode is architecturally optional; but it is always present on the 24K core, so the VInt bit will always read as a 1 for the 24K core.
    ·External Interrupt Controller (EIC) mode, which redefines the way in which interrupts are handled to provide full support for an external interrupt controller handling prioritization and vectoring of interrupts. This presence of this mode denoted by the VEIC bit in the Config3 register. Again, this mode is architecturally optional. On the 24K core, the VEIC bit is set externally by the static input, SI_EICPresent, to allow system logic to indicate the presence of an external interrupt controller.
    该段主要是介绍了三种中断模式:Interrupt-CompatibilityVIEIC
    每种模式的配置条件如下:
    5.3.1.1 Interrupt Compatibility Mode
    This is the default interrupt mode for the processor and is entered when a Reset exception occurs. In this mode, interrupts are non-vectored and dispatched though exception vector offset 16#180 (if CauseIV = 0) or vector offset 16#200 (if CauseIV= 1). This mode is in effect if any of the following conditions are true:
    CauseIV =  0
    StatusBEV = 1
    IntCtlVS = 0, which would be the case if vectored interrupts are not implemented, or have been disabled.
     
    该段主要简介了Interrupt Compatibility Mode的模式,该模式的生成条件由CauseIV)、SRBEV)和IntCtlVS)控制。并且是处理器中断的默认工作方式,复位异常产生时进入该模式。
    接下来是比较重要的一段汇编,它的意义也很重要:
    /*
     * Assumptions:
     * - CauseIV = 1 (if it were zero, the interrupt exception would have to
     *               be isolated from the general exception vector before getting here)
     * - GPRs k0 and k1 are available (no shadow register switches invoked in
     *                             compatibility mode)
     * - The software priority is IP7..IP0 (HW5..HW0, SW1..SW0)
     *
     * Location: Offset 0x200 from exception base
     */
    IVexception:
    mfc0 k0, C0_Cause                                          /* Read Cause register for IP bits */
    mfc0 k1, C0_Status                                                 /* and Status register for IM bits */
    andi k0, k0, M_CauseIM                                  /* Keep only IP bits from Cause */
    and k0, k0, k1                                                  /* and mask with IM bits */
    beq k0, zero, Dismiss                                       /* no bits set - spurious interrupt */
    clz k0, k0                                                       /* Find first bit set, IP7..IP0; k0 = 16..23 */
    xori k0, k0, 0x17                                             /* 16..23 => 7..0 */
    sll k0, k0, VS                                                  /* Shift to emulate software IntCtlVS*/
    la k1, VectorBase                                                  /* Get base of 8 interrupt vectors */
    addu k0, k0, k1                                             /* Compute target from base and offset */
    jr k0                                                                      /* Jump to specific exception routine */
    nop
    此段是处理CauseIV= 1条件下的很重要的处理过程。首先读取CauseSR寄存器的内容,并将Cause(IP)SRIM)按位与检验当前是否有中断,若此时值为0,则此中断为spurious interrupt,直译为伪造中断。因为笔者之前设计电路时IP位的是否有效即考虑过IM位是否屏蔽,以此来检验,用硬件做的此处检验。然而,该程序代码则说明MIPS其实是将中断请求信号硬连线IP位,连是否屏蔽都由软件测试。接下来是两条不常用的指令clzxoriclz指令笔者也没接触过,MIPS程序员手册翻译为Count the number of leading zeros in a word,其实就是找到由最高位到最低位找到第一个为1的位的位置。因为之前用M_CauseIM按位与过,因此其可能的值仅限于IP[7:0]位间,即16~23(从高位数起)。下一条疑惑,同样与特定值疑惑,将16~23转化为7~0。然后通过la指令及addu指令将跳转地址保存在k0寄存器中,jr指令跳转到相应的中断处理程序。需要注意的是,我相信很多人可能很容易看出其实MIPS就是在用软件进行中断的向量化,仅仅用4~5条指令就进行地址跳转。而并非是我曾经想过的condition-branch跳转。我相信也因此,所以很少有人再采用向量化中断,这恰恰证明力RISC指令集的特点,虽然指令精简,但是由人为的妙用会提高效率。会提高很大的效率。
    继续解读:
    /*
     * Each interrupt processing routine processes a specific interrupt, analogous
     * to those reached in VI or EIC interrupt mode. Since each processing routine
     * is dedicated to a particular interrupt line, it has the context to know
     * which line was asserted. Each processing routine may need to look further
     * to determine the actual source of the interrupt if multiple interrupt requests
     * are ORed together on a single IP line. Once that task is performed, the
     * interrupt may be processed in one of two ways:
     *
     * - Completely at interrupt level (e.g., a simply UART interrupt). The
     *   SimpleInterrupt routine below is an example of this type.
     * - By saving sufficient state and re-enabling other interrupts. In this
     *   case the software model determines which interrupts are disabled during
     *   the processing of this interrupt. Typically, this is either the single
     *   StatusIM bit that corresponds to the interrupt being processed, or some
     *   collection of other StatusIM bits so that lower priority interrupts are
     *   also disabled. The NestedInterrupt routine below is an example of this type.
     */
    其实该段内容很简单就是在说中断处理程序的两种可能方式事情,即Completely at interrupt level和中断嵌套,这部分内容《see mips run》一书中介绍的很详细,不多说。
    SimpleInterrupt:
    /*
     * Process the device interrupt here and clear the interupt request
     * at the device. In order to do this, some registers may need to be
     * saved and restored. The coprocessor 0 state is such that an ERET
     * will simple return to the interrupted code.
     */
    eret                                                               /* Return to interrupted code */
    这段内容就是在说简单中断的处理:处理设备中断以及中断请求,为此,一些寄存器需要保存回复,使用一条eret语句可以返回到被中断原程序处。
    NestedException:
    /*
     * Nested exceptions typically require saving the EPC and Status registers,
     * any GPRs that may be modified by the nested exception routine, disabling
     * the appropriate IM bits in Status to prevent an interrupt loop, putting
     * the processor in kernel mode, and re-enabling interrupts. The sample code
     * below can not cover all nuances of this processing and is intended only
     * to demonstrate the concepts.
     */
    /* Save GPRs here, and setup software context */
    mfc0 k0, C0_EPC                                            /* Get restart address */
    sw k0, EPCSave                                               /* Save in memory */
    mfc0 k0, C0_Status                                          /* Get Status value */
    sw k0, StatusSave                                             /* Save in memory */
    li k1, ~IMbitsToClear                                       /* Get Im bits to clear for this interrupt */
    /*   this must include at least the IM bit */
    /*   for the current interrupt, and may include */
    /*   others */
    and k0, k0, k1                                                  /* Clear bits in copy of Status */
    ins k0, zero, S_StatusEXL, (W_StatusKSU+W_StatusERL+W_StatusEXL)
    /* Clear KSU, ERL, EXL bits in k0 */
    mtc0 k0, C0_Status                                           /* Modify mask, switch to kernel mode, */
    /*   re-enable interrupts */
    /*
     * Process interrupt here, including clearing device interrupt.
     * In some environments this may be done with a thread running in
     * kernel or user mode. Such an environment is well beyond the scope of
     * this example.
     */
    /*
     * To complete interrupt processing, the saved values must be restored
     * and the original interrupted code restarted.
     */
    di                                                               /* Disable interrupts - may not be required */
    lw k0, StatusSave                                             /* Get saved Status (including EXL set) */
    lw k1, EPCSave                                               /*   and EPC */
    mtc0 k0, C0_Status                                                 /* Restore the original value */
    mtc0 k1, C0_EPC                                             /* and EPC */
    /* Restore GPRs and software state */
    eret                                                                 /* Dismiss the interrupt */
    这段代码就是MIPS对中断嵌套的处理,相信很多人看到ins这条指令时都有一些头大。的确,ins这条指令并不是常规的MIPS指令。其指令格式为ins rtrspossize。该指定功能为GPR[rt] InsertField(GPR[rt], GPR[rs], msb, lsb),即使一个插入某些位的指令,MIPS用这条指令清KSUERLEXL位。然后写会SR寄存器,在写回之前保存现场并修改SRIM)位。显然,MIPS的嵌套处理与我们想象的很相似。当完成中断处理时,也需要返回现场,其中di指令是为了修改SR寄存器时可以原子的进行。其他代码均很简单。
    通过读此模式的代码,了解到其实该模式并不只是传统意义上的中断查询的那种不断条件分支的方式,我认为只是用软件的手段实现一个向量地址生成器。
    下面,我们来浅析一下VI模式。
    5.3.1.2 Vectored Interrupt Mode
    Vectored Interrupt mode builds on the interrupt compatibility mode by adding a priority encoder to prioritize pending interrupts and to generate a vector with which each interrupt can be directed to a dedicated handler routine. This mode also allows each interrupt to be mapped to a GPR shadow set for use by the interrupt handler. Vectored Interrupt mode is in effect if all of the following conditions are true:
    ·Config3VInt = 1
    ·Config3VEIC = 0
    ·IntCtlVS 0
    ·CauseIV = 1
    ·StatusBEV = 0
    与前面一小节相似,该段也在介绍VI模式的有效条件,并已经指明该模式只是在Interrupt-Compatibility的基础上增加优先级译码器。显然,MIPS体系结构的Interrupt-Compatibility模式一定也比我们想象的复杂。并且该模式利用了影子寄存器。

    架构图如下:

    这个架构就是标准的我们在书本中学到的程序中断电路方式的接口组成,笔者在进行实际仿真后才发现其实使我们把前一种模式设计的太简单了,我看过很多学校的基于MIPS架构的RISC处理器,有的甚至根本没有引入协处理器。所以我觉得在这一部分,需要花费很多时间和精力才能真正了解MIPS到底是怎样做的。
    我还记得有位老师说过RISC机也只是在CISC机上做的改进,我想说的是:可能它的改进比我们想到的或者直观看到的,或者自以为的要复杂的多。RISC的原则并不是单纯的精简指令,它有它的价值和优点。万事屋绝对。
    其实,直到刚刚过去的昨天我还傻傻的认为向量化中断要比查询方式快的多,方便的多,原来真的不是这样。很多东西,都不是表面的,是需要花时间和精力去思考的。
    希望感兴趣的同学可以和我联系交流,我也是刚刚了解MIPS的新人。以前有句很土的话叫书山有路勤为径,学海无涯苦作舟。不知何时,我把这句话忘记了,直到最近才想来。

    或许,明天我还会发现今天自己想的不对。自己能够看到自己走过的弯路,才证明真正有所收获,仅此而已。

  • 相关阅读:
    介绍一款超实用的演讲必备工具 ZoomIt
    兼容ie6/ff/ch/op的div+css实现的圆角框
    POJ 2377 Bad Cowtractors
    POJ 2349 Arctic Network
    PHP中数组转换为XML格式
    [置顶] 白话二分匹配之最大匹配+附上hdu2063解题报告
    POJ 3723 Conscription
    [置顶] 软件之道 -- 道篇全文
    OracleL
    开源存储之ceph
  • 原文地址:https://www.cnblogs.com/bombe1013/p/3294662.html
Copyright © 2011-2022 走看看