Sdílené interrupty v systémech se sběrnicí PCI Express - proč?

(Poslední úprava: 4.12.2017)

Úvodem

Poněkud netradičně začnu odkazy na jiné úvodní čtení:


Tímto se máme od čeho odrazit. Na druhou stranu ta zdlouhavá četba jistě není povinná...

Zdálo by se, že pokud máte hardware se sběrnicí PCI Express, který potažmo obsahuje patrně více než jeden APIC, a k tomu operační systém, o kterém spolehlivě víte, že umí pracovat s APICem jak přes ACPI tak přes MPS, nemůže se Vám stát, že bude docházet ke sdílení interruptů. Mělo by se jednat po všech stránkách o progresivní kombinaci.

Chyba lávky! Na moderních "expresových" čipsetech Intel ke sdílení obvykle dochází, a to bohužel obvykle u zařízení, u kterých je průchodnost IRQ událostí kritická, jako jsou Gb Ethernety a diskové řadiče. Je to dáno nepřipraveností operačních systémů a ovladačů na message-signaled interrupty!

Zde by se slušelo poznamenat, že tento článek byl napsán v létě 2007. Na trhu jsou čipsety jako Intel 965, P33, P35 nebo 5000 a 3000 series. Aktuální Linux je 2.6.22.1, poslední verze Windows jsou XP SP2, první release Vista a W2k3 Server SR1.

Zevrubná pitva

V moderních "expresových" motherboardech se nachází jeden či více IO(x)APICů. Jeden je rozhodně v south bridgi. Pokud motherboard obsahuje sloty PCI-X, pak v každém bridgi 6700PXH (PCIe to 2x PCI-X) jsou dva IO(x)APICy (na každý ze dvou PCI-X portů jeden). Takže by se zdálo, že interruptových vstupů je k dispozici mraky - běžně 96.

Problém je s nativními PCIe zařízeními, kterých může být v "expresovém" počítači klidně většina. Na sběrnici PCIe v "legacy" režimu se IRQčka nesignalizují po vyhrazených drátech, ale tyto jsou emulovány pomocí tzv. INTx zpráv (říká se tomu "virtual wire"). Tyto zprávy jsou doručovány IO(x)APICu v south bridgi a potom dále běžným způsobem na procesor. Toto platí i pro běžný APICový režim - který už se taky dostal do kategorie "legacy" :-)

Podobně jako na sběrnici PCI, každý PCIe "port" v příslušném upstream bridgi má čtyři "virtuální dráty" (tj. řekněme sloty) pro virtuální INTA až INTD. Pokud je na port připojeno několik PCI periferií, dostanou postupě každá jiný slot. První problém spočívá v tom, že na konkrétním PCIe portu bývá typicky jediné PCIe zařízení, takže se uplatní typicky jenom INTA. Interrupty jsou dále čipsetem standardně shrábnuty na hromadu, takže ve standardním případě by všechny PCIe periferie sdílely jediný "virtuální IRQ drát" zvaný INTA, který by byl virtuálně nadrátovaný na jediný vstup IO(x)APICu v south bridgi. Takže by všechna PCIe zařízení sdílela jediné IRQ!

Without swizzle
Obrázek típnutý z PDFka firmy Intel (viz literatura)

Firma Intel toto řeší tak, že její PCIe porty v north bridgi a south bridgi obsahují proprietární konfigurační registry, kterými lze nastavit mapování INTA slotu na jiný INTx slot (plus totéž pro ostatní tři vstupní sloty). Tento překlad se děje při průchodu INTx zprávy PCIe portem. Intel tomu říká "Interrupt Swizzling", a jedná se vlastně o obdobu "protáčení" pořadí drátů INTA-INTB-INTC-INTD ve slotech klasické paralelní PCI. Díky tomuto opatření se systém v "legacy APIC" režimu chová tak, že všechna PCIe zařízení si mezi sebou rozdělí přesně 4 APICové interrupty. Na nich visí typicky PCIe Ethernety, on-chip USB kanály a SATA řadiče v south bridgi, plus zásuvné PCIe karty. Pokud se podíváte jenom na on-chip integrovaná zařízení v čipsetu, vyjde Vám, že každý "virtuální drát" sdílejí minimálně dvě periferie! Je zvláštní, že Intel nezařídil "swizzling" na všech 8 level-triggered PCI-only vstupů hlavního IO-APICu (GSI 16-23), ale prostě je to tak.

Without swizzle
Obrázek típnutý z PDFka firmy Intel (viz literatura)

Intel patrně záměrně rezignoval na rozvíjení "virtuálně drátovaného" konceptu předchozí generace, založeného na IO(x)APICu. Ať už kvůli snižování složitosti konfigurace motherboardů, nebo za účelem prosazení nového způsobu sběru interruptů, kterým jsou MSI.

Ještě jeden jedovatý postřeh: Povšimněte si, že v tomto "legacy APIC compatible" režimu, pokud máte nějaké PCIe zařízení připojené přímo k north bridgi (MCH), jeho INTx zprávy putují do south bridge na IO(x)APIC, a pak zase zpátky skrz north bridge do CPU :-) Je to jistě velice efektivní způsob doručování interruptů, zejména pro výkonná zařízení, která se do širokých segmentů PCIe na northbridgi připojují (RAIDy, grafika apod.).

