日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

中断处理的那些事儿

發布時間:2025/3/15 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 中断处理的那些事儿 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

繼續“那些事兒”系列,這次的主題是Intel的中斷處理。參考的資料主要來自Intel文檔第三冊的第六、第十和第二十九章節,以及這篇文章。其中,有一部分的內容來自于上面提到的那篇文章。

以下內容主要圍繞下面五個問題來展開:

  • 第一,中斷是什么,種類有哪些?
  • 第二,中斷是如何被發送給CPU的?
  • 第三,CPU是如何對接收到的中斷進行處理的?
  • 第四,中斷的優先級問題?
  • 第五,虛擬化環境對中斷提供了哪些支持?

接下來會對它們一一進行解答。

中斷是什么,種類有哪些?

我們經常會將中斷(Interrupt)和異常(Exception)混在一起進行說明,可以說,它們有相似的地方,也有不同的地方。相似的地方在于,它們都是因為系統發生了某些事件,使得處理器需要暫停當前的執行流,從而抽出精力(進到某個預先設定好的路徑中)來處理這些事件。不同的地方在于它們的來源,以及從事件發生到最終被處理的整條路徑都是不一樣的。這篇博文主要關注中斷,所以對異常就不去詳談了。

一般來說,中斷主要是由一些硬件設備產生的,表示這些硬件有一些重要的事件需要通知處理器,比如某些從外部設備請求的數據準備好了,需要通知處理器對其進行讀取等。當然這里所謂的“一般來說”是指也可以通過軟件的方式來觸發中斷,比如調用INT n指令,當然這種方式產生的中斷和通過意見產生的中斷最終的處理方式會有很大的不同。 因此從種類來分,可以將中斷分為通過硬件產生的外部中斷(External interrupt)和通過軟件產生的軟件中斷(Software interrupt)。不管是外部中斷還是軟件中斷,每個中斷都有一個中斷號與之對應,對于外部中斷來說,可使用的中斷號范圍從16到255(0到15)為系統預留的中斷號,而對于軟件中斷來說,可使用的中斷號為0到255。除此之外,16到255范圍內的中斷是可以通過EFLAGS中的IF flag進行disable的,如果EFLAGS中的IF flag被清零,則表示當前CPU不接受這個范圍內的中斷,如果其被置為1,則表示當前CPU可以正常處理這個范圍內的中斷。

中斷是如何被發送給CPU的?

中斷在進入CPU之前,首先會進入一個被稱為Advanced Programmable Interrupt Controller(APIC)的控制器中,可以說,每個CPU都有一個APIC,被稱為該CPU的Local APIC(LAPIC)。每個LAPIC由一系列的寄存器組成,這些寄存器控制了LAPIC如何將中斷送到處理器中。而根據實現的不同,對這些寄存器的訪問方式也不一樣,比如,對于傳統的APIC和xAPIC來說,這些寄存器都是被映射在內存中的,可以直接通過內存讀寫的方式對其進行訪問,而對于x2APIC來說,需要通過訪問MSR的方式來訪問這些寄存器,具體的地址和訪問方法可以查看Intel文檔。

下圖展示了一個LAPIC的架構,里面包含了各種各樣的寄存器,大部分的功能都可以通過查詢Intel文檔獲得,其中有幾個特別重要的寄存器:In-Service Register (ISR),Interrupt Request Register (IRR),EOI Register,Task Priority Register (TPR),Processor Priority Register (PPR),Interrupt Command Register (ICR),Local Vector Table (LVT)。這些會在接下來的篇幅中一一進行介紹。

對于目前的LAPIC來說,它可能從以下幾個來源接收到中斷:

  • Locally connected I/O devices:這個主要是指通過local interrupt pins (LINT0 and LINT1)直接和處理器相連的I/O設備;
  • APIC timer generated interrupts:LAPIC可以通過編程設置某個counter,在固定時間內向處理器發送中斷;
  • Performance monitoring counter interrupts:這個是指處理器中的性能計數器在發生overflow事件的時候向處理器發送中斷進行通知;
  • Thermal Sensor interrupts:這個是由溫度傳感器觸發的中斷;
  • APIC internal error interrupts:這個是LAPIC內部錯誤觸發的中斷;
  • Externally connected I/O devices:這個是指外部設備通過IOAPIC和LAPIC進行相連;
  • Inter-processor interrupts (IPIs):這個是指處理器之間通過IPI的方式進行中斷的發送和接收。

