Interupsi Eksternal dalam sistem x86. Bagian 1. Mengganggu evolusi pengontrol

Artikel ini adalah tentang proses pengiriman interupsi dari perangkat eksternal dalam sistem x86. Mencoba menjawab pertanyaan seperti:

  • Apa itu pic dan untuk apa?
  • Apa itu APIC dan untuk apa? Apa tujuan LAPIC dan I / O APIC?
  • Apa perbedaan antara APIC, xAPIC, dan x2APIC?
  • Apa itu MSI? Apa perbedaan antara MSI dan MSI-X?
  • Apa peran tabel $ PIR, MPtable, dan ACPI?

Jika Anda ingin mengetahui jawaban untuk salah satu dari pertanyaan ini, atau jika Anda hanya ingin tahu tentang evolusi pengendali interupsi, silakan, selamat datang.

Pendahuluan


Bagi mereka yang tidak tahu apa itu interupsi, berikut adalah kutipan dari Wikipedia:
Dalam pemrograman sistem, interupsi adalah sinyal ke prosesor yang dipancarkan oleh perangkat keras atau perangkat lunak yang mengindikasikan suatu peristiwa yang perlu segera diperhatikan. Sebuah interupsi memberi tahu prosesor pada kondisi prioritas tinggi yang memerlukan gangguan kode saat ini yang dijalankan prosesor. Prosesor merespons dengan menangguhkan aktivitasnya saat ini, menyimpan keadaannya, dan menjalankan fungsi yang disebut interrupt handler (atau interrupt service rutin, ISR) untuk menangani peristiwa tersebut. Gangguan ini bersifat sementara, dan, setelah pengendali interupsi selesai, prosesor melanjutkan aktivitas normal.

Ada dua jenis interupsi: interupsi perangkat keras dan interupsi perangkat lunak (softirqs):

  • Gangguan perangkat keras digunakan oleh perangkat untuk berkomunikasi yang memerlukan perhatian dari sistem operasi. Secara internal, gangguan hardware diimplementasikan menggunakan sinyal peringatan elektronik yang dikirim ke prosesor dari perangkat eksternal, yang merupakan bagian dari komputer itu sendiri, seperti pengontrol disk, atau periferal eksternal. Misalnya, menekan tombol pada keyboard atau menggerakkan mouse memicu gangguan perangkat keras yang menyebabkan prosesor membaca ketukan tombol atau posisi mouse. Tindakan memulai interupsi perangkat keras disebut sebagai permintaan interupsi (IRQ).
  • Gangguan perangkat lunak disebabkan oleh kondisi luar biasa pada prosesor itu sendiri, atau instruksi khusus dalam rangkaian instruksi yang menyebabkan gangguan ketika dijalankan. Yang pertama sering disebut jebakan atau pengecualian dan digunakan untuk kesalahan atau peristiwa yang terjadi selama pelaksanaan program yang cukup luar biasa sehingga tidak dapat ditangani dalam program itu sendiri. Misalnya, pengecualian bagi-oleh-nol akan dilemparkan jika unit logika aritmatika prosesor diperintahkan untuk membagi angka dengan nol karena instruksi ini merupakan kesalahan dan tidak mungkin.

Artikel ini membahas tentang gangguan hardware / eksternal IRQ.

Apa tujuan dari interupsi? Misalnya, kami ingin melakukan tindakan dengan paket yang masuk dari kartu jaringan segera setelah paket tersebut tiba. Jika Anda tidak ingin terus bertanya pada kartu jaringan, "Apakah paket saya sudah tiba?" dan buang waktu prosesor Anda, Anda dapat menggunakan IRQ interupsi perangkat keras eksternal. Jalur interupsi dari perangkat harus terhubung ke jalur INTR CPU, dan setelah setiap paket diterima, kartu jaringan akan membuat sinyal melalui jalur ini. CPU akan merasakan sinyal ini dan tahu bahwa kartu jaringan memiliki informasi untuk itu. Baru setelah itu CPU akan membaca paket yang masuk.

