PCI IRQ Routing

PCI IRQ Routing

1.  Why IRQ Routing

 

在计算机发展的历史中,很多技术的出现都是为了解决当前所面临的问题而产生和发展出来的,PCI IRQ Routing也不例外,随着计算机系统的功能需求的增加,越来越多的PCI/PCIE设备被加入到系统中来,可是PIC mode下却只有15 IRQ可供使用(即使是APIC,目前也只是有24INTIN),而且在早期device都是直接拉线到8259  IRQ,所以一旦确定就没法改变,没有灵活性。于是中断共享就是这种情况下解决这一问题的一个方法(当然其他的方法如使用MSI,SIRQ等也都可以实现中断的复用),可是中断共享了以后又会有新的问题出现 那就是如何分配这些中断的使用 才能够达到负载均衡(Loading Banlance),上述的这些问题就使得PCI IRQ Routing应运而生了。

2.  How to Routing

 

1.     Routing for Internal Device

 

新的chipset为了Internal Device Interrupt Routing有更大的灵活性,在chipset内部加入了以下几个新的register 为方便SBIOS去配置;这几个register分别是D**IPIntertupt Pin Register)用于设定对应的device所使用的Interupt PinD**IRInterrupt Router Register)用于设定Interrupt Pin所使用的Interrupt RouterPIRQA#-H#);PIRQ_ROUT Routing Control Register),用于设定PCI Device Interrupt Pin INTA#-H# 连接到具体PIC controllerIRQ*上,在8259 PIC ModeSBIOS需要去设置PIRQ_ROUTregister 用于指定具体的IRQAPIC Mode PIRQ_ROUT则是固定的连接到APIC INTIN pin上,PIRQA#-H#分别连接到INTIN16-INT23。比如我们想配置Device31 Function2 也就是Sata Controller 1IRQ Routing 是使用INTA#  PIRQA# 最终接到PIC IRQ5,那么我们需要做的配置将会如下图所示:

 

    

 


2.     Routing for PCIE Root Ports

 

PCIE Root Ports扮演的是一个P2P bridge的角色,Root Ports自身产生的Intterupts的处理方式和Internal Devices处理方式一样;Root Ports所接入的设备所产生的Intterupts,则会有Root Ports转发给上一级的Root Complex去处理。为了Intterupt Sharing更加的均衡合理, 在转发给Root Complex之前这些来自Downstream PCIE Devices产生的Intterupt将会被chipset内部的称之为swizzling的一个机制处理过之后再丢给Root Complex,这个部分就是完全的HW机制,它的基本原理就是将来自Downstream PCIE Devices INTA#=H# 产生的中断请求 再转化一遍,比如接在Root Ports 2上的INTA#将会被转成INTB# 然后再丢给上层的Root Complex。经过Swizzling之后,INTA#-H# 会被分别连接到PIRQA#-H#.

3.     Routing for PCI Expansion Slots

 

PCI Expansion Slots通常是指通过PNP Bridge扩展出来的PCI 插槽(slots),在这些slots上可以接入PCI Device。这些PCI Expansion Slots IRQ RoutingPCIE Root Ports非常接近,主要的区别可能就是swizzling的部分需要HW自己去拉,实现的原理和chipset 内置的swizzling应该是类似的。最终PCI Slot上的device经过swizzling之后 INTA#-H#会被分别连接到PIRQA#-H#.

3.  Reporting IRQ Routing to OS

 

SBIOSPCI IRQ Routing信息配置好以后就需要将这些信息提供给OS,为OS获取系统整个IRQ的分配提供一个基本的参考依据。当然OS并不一定要严格按照SBIOS提供的信息去配置PCI Device它也会依据获取信息动态的去分配这些IRQ Routing。通常SBIOS回报给OS这些信息有两种方式,

对于Legacy OSSBIOS会通过PCI IRQ Routing Table 的方式告知OS;对于ACPI OS SBIOS则是通过在对应的PCI Device space中提供_PRT method告知ACPI OS 系统的IRQ Routing的方式。

1.      PCI IRQ Routing Table (Legacy OS)

 

