Intel VT-d(4)- Interrupt Posting

Interrupt-posting是VT-d中中斷重映射功能的一個擴展功能,該功能也是針對可重映射的中斷請求。Interrupt-posting功能讓一個可重映射的中斷請求能夠被暫時以一定的數據形式post(記錄)到物理內存中,並且可選擇性地主動告知CPU物理內存中暫時記錄著pending的中斷請求。

在x86處理器的虛擬化中,Interrupt-posting再加上APIC Virtualization讓VMM能夠更加高效地處理分配各虛擬機的設備產生的中斷請求。VT-d重映射硬體是否支持Interrupt-posting功能可以通過查詢Capability Register的bit 59 Posted Interrupt Support(PI)知道硬體是否支持該功能。

對於VT-d而言,所有可重定向的中斷都需要經過IRTE(Interrupt Remapping Table Entry)的處理,在進行處理之前會先通過IRTE的bit 15(IRTE Mode)判斷該IRTE的模式,如果為0,則VT-d硬體將會以Remapped Interrupt的形式來解析該IRTE(前一篇文章講的中斷重映射),如果為1,則VT-d硬體將會以Posted Interrupt的形式來解析該IRTE,如下圖所示:

Posted Interrupt格式的IRTE的定義會有一些不同,主要是:

  1. 多了一個Posted Descriptor Address Low/High,該區域保存一個指向內存的指針,該指針指向的位置就是保存中斷(Posted Interrupt)的結構體。
  2. Urgent位,該位用於表示該中斷是否是緊急的,是否需要目標CPU的立即響應。
  3. Vector用於設置Posted Interrupt Descriptor數據結構中相應的位,而不是用於設置直接產生的中斷的vector值。

每個Posted Interrupt Descriptor的大小為64 Byte,用於記錄VT-d硬體那邊post過來的中斷,即在內存中暫時記錄一些中斷請求,等待CPU的處理,而不是主動打斷CPU的運行,讓其跳轉過來處理,其格式如下所示:

  • Posted Interrupt Requests (PIR),一共256 bit,每個bit對應一個中斷向量(Vector),當VT-d硬體將中斷請求post過來的時候,中斷請求相應的vector對應的bit將會被置起來。
  • Outstanding Notification(ON),表示對於該Posted Interrupt Descriptor當前是否已經發出了一個Notification Event等待CPU的處理。當VT-d硬體將中斷請求記錄到PIR的時候,如果ON為0,並且允許立即發出一個Notification Event時,則將會將ON置起來,並且產生一個Notification Event;如果ON已經被置起來,則VT-d硬體不做其他動作。
  • Suppress Notification(SN),表示當PIR寄存器記錄到non-urgent的中斷時,是否不發出Notification Event,如果該位為1,則當PIR記錄到中斷的時候,則不發出Notification Event,並且不更改Outstanding Notification位的值。
  • Notification Vector(NV)表示如果發出Notification Event時,具體的Vector值。
  • Notification Destination(NDST),表示若產生Notification Event時,傳遞的目標邏輯CPU的LAPIC ID(系統中以邏輯CPU的LAPIC ID來表示具體的邏輯CPU,BIOS/UEFI其初始化系統的時候,會為每個邏輯CPU分配一個唯一的LAPIC ID)。

在硬體上整個Posted Interrupt的處理過程如下所示:

當VT-d硬體接收到其旗下I/O設備傳遞過來的中斷請求時,會先查看自己的中斷重定向功能是否打開,如果沒有打開則,直接上傳給LAPIC。如果中斷重定向功能打開,則會查看中斷請求的格式,如果是不可重定向格式,則直接將中斷請求提交給LAPIC。如果是可重定向的格式,則會根據演算法計算Interrupt_Index值,對中斷重定向表進行索引找到相應的IRTE。然後,查看IRTE中的Interrupt Mode,如果為0,則該IRTE的格式為Remapped Format,即立即根據IRTE的信息產生一個新的中斷請求,提交到LAPIC。如果Interrupt Mode為1,則表示該IRTE的格式為Posted Format,根據IRTE中提供的Posted Interrupt Descriptor的地址,在內存中找到相應Posted Interrupt Descriptor,並根據其ON、URG和SN的設置判斷是否需要立即產生一個Notification Event(Outstanding Notification為0,並且該中斷為Urgent(URG=1)或者不抑制該Notification(SN==0)),如果不需要,則只是將該中斷信息記錄到Posted Interrupt Descriptor的PIRR(Posted Interrupt Request Register)欄位,等待CPU的主動處理。如果需要立即產生一個Notification Event,則根據Posted Interrupt Descriptor(會提供目標APIC ID、vector、傳輸模式和觸發模式等信息)產生一個Notification Event,並且將該中斷請求記錄到PIRR欄位。

