在PCIe总线中,MSI和MSI-X中断机制使用存储器写请求TLP向处理器提交中断请求,下文为简便起见将传递MSI/MSI-X中断消息的存储器写报文简称为MSI/MSI-X报文。这些PCI设备可能并不支持MSI/MSI-X中断机制,因此必须使用INTx信号进行中断请求。目前绝大多数PCIe设备使用MSI或者MSI-X中断机制提交中断请求。与MSI中断机制相比,MSI-X中断机制更为合理。......
2023-10-20
如果PCI/PCIe设备需要使用MSI中断机制,将调用pci_enable_msi函数,在Linux2.6.31内核中,pci_enable_msi函数使用pci_enable_msi_block(pdev,1)实现。pci_enable_msi_block函数在./drivers/pci/msi.c文件中,如源代码15-8所示。pci_enable_msi_block函数具有两个入口参数,其中dev参数存放PCIe设备的pci_dev结构,而nvec参数为申请的irq号个数。
该函数返回值为0时,表示成功返回,此时该函数将更新pci_dev→irq参数,此时在Linux设备驱动程序中,可以使用的irq号在pci_dev→irq~pci_dev→irq+nvec-1之间;当函数返回值为负数时,表示出现错误;而为正数时,表示pci_enable_msi_block函数没有成功返回,返回值为该PCIe设备MSI Cabalibities结构的Multiple Message Capable字段。
源代码15-8 pci_enable_msi_block函数
这段代码首先检查PCI设备是否支持MSI中断机制,如果不支持将直接退出该函数。否则检查nvec参数和Multiple Message Capable字段的大小,如果nvec的值较大时,该函数直接使用Multiple Message Capable字段返回。
如果pci_enable_msi_block函数通过了这些检查,将调用pci_msi_check_device函数,检查Linux系统是否能够使能PCI设备的MSI中断机制。这个检查包含两方面内容,一方面是纯软件层面的,包括检查全局变量pci_msi_enable、pci_dev→no_msi参数等;一方面是硬件层面的检测,包括当前PCI设备的上游PCI桥是否支持MSI报文的转发,PCI设备是否具有Capabilities链表,是否具有MSI Capability结构。完成这些检查后,pci_enable_msi将进一步调用msi_capability_init函数,完成与MSI中断相关的设置,msi_capability_init函数的实现如源代码15-9~10所示。
源代码15-9 msi_capability_init函数片段1
msi_capability_init函数具有两个入口参数,在Linux 2.6.30内核中,该函数具有一个入口参数,仅能获得一个irq号。msi_capability_init函数参考了msix_capability_init函数的实现机制。这段代码置PCI设备的MSI Capability结构的Enable位为0,msi_capability_init函数需要对MSI Capability结构进行读写操作,因此需要暂时禁止当前设备使用MSI中断机制。
这段程序随后读取MSI Capabilty结构的Message Control字段,并暂时保存在control变量中,在control变量中存放PCIe设备使用的MSI Capability结构的格式,如图10-1所示,MSI Capability结构可以使用4种格式。
最后这段程序调用alloc_msi_entry函数分配一个msi_desc结构的entry参数,并将其初始化后,加入到pci_dev→msi_list链表中。在entry参数中存放该PCI设备使用的MSI中断机制的详细信息。
源代码15-10 msi_capability_init函数片段2
这段代码继续调用arch_setup_msi_irqs函数设置MSI Capability结构的其他字段,并设置entry结构的irq参数,arch_setup_msi_irqs函数的实现与体系结构相关,下文将分别介绍x86和PowerPC处理器的实现方式。
然后这段代码调用pci_intx_for_msi函数,关闭PCI设备配置空间Command寄存器的In-terrupt Disable位,因为该PCI设备将使用MSI中断机制,而不是传统的INTx中断机制;并调用msi_set_enable函数使能MSI Capability结构的Enable位;最后对pci_dev→msi_enabled位置1,并将pci_dev→irq参数赋值。(www.chuimin.cn)
1.Linux x86
Linux x86使用的arch_setup_msi_irqs函数在./arch/x86/kernel/apic/io_apic.c文件中,其实现如源代码15-1所示,本节并不关心intr_remapping_enabled参数为1的情况,该参数与IOMMU机制的IRQ Remapping相关。
源代码15-11 Linux x86使用的arch_setup_msi_irqs函数
这段代码首先判断type是否为PCI_CAP_ID_MSI,而且nvec参数是否大于1,如果满足这两个条件,该函数将直接返回1。通过这段代码可以发现,虽然在Linux 2.6.31内核中定义了一个新的pci_enable_msi_block函数,但是PCIe设备依然只能使用一个中断向量号。
这段程序随后调用create_irq_nr函数,分配PCI设备使用的irq号,并将其保存到irq变量中,之后调用setup_msi_irq函数初始化当前PCI设备的MSI Capability结构。setup_msi_irq函数是一个重要函数,其实现如源代码15-12所示。
源代码15-12 setup_msi_irq函数
这段代码首先调用msi_compose_msg函数,初始化msg结构的address_hi、address_lo和data参数,与MSI Capability结构的Message Upper Address、Message Address和Message Data字段对应。
对于x86处理器系统,Message Address字段的格式见图10-1,其中Destination ID字段与CPU的ACPI ID相关,Linux x86使用cpu_mask_to_apicid_and函数获得该字段的值;而Message Data字段的格式如图10-1所示,其Vector字段由assign_irq_vector函数设置,Trig-ger Mode字段为0x00表示使用边沿触发方式,而Delivery Mode字段为“Fixed Mode”或者“Lowest Priority”。值得注意的是,在Message Data字段中存放的是中断向量号(vector),是一个硬件的概念,而设备驱动程序中使用的irq号是一个软件关系,两者之间存在对应关系,但是并不等同。
set_irq_msi函数设置PCIe设备使用的irq_desc结构;而write_msi_msg函数将msg结构中的参数写入到PCIe设备的对应寄存器中;而set_irq_chip_and_handler_name函数设置MSI中断使用的中断处理程序。本节对这些函数不做进一步介绍。
2.PowerPC
Linux PowerPC使用的arch_setup_msi_irqs函数在./arch/powerpc/kernel/msi.c文件中,对于Freescale的PowerPC处理器,该函数等效与fsl_setup_msi_irqs。fsl_setup_msi_irqs函数的实现,如源代码15-13所示。
源代码15-13 fsl_setup_msi_irqs函数
该函数的实现机制与x86处理器类似,值得提醒读者注意的是在fsl_compose_msi_msg函数中msg→address_hi等于fsl_msi→msi_addr_lo,其值为MSIIR寄存器在PCI总线域的物理地址。在该函数中使用的address_hi、address_lo和data参数的详细描述见第10.2节。本节对此不一一叙述。目前在PowerPC处理器系统中,PCIe设备也只能使用一个中断向量号。
有关PCI Express体系结构导读的文章
在PCIe总线中,MSI和MSI-X中断机制使用存储器写请求TLP向处理器提交中断请求,下文为简便起见将传递MSI/MSI-X中断消息的存储器写报文简称为MSI/MSI-X报文。这些PCI设备可能并不支持MSI/MSI-X中断机制,因此必须使用INTx信号进行中断请求。目前绝大多数PCIe设备使用MSI或者MSI-X中断机制提交中断请求。与MSI中断机制相比,MSI-X中断机制更为合理。......
2023-10-20
PowerPC处理器使用OpenPIC中断控制器或者MPIC中断控制器,处理外部中断请求。值得注意的是,PowerPC处理器和x86处理器处理MSI报文的方式有较大的不同。MPIC中断控制器是Freescale的PowerPC处理器使用的通用中断控制器,目前基于E500内核的处理器,如MPC854x、8572等处理器使用这种中断控制器。目前Freescale的P4080处理器对MPIC中断控制器进行了优化。目前Freescale并没有完全公开P4080处理器的实现细节,因此本节仍以MPC8572处理器为例介绍PCIe设备的MSI中断请求。......
2023-10-20
在PowerPC处理器系统中,MSI机制的实现过程是PCIe设备向MSIIR寄存器写入指定的数据。MPIC中断控制器发现该寄存器被写入后,将向处理器提交中断请求。处理器收到这个中断请求后,将通过读取MPIC中断控制器的ACK寄存器确定中断向量,并依此确定中断源。表10-3 MSIIR寄存器PCIe设备通过MSI机制,向此寄存器写入数据时,MSIR0~7寄存器的相应位SH0~31将有一位置1。......
2023-10-20
在Linux系统中,如果PCI/PCIe设备需要使用MSI-X中断机制,需要调用pci_enable_msix函数,pci_enable_msix函数调用的大多数函数与pci_enable_msi类似,本节并不会重复解释这些函数,该函数的实现如源代码15-14所示。下文将以Intel的e1000e网卡驱动程序说明如何使用MSI-X中断机制挂接中断服务例程。源代码15-15 e1000e_set_interrupt_capability函数当e1000e_set_interrupt_capability函数返回后,MSI-X中断机制使用的中断向量将被保存在adapter->msix_entries数组中,之后e1000_open→e1000_request_irq→e1000_request_msix函数将多次调用request_irq函数将e1000e使用的中断服务例程挂接到系统中断服务程序中,e1000_request_msix函数的实现如源代码15-16所示。......
2023-10-20
1基本中断处理流程Linux内核的中断处理框架当然要满足之前提到的各种需求。对Linux内核来说,每个中断号都是通过irq_desc进行描述的,可以说irq_desc是中断处理的核心。通过这些抽象结构就可以实现整个中断处理的框架。2中断处理延时操作下面介绍系统如何解决中断中大数据量时的延时处理问题。图4-28是Linux内核中断处理流程。......
2023-11-22
[5]微软规定了一系列PnP设备规范,详见http://www.microsoft.com/whdc/system/pnppwr/pnp/default.mspx。而SCI中断也被称为ACPI中断,下文将详细介绍该中断的实现机制。[11]ACPI 4.0规范的第5.6节APIC Event Programming Model中定义了一系列回调号。[12]在FACP.dsl文件中存放SCI Interrupt使用的中断向量。[13]该函数为ACPICA提供的OS服务层接口函数。[20]如第14.1.3节所示,pci_legacy_init函数在执行过程中需要检查pcibios_scanned参数,当该参数为1时,该函数将直接返回。PCIe设备可以通过INTx中断消息报文,向I/O APIC提交中断请求,详见第6.3.4节。......
2023-10-20
图4-25中断在系统中的连接示意图从图4-25中可见,中断相关的硬件包括设备、中断控制器和处理器。这需要对中断控制器进行不同的操作逻辑来避免该类问题的发生,中断处理逻辑需要和中断控制器的操作相结合以使中断处理能正确的执行。以上主要还是功能需求,对于性能方面,中断处理都是有时间要求的,所以会有中断响应时间这一性能指标的要求。好的系统需要在大量上报中断时仍能有较小的中断响应时间。......
2023-11-22
Linux操作系统为串行口提供了很好的支持。Linux系统中串口设备被当做一个字符设备处理。图7.6m inicom配置端口结束如图7.6所示,串口被设置为tty0,波特率是38 400,其他配置为默认设置。图7.7m inicom命令界面2.操作串口需要用到的头文件在Linux系统操作串口需要用到以下头文件:在编写串口操作程序的最开始引用这些文件即可。串口的打开和关闭和文件相同。......
2023-11-19
相关推荐