Legacy OS Intterupt Controller 通常是工作在PIC ModeBIOS需要按照微软规定的PCI IRQ Routing Table SpecificationPCI Devices IRQ Routing信息回报给Legacy OS。这张IRQ Routing Table的格式如下所示:

 

Byte Offset

Size in Bytes

Name

0

4

Signature

4

2

Version

6

2

Table Size

8

1

PCI Interrupt Router's Bus

9

1

PCI Interrupt Router's DevFunc

10

2

PCI Exclusive IRQs

12

4

Compatible PCI Interrupt Router

16

4

Miniport Data

20

11

Reserved (Zero)

31

1

Checksum

2

16

First Slot Entry

48

16

Second Slot Entry

(N + 1) * 16

16

Nth Slot Entry

 

Byte Offset

Size in Bytes

Name

0

Byte

PCI Bus Number

1

Byte

PCI Device Number (in upper five bits)

2

Byte

Link Value for INTA#

3

Word

IRQ Bitmap for INTA#

5

Byte

Link Value for INTB#

6

Word

IRQ Bitmap for INTB#

8

Byte

Link Value for INTC#

9

Word

IRQ Bitmap for INTC#

11

Byte

Link Value for INTD#

12

Word

IRQ Bitmap for INTD#

14

Byte

Slot Number

15

Byte

Reserved

 

SBIOS会将这张table放在F segmentF0000h-FFFFF, 我们可以通过Search “$PIR” Signature去找到这张表格。

2.      ACPI _PRT Packages (ACPI OS)

 

ACPI OS 需要通过_PRT Packages Routing的信息 ReportOS,而且根据PIC/APIC Mode的不同,_PRT回报给OS Packages也会有不同。

A.PIC Mode回报Routing信息的sample code如下所示:(所有code 均来自google 大神):

   OperationRegion (/_SB.PCI0.SBRG.PIX0, PCI_Config, 0x60, 0x0C)

    Field (/_SB.PCI0.SBRG.PIX0, ByteAcc, NoLock, Preserve)

    {

        PIRA,   8,

        PIRB,   8,

    }

  Device (LNKA)

        {

            Name (_HID, EisaId ("PNP0C0F"))

            Name (_UID, 0x01)

            Method (_STA, 0, NotSerialized)

            {

                And (PIRA, 0x80, Local0)

                If (Local0)

                {

                    Return (0x09)

                }

                Else

                {

                    Return (0x0B)

                }

            }

 

            Method (_PRS, 0, NotSerialized)

            {

                Return (PRSA)

            }

 

            Method (_DIS, 0, NotSerialized)

            {

                Or (PIRA, 0x80, PIRA)

            }

 

            Method (_CRS, 0, NotSerialized)

            {

                And (PIRA, 0x0F, Local0)

                ShiftLeft (0x01, Local0, IRA0)

                Return (BUFA)

            }

 

            Method (_SRS, 1, NotSerialized)

            {

                CreateWordField (Arg0, 0x01, IRA)

                FindSetRightBit (IRA, Local0)

                Decrement (Local0)

                Store (Local0, PIRA)

            }

        }

  Name (PR00, Package (0x12)

        {

            Package (0x04)

            {

                0x0001FFFF,

                0x00,

                LNKA,

                0x00

            },

 

            Package (0x04)

            {

                0x0001FFFF,

                0x01,

                LNKB,

                0x00

            },

        ……

         Package (0x04)

            {

                0x001DFFFF,

                0x00,

                LNKH,

                0x00

            },

 

            Package (0x04)

            {

                0x001DFFFF,

                0x01,

                LNKD,

                0x00

            },

 

            Package (0x04)

            {

                0x001DFFFF,

                0x02,

                LNKC,

                0x00

            },

 

            Package (0x04)

            {

                0x001DFFFF,

                0x03,

                LNKA,

                0x00

            },

       

        })

    Device (PCI0)

            {

             Name (_HID, EisaId ("PNP0A08"))

            Name (_CID, 0x030AD041)

            Name (_ADR, 0x00)             

            Method (_PRT, 0, NotSerialized)

                {

                    If (PICM)

                    {

                        Return (AR00)

                    }

 

                    Return (PR00)

                }

       

}