其中,前面五種中斷來源被稱為本地中斷源(local interrupt sources),LAPIC會預先在Local Vector Table (LVT)表中設置好相應的中斷遞送(delivery)方案,在接收到這些本地中斷源的時候根據LVT中的方案對相關中斷進行遞送。

除此之外,對于從IOAPIC中發送過來的外部中斷,以及從其它處理器中發過來的IPI中斷,LAPIC會直接將該中斷交給本地的處理器進行處理。而如果需要向其它處理器發送IPI,則可以通過寫LAPIC中的ICR寄存器完成。這部分這里就不詳述,直接看文檔就可以了。

那么我們現在就來看看當一個外部設備產生中斷,到這個中斷被發送給相應的CPU,這中間都會經歷些什么過程。

在IOAPIC內部,有一個非常重要的數據結構,叫做可編程重定向表(Programmable Redirection Table,PRT),在PRT表中,包含了若干個重定向表項(Redirection Table Entry,RTE),每個RTE對應一個中斷管腳,比如,典型的IOAPIC可能包含24個中斷管腳,相應的PTR表中就有24個與之相對應的RTE。 通常情況下,每個外部設備都會通過特定的管腳和IOAPIC相連,中斷產生之后,會通過該管腳進入IOAPIC,而當IOAPIC的某個管腳接收到中斷信號后,會根據該管腳對應的一個RTE,格式化出一條中斷消息,發送給某個(或多個)處理器的LAPIC。下表列出了RTE的格式:

Bits 描述
63:56 Destination Field,目的字段,R/W(可讀寫)。根據 Destination Filed(見下)值的不同,該字段值的意義不同,它有兩個意義:Physical Mode(Destination Mode 為 0 時 ): 其值為 APIC ID,用于標識一個唯一的 APIC。Logical Mode(Destination Mode 為 1 時):其值根據 LAPIC 的不同配置,代表一組CPU。
55:17 Reserved,預留未用。
16 Interrupt Mask,中斷屏蔽位,R/W。置一時,對應的中斷管腳被屏蔽,這時產生的中斷將被忽略。清零時,對應管腳產生的中斷被發送至LAPIC。
15 Trigger Mode,觸發模式,R/W。指明該管腳的的中斷由什么方式觸發。1:Level,電平觸發;2:Edge,邊沿觸發。
14 Remote IRR,遠程 IRR,RO(只讀)。只對level觸發的中斷有效,當該中斷是edge觸發時,該值代表的意義未定義。當中斷是level觸發時,LAPIC接收了該中斷,該位置一,LAPIC寫EOI 時,該位清零。
13 Interrupt Input Pin Polarity(INTPOL),中斷管腳的極性,R/W。指定該管腳的有效電平是高電平還是低電平。0:高電平;1:低電平。
12 Delivery Status,傳送狀態,RO。0:IDEL,當前沒有中斷;1:Send Pending,IOAPIC 已經收到該中斷,但由于某種原因該中斷還未發送給LAPIC
11 Destination Mode,目的地模式,R/W。0:Physical Mode,解釋見 Destination Field;1:Logical Mode,同上。
10:8 Delivery Mode,傳送模式,R/W。用于指定該中斷以何種方式發送給目的 APIC,各種模式需要和相應的觸發方式配合。詳見Intel文檔。
7:0 Interrupt Vector,中斷向量,R/W。指定該中斷對應的vector,范圍從10h到FEh。

從上表我們可以看出,該消息包含了一個中斷的所有信息。其中Destination field和Destination mode定義了該中斷將被遞送的目標處理器。 從IOAPIC到LAPIC有兩種可能的路徑,如下圖所示:第一種是通過系統總線(System bus),該種路徑實現在Pentium 4和Intel Xeon系列的處理器上;第二種是通過APIC bus,這種路徑實現在Pentium and P6家族的處理器上。至于它們有什么區別,還是去看文檔的解釋吧。

