Linux中PowerPC的中斷原理分析

來源:互聯網
上載者:User

    在瞭解中斷處理機制前,先看一下PowerPC的中斷源,這裡使用的是e300c3的核心,從E300核的角度,中斷源可分為異常和外部中斷,異常是e300核心產生的,如出現非法指令,或者是訪問儲存空間時出現TLB Miss等情況。這種情況太複雜了,沒有深究,這裡所說的中斷為外部中斷。所謂外部中斷,就是通過e300外部引腳產生的中斷。E300的外部中斷主要有:int#, cint#, mcp#. 這三根pin分別對應一般中斷,critical中斷和machine
check中斷。

    在裝置驅動過程中,使用者可以使用request_irq函數將外設的插斷服務常式掛載到外部中斷處理常式中。外部中斷處理常式,可以直接處理硬體中斷,但是request_irq函數試用軟體中斷號進行掛載,因此linux必然採用了某種方式進行軟硬體中斷的映射。

    這裡需要瞭解下中斷向量表的概念,就是它將軟體中斷號與硬體中斷號聯絡起來,在系統中,中斷源有很多,當某一種中斷髮生時,處理器最早進入的是處理函數的地址,就是中斷向量。每種類型對應一個中斷向量號,一系列的中斷號構成中斷向量表。比如驅動程式關心的外部中斷,當這種中斷髮生時,處理器核心(e300)就會到指定寄存器中去取得中斷處理函數的入口地址。

    硬體中斷號是當中斷髮生時,處理器從外部的PIC(Programable Interrupt Controller)上讀到的數值。因為在PowerPC Linux中有dts的概念,驅動程式員需要知道自己所負責的裝置對應的device node上的interrupt項如何寫的問題,這裡的interrupt上的數字就是硬體中斷號。在Linux系統初始化期間,通過對PIC的配置,可以將硬體的串連轉化成相應的硬體中斷號,例如,8315上的8根外設中斷線IRQ0~IRQ7,可以通過PIC的配置,分別映射成的硬體中斷號為10~18,那麼當IRQ0上有插斷要求時,處理器通過讀取PIC,就得到P1所對應的硬體中斷號為10。這些都是硬體層面的東西,當驅動程式安裝它們的中斷處理常式時,是基於軟體中斷號的,也就是核心功能request_irq中的參數irq是個軟體中斷號。

    軟體中斷號是Linux下的概念,為了支援多平台的關係,Linux不直接用硬體中斷號索引irq_desc。所以當外部中斷髮生時,在外部中斷入口函數中會通過讀取PIC來獲得本次中斷的硬體中斷號,獲得硬體中斷號後,會將其映射成對應的軟體中斷號來索引irq_desc數組,從而獲得該軟體中斷號上的中斷處理函數。顯然,這種硬體中斷號到軟體中斷號的映射關係,應該在裝置可以處理中斷前就要建立好了。在Linux PowerPC中,這種映射關係是由函數irq_of_parse_and_map(struct
device_node *dev, int index)來完成的。

    注意:在8315中,關於MSI的硬體中斷號,可以在系統全域中斷向量寄存器SIVCR中查詢。另外,其實,如果沒有軟體中斷號,裝置驅動程式也能以硬體中斷號作索引掛載處理常式,從功能上說沒有任何問題。軟體中斷號的引入,是為了硬體中斷號對OS透明。這樣處理能減少OS對硬體平台的依賴性。

下面貼些核心的代碼,方便細細分析:

    linux使用結構體struct irq_map_entry irq_map[NR_IRQS]完成軟體與硬體的中斷號映射,一般系統自動尋找可用的軟體號以對應請求的硬體中斷號。

    在使用open firmware的系統中,驅動程式在執行ruquest_irq之前要先進行軟硬體中斷號的映射,具體通過函數:
irq_of_parse_and_map(struct device_node * dev, int index);
    實現,具體函數調用過程如下:
irq_create_of_mapping(struct device_node * controller, u32 * inspec, unsigned int intsize);
irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq);
    程式除了進行軟硬體中斷號的映射外還需要初始後相應結構。
下面看看與中斷相關的另外幾個主要資料結構:
1、結構體:struct irq_desc(include/linux/irq.h)