上面是从网上搜到的一个PIC Mode Routing 信息的一部分的code,我们从底往上看,上述code表示Device (PCI0) scope下的所有device Routing信息PICM用于表示当前使用的是PIC 还是APIC  Mode,当PIC Mode时就回复PR00packagePR00表示bus 0 device 0x1f INTA#routingPIRQAbus 0 device 0x1f INTB#routingPIRQB,后面的一个bus 0 device 0x1d也是表示相同的意义。PR00 Package中的LNKA LNKB  device其实表示的是PIRQA PIRQB这些register以及操作这些registerfunction Device (LNKA)中的_STA表示现在使用的PIRQ* Status 如果Interrupt Routing Enable bitdisable了,将会report 0x1001表示device is disable and do not decode its resource_PRS表示该PIRQ* 可以使用的interrupt 范围以及相关的属性(level /edge trigger  active low/high shared …;_CRS表示当前的Interrupt 以及属性,_SRS用设定相应的interrupt及属性;所有这些操作都是对PIRQ* register进行,这些register则通过ACPI OperationRegion的方式宣告出来如下所示:

   OperationRegion (/_SB.PCI0.SBRG.PIX0, PCI_Config, 0x60, 0x0C)

    Field (/_SB.PCI0.SBRG.PIX0, ByteAcc, NoLock, Preserve)

    {

        PIRA,   8,

        PIRB,   8,

}

B.APIC Mode回报Routing信息的sample code如下所示:(所有code 均来自google 大神):

Name (AR00, Package (0x12)

        {

            Package (0x04)

            {

                0x0001FFFF,

                0x00,

                0x00,

                0x10

            },

 

            Package (0x04)

            {

                0x0001FFFF,

                0x01,

                0x00,

                0x11

            },

 

            Package (0x04)

            {

                0x0001FFFF,

                0x02,

                0x00,

                0x12

            },

 

            Package (0x04)

            {

                0x0001FFFF,

                0x03,

                0x00,

                0x13

            },

 

            Package (0x04)

            {

                0x001FFFFF,

                0x00,

                0x00,

                0x12

            },

 

            Package (0x04)

            {

                0x001FFFFF,

                0x01,

                0x00,

                0x13

            },

 

            Package (0x04)

            {

                0x001DFFFF,

                0x00,

                0x00,

                0x17

            },

 

            Package (0x04)

            {

                0x001DFFFF,

                0x01,

                0x00,

                0x13

            },

 

            Package (0x04)

            {

                0x001DFFFF,

                0x02,

                0x00,

                0x12

            },

 

            Package (0x04)

            {

                0x001DFFFF,

                0x03,

                0x00,

                0x10

            },

 

           

        })

    Device (PCI0)

            {

             Name (_HID, EisaId ("PNP0A08"))

            Name (_CID, 0x030AD041)

            Name (_ADR, 0x00)             

            Method (_PRT, 0, NotSerialized)

                {

                    If (PICM)

                    {

                        Return (AR00)

                    }

 

                    Return (PR00)

                }

       

}

APIC Mode _PRT就比较简单了,Package AR00回报bus 0 device 0x1f INTA#直接连接到APIC INTIN16 INTB#连接到INTIN17INTC#连接到INTIN18, INTD#连接到INTIN19等等,在ACPI OS下会有APIC相关的driver根据这些信息设置REDIR_TBL中每个INITIN* 的属性及中断向量等信息。

SBIOS如果需要更改Routing信息,就可以按照上面的sample code的做法去修改AR00 PR00 package中的设置。另外关于APICI/O APIC ,LAPICBase  Address GlobalIrqBase…等信息 SBIOS会通过Multiple APIC Description Table (MADT) 回报给ACPI OS,这样OS下的driver就可以直接配置和处理与APIC相关的中断的产生、处理、属性等。

 

 

Refer

 

PCI IRQ Routing Table Specification

PCI IRQ Routing on a Multiprocessor ACPI System

ACPI Spec 3.0

 

 

 

 

Peter

2010-10-29

 

你可能感兴趣的:(BIOS,Internals)