Tetapi apa yang harus kita lakukan jika ada banyak perangkat eksternal? Akan sangat tidak produktif untuk membuat satu ton pin INTR pada CPU untuk semuanya.



Untuk mengatasi masalah ini, sebuah chip khusus ditemukan - sebuah pengontrol interupsi.

Foto


( wiki / osdev )

Chip pengendali interupsi pertama adalah Intel 8259 PIC . Itu memiliki 8 jalur input (IRQ0-7) dan 1 jalur output (yang menghubungkan pengontrol interupsi dengan jalur INTR CPU). Ketika ada interupsi dari salah satu perangkat pada jalur inputnya, 8259 akan membuat sinyal melalui jalur INTR. Setelah itu CPU akan tahu bahwa beberapa perangkat memerlukan perhatian segera, dan prosesor akan menanyakan PIC mana dari 8 jalur input (IRQx) yang merupakan sumber interupsi ini. Ada beberapa overhead untuk jajak pendapat ini, tetapi sekarang kami memiliki 8 jalur interupsi alih-alih 1.



Segera 8 baris tidak cukup. Untuk menambah jumlah garis interupsi, dua pengontrol 8259 (master dan slave) dihubungkan dalam kaskade (Dual PIC).

IRQ dari 0 hingga 7 diproses dengan Intel 8259 PIC (master) pertama, dan IRQ dari 8 hingga 15 diproses dengan Intel 8259 PIC (master) kedua. Hanya master yang terhubung ke CPU dan dapat memberi sinyal tentang interupsi yang masuk. Jika ada interupsi pada jalur 8-15, PIC kedua (slave) akan memberi sinyal tentang hal itu kepada master di jalur IRQ2, dan setelah itu master akan memberi sinyal CPU. Interupsi bertingkat ini menghilangkan 1 dari 16 baris, tetapi membuat total 15 interupsi untuk semua perangkat eksternal.



Skema ini diadopsi oleh komunitas, dan sekarang ketika seseorang berbicara tentang PIC (Programm Interrupt Controller) yang mereka maksudkan adalah sistem Dual PIC ini. Setelah beberapa waktu, pengendali 8259 ditingkatkan dan mendapat nama baru: 8259A. Dengan pengontrol ini, sistem DUAL PIC dimasukkan ke dalam chipset. Pada saat bus utama untuk koneksi perangkat eksternal adalah ISA, sistem ini cukup. Itu hanya diperlukan bahwa perangkat yang berbeda tidak terhubung ke jalur IRQ yang sama, karena interupsi ISA tidak dapat dibagikan.

Pemetaan interupsi perangkat cukup standar:

Contoh (dari sini ):
IRQ 0 - timer sistem
IRQ 1 - pengontrol keyboard
IRQ 2 - cascade (interupsi dari slave controller)
IRQ 3 - port serial COM2
IRQ 4 - port serial COM1
IRQ 5 - port paralel 2 dan 3 atau kartu suara
IRQ 6 - pengontrol floppy
IRQ 7 - port paralel 1
Penghitung waktu IRQ 8 - RTC
IRQ 9 - ACPI
IRQ 10 - terbuka / SCSI / NIC
IRQ 11 - terbuka / SCSI / NIC
IRQ 12 - pengendali mouse
IRQ 13 - co-prosesor matematika
IRQ 14 - saluran ATA 1
IRQ 15 - saluran ATA 2

Konfigurasi dan bekerja dengan 8259 chip dilakukan dengan port I / O:
ChipDaftarI / O port
Master picPerintah0x0020
Master picData0x0021
Foto budakPerintah0x00A0
Foto budakData0x00A1

Dokumentasi lengkap 8259A dapat ditemukan di sini .