struct irq_desc {unsigned intirq;struct timer_rand_state *timer_rand_state;unsigned int            *kstat_irqs;#ifdef CONFIG_INTR_REMAPstruct irq_2_iommu      *irq_2_iommu;#endifirq_flow_handler_thandle_irq;struct irq_chip*chip;struct msi_desc*msi_desc;void*handler_data;void*chip_data;struct irqaction*action;/* IRQ action list */unsigned intstatus;/* IRQ status */unsigned intdepth;/* nested irq disables */unsigned intwake_depth;/* nested wake enables */unsigned intirq_count;/* For detecting broken IRQs */unsigned longlast_unhandled;/* Aging timer for unhandled count */unsigned intirqs_unhandled;raw_spinlock_tlock;#ifdef CONFIG_SMPcpumask_var_taffinity;const struct cpumask*affinity_hint;unsigned intnode;#ifdef CONFIG_GENERIC_PENDING_IRQcpumask_var_tpending_mask;#endif#endifatomic_tthreads_active;wait_queue_head_t       wait_for_threads;#ifdef CONFIG_PROC_FSstruct proc_dir_entry*dir;#endifconst char*name;} ____cacheline_internodealigned_in_smp;

這個結構體用來描述中斷源,是用來串連硬體中斷和驅動程式中通過request_irq註冊的中斷處理函數之間的橋樑。數組irq_desc[NR_IRQS](NR_IRQS=225)中每一項都對應一個相應的中斷源,他的每一項對應著中斷向量表中的一項,即該數組的第一項對應著中斷向量表中的第32項(中斷向量號為0x20),往下依次對應。中斷向量表一共有256項。
部分成員解釋:
status:或者是0,或者是從一個特定的集合中抽取的一個標誌位(不太清楚)。這些標誌位代表了IRQ的狀態--是否被禁止,有關IRQ的裝置當前是否正被自動檢測等。
chip:是一個指向hw_interrupt_type(或者irq_chip)的指標。其中定義的函數是平台相關的(更具體的,是中斷控制器相關的),很顯然不同平台的中斷控制器擁有不同的操作函數,比如enable, disable, mask, unmask某個中斷的操作。從平台移植的角度,chip屏蔽了底層硬體的不同,使得在核心中某些代碼成了平台無關性。但是對於不同平台的Linux,必須由BSP部分負責初始化irq_desc中的chip變數。

action:是一個指向由irqaction結構體組成的一個單向鏈表的頭的指標。若一個IRQ只被一個中斷源使用,那麼該鏈表的長度就是1,當有多個裝置共用一個中斷源時,該鏈表就會由多個irqaction結構體組成,下面對此有介紹。
depth:irq_desc_t的目前使用者的個數,主要用來保證事件正在處理的過程中IRQ不會被禁止。

從驅動程式開發人員角度,不需要直接調用chip中的函數。但是在驅動程式request_irq時,因為要在irq_desc所對應的某一項中安裝中斷處理函數,request_irq函數原型如下:
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id)

其中第三個參數irqflags會影響到核心對chip中函數的調用,所以從這個角度而言,瞭解一些chip相關的中斷enable/disable/mask/unmask對驅動程式員是有協助的。
2、結構體:struct irqaction(include/linux/interrupt.h)

struct irqaction {irq_handler_t handler;unsigned long flags;const char *name;void *dev_id;struct irqaction *next;int irq;struct proc_dir_entry *dir;irq_handler_t thread_fn;struct task_struct *thread;unsigned long thread_flags;};

這個結構體包含了處理一種中斷所需要的各種資訊,它代表了核心接受到特定IRQ之後應該採取的操作。
主要成員:
handler—該指標所指向的函數就是在中斷服務程式,當中斷髮生時核心便會調用這個指標指向的函數。
flags:該標誌位可以是0,也可以是:SA_INTERRUPT(表示此中斷處理常式是一個快速中斷處理常式,在2.6中預設情況下沒有這個標誌)SA_SAMPLE_RANDOM(表示這個中斷對核心池有貢獻,我理解為就是在中斷時產生一些隨機數,這些隨機數被用來作為加密密匙,因為中斷是隨機發生的,如果某種中斷是有頻率的被產生,那麼它就不要設定此標誌位,還有就是那種裝置容易被攻擊也不應該設定此標誌位)SA_SHIRQ(此標誌位表示允許多個中斷服務程式共用一個中斷號,如不設則一個程式對應一個中斷線)。
mask:在x86上不會用到。
name:產生中斷的硬體的名字.
dev_id:該標誌位主要在共用中斷號時使用,即你設定flags=SA_SHIRQ時,有多個中斷服務程式共用一個中斷號時,核心就需要知道在用完中斷程式後該刪除那個中斷服務程式。不共用時此成員為null。
next:如果flags=SA_SHIRQ,那麼這就是指向對列中下一個struct irqaction結構體的指標,否則為空白。
irq:不用說這就是中斷號了。
3 結構體:struct hw_interrupt_type(include/linux/irq.h)

struct irq_chip {const char*name;unsigned int(*startup)(unsigned int irq);void(*shutdown)(unsigned int irq);void(*enable)(unsigned int irq);void(*disable)(unsigned int irq);void(*ack)(unsigned int irq);void(*mask)(unsigned int irq);void(*mask_ack)(unsigned int irq);void(*unmask)(unsigned int irq);void(*eoi)(unsigned int irq);void(*end)(unsigned int irq);int(*set_affinity)(unsigned int irq,const struct cpumask *dest);int(*retrigger)(unsigned int irq);int(*set_type)(unsigned int irq, unsigned int flow_type);int(*set_wake)(unsigned int irq, unsigned int on);void(*bus_lock)(unsigned int irq);void(*bus_sync_unlock)(unsigned int irq);/* Currently used only by UML, might disappear one day.*/#ifdef CONFIG_IRQ_RELEASE_METHODvoid(*release)(unsigned int irq, void *dev_id);#endif/* * For compatibility, ->typename is copied into ->name. * Will disappear. */const char*typename;};

它是用來描述中斷控制器的,也就是一個抽象的中斷控制器,其成員是一系列指向函數的指標。
typename:給相應的控制器起一個便於理解的名字。
startup:允許從給定的控制器的IRQ所產生的事件。(基本上與enable相同)
shutdown:禁止從給定的控制器的IRQ所產生的事件。(基本上與disable相同)
以上三個結構體的關係可以用下面一張圖來說明IRQ結構間的關係:

 

數組irq_desc_t用來描述中斷的相關資訊,它有225項,每一項代表一個中斷源,其中欄位irq(注意這個欄位就是中的handler欄位),此結構體用來描述中斷控制器,action欄位用來描述處理一種中斷所需要的各種資訊,它代表了核心接受到特定IRQ之後應該採取的操作。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.