ARM GIC(六)gicv3架構-LPI
在gicv3中,引入了一種新的中斷型別。message based interrupts,訊息中斷。
一、訊息中斷
外設,不在通過專用中斷線,向gic傳送中斷,而是寫gic的暫存器,來發送中斷。
這樣的一個好處是,可以減少中斷線的個數。
為了支援訊息中斷,gicv3,增加了LPI,來支援訊息中斷。並且為他分配了特別多的中斷號,從8192開始,移植到16777216。
LPI,locality-specific peripheral interrupts。spec中,用了一章,來介紹這個LPI。
二、LPI介紹
LPI是一種基於訊息的邊沿中斷。也就是,中斷資訊,不在通過中斷線,進行傳遞,而是通過memory。gic內部,提供一個暫存器,當外設往這個地址,寫入資料時,就往gic傳送了一箇中斷。
在soc系統中,外設想要傳送中斷給gic,是需要一根中斷線的。如果現在一個外設,需要增加一箇中斷,那麼就要增加一根中斷線,然後連線到gic。這樣,就需要修改設計。而引入了LPI之後,當外設需要增加中斷,只需要使用LPI方式,傳輸中斷即可,不需要修改soc設計。
引入了LPI之後,gicv3中,還加入了ITS元件,interrupt translation service。ITS將接收到的LPI中斷,進行解析,然後傳送到對應的redistributor,再由redistributor將中斷資訊,傳送給cpu interface。
以下是帶LPI的框圖。外設,通過寫 GITS_TRANSLATER 暫存器,來傳遞訊息中斷。
LPI,和SPI,PPI,SGI有些差別,LPI的中斷的配置,以及中斷的狀態,是儲存在memory的表中,而不是儲存在gic的暫存器中的。
◾GICR_PROPBASER:儲存LPI中斷配置表的基地址
◾GICR_PENDBASER: 儲存LPI中斷狀態表的基地址
這裡,就涉及到兩個表:
1、LPI中斷配置表
該表,儲存在memory中。基地址,由GICR_PROPBASER暫存器決定。
該暫存器描述如下:
其中的Physical_Address欄位,指定了LPI中斷配置表的基地址。
對於LPI配置表,每個LPI中斷,佔用1個位元組,指定了該中斷的使能和中斷優先順序。
當外部發送LPI中斷給redistributor,redistributor首先要查該表,也就是要訪問memory來獲取LPI中斷的配置。為了加速這過程,redistributor中可以配置cache,用來快取LPI中斷的配置資訊。
因為有了cache,所以LPI中斷的配置資訊,就有了2份拷貝,一份在memory中,一份在redistributor的cache中。如果軟體修改了memory中的LPI中斷的配置資訊,需要將redistributor中的cache資訊給無效掉。
2、LPI中斷狀態表
該表,處於memory中,儲存了LPI中斷的狀態,是否pending狀態。
LPI中斷的狀態,不是儲存在暫存器中,而是儲存在memory中的pending表中。該狀態表,由redistributor來進行更改。而該table的基地址,是由軟體來設定的。
軟體通過設定 GICR_PENDBASER 暫存器來設定。
該暫存器,設定LPI狀態表的基地址,該狀態表的memory的屬性,如shareability,cache屬性等。
每個LPI中斷,佔用一個bit空間
◾0: 該LPI中斷,沒有處於pending狀態
◾1: 該LPI中斷,處於pending狀態
該狀態表,由redistributor來設定。軟體如果修改該表,會引發unpredictable行為。
三、LPI的實現方式
為了實現LPI,gicv3定義了以下兩種方法來實現:
◾使用ITS,將外設傳送到eventID,轉換成LPI 中斷號
◾forwarding方式,直接訪問redistributor的暫存器GICR_SERLPIR,直接傳送LPI中斷
1、forwarding方式
這種方式,比較簡單,主要由下面幾個暫存器來實現:
◾GICR_SERLPIR
◾GICR_CLRLPIR
◾GICR_INVLPIR
◾GICR_INVALLR
◾GICR_SYNCR
其gic框圖如下所示:
GICR_SERLPIR,將指定的LPI中斷,設定為pending狀態。
GICR_INVLPIR,將指定的LPI中斷,清除pending狀態。暫存器內容和GICR_SERLPIR一致。
GICR_INVLPIR,將快取中,指定LPI的快取給無效掉,使GIC重新從memory中載入LPI的配置。
GICR_INVALLR,將快取中,所有LPI的快取給無效掉,使GIC重新從memory中,載入LPI中斷的配置。
GICR_SYNCR,對redistributor的操作是否完成。
暫存器,只有第0bit是有效的。如果為0,表示當前對redistributor的操作是完成的,如果為1,那麼是沒有完成的。
2、使用ITS方式
理解了forwarding方式,那麼理解ITS方式,就要容易了。forwarding方式,是直接得到了LPI的中斷號。
但是對於ITS方式,是不知道LPI的中斷號的。需要將外設傳送的DeviceID,eventID,通過一系列查表,得到LPI的中斷號以及該中斷對應的target redistributor,然後將LPI中斷,傳送給對應的redistributor。
下圖是帶有ITS的gic框圖:
外設,通過寫GITS_TRANSLATER暫存器,發起LPI中斷。寫操作,給ITS提供2個資訊:
◾EventID:值儲存在GITS_TRANSLATER暫存器中,表示外設傳送中斷的事件型別
◾DeviceID:表示哪一個外設發起LPI中斷。該值的傳遞,是實現自定義,例如,可以使用AXI的user訊號來傳遞。
ITS將DeviceID和eventID,通過一系列查表,得到LPI中斷號,再使用LPI中斷號查表,得到該中斷的目標cpu。
ITS將LPI中斷號,LPI中斷對應的目標cpu,傳送給對應的redistributor。redistributor再將該中斷資訊,傳送給CPU。
四、ITS
ITS是一個元件,用來提供給外設,傳送LPI中斷的,然後將LPI中斷,傳送給redistributor。
1、ITS處理流程
ITS使用三類表格,實現LPI的轉換和對映:
◾device table: 對映deviceID到中斷轉換表
◾interrupt translation table:對映EventID到INTID。以及INTID屬於的collection組
◾collection table:對映collection到redistributor
當外設往GITS_TRANSLATER暫存器中寫資料後,ITS做如下操作:
◾使用DeviceID,從裝置表(device table)中選擇索引為DeviceID的表項。從該表項中,得到中斷對映表的位置
◾使用EventID,從中斷對映表中選擇索引為EventID的表項。得到中斷號,以及中斷所屬的collection號
◾使用collection號,從collection表格中,選擇索引為collection號的表項。得到redistributor的對映資訊
◾根據collection表項的對映資訊,將中斷資訊,傳送給對應的redistributor
以上是物理LPI中斷的ITS流程。虛擬LPI中斷的ITS流程與之類似。以下是處理流程圖:
2、ITS命令
ITS操作,會涉及到很多表,而這些表的建立,維護是通過ITS命令,來實現的。雖然這些表,是在記憶體中的,但是GICv3和GICv4,不支援直接訪問這些表,而是要通過ITS命令,來配置這些表。
ITS的操作,是通過命令,來控制的。外部通過傳送命令給ITS,ITS然後去執行命令,每個命令,佔32位元組。
ITS有command佇列,命令寫在這個佇列裡面。ITS會自動的按照佇列順序,一一執行。
每個命令佔32個位元組。
命令,存放在記憶體中,GITS_CBASE,儲存命令的首地址。GITS_CREADR,是由ITS控制,表示下一個命令的地址。GITS_CWRITER,是下一個待寫命令的地址。軟體往GITS_CWRITER地址處,寫入命令,之後ITS就會執行這個命令。
ITS提供的命令,有很多,可以查閱GIC手冊獲取更多。
以下是CLEAR命令。
3、ITS table
ITS包括很多個表,這些表均處於 non-secure區域。
GITS_BASER,指定ITS表的基地址和大小。軟體,在使用ITS之前,必須要配置。
其中的Physical_Address欄位,就指定了表的基地址所在位置。
以下是各個表的基地址,對應的暫存器。
五、總結
gicv3中,引入了訊息中斷,並且為之,支援了LPI。分配了大量的中斷號,用於LPI。對於LPI的實現,有2種方式,一種是訪問redistributor提供的暫存器,一種是使用ITS。
不過對於手機arm cpu來說,其實是不需要LPI的,因為現有的中斷,已經符合要求,加入了LPI,讓gic更復雜,讓軟體操作,也更復雜。但是對於伺服器arm cpu,這個,就需要了,因為這個可以和PCIE相連,實現訊息中斷。個人感覺,這個LPI中斷,是為arm伺服器cpu,所使用的。
對於提供的gic IP來說,比如gic600,是有配置選項,決定,是否是否支援LPI中斷,以及是否需要ITS。
原文首發於駿的世界部落格
作者:盧駿.
更多Arm技術相關的文章請關注我,每週都有更新。