硬體在對Posted Interrupt Descriptor進行修改的時候,要保證該修改是原子操作,即對Posted Interrupt Descriptor的讀取、修改和寫入必須是原子操作,並且在寫入之後,要保證相應內存在各個cache agent之間的一致性,即所有的CPU應該立馬能夠看到該內存修改。

從軟體的角度來看,VMM可能會對Interrupt Posting做如下設置和操作:

  1. 對於每個vCPU而言,VMM都會分配一個對應的Posted Interrupt Descriptor用於記錄和傳遞經過重定向,並且目的地為對應vCPU的所有中斷請求。
  2. VMM軟體為所有的Notification Event分配兩個物理中斷vector:
    1. 第一個稱作Active Notification Vector(ANV),該Vector對應到當中斷目標vCPU當前正在被邏輯CPU執行(即vCPU的狀態為active)時,Notification Event所使用的中斷vector。
    2. 第二個稱作Wake-up Notification Vector(WNV),該Vector對應到中斷目標vCPU當前不在邏輯CPU上被執行時,由於Urgent被置起來產生的Notification Event所使用的中斷Vector。
  3. 對於從直接分配給VM的I/O設備產生的中斷而言,VMM會為每個這樣的中斷分配一個IRTE。並且VMM可能會為vCPU使能硬體上的APIC Virtualization,APIC Virtualization主要包括兩方面功能:virtual-interrupt delivery和process posted-interrupts,其主要工作形式表現在:
    1. 當一個vCPU被VMM調度即將執行的時候,該vCPU的狀態為active,該狀態的一個表現形式是VMM會將Posted Interrupt Descriptor的Notification Vector欄位設置為ANV(Active Notification Vector)。這樣就允許當這個vCPU在邏輯CPU上執行的時候,所有指向該vCPU的中斷都能夠直接被該vCPU處理,不需要經過VMM。vCPU通過將記錄在Posted Interrupt Descriptor中的中斷直接轉移到Virtual-APIC Page中,並直接將中斷信號傳遞給vCPU,讓vCPU直接獲取到該中斷信號的方式來處理Notification Event。
    2. 當一個vCPU被搶佔後,即vCPU的狀態為ready-to-run,該狀態的一個表現形式是VMM會將Posted Interrupt Descriptor的Notification Vector欄位設置為WNV(Wake-up Notification Vector),並且SN(Suppress Notification)設置為1。只有當接收到的中斷請求為Urgent的時候,才會發出Notification Event,觸發VMM的執行,讓VMM調度目標vCPU處理該緊急中斷。
    3. 當一個vCPU處於Halt狀態的時候,邏輯CPU執行VMM軟體,VMM將該vCPU標記為halted狀態。該狀態的一個表現形式就是將Posted Interrupt Descriptor的Notification Vector欄位設置為WNV(Wake-up Notification Vector),並且SN(Suppress Notification)設置為0,即任何到達該Posted Interrupt Descriptor的中斷請求都會觸發Notification Event,讓VMM喚醒vCPU,讓vCPU處理中斷請求。
  4. 當VMM調度並執行一個vCPU的時候,VMM會對被記錄到Posted Interrupt Descriptor的中斷請求進行處理:
    1. 首先,VMM會通過將Posted Interrupt Descriptor的Notification Vector欄位的值改為ANV將vCPU的狀態變為active。
    2. VMM檢測在Posted Interrupt Descriptor中是否有待處理的中斷請求。
    3. 如果有待處理的中斷請求,則VMM會給當前CPU發送一個sefl-IPI中斷(即CPU自己給自己發送一個中斷),並且中斷向量值為ANV。當vCPU一使能中斷的時候,就能夠立馬識別到該中斷。該中斷的處理類似於vCPU處於active狀態時,接收到了Active Notification Vector的中斷請求,vCPU可以直接對其進行處理,不需要VMM的參與。

同樣VMM可以可以利用Posted Interrupt的處理機制,通過設置Posted Interrupt Descriptor向vCPU注入中斷請求。

總體上來說,Interrupt Posting的功能就是讓系統可以選擇性地將中斷請求暫存在內存中,讓CPU主動去獲取,而不是中斷請求一過來就讓CPU進行處理,這樣在虛擬化的環境中,就能夠防止外部中斷頻繁打斷vCPU的運行,從而提高系統的能能。


推薦閱讀:

TAG:英特爾(Intel) | 中斷 | 虛擬化 |