Bus PCI kemudian menggantikan bus ISA. Sayangnya, jumlah perangkat mulai melebihi angka 15. Juga bukan bus ISA statis, perangkat di bus PCI dapat ditambahkan ke sistem secara dinamis yang berpotensi menyebabkan masalah lebih banyak lagi. Namun untungnya, interupsi dalam bus PCI dapat dibagi, sehingga dimungkinkan untuk menghubungkan banyak perangkat ke satu jalur interupsi IRQ. Pada akhirnya, untuk mengatasi masalah kurangnya jalur interupsi, diputuskan untuk mengelompokkan interupsi dari semua perangkat PCI ke jalur PIRQ (Programmable Interrupt Request).

Sebagai contoh, misalkan kita memiliki 4 jalur interupsi gratis pada pengontrol PIC dan 20 perangkat PCI. Kami dapat menggabungkan interupsi dari 5 perangkat menjadi satu baris PIRQx, dan menghubungkan garis PIRQx ini ke pengontrol PIC. Dalam hal ini jika ada interupsi pada salah satu jalur PIRQx, prosesor harus menanyakan semua perangkat yang terhubung ke baris ini tentang interupsi untuk mengetahui siapa yang bertanggung jawab untuknya, tetapi pada akhirnya itu menyelesaikan masalah. Perangkat yang menghubungkan jalur interupsi PCI ke jalur PIRQ sering disebut router PIR.

Dengan metode ini, perlu untuk memastikan bahwa garis PIRQx tidak terhubung ke garis dengan interupsi ISA (karena ini akan menghasilkan konflik) dan bahwa garis PIRQx seimbang (semakin banyak perangkat yang kita hubungkan ke satu garis, semakin banyak perangkat yang dibutuhkan CPU. untuk polling ketika perlu memeriksa perangkat mana yang bertanggung jawab atas interupsi).



Catatan : pada gambar, pemetaan perangkat PCI -> PIR digambarkan secara abstrak, karena dalam kasus sebenarnya ini sedikit lebih rumit. Di dunia nyata setiap perangkat PCI memiliki 4 jalur interupsi (INTA, INTB, INTC, INTD) dan hingga 8 fungsi, di mana setiap fungsi hanya dapat memiliki satu dari interupsi INTx ini. Garis INTx mana yang akan digunakan oleh setiap fungsi ditentukan oleh konfigurasi chipset.

Pada dasarnya fungsi mereka adalah blok logis yang terpisah. Misalnya, satu perangkat PCI dapat memiliki fungsi pengontrol Smbus, fungsi pengontrol SATA, dan fungsi jembatan LPC. Dari sudut pandang sistem operasi (OS), setiap fungsi seperti perangkat terpisah dengan ruang konfigurasi sendiri (PCI config).

Informasi tentang perutean interupsi pengontrol PIC dikirim ke OS oleh BIOS, dengan bantuan tabel $ PIR dan melalui register 3Ch (INT_LN Interrupt Line (R / W)) dan 3Dh (INT_PN Interrupt Pin (RO)) dari ruang konfigurasi PCI untuk setiap fungsi.

Spesifikasi untuk tabel $ PIR baru-baru ini ada di situs web Microsoft , tetapi saat ini tidak tersedia. Dimungkinkan untuk memahami konten tabel dari Spesifikasi PCI BIOS [4.2.2. Dapatkan Opsi Perutean Interupsi PCI] atau dari sini (tautan terakhir dalam bahasa Rusia, tetapi Anda dapat mencoba google "Spesifikasi Tabel Perutean PCI IRQ")

Apic


( wiki , osdev )

Metode terakhir bekerja hingga sistem multiprosesor tiba. Secara alami, PIC hanya dapat mengirim interupsi ke satu CPU, dan dalam sistem multiprosesor diinginkan untuk memuat CPU secara seimbang. Solusi untuk masalah ini adalah antarmuka APIC baru (Advanced PIC).

Kontroler khusus yang disebut LAPIC (Local APIC) telah ditambahkan untuk setiap prosesor, serta kontroler I / O APIC untuk routing yang mengganggu dari perangkat eksternal. Semua pengontrol ini digabungkan dalam bus umum dengan nama APIC (perhatikan bahwa sistem modern menggunakan bus sistem standar alih-alih bus APIC terpisah untuk tugas ini).

