cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

genericirq.rst (11535B)


      1.. include:: ../disclaimer-zh_CN.rst
      2
      3:Original: Documentation/core-api/genericirq.rst
      4
      5:翻译:
      6
      7 司延腾 Yanteng Si <siyanteng@loongson.cn>
      8
      9:校译:
     10
     11 吴想成 Wu XiangCheng <bobwxc@email.cn>
     12
     13.. include:: <isonum.txt>
     14
     15.. _cn_core-api_genericirq:
     16
     17================
     18Linux通用IRQ处理
     19================
     20
     21:版权: |copy| 2005-2010: Thomas Gleixner
     22:版权: |copy| 2005-2006:  Ingo Molnar
     23
     24简介
     25====
     26
     27通用中断处理层是为了给设备驱动程序提供一个完整的中断处理抽象(层)。它能够处
     28理所有不同类型的中断控制器硬件。设备驱动程序使用通用API函数来请求、启用、禁
     29用和释放中断。驱动程序不需要知道任何关于硬件处理中断的细节,所以它们可以在不同的
     30平台上使用而不需要修改代码。
     31
     32本文档提供给那些希望在通用IRQ处理层的帮助下实现基于其架构的中断子系统的开发
     33者。
     34
     35理论依据
     36========
     37
     38Linux中中断处理的原始实现使用__do_IRQ()超级处理程序,它能够处理每种类型的
     39中断逻辑。
     40
     41最初,Russell King确定了不同类型的处理程序,以便为Linux 2.5/2.6中的ARM中
     42断处理程序实现建立一个相当通用的集合。他区分了以下几种类型:
     43
     44-  电平触发型
     45
     46-  边沿触发型
     47
     48-  简单型
     49
     50在实现过程中,我们发现了另一种类型:
     51
     52-  响应EOI(end of interrupt)型
     53
     54在SMP的__do_IRQ()超级处理程序中,还需定义一种类型:
     55
     56-  每cpu型(针对CPU SMP)
     57
     58这种高层IRQ处理程序的拆分实现使我们能够为每个特定的中断类型优化中断处理的流
     59程。这减少了该特定代码路径的复杂性,并允许对特定类型进行优化处理。
     60
     61最初的通用IRQ实现使用hw_interrupt_type结构体及其 ``->ack`` ``->end`` 等回
     62调来区分超级处理程序中的流控制。这导致了流逻辑和低级硬件逻辑的混合,也导致了
     63不必要的代码重复:例如i386中的 ``ioapic_level_irq`` 和 ``ioapic_edge_irq`` ,
     64这两个IRQ类型共享许多低级的细节,但有不同的流处理。
     65
     66一个更自然的抽象是“irq流”和“芯片细节”的干净分离。
     67
     68分析一些架构的IRQ子系统的实现可以发现,他们中的大多数可以使用一套通用的“irq
     69流”方法,只需要添加芯片级的特定代码。这种分离对于那些需要IRQ流本身而不需要芯
     70片细节的特定(子)架构也很有价值——以提供了一个更透明的IRQ子系统设计。
     71
     72每个中断描述符都被分配给它自己的高层流程处理程序,这通常是一个通用的实现。(这
     73种高层次的流程处理程序的实现也使得提供解复用处理程序变得简单,这可以在各种架
     74构的嵌入式平台上找到。)
     75
     76这种分离使得通用中断处理层更加灵活和可扩展。例如,一个(子)架构可以使用通用
     77的IRQ流实现“电平触发型”中断,并添加一个(子)架构特定的“边沿型”实现。
     78
     79为了使向新模型的过渡更容易,并防止破坏现有实现,__do_IRQ()超级处理程序仍然
     80可用。这导致了一种暂时的双重性。随着时间的推移,新的模型应该在越来越多的架构中
     81被使用,因为它能使IRQ子系统更小更干净。它已经被废弃三年了,即将被删除。
     82
     83已知的缺陷和假设
     84================
     85
     86没有(但愿如此)。
     87
     88抽象层
     89======
     90
     91中断代码中主要有三个抽象层次:
     92
     931. 高级别的驱动API
     94
     952. 高级别的IRQ流处理器
     96
     973. 芯片级的硬件封装
     98
     99中断控制流
    100----------
    101
    102每个中断都由一个中断描述符结构体irq_desc来描述。中断是由一个“无符号整型”的数值来
    103引用的,它在描述符结构体数组中选择相应的中断描述符结构体。描述符结构体包含状态
    104信息和指向中断流方法和中断芯片结构的指针,这些都是分配给这个中断的。
    105
    106每当中断触发时,低级架构代码通过调用desc->handle_irq()调用到通用中断代码中。
    107这个高层IRQ处理函数只使用由分配的芯片描述符结构体引用的desc->irq_data.chip
    108基元。
    109
    110高级驱动程序API
    111---------------
    112
    113高层驱动API由以下函数组成:
    114
    115-  request_irq()
    116
    117-  request_threaded_irq()
    118
    119-  free_irq()
    120
    121-  disable_irq()
    122
    123-  enable_irq()
    124
    125-  disable_irq_nosync() (SMP only)
    126
    127-  synchronize_irq() (SMP only)
    128
    129-  irq_set_irq_type()
    130
    131-  irq_set_irq_wake()
    132
    133-  irq_set_handler_data()
    134
    135-  irq_set_chip()
    136
    137-  irq_set_chip_data()
    138
    139详见自动生成的函数文档。
    140
    141.. note::
    142
    143    由于文档构建流程所限,中文文档中并没有引入自动生成的函数文档,所以请读者直接
    144    阅读源码注释。
    145
    146电平触发型IRQ流处理程序
    147-----------------------
    148
    149通用层提供了一套预定义的irq-flow方法:
    150
    151-  handle_level_irq()
    152
    153-  handle_edge_irq()
    154
    155-  handle_fasteoi_irq()
    156
    157-  handle_simple_irq()
    158
    159-  handle_percpu_irq()
    160
    161-  handle_edge_eoi_irq()
    162
    163-  handle_bad_irq()
    164
    165中断流处理程序(无论是预定义的还是架构特定的)由架构在启动期间或设备初始化期间分配给
    166特定中断。
    167
    168默认流实现
    169~~~~~~~~~~
    170
    171辅助函数
    172^^^^^^^^
    173
    174辅助函数调用芯片基元,并被默认流实现所使用。以下是实现的辅助函数(简化摘录)::
    175
    176    default_enable(struct irq_data *data)
    177    {
    178        desc->irq_data.chip->irq_unmask(data);
    179    }
    180
    181    default_disable(struct irq_data *data)
    182    {
    183        if (!delay_disable(data))
    184            desc->irq_data.chip->irq_mask(data);
    185    }
    186
    187    default_ack(struct irq_data *data)
    188    {
    189        chip->irq_ack(data);
    190    }
    191
    192    default_mask_ack(struct irq_data *data)
    193    {
    194        if (chip->irq_mask_ack) {
    195            chip->irq_mask_ack(data);
    196        } else {
    197            chip->irq_mask(data);
    198            chip->irq_ack(data);
    199        }
    200    }
    201
    202    noop(struct irq_data *data))
    203    {
    204    }
    205
    206
    207
    208默认流处理程序的实现
    209~~~~~~~~~~~~~~~~~~~~
    210
    211电平触发型IRQ流处理器
    212^^^^^^^^^^^^^^^^^^^^^
    213
    214handle_level_irq为电平触发型的中断提供了一个通用实现。
    215
    216实现的控制流如下(简化摘录)::
    217
    218    desc->irq_data.chip->irq_mask_ack();
    219    handle_irq_event(desc->action);
    220    desc->irq_data.chip->irq_unmask();
    221
    222
    223默认的需回应IRQ流处理器
    224^^^^^^^^^^^^^^^^^^^^^^^
    225
    226handle_fasteoi_irq为中断提供了一个通用的实现,它只需要在处理程序的末端有一个EOI。
    227
    228实现的控制流如下(简化摘录)::
    229
    230    handle_irq_event(desc->action);
    231    desc->irq_data.chip->irq_eoi();
    232
    233
    234默认的边沿触发型IRQ流处理器
    235^^^^^^^^^^^^^^^^^^^^^^^^^^^
    236
    237handle_edge_irq为边沿触发型的中断提供了一个通用的实现。
    238
    239实现的控制流如下(简化摘录)::
    240
    241    if (desc->status & running) {
    242        desc->irq_data.chip->irq_mask_ack();
    243        desc->status |= pending | masked;
    244        return;
    245    }
    246    desc->irq_data.chip->irq_ack();
    247    desc->status |= running;
    248    do {
    249        if (desc->status & masked)
    250            desc->irq_data.chip->irq_unmask();
    251        desc->status &= ~pending;
    252        handle_irq_event(desc->action);
    253    } while (status & pending);
    254    desc->status &= ~running;
    255
    256
    257默认的简单型IRQ流处理器
    258^^^^^^^^^^^^^^^^^^^^^^^
    259
    260handle_simple_irq提供了一个简单型中断的通用实现。
    261
    262.. note::
    263
    264   简单型的流处理程序不调用任何处理程序/芯片基元。
    265
    266实现的控制流程如下(简化摘录)::
    267
    268    handle_irq_event(desc->action);
    269
    270
    271默认的每CPU型流处理程序
    272^^^^^^^^^^^^^^^^^^^^^^^
    273
    274handle_percpu_irq为每CPU型中断提供一个通用的实现。
    275
    276每个CPU中断只在SMP上可用,该处理程序提供了一个没有锁的简化版本。
    277
    278以下是控制流的实现(简化摘录)::
    279
    280    if (desc->irq_data.chip->irq_ack)
    281        desc->irq_data.chip->irq_ack();
    282    handle_irq_event(desc->action);
    283    if (desc->irq_data.chip->irq_eoi)
    284        desc->irq_data.chip->irq_eoi();
    285
    286
    287EOI边沿型IRQ流处理器
    288^^^^^^^^^^^^^^^^^^^^
    289
    290handle_edge_eoi_irq提供了一个异常的边沿触发型处理程序,它只用于拯救powerpc/cell
    291上的一个严重失控的irq控制器。
    292
    293坏的IRQ流处理器
    294^^^^^^^^^^^^^^^
    295
    296handle_bad_irq用于处理没有真正分配处理程序的假中断。
    297
    298特殊性和优化
    299~~~~~~~~~~~~
    300
    301通用函数是为“干净”的架构和芯片设计的,它们没有平台特定的IRQ处理特殊性。如果一
    302个架构需要在“流”的层面上实现特殊性,那么它可以通过覆盖高层的IRQ-流处理程序来实
    303现。
    304
    305延迟中断禁用
    306~~~~~~~~~~~~
    307
    308每个中断可选择的功能是由Russell King在ARM中断实现中引入的,当调用disable_irq()
    309时,不会在硬件层面上屏蔽中断。中断保持启用状态,而在中断事件发生时在流处理器中被
    310屏蔽。这可以防止在硬件上丢失边沿中断,因为硬件上不存储边沿中断事件,而中断在硬件
    311级被禁用。当一个中断在IRQ_DISABLED标志被设置时到达,那么该中断在硬件层面被屏蔽,
    312IRQ_PENDING位被设置。当中断被enable_irq()重新启用时,将检查挂起位,如果它被设置,
    313中断将通过硬件或软件重发机制重新发送。(当你想使用延迟中断禁用功能,而你的硬件又不
    314能重新触发中断时,有必要启用CONFIG_HARDIRQS_SW_RESEND。) 延迟中断禁止功能是不可
    315配置的。
    316
    317芯片级硬件封装
    318--------------
    319
    320芯片级硬件描述符结构体 :c:type:`irq_chip` 包含了所有与芯片直接相关的功能,这些功
    321能可以被irq流实现所利用。
    322
    323-  ``irq_ack``
    324
    325-  ``irq_mask_ack`` - 可选的,建议使用的性能
    326
    327-  ``irq_mask``
    328
    329-  ``irq_unmask``
    330
    331-  ``irq_eoi`` - 可选的,EOI流处理程序需要
    332
    333-  ``irq_retrigger`` - 可选的
    334
    335-  ``irq_set_type`` - 可选的
    336
    337-  ``irq_set_wake`` - 可选的
    338
    339这些基元的意思是严格意义上的:ack是指ACK,masking是指对IRQ线的屏蔽,等等。这取决
    340于流处理器如何使用这些基本的低级功能单元。
    341
    342__do_IRQ入口点
    343==============
    344
    345最初的实现__do_IRQ()是所有类型中断的替代入口点。它已经不存在了。
    346
    347这个处理程序被证明不适合所有的中断硬件,因此被重新实现了边沿/级别/简单/超高速中断
    348的拆分功能。这不仅是一个功能优化。它也缩短了中断的代码路径。
    349
    350在SMP上的锁
    351===========
    352
    353芯片寄存器的锁定是由定义芯片基元的架构决定的。每个寄存器的结构通过desc->lock,由
    354通用层保护。
    355
    356通用中断芯片
    357============
    358
    359为了避免复制相同的IRQ芯片实现,核心提供了一个可配置的通用中断芯片实现。开发者在自
    360己实现相同的功能之前,应该仔细检查通用芯片是否符合他们的需求,并以稍微不同的方式实
    361现相同的功能。
    362
    363该API在以下内核代码中:
    364
    365kernel/irq/generic-chip.c
    366
    367结构体
    368======
    369
    370本章包含自动生成的结构体文档,这些结构体在通用IRQ层中使用。
    371
    372该API在以下内核代码中:
    373
    374include/linux/irq.h
    375
    376include/linux/interrupt.h
    377
    378提供的通用函数
    379==============
    380
    381这一章包含了自动生成的内核API函数的文档,这些函数被导出。
    382
    383该API在以下内核代码中:
    384
    385kernel/irq/manage.c
    386
    387kernel/irq/chip.c
    388
    389提供的内部函数
    390==============
    391
    392本章包含自动生成的内部函数的文档。
    393
    394该API在以下内核代码中:
    395
    396kernel/irq/irqdesc.c
    397
    398kernel/irq/handle.c
    399
    400kernel/irq/chip.c
    401
    402鸣谢
    403====
    404
    405感谢以下人士对本文档作出的贡献:
    406
    4071. Thomas Gleixner tglx@linutronix.de
    408
    4092. Ingo Molnar mingo@elte.hu