天天看點

android qemu-kvm i8259 中斷控制器虛拟裝置初始化elcr的讀寫8259寄存器的讀寫如何通知CPU來了一個中斷?apic,iopic,lapic是啥?結尾

8259主片的IRQ0~7對應INT 8~INT F,從片的IRQ8~IRQ15對應INT 70~INT 77。

8259是在pc_init1中初始化的,cpu_irq是8259的parent_irq:

qemu_allocate_irqs用來申請并設定qemu_irq結構體的:

i8259_init是8259的初始化函數,初始化了主從兩片8259,iobase分别為0x20,0xa0,length都是2,寬度都是8bit。

elcr位址分别為0x4d0,0x4d1,分别對應兩片8259,每一位對應一個irq,是控制邊沿觸發還是電平觸發的,置1時是電平觸發,elcr_mask是因為有些irq不支援電平觸發,是以需要mask。

最後申請了GFD_MAX_IRQ個,也就是16個qemu_irq結構體:

pic_init1用來真正初始化每一片8259的,綁定了寄存器和讀寫函數,qemu_register_reset把寄存器的複位函數放到連結清單裡:

elcr的讀寫函數非常簡單,稍微注意下mask的使用就行了:

8259的寫函數為pic_ioport_write,因為每片就兩個寄存器,addr不是0就是1,是以addr &= 1。

ICW1位址為0,ICW2~4位址為1;OCW2~3位址為0,OCW1位址為1。

需要注意位址的複用如何處理,ICW的指令是用于初始化的,先往位址0寫ICW1,然後往位址1寫剩下的幾個ICW指令,具體寫的是哪個,由狀态機init_state來确定。

初始化完畢後才可以寫入OCW指令。

ICW1,OCW2,OCW3複用位址0,是根據val中的特殊位來區分的。初始化完畢後,位址1僅僅對應OCW1。

OCW2需要詳細說明下:

1、中斷優先級:每片8259由irq0~irq7共計8個中斷輸入,預設情況下irq0優先級最高,irq7優先級最低,同時發生中斷請求時,優先級高的先處理,在嵌套模式下,優先級高的還可以打斷優先級低的中斷服務程式的執行。

2、循環優先級:這次優先級最高的是0,下一次中斷時,優先機最高的輪到1,然後輪到2......,到7,然後再到0。

3、SL用來設定一個偏移量的,加上這個偏移并對8取模後再比較優先級。

尋找這片8259的優先級最高的中斷,mask就是isr,需要考慮優先級循環和SL設定的偏移對優先級的影響。

沒有中斷時傳回8。

priority_add綜合了自動循環和SL設定的東西的因素,對優先級進行調整。

更新中斷的狀态,如果有中斷請求,那麼qemu_irq_raise請求parent_irq,也就是cpu_irq,去對CPU産生中斷請求

irr中斷請求,isr中斷服務。經過irr後才能到isr。irr表示請求中斷,isr表示正在處理的中斷。

設定中斷請求寄存器irr

8259的讀函數為pic_ioport_read

qemu_set_irq用來設定中斷請求,會調用申請qemu_irq時設定的handler函數,對于cpu_irq來說,handler是pic_irq_request;對于8259來說,handler是i8259_set_irq

pic_irq_request會設定cpu->interrupt_request |= CPU_INTERRUPT_HARD。

i8259_set_irq最終也會調用到pic_irq_request函數。

cpu_interrupt注入的中斷,會在kvm_arch_pre_run中進行處理。根據cpu->interrupt_request的設定,會調用kvm_vcpu_ioctl(cpu, KVM_INTERRUPT, &intr):

kvm_arch_pre_run會在kvm_cpu_exec的循環中執行的,每次退出kvm核心态,重新kvm_run之前會調用這個。是以中斷的注入并不是實時的,需要等kvm退出後,才能夠進行真正的注入:

APIC(Advanced Programmable Interrupt Controller)取代了8259,成為目前标準的中斷控制器,包括了兩部分: iopic和lapic,iopic接裝置,每個cpu都有lapic。iopic把中斷請求發給lapic。

APIC方式下,支援更多的中斷,無需使用中斷共享。

android goldfish platform bus的中斷控制器在guest為x86時不啟用的。

現在qemu的8259都是使用了QOM模型了,這個模型太TMD的複雜了。另外hw/i386/kvm/timer/i8259.c中提供了kvm版本的8259,使用kvm提供的核心态的8259的模拟,中斷的處理和IO的讀寫都在核心态,不需要退出kvm了,速度要更快些,有提供了核心态的apic的模拟。類似的,8254之類的也有kvm核心态的實作,是以說android emulator的性能還是有提升空間的。

繼續閱讀