Ketika interupsi eksternal tiba pada input I / O APIC, pengontrol akan mengirimkan pesan interupsi ke LAPIC dari salah satu CPU sistem. Dengan cara ini kontroler I / O APIC membantu menyeimbangkan beban interupsi antar prosesor.

Chip APIC pertama adalah 82489DX , yang merupakan chip terpisah yang memiliki LAPIC dan I / O APIC yang terhubung. Untuk sistem prosesor ganda diperlukan tiga chip seperti itu: dua untuk LAPIC dan satu untuk I / O APIC. Fungsionalitas LAPIC kemudian langsung dimasukkan dalam prosesor, dan bagian I / O APIC dipisahkan ke chip 82093AA.

I / O APIC 82093AA memiliki 24 input, dan arsitektur APIC dapat mendukung hingga 16 CPU. Interupsi 0-15 merupakan interupsi ISA lama untuk kompatibilitas dengan sistem yang lebih lama, dan interupsi 16-23 ditujukan untuk semua perangkat PCI. Dengan pembatasan ini semua konflik antara ISA dan interupsi PCI dapat dengan mudah dihindari. Dengan meningkatnya jumlah jalur interupsi bebas, dimungkinkan juga untuk meningkatkan jumlah saluran PIRQx.



Pemrograman I / O APIC dan LAPIC dilakukan dengan bantuan MMIO. Register LAPIC biasanya ditempatkan pada alamat 0xFEE00000, dan I / O APIC mendaftar pada alamat 0xFE0000, meskipun dimungkinkan untuk mengkonfigurasi ulang mereka.

Seperti dalam kasus PIC, chip yang terpisah pada awalnya menjadi bagian dari chipset nanti.

Arsitektur APIC kemudian dimodernisasi, dan varian barunya bernama xAPIC (x-extended). Dengan kompatibilitas penuh mundur, jumlah total CPU yang mungkin dalam sistem ditingkatkan menjadi 256.

Langkah selanjutnya dalam pengembangan arsitektur bernama x2APIC . Jumlah CPU yang mungkin dalam sistem meningkat menjadi 2 ^ 32. Pengontrol ini dapat bekerja dalam mode kompatibilitas mundur dengan xAPIC, atau mereka dapat bekerja dalam mode x2APIC baru. Dalam mode baru ini, pemrograman pengontrol tidak dilakukan melalui MMIO, tetapi melalui register MSR (yang jauh lebih cepat). Menurut tautan ini , dukungan IOMMU diperlukan untuk mode ini.

Penting untuk dicatat bahwa ada kemungkinan untuk memiliki beberapa pengontrol APIC I / O dalam sistem. Misalnya, satu untuk 24 interupsi di southbridge dan yang lain untuk 32 interupsi di northbridge. Dalam konteks I / O APIC, interupsi biasanya disebut GSI (Global System Interrupt). Jadi, sistem yang disebutkan sebelumnya memiliki GSI 0-55.

Bagaimana kita dapat menentukan apakah CPU memiliki LAPIC internal dan arsitektur APIC apa yang didukungnya? Dimungkinkan untuk menjawab pertanyaan ini dengan memeriksa bit-flag dari CPUID.
Untuk membantu OS menemukan LAPIC dan I / O APIC, BIOS harus menyajikan informasi tentang mereka baik melalui MPtable (metode lama) atau melalui tabel ACPI (tabel MADT dalam kasus ini). Selain informasi umum, MPtable dan ACPI (dalam hal ini tabel DSDT) harus berisi informasi tentang interrupt routing. Ini berarti informasi tentang perangkat mana yang menggunakan jalur interupsi (mirip dengan tabel $ PIR).

Anda dapat membaca tentang MPtable dalam spesifikasi resmi. Sebelumnya spesifikasinya ada di situs web Intel, tetapi saat ini hanya mungkin menemukannya dalam versi arsip. Spesifikasi ACPI dapat ditemukan di situs web UEFI (versi saat ini adalah 6.2 ). Perlu diperhatikan bahwa dengan ACPI dimungkinkan untuk mendeklarasikan perutean interupsi untuk sistem tanpa APIC (alih-alih menyediakan tabel $ PIR yang terpisah).