總之,外部設備產生的中斷最終通過IOAPIC被遞送到了某個(或者多個)處理器中的LAPIC中。接下來,就要看LAPIC是如何將這些中斷遞送給處理器進行處理了。

CPU是如何對接收到的中斷進行處理的?

LAPIC無論是接收到來自IOAPIC的中斷,來自本地中斷源的中斷,還是來自其他處理器發送的IPI中斷,都會將其交由CPU進行處理,但是由于CPU這個時候可能正在處理其它中斷,所以需要一套機制來保證中斷處理的安全性。

首先需要注意的是,在RTE格式那張表中,中斷的delivery mode可能有好幾種,其中NMI、SMI、INIT、ExtINT和SIPI這幾種delivery mode的中斷將會直接交由CPU進行處理,如果當前CPU正在處理這些delivery mode的中斷,則會禁止相同的中斷被遞送進來。除此之外,還有一種被稱為fixed的delivery mode,也就是普通的中斷,它們的遞送機制是通過IRR和ISR寄存器完成的。在X86平臺上,這兩個都是256bits的寄存器(其實是由8個64bits的寄存器組成的),每個bit代表一個中斷的vector,其中第0到第16個bit是reserve的。IRR和ISR每個bit代表的意思分別如下:

  • IRR:如果第n位的bit被置上,則代表LAPIC已接收vector為n的中斷,但還未交CPU處理。
  • ISR:如果第n位的bit被置上,則代表CPU已開始處理vector為n的中斷,但還未完成。

需要注意的是,當CPU正在處理某中斷時,如果又被遞送過來一個相同vector的中斷,則相應的IRR bit會再次置一; 如果某中斷被pending在IRR中,同類型的被再次遞送過來,則ISR中相應的bit被置一。 這說明在APIC系統中,同一類型中斷最多可以被計數兩次。

另外,當某個中斷被處理完之后,LAPIC需要通過軟件寫EOI寄存器來告知。

因此,根據處理器的不同,一個典型的LAPIC中斷處理流程是這樣的:

對于Pentium4和Xeon系列:

  • 通過中斷消息的destination field字段,確定該中斷是否是發送給自己的;
  • 如果該中斷的delivery mode為 NMI、SMI、INIT、ExtINT、SIPI,直接交由CPU處理;
  • 如果不為以上所列舉的中斷,則將IRR中相應的bit置一;
  • 當中斷被pending到IRR寄存器中后,根據TPR和PPR寄存器,判斷當前最高優先級的中斷是否能發送給CPU進行處理,并將ISR寄存器中相應的bit置一;
  • 軟件寫EOI寄存器通知中斷處理完成。如果中斷為level觸發,該EOI廣播到所有IOAPIC,NMI、SMI、INIT、ExtINT、SIPI類型中斷無需寫EOI。

對于Pentium系列和P6架構:

  • 確定該中斷是否由自己接收。如果是一個IPI,且delivery mode為lowest priority,LAPIC與其它LAPIC一起仲裁該IPI由誰接收。
  • 若該中斷由自己接收,且類型為NMI、SMI、INIT、ExtINIT、INIT-deassert、或MP協議中的IPI中斷(BIPI、FIPI、SIPI),直接交由CPU處理。
  • 將中斷pending到IRR或ISR寄存器,若已有相同的的中斷pending在IRR和ISR寄存器上,拒絕該中斷消息,并通知sender “retry”。
  • 同Pentium4、Xeon系列流程。
  • 同Pentium4、Xeon系列流程。

在上面的這兩套流程中,涉及到幾個關鍵的寄存器(TPR,PRR)和delivery mode(lowest priority),這就涉及到中斷的優先級問題了,會在“中斷的優先級問題”中進行解釋。

當CPU開始處理中斷的時候,會查詢一個被稱為中斷描述符表(Interrupt Descriptor Table,IDT)的數據結構,該數據結構的每一項都被預先填上了一個門描述符(gate descriptor),其中有三種門描述符:task, interrupt和trap,這里我們主要關注的是interrupt-gate descriptor。下圖顯示了interrupt gate的相關信息:

通過它,就可以找到相應vector的中斷的處理函數了。在進入處理函數之前,一般會對棧進行一個切換,并且將相應的寄存器信息(包括RFLAGS, CS, RIP等)壓入棧中,從而保證在中斷處理結束之后可以恢復相關信息。切換棧和保存相關信息的過程如下圖所示:

主要包括兩種情況,第一種情況是被中斷的進程不是內核進程,則需要有一個權限級別的切換,因此需要換一個棧;第二種情況是被中斷的進程是一個內核進程,因此不需要切換棧,只需要在原來的棧中保存信息就可以了。整個流程還是比較清楚的,因此這里也不詳述了。

中斷的優先級問題?

就像之前提到的,中斷是有優先級概念的,具體體現在優先級高的中斷會被先遞送給CPU進行處理,而優先級低的中斷往往需要在優先級高的中斷被處理完之后才會被處理。為了簡單起見,中斷的優先級是由中斷本身的vector信息來得到的。

我們知道每個中斷都有一個vector與之對應,而中斷的優先級別由下列公式得到:

優先級別 = vector / 16

因此,16~255號vector的中斷構成了1~15共15個優先級別。而對于同一個級別的中斷,vector號越大的優先級越高。例如vector33、34都屬于級別2,34的優先級就比33 高。所以,對于8bit的vector,又可以劃分成兩部分,高4bit表示中斷優先級別,低4bit表示該中斷在這一級別中的位置。

除此之外,LAPIC中還有兩個寄存器是和優先級相關的,它們分別是任務優先級寄存器(task priority register, TPR)和處理器優先級寄存器(processor priority register, PPR)。

其中,TPR確定當前CPU可處理什么優先級別范圍內的中斷。具有如下的格式:

TPR寄存器接收0~15共16個值,對應16個CPU規定的中斷優先級級別,值越大優先級越高。CPU只處理比TPR中值優先級別更高的中斷。例如TPR中值為8,則級別小于等于8的中斷被屏蔽(注意,屏蔽不代表拒絕,LAPIC 接收它們,把它們pending到IRR中,但不交CPU處理)。值15表示屏蔽所有中斷;值0表示接收所有中斷,這也是Linux為TPR設置的默認值。注意,TPR是由軟件讀/寫的,硬 件不更改它。因此,TPR的值增加 1,將會屏蔽16個vector對應的中斷。當然,NMI、SMI、ExtINT、INIT、start-up delivery的中斷不受TPR約束。

而PPR決定當前CPU正在處理的中斷的優先級級別,以確定一個pending在IRR上的中斷是否發送給CPU。具體格式如下圖所示:

與TPR不同,它的值由CPU寫而不是軟件寫。PPR取值范圍為[0,15],計算方式由下列偽代碼描述:

1 2 3 4 5 If TPR[7:4] >= ISR[7:4] THEN PPR[7:0] = TPR[7:0] ELSE PPR[7:4] = ISRV[7:4] PPR[3:0] = 0

這里,ISRV[7:4]標識當前ISR中,最高優先級中斷對應vector的高4bit,如前面所說,這代表了該中斷的優先級級別。簡而言之,取TPR和正在服務的最高優先級中斷中,優先級級別高的。所以說,IRR中pending的中斷,優先級級別必須高于PPR中值才會被發送給CPU處理,否則,繼續等…

最后一個概念是lowest priority。RTE的delivery mode有一中模式為lowest priority,即最低優先級。需要注意的是,這里的最低優先級不是指中斷的優先級,而是指將中斷發送給destination field列出的CPU中,優先級最低的一個。而如何選擇所有CPU中優先級最低的一個呢,答案應該是通過每個CPU所對應的TPR來決定的。

這里舉一個例子:假設有CPU1、CPU2、CPU3三個CPU,相應的TPR值為:TPR1=5、TPR2=6、TPR3=10,IOAPIC以lowest priority模式發送一條中斷消息,該中斷對應的優先級級別為3。則CPU1具有最低優先級,接收該中斷。此時,該中斷被pending到CPU1的IRR中,但不會交給CPU1處理,因為其優先級級別低于TPR值。

虛擬化環境對中斷提供了哪些支持?