Každé PCIe zařízení povinně umí Message-signaled interrupty. V momentě, kdy se operační systém domluví s konkrétní PCIe periferií na použití MSI a přidělí jí volný slot v lokálním APICu některého procesoru, tato periferie má od té chvíle svůj vlastní nesdílený interrupt, o který se nemusí s nikým dělit, bez ohledu na to, že snad při bootu v "legacy APIC" režimu nějaký virtuální drát s kýmsi sdílela. Na rozdíl od INTx zpráv, MSI zprávy jdou přímo z periferie do procesoru, bez dalších APICových mezistupňů (snad s nějakou nutnou konverzí zpráv v north bridgi, z PCI na FSB).

Jádro pudla - podpora ze strany OS

A tím se dostáváme konečně k věci. Problém totiž spočívá v nedostatečné podpoře MSI ze strany softwaru - tj. v první řadě ze strany operačních systémů a jejich hardwarových ovladačů.

Windows XP (SP2) podle všeho ještě MSI neznají. Totéž platí o Windows 2003 Serveru. MSI jsou podporovány v OS Windows Vista - jedná se možná o první pádný důvod, proč na moderní expresový hardware instalovat Visty a ne XPčka. Nicméně zřejmě bude záležet ještě na dostupnosti ovladačů, které dokážou s MSI pracovat (pokud se jich na to OS Windows Vista vůbec ptá). Další problém Windowsů je, že větší počet PCIe periferií lze očekávat spíše v serverových strojích, a odpovídající serverová verze Windowsů na úrovni Windows Vista ještě v létě 2007 není na trhu - Windows Server 2008 je teprve na obzoru.

Linuxová jádra řady 2.6 obsahují podporu MSI už poměrně dlouho. Nicméně konkrétně Linux nechává rozhodnutí, zda zapnout MSI či nikoli, na HW-specifických ovladačích. Je sice pravda, že standardní PCI Config Space obsahuje informaci, zda dané zařízení podporuje "MSI capability", a tuto lze opět standardním/jednotným způsobem v PCI hardwaru zapnout. Však také Linux obsahuje v rámci kernelového API jednotné rutiny, pomocí kterých lze danému zařízení "přehodit výhybku" interruptů z tradičního "buzení drátů" na MSI, což je dotaženo až po LAPIC na CPU. Nicméně, funkci zvanou pci_enable_msi() musí explicitně zavolat ovladač daného periferního PCI hardwaru (těsně před tím, než zavolá request_irq() nebo ekvivalent). A konkrétně v tom je (byl) v Linuxu kámen úrazu. Všechny ovladače pro hardware, který MSI umí, bude třeba upravit, aby volaly pci_enable_msi(). Například v jádře 2.6.18.8 obsahují podporu MSI pouze ovladače e1000, aic79xx (PCI-X !) a pciehp (PCI-Express Hotplug - tak proto mají expresové porty přidělený "režijní" interrupt!). Ve 2.6.22.1 už je situace mnohem lepší - MSI podporují například ovladače sata_mv, ahci, LSI Fusion MPT, sky2, tg3 nebo qla2xxx. Ale třeba aacraid, ať už vanilkový nebo čerstvý od Adaptecu, podporu MSI neobsahuje, přestože je na trhu už druhá generace PCIe RAIDů Adaptec. Žeby Intel IOP333 neuměl MSI?

Na okraj - Fake MSI

V BIOSu některých desek firmy SuperMicro (serverový čipset 5000 series) lze nalézt položku zvanou "Emulated IRQ solution". Tato věc patrně odpovídá fintě, které Intel říká "Fake MSI". V tomto případě je PCI-e periferie nakonfigurována, aby posílala opravdové MSI, ale tyto jsou nasměrovány na IO(x)APIC, kde jsou konvertovány na standardní IO(x)APIC interrupty. Takže periferie si běží v MSI režimu, ale na procesor doběhnou APICové interrupty. Nebo-li u PCIe periferií připojených přímo na north bridge opět platí, že interrupty cestují tam a zpátky skrz south bridge.

Tato položka v BIOSu, pokud jsem ji povolil, mi způsobovala tuhnutí Windows i Linuxu, takže netuším, jestli je k něčemu dobrá :-) Ono se v popisu Fake MSI v intelově dokumentaci píše, že je k tomu potřeba podpora v OS, která v zásadě neexistuje.

Sumárum - co včil

Pokud chcete na moderním hardwaru provozovat server na bázi Windows, budete se muset smířit s tím, že pod W2k3 Vám sdílené interrupty budou zvyšovat zátěž CPU. Dokud nepřijde Windows Server 2008 - ten by snad MSI mohl umět (přestože Google aktuálně našel zmínky jenom v souvislosti s Vistou).

Pokud chcete provozovat Linux, volte čerstvou distribuci, hlavně kvůli aktuálnímu jádru - záleží speciálně na ovladačích, aby podporovaly MSI. Situaci v síťovacím hardwaru usnadnil Intel tím, že podporu MSI zařadil do svého ovladače e1000 mezi prvními. Čipset Intel s novým linuxovým kernelem podají optimální výkon. (Zkste se v této souvislosti mrknout taky na intelský "DMA engine", který je součástí serverových čipsetů Intel řady 5000). A pokud máte náladu, můžete zkusit do zaostávajícího "MSI-negativního" ovladače přidat volání pci_enable_msi() - třeba to pomůže :-)

Literatura