SMM, USB Legacy Desteği ve USB Handoff üzerine
by faik, 02.18.07 at 12:45 am :: Çekirdek :: permalink :: rss
x86 işlemcilerin protected, real ve virtual-8086 modlarının dışında çalıştığı özel bir mod daha bulunuyor: System Management Mode (SMM). Bu mod, güç yönetimi, sıcaklık ve fan takibi gibi sistem kontrolüne yönelik özel işler için ve yalnızca BIOS’un kullanımına yönelik olarak tasarlanmış bir mod. ACPI öncesi bahsi geçen işler, işlemcinin bu özelliği kullanılarak yapılıyor. Mekanizma şu şekilde işliyor: İşlemci’de aynı INTR# pin’i gibi bir de SMI# pin’i bulunuyor. Bu pin aktif olduğu anda işlemci ne yapıyorsa yapsın o işi bırakıyor, bekleyen tüm komutların sonuçlanmasını bekliyor, write-buffer’ını boşaltıyor, işlemci durumunu sistem hafızasından ayrı bir adres uzayı olan SMRAM‘e yazıyor ve SM mod’a geçiş yapıyor. SMRAM içerisinde gerçekleşen durum ile başa çıkacak BIOS SMI handler kodu çalışıyor. İş bitince yalnızca bu modda çalışan RSM opkodu çalıştırılıp, moddan çıkılıyor. İşletim sisteminin ruhu duymadan, sanki hiç bir şey olmamış gibi herşey kaldığı yerden devam ediyor.
SMRAM, SM modunda kullanılan özel bir hafıza bölgesi. SMRAM sistem tasarımına bağlı olarak ne uygulamaların, ne de işletim sisteminin görebileceği bir yerde bulunuyor. BIOS, POST sonrası bu modda çalışacak SMI handler’ın kod, data ve stack bölümlerini daha önceden buraya kopyalamış oluyor. Geçiş sırasında da işlemci durumu daha sonra geri dönülebilmesi için SMRAM’in belirli bir bölgesinde saklanıyor. SMRAM sistem tasarımı açısından ayrı bir hafıza modülünde olabileceği gibi sistem hafızasının bir bölümü de SMRAM olarak kullanılabiliyor. Genelde de ikinci yöntem tercih ediliyor. Bu bölgeye işletim sistemi’nin dahi erişiminin engellenmesi işi chipset tasarımı ile sağlanıyor. Genelde uygulanan yöntem 640 KB ile 1 MB arasındaki 0xA0000 adresi ile başlayıp 0xBFFFF adresine haritalanmış olan Video RAM’i ile SMRAM’in sistem hafızasında aynı bölgeye haritalanması ile sağlanıyor. Herhangi bir modda 0xA0000 - 0xBFFFF fiziksel adresi arasına erişim istendiğinde chipset Video RAM’e ulaştırırken, SMI# sonrası SMM moda geçiş yapıldığında hafıza kontrolörü SMRAM’e erişim sağlıyor.SMI kullanımına örnek olarak sistemde yerleştirilmiş olan bir sıcaklık sensörünün bağlı olduğu mikrodenetleyicinin belli bir sıcaklık seviyesine ulaştığında SMI (System Management Interrupt) ile işlemciyi uyarması ve ardından BIOS SMI handlerı çalışarak firmware seviyesinde gereken işi yapması olarak verilebilir. Kritik seviyede BIOS makineyi kapatabilir. Burada önemli nokta bu durumdan işletim sisteminin haberi olmaması. ACPI’de ise durum farklı, bu durumdan işletim sisteminin de haberi oluyor, ilgili mesajları gösterebiliyor ve ACPI işletim sistemi tarafında makine kapatılıyor.
SMI’ı kullanan daha ileri seviye bir yapı daha var. O da BIOS’lardaki USB Legacy Desteği özelliği.Bu ileri seviye özellik, USB mouse ve klavye kullanan makinelerin USB desteği olmayan işletim sistemlerinde PS/2 mouse/klavye emülasyonu yapılması için tasarlanmış. İşletim sistemi mouse ve klavye verilerini PS/2 veri yolu üzerinden aldığını zannediyor.
Tabi ki bu işin bir patenti var. Muhteşem google patents hizmeti sayesinde ayrıntılı olarak işleyişi görebiliriz. İşleyiş Open Host Controller Interface Speklerinin Appendix B kısmında “Legacy Support Interface Specification” başlığı altında anlatılıyor. Tabi ki patent bunun donanımsal olarak implimentasyonu üzerine.
İşleyiş OHCI host controller için şu şekilde:
Öncelikle standart olarak klavye ve mouse veri alışverişinin “keyboard controller (KBC)” üzerinden 0×60 ve 0×64 portları aracılığı ile gerçekleştiğini bilmemiz gerekiyor. Yine PC mimarisinde standart olarak klavye için IRQ1 ve mouse için IRQ12 interruptlarının kullanıldığını bilmeliyiz. Sisteminizde /proc/interrupts dosyasına baktığınızda bu iki interrupt’ın da i8042 tarafından kullanıldığını göreceksiniz. Şu adreste i8042 yazmaçları için güzel bir özet bulunuyor. Burada daha fazla detaylandırmak anlamsız. Çekirdekte düşük seviye i8042 sürücüsü ise drivers/input/serio/i8042.c altında bulunuyor.
Emülasyon modunda 0×60 ve 0×64 portlarına okuma ve yazmalar host controller üzerindeki yazmaçlara gerçekleşiyor. USB legacy desteği açık ise ve USB klavye ve ya mouse takılı ise host controller usb paketlerini yakaladığı anda işlemciye SMI gönderiyor, SM moduna giren işlemci’de BIOS SMI handler‘da USB paketlerini yorumlayarak PS/2 datasına çeviriyor ve bu portlardan erişilecek şekilde host controller üzerinde ilgili yere yazıyor. Portlara herhangi bir yazma işlemi yapıldığında host controller yakalandığı için yine bir SMI göndererek BIOS’a girilip PS/2 data USB paketlerine çevrilip host controller’a iletiliyor. Host controllerda USB paketlerini cihazlara gönderiyor.
Buradaki ilginç nokta eğer USB emulasyonu açık ise ve sisteminizde hiç USB cihaz bağlı değil, yalnızca PS/2 klavye ve mouse kullanıyor olsanız bile herşey yine host controller emulasyonu ile gerçekleşiyor. Bunun için asıl KBC arayüzünün oluşturduğu interruptlar IRQ1 ve IRQ12 host controller üzerinden geçiriliyor. Yani asıl interrupt controller ile interrupt üreticisi arasında bulunuyor. Yakaladığı anda biliyor ki KBC de PS/2 datası bulunuyor. Bunları alıp emülasyonda asıl kendi üzerinden erişilen portların bulunduğu bölgeye ilgili PS/2 verilerini yerleştiriyor ve ardından ilgili interrupt’ı gönderiyor. İşletim sistemi interruptı yakalandıktan sonra verileri host controller’ın legacy portları (0×60 ve 0×64) üzerinden okunuyor. Biraz saçma gibi gelebilir. Ortada USB filan yokken neden böyle bir şeye gerek var. Sebebi USB’nin de olabileceği. Yani USB mouse ile PS/2 klavye’yi birlikte kullanabilmelisiniz. Bu yüzden emülasyon modundan herşey host controller üzerinden geçiyor. Bu emulasyon yapısı’nın OHCI için geçerli olduğunu belirtelim, UHCI ile benzer ancak ufak farklar içeren bir şekilde emulasyon işi gerçekleşiyor. Tüm host controller’ların speklerinde ilgili bölümlerde ayrıntılı bilgi bulunuyor.
USB mouse ve klavye paketleri host controller’a geldikten sonra işlemciye SMI gönderiyor, böylece emulasyon yapılıyor dedik. Emulasyonun amacı USB desteği olmayan ancak PS/2 desteği olan işletim sistemleri içindi. O zaman USB desteği olan işletim sistemlerinde host controller sürücüsü‘nün bir noktada USB interruptlarını karşılıyor olması gerekiyor. İşte bu işleme BIOS’un işletim sistemine USB devri (“USB Handoff”) ismi veriliyor. OpenHCI için konuşacak olursak, host controller basit bir şekilde HcControl yazmacında InterruptRouting bitini 1 ve ya 0 yaparak sırasıyla interruptları SMI aracılığı ile işlemciye ya da sistem interrupt kontrolörüne iletmeye başlıyor. Sistem interrupt kontrolörü işlemeye başladıktan sonra artık BIOS değil işletim sistemi USB paketlerini işliyor. InterruptRouting biti yalnızca okunabilir bir bit. Bu biti değiştirmek için önce HcInterruptStatus yazmacında OC (OwnershipChange) bitini set etmek daha sonra da HcControlStatus yazmacının OCR (OwnershipChangeRequest) bitini set etmek gerekiyor. Eğer InterruptRouting biti 0 olmuş ise artık interruptlar sistem kontrolörüne gidecek ve işletim sistemi yönetecek demektir. Handoff bir sebeple gerçekleşmez ise USB hiç bir cihaz çalışmayacak. InterruptRouting bitinin 0 olmadığı sürece host controller tüm interruptlerı SMI’a route edecek. Çekirdeğe baktığımızda bu işin şu şekilde yapıldığını görüyoruz:
[drivers/usb/host/ohci-hcd.c]
#ifndef IR_DISABLE
/* SMM owns the HC? not for long! */
if (!no_handshake && ohci_readl (ohci,
&ohci->regs->control) & OHCI_CTRL_IR) {
u32 temp;
ohci_dbg (ohci, "USB HC TakeOver from BIOS/SMM\n");
/* this timeout is arbitrary. we make it long, so systems
* depending on usb keyboards may be usable even if the
* BIOS/SMM code seems pretty broken.
*/
temp = 500; /* arbitrary: five seconds */
ohci_writel (ohci, OHCI_INTR_OC, &ohci->regs->intrenable);
ohci_writel (ohci, OHCI_OCR, &ohci->regs->cmdstatus);
while (ohci_readl (ohci, &ohci->regs->control) & OHCI_CTRL_IR) {
msleep (10);
if (--temp == 0) {
ohci_err (ohci, "USB HC takeover failed!"
" (BIOS/SMM bug)\n");
return -EBUSY;
}
}
ohci_usb_reset (ohci);
}
#endif
SMM özel bir mod. BIOS’daki herhangi bir hata ile makine hard freeze olabilir. Documentation/i386/usb-legacy-support.txt eski bir belge ama spesifik makinelerde legacy usb ile ilgili karşılaşılan bazı sorunlar dokümante edilmiş. Daha fazla örnek olsa güzel olurmuş.Burada da Windows 98 işletim sistemine özgü olduğu belirtilmiş bir race’in yol açtığı sorundan bahsediliyor. PCI enumeration sırasında işletim sistemleri, cihazların “configuration space”‘inde bulunan BAR’lara belli bir pattern yazarak, daha önce BIOS’un haritaladığı adres’in ne uzunlukta olduğu bilgisini alıyor. /proc/iomem altında görünen başlangıç adresi BAR’dan alınırken, boyut da aynı şekilde bu pattern yazılarak alınıyor ve eklenerek bittiği adres bulunuyor. Windows 98′de karşılaşılan race durumunda ise işte tam bu esnada SMI gelir ve BIOS’a girilirse normalde controller yazmaçlarına eriştiği adres olan BAR’daki adres hatalı olacak ve bu da SMI#’ın sürekli aktif olması ile sonuçlanacak denilmiş. Yanlış isem düzeltiniz: SMI kaynağı, chipsetlerde belli bitlerin aktif hale gelmesi ile anlaşılıyor. Chipset aktif bit gördüğü anda SMI üretiyor. [Güncelleme: Intel 82801AA (ICH) datasheetinden bir örnek verirsek: 5.12.6.1 de THRM# sinyali aktif olduğu anda THRM_STS biti 1 yapılıyor. Eğer THRM_EN biti de aktif ise ikisinin aktif olduğu an SMI üretiliyor.] SMM’de işini bitirince bu biti temizliyor. Temizlemeden handler’dan çıkılırsa sürekli SMI üretilip duruluyor çünkü bit aktif ve sanki yeni bir SMI’mış gibi algılanıyor. Bundan sonra OHCI spekinin 5.1.13.3 bölümünde anlatıldığı üzere OS OwnershipChangeRequest bitini set ettiği anda SMM bundan haberdar olup temizlik işlerini yapıp InterruptRouting bitini temizliyor. Böylece handoff gerçekleşiyor. Ancak adresteki raporda belirtildiğine göre SMI’ın sürekli aktif olması sebebiyle bu request SMM tarafından karşılanmıyor ve handoff gerçekleşmiyor. Bu da Windows 98 makinede USB cihazların algılanamaası ile sonuçlanıyor.


No comments at the moment.
Add a comment