最后我們來談談硬件虛擬化對中斷提供了哪些支持。該部分主要參考Intel文檔第三冊的第二十九章節。

中斷的虛擬化主要分為兩個部分:第一,需要模擬虛擬機對APIC控制寄存器的讀寫操作;第二,需要虛擬化中斷的delivery步驟,換句話說,當虛擬機正在運行的時候來了一個中斷,虛擬化層需要判斷該中斷是否應該遞送給虛擬機,以及如何遞送。

APIC虛擬化

在虛擬機中,不可避免地會對APIC中的寄存器進行訪問,而虛擬化層有兩種方式可以對其進行模擬:

  • 第一,通過設置EPT中的權限位,使得虛擬機在訪問APIC對應的頁的時候產生EPT violation的下陷,從而在虛擬化層對其進行模擬。
  • 第二,通過設置VMCS里面Secondary Processor-Based VM-Execution Controls域中的virtualize APIC accesses?bit。在這種情況下,通過設置特定的VM-execution controls的位,使得虛擬機在訪問APIC對應的頁的時候可能產生APIC-access VM exit的下陷,或者不產生下陷。

我們主要考慮第二種方式。

第二種方式的前提是virtualize APIC accesses bit被置一。在這個前提下,如果non-root中的虛擬機通過linear address對APIC page進行訪問,則需要對相關操作進行虛擬化。這里有兩個比較重要的VMCS域:APIC-access address和Virtual-APIC address。其中,APIC-access address表示當虛擬機訪問該地址,將會觸發之后APIC的虛擬化步驟,也就是說,它是真實的APIC在內存中映射的地址;而virtual-APIC address表示一個virtual-APIC page的物理地址,而這個virtual-APIC page是在APIC虛擬化過程中,實際被訪問的頁,所以它是一個被虛擬化的APIC頁,但是是被實際訪問的,之后會進行詳細描述。這里需要注意的是,這兩個address存放的都是真實主機的物理地址。

接下來,我們通過對APIC的讀和寫操作分別進行APIC虛擬化步驟的闡述。在介紹之前,需要先解釋一下,以下對memory mapped的內存頁的讀寫是基于xAPIC環境下的,而在x2APIC環境下,都是通過RDMSR和WRMSR來對相應APIC的寄存器進行讀寫的,這里就略過了。

  • APIC-access頁的讀操作虛擬化

當non-root環境下虛擬機對APIC-access address進行了一個讀操作,當滿足下列任何一個條件時,會發生VMExit:

  • Primary Processor-Based VM-execution control的use TPR shadow bit為0;
  • 該讀操作是一個instruction fetch的操作;
  • 該讀操作大于32 bits(對于32位的系統)或者64 bits(對于64位的系統);
  • The access is part of an operation for which the processor has already virtualized a write to the APIC-access page.
  • 該讀操作所訪問的地址不是16byte對齊的。
  • 否則,這個對APIC-access address的讀操作會觸發以下虛擬化過程:

  • 如果Secondary Processor-Based VM-Execution Controls中的APIC-register virtualization bit為0,則只虛擬化page offset為080H(task priority)的讀操作,否則,觸發APIC-access的VMExit;
  • 如果Secondary Processor-Based VM-Execution Controls中的APIC-register virtualization bit為1,則對以下page offset的讀操作會進行虛擬化過程:
  • 描述 Page offset
    local APIC ID 020H–023H
    local APIC version 030H–033H
    task priority 080H–083H
    end of interrupt 0B0H–0B3H
    logical destination 0D0H–0D3H
    destination format 0E0H–0E3H
    spurious-interrupt vector 0F0H–0F3H
    in-service 100H–103H, 110H–113H, 120H–123H, 130H–133H, 140H–143H, 150H–153H, 160H–163H, 170H–173H
    trigger mode 180H–183H, 190H–193H, 1A0H–1A3H, 1B0H–1B3H, 1C0H–1C3H, 1D0H–1D3H, 1E0H–1E3H, 1F0H–1F3H
    interrupt request 200H–203H, 210H–213H, 220H–223H, 230H–233H, 240H–243H, 250H–253H, 260H–263H, 270H–273H
    error status 280H–283H
    interrupt command 300H–303H, 310H–313H
    LVT entries 320H–323H, 330H–333H, 340H–343H, 350H–353H, 360H–363H, 370H–373H
    initial count 380H–383H
    divide configuration 3E0H–3E3H

    除此之外,其它offset的讀訪問都會造成VMExit。而對于這些offset的讀訪問,數據可以直接從virtual-APIC page中相應的offset中獲得。

    • APIC-access頁的寫操作虛擬化

    對APIC的寫比讀操作復雜一些。首先,和讀操作類似,我們得先確定什么時候會觸發APIC寫操作的虛擬化過程。

    當non-root環境下虛擬機對APIC-access address進行了一個寫操作,當滿足下列任何一個條件時,會發生VMExit:

  • Primary Processor-Based VM-execution control的use TPR shadow bit為0;
  • 該寫操作大于32 bits(對于32位的系統)或者64 bits(對于64位的系統);
  • The access is part of an operation for which the processor has already virtualized a write (with a different page offset or a different size) to the APIC-access page.
  • 該寫操作所訪問的地址不是16byte對齊的。
  • 否則,是否對APIC-access address的寫操作進行虛擬化由以下條件決定:

  • 如果Secondary Processor-Based VM-Execution Controls中的APIC-register virtualization bit和virtual-interrupt delivery bit同時為0,則只虛擬化page offset為080H(task priority)的寫操作,否則,觸發APIC-access的VMExit;
  • 如果Secondary Processor-Based VM-Execution Controls中的APIC-register virtualization bit為0,而virtual-interrupt delivery bit為1,則只虛擬化page offset為080H(task priority),0B0H(end of interrupt)和300H(interrupt command — low)的寫操作,否則,觸發APIC-access的VMExit;
  • 如果Secondary Processor-Based VM-Execution Controls中的APIC-register virtualization bit為1,則對以下page offset的寫操作會進行虛擬化過程:
  • 描述 Page offset
    local APIC ID 020H–023H
    task priority 080H–083H
    end of interrupt 0B0H–0B3H
    logical destination 0D0H–0D3H
    destination format 0E0H–0E3H
    spurious-interrupt vector 0F0H–0F3H
    error status 280H–283H
    interrupt command 300H–303H, 310H–313H
    LVT entries 320H–323H, 330H–333H, 340H–343H, 350H–353H, 360H–363H, 370H–373H
    initial count 380H–383H
    divide configuration 3E0H–3E3H

    除此之外,其它offset的寫操作都會造成VMExit。而對于這些offset的寫操作,數據直接被寫到virtual-APIC page相應的offset中。但是,由于對APIC某些寄存器的寫會產生一些side-effect,因此需要進行一些所謂的APIC-write emulation,具體的emulation操作由APIC page offset來決定(參考Intel手冊第三冊的29.4.3.2),這里就不詳述了。

    • 幾個比較重要的APIC寄存器的虛擬化過程

    接下來列舉幾個在virtual-APIC page中比較重要的寄存器:

    Virtual task-priority register (VTPR),?Virtual processor-priority register (VPPR),?Virtual end-of-interrupt register (VEOI),?Virtual interrupt-service register (VISR),?Virtual interrupt-request register (VIRR),?Virtual interrupt-command register (VICR_LO),?Virtual interrupt-command register (VICR_HI)

    以及它們的虛擬化過程:

    TPR Virtualization: 發生在以下三個場景中:(1)對MOV to CR8指令的虛擬化;(2)對APIC-access page的offset為080H進行訪問的虛擬化(xAPIC);(3)對WRMSR指令中ECX = 808H的虛擬化(x2APIC)。虛擬化的過程偽代碼如下:

    1 2 3 4 5 6 7 8 9 IF virtual-interrupt delivery is 0 THEN IF VTPR[7:4] < TPR threshold THEN cause VM exit due to TPR below threshold; FI; ELSE perform PPR virtualization; evaluate pending virtual interrupts (see Section 29.2.1); FI;

    PPR Virtualization: 發生在以下三個場景中:(1)VM entry;(2)TPR virtualization;(3)EOI virtualization。虛擬化的過程偽代碼如下:

    1 2 3 4 5 6 IF VTPR[7:4] SVI[7:4] THEN VPPR VTPR & FFH; ELSE VPPR SVI & F0H; FI;

    EOI Virtualization: 發生在以下兩個場景中:(1)對APIC-access page的offset為0B0H進行訪問的虛擬化(xAPIC);(2)對WRMSR指令中ECX = 80BH的虛擬化(x2APIC)。EOI的虛擬化會使用和更新VMCS中的guest interrupt status域中的SVI。虛擬化的過程偽代碼如下:

    1 2 3 4 5 6 7 8 9 10 11 Vector SVI; VISR[Vector] 0; IF any bits set in VISR THEN SVI highest index of bit set in VISR ELSE SVI 0; FI; perform PPR virtualiation; IF EOI_exit_bitmap[Vector] = 1 THEN cause EOI-induced VM exit with Vector as exit qualification; ELSE evaluate pending virtual interrupts; FI;

    Self-IPI Virtualization: 發生在以下兩個場景中:(1)對APIC-access page的offset為300H進行訪問的虛擬化(xAPIC);(2)對WRMSR指令中ECX = 83FH的虛擬化(x2APIC)。self-IPI的虛擬化會更新VMCS中的guest interrupt status域中的RVI,相應的偽代碼如下:

    1 2 3 VIRR[Vector] 1; RVI max{RVI,Vector}; evaluate pending virtual interrupts;

    虛擬化環境中對中斷的evaluation和delivery

    首先,在VMCS中的Pin-Based VM-Execution Controls域中,有一個bit用于控制External-interrupt exiting,如果該bit置一,則表示所有的外部中斷都會產生VMExit,否則,所有的外部中斷不會產生VMExit,這就意味著,如果當前CPU處于non-root模式,那么中斷就直接由虛擬機進行處理了。

    當然這種將所有中斷都直接讓虛擬機自身來處理的做法很不安全,所以,一般情況下發生中斷還是會引起下陷的,而在虛擬化層處理完返回虛擬機(VMEntry)時,就需要做中斷的evaluation和delivery了。

    所謂的evaluation,其實就是判斷當前是否有中斷需要交給虛擬機進行處理,而delivery就是將evaluation好的中斷交由虛擬機內核中的相應的IDT進行處理。

    當Secondary Processor-Based VM-Execution Controls中的virtual-interrupt delivery bit為1時,以下場景會觸發處理器evaluate pending的中斷:(1)VM entry;(2)TPR virtualization;(3)EOI virtualization;(4)self-IPI virtualization;(5)posted-interrupt processing。對pending virtual interrupts的evaluation會使用guest interrupt status中的RVI,相應的偽代碼如下:

    1 2 3 4 IF interrupt-window exiting is 0 AND RVI[7:4] > VPPR[7:4] THEN recognize a pending virtual interrupt; ELSE do not recognize a pending virtual interrupt; FI;

    當該中斷被recognized了,并且滿足以下四個條件,就會觸發該虛擬中斷的delivery:(1)RFLAGS.IF = 1;(2)沒有因為STI產生的blocking;(3)沒有因為MOV SS或者POP SS產生的blocking;(4)Primary Processor-Based VM-Execution Controls中的interrupt-window exiting bit為0。

    虛擬中斷的delivery會更新guest interrupt status中的RVI和SVI,并且在non-root環境下產生一個中斷事件,相應的偽代碼如下:

    1 2 3 4 5 6 7 8 9 10 11 Vector RVI; VISR[Vector] 1; SVI Vector; VPPR Vector & F0H; VIRR[Vector] 0; IF any bits set in VIRR THEN RVI highest index of bit set in VIRR ELSE RVI 0; FI; deliver interrupt with Vector through IDT; cease recognition of any pending virtual interrupt;

    至此,對“中斷處理的那些事兒”的介紹就結束了,對于這一塊的內容,我也還在學習中,很多細節上的東西之后也會慢慢再補充進去吧。

    原文地址:?http://ytliu.info/blog/2016/12/24/zhong-duan-chu-li-de-na-xie-shi-er/

    總結

    以上是生活随笔為你收集整理的中断处理的那些事儿的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。