Msi


( wiki )

Varian terakhir dari APIC adalah baik, tetapi bukan tanpa kerugian. Semua jalur interupsi dari perangkat membuat sistem sangat rumit dan dengan demikian meningkatkan kemungkinan kesalahan. PCI express bus datang untuk menggantikan PCI bus, yang menyederhanakan semua sistem interupsi sepenuhnya. Itu tidak memiliki garis interupsi sama sekali. Untuk sinyal interupsi kompatibilitas mundur (INTx #) ditiru dengan jenis pesan terpisah. Dengan jalur interupsi PCI, koneksi mereka dibuat dengan kabel fisik. Dengan jalur interupsi PCI express, koneksi logis dan dibuat oleh PCI express bridges. Tetapi dukungan legacy INTx interrupts ini hanya ada untuk kompatibilitas dengan PCI bus. PCI express memperkenalkan metode pengiriman interupsi yang sepenuhnya baru - MSI (Message Signaled Interrupts). Dalam metode ini, perangkat memberi sinyal tentang interupsi hanya dengan menulis ke tempat khusus di wilayah MMIO CPU LAPIC.



Sebelumnya perangkat PCI tunggal (ini berarti semua fungsinya) hanya dapat memiliki 4 interupsi, tetapi sekarang menjadi mungkin untuk mengatasi hingga 32 interupsi.

Dalam kasus MSI tidak ada pembagian garis interupsi: setiap interupsi secara alami sesuai dengan perangkatnya.

MSI menyela juga memecahkan satu masalah lagi. Misalnya, mari kita bayangkan situasi di mana perangkat melakukan transaksi penulisan-memori, dan ingin memberi sinyal tentang penyelesaiannya melalui interupsi. Tetapi transaksi tulis dapat ditunda di bus dalam proses transmisi (dan perangkat tidak dapat mengetahuinya). Dalam hal ini sinyal tentang interupsi akan datang ke CPU terlebih dahulu, sehingga prosesor akan membaca data yang belum valid. Jika MSI digunakan, informasi tentang MSI ditransmisikan dengan cara yang sama seperti pesan data, sehingga tidak bisa datang lebih awal.

Perlu diperhatikan bahwa interupsi MSI tidak dapat bekerja tanpa LAPIC, tetapi MSI dapat menggantikan I / O APIC (satu lagi penyederhanaan desain).

Setelah beberapa waktu, metode MSI diperluas ke MSI-X. Sekarang setiap perangkat dapat memiliki hingga 2048 interupsi. Sekarang juga memungkinkan untuk menentukan CPU mana yang harus memproses interupsi. Ini bisa sangat berguna untuk perangkat dengan beban tinggi, seperti kartu jaringan misalnya.

Tidak perlu untuk tabel BIOS terpisah untuk dukungan MSI. Tetapi perangkat harus menunjukkan dukungan MSI melalui salah satu Kemampuan dalam ruang PCI Config-nya. Juga, driver perangkat harus mencakup semua dukungan yang diperlukan untuk bekerja dengan MSI.

Kesimpulan


Pada artikel ini, kami telah mempelajari informasi tentang evolusi pengontrol interupsi dan telah mendapatkan pengetahuan teori umum tentang pengiriman interupsi dari perangkat eksternal dalam sistem x86.

Pada bagian selanjutnya kita akan berlatih dan melihat bagaimana cara melibatkan masing-masing pengendali interupsi yang disebutkan di Linux.

Pada bagian ketiga kita akan melihat ke dalam kode coreboot dan melihat pengaturan apa yang diperlukan dalam chipset untuk perutean interupsi yang benar.

Tautan:



Segmen yang diakui


Terima kasih khusus kepada Jacob Garber dari komunitas coreboot yang telah membantu saya dengan terjemahan artikel ini.

Source: https://habr.com/ru/post/id446312/


All Articles