NT 3.1 çekirdeğine girmeye çalışınca 486DX4 makinem neden yeniden başlıyor?
(retrocomputing.stackexchange.com)- Windows NT 3.1’de
i386kdile Ctrl-C break-in yapıldığındakd>istemi yerine hedef 486DX4 sistemi yeniden başlıyordu; nedenin enhanced 486 uyumluluğu sorunu olduğu ortaya çıktı - NTOSKRNL.EXE içindeki
KiSaveProcessorControlStateveKiRestoreProcessorControlState, CPU tipini kontrol ederken word karşılaştırması kullandığı için CPUID destekli 486’yı Pentium veya daha üstü gibi yanlış değerlendiriyor - KPRCB’deki
CpuTypeveCpuIDbirlikte okununca CPUID destekli 486’nın model numarası 256 fazla yorumlanıyor; bunun sonucunda 486’da bulunmayan CR4 register’ına erişim gerçekleşiyor - Başta takılı olan 486DX-33 ve SMM’siz write-through Am486DX4-NV8T ile kernel debugging normal çalıştığından, sorun CPUID komutunu sağlayan enhanced 486’lara daraltıldı
- NTOSKRNL.EXE içindeki iki
cmp ds:word_FFDFF138, 5konumu byte compare olarak yamalanırsa hem özgün NT 3.1 Advanced Server’da hem de NT 3.1 SP3’te düzeltilebiliyor
Yeniden üretme ortamı ve belirtiler
- Compaq ProSignia 3080’e Windows NT 3.1 kurulduktan sonra kernel debugging deneniyor
- Bu sistem gerçek kullanımda Windows NT 3.1 çalıştırmıştı ve Windows NT’nin açıkça hedeflediği makinelerden biri gibi görünüyor
- RAM 128 MB’a çıkarılmış, soketli Intel 486DX-33 ise AMD enhanced 486DX4-SV8B ile değiştirilmişti
- Bu CPU write-back cache ve SMM destekliyor ve voltaj adaptörü soketine takılıyor
- BIOS’un 486DX4 desteğini ele alması ertelenip CPU 2x çarpan ile jumper’dan ayarlanıyor
- Yonga setinin L1 write-back desteği olmadan 2x çarpanla ayarlandığında Intel 80486DX2-66 ile yazılım uyumlu olması bekleniyor
- Intel 80486DX2-66 bu sistemin desteklediği seçeneklerden biri
- Windows NT 3.1 kurulumu kendi başına sorunsuz tamamlanıyor
- Windows NT 3.1 CD’sinde tüm debugging sembolleri bulunduğundan kernel debugging deneniyor
- Amaç, NetDDE’nin event log’a neden hata bıraktığını araştırmaktı
- Belirli bir EISA Ethernet kartında sistemin çökmesi sorunu da vardı ve donanım arızası olasılığı hâlâ duruyordu
- En yeni Windows 10 geliştirme kitindeki
kdveyantkdyerine, kernel debugging ayarlarının uyması için Windows NT 3.1 ile geleni386kdkullanılmalı i386kdiçinde Ctrl-C break-in denendiğinde hedef makinekd>istemini sunmadan yeniden başlıyor
Neden olarak elenenler
- Belleğin sağlam olduğu doğrulandı
- Sistem dosyası bozulması değildi
- Çekirdek debugging için durduğunda sistemi yeniden başlatan bir donanım watchdog’u etkin değildi
- Host tarafındaki USB-serial adaptör normal iletişim kuruyordu
- Sahte PL2301 gibi görünen bir cihaz olsa da debugger komutlarını yanlış gönderip “reboot system” komutu iletmiş değildi
- KD protokolünde gerçekten reboot system komutu var
- Anakartın uzaktan yönetim veya uyarı seçenekleriyle de ilişkili değildi
Asıl neden: enhanced 486 ile NT 3.1 çekirdeğinin uyumsuzluğu
- Windows NT 3.1 çekirdeği enhanced 486 işlemcilerle uyumlu değil
- Daha spesifik olarak sorun,
CPUIDkomutunu sağlayan 486 işlemcilerde ortaya çıkıyor - Kernel debugging şu CPU’larda normal çalışıyor
- Başta takılı olan 486DX-33
- SMM’siz, daha eski non-enhanced core’a sahip write-through Am486DX4-NV8T
- Amaç yalnızca NT 3.1 kernel debugging’i denemekse Windows NT 3.1 ile temel olarak uyumlu bir CPU kullanmak daha uygun
- NT’nin kendisini düzeltmek için NTOSKRNL.EXE’deki CPU tipi belirleme hatasını yamalamak gerekiyor
Sorunun patladığı çekirdek kod yolu
- Uyumsuzluğun doğrudan nedeni
KiSaveProcessorControlStateiçindeki bug- Karşılık gelen fonksiyon
KiRestoreProcessorControlStateiçinde de benzer bir bug var
- Karşılık gelen fonksiyon
KiSaveProcessorControlState, NTOSKRNL.EXE içinde üç yerde çağrılıyor- Bir exception
KdpTrapüzerinden kernel debugger’a yansıtıldığında- Ctrl-C break-in sırasında, timer tick interrupt içindeki break-in polling özelliğinden breakpoint exception oluşuyor
KeBugCheckExçağrıldığında, yani “mavi ekran” durumundaKiSaveProcessorStateçağrıldığında- IDA’nın NTOSKRNL.EXE control flow analizi eksiksizse bu fonksiyon export edilmiyor ve NTOSKRNL içinde de çağrılmıyor; dolayısıyla pratikte gerçekleşmiyor gibi görünüyor
- Bir exception
KiSaveProcessorControlState, genişletilmişCONTEXTyapısına işlemci kontrol durumunu kaydediyor- CR0, CR2, CR3’ü kaydediyor
- Pentium ve üzeri için CR4’ü de kaydediyor
- DR0~DR3, DR6, DR7 debug register’larını kaydediyor
- GDT adresi, IDT adresi, etkin TSS selector, LDT selector gibi global protected mode ayarlarını da kaydediyor
KPRCB alanlarını yorumlama hatası
- İşlemci tipini belirlemek için KPRCB’deki değer kullanılıyor
- KPRCB, KPCR’nin bir parçası
- Boot işlemcisinin veya tek işlemcili sistemin KPRCB’si sanal adres
FFDFF120üzerinde ve ilgili metoda hardcode edilmiş
- Geoff Chappell tarafından derlenen NT 3.1 KPRCB alanları şöyle
+018 CHAR CpuType+019 CHAR CpuID+01A UShort CpuStep
- Bu alanlar
KiSetProcessorTypeiçinde başlatılıyor- 486 işlemcinin offset 18 byte’ı 4 olarak ayarlanıyor
- Pentium işlemciler için 5 olarak ayarlanıyor
- Pentium Pro ve Pentium II/III işlemciler için 6 olarak ayarlanıyor
- offset 19 byte’ı, işlemcinin CPUID destekleyip desteklemediğini ve “reasonable” şekilde çalışıp çalışmadığını gösteren boolean flag
- Sorunlu karşılaştırma komutu
FFDFF138adresindeki byte’ı değil word’ü okuyorFFDFF138, KPRCB başlangıcından 18h byte uzaklıktaki konum- Bu yüzden yalnızca
CpuTypedeğil, hemen sonraki byte olanCpuIDde model numarasının bir parçası olarak birlikte yorumlanıyor
- CPUID destekleyen işlemcilerde model numarası gerçekte olduğundan 256 fazla ele alınıyor
- CPUID destekli 80-4-86, Windows NT 3.1’de 80-260-86 gibi ele alınıyor
- 260, Pentium eşiği olan 5’ten çok daha büyük olduğundan çekirdek bu işlemcide CR4 olması gerektiğine karar veriyor
- Enhanced 486’da CR4 bulunmadığı için break-in yolunda sorun oluşuyor
Yama yöntemi
- Bug doğrulandıktan sonra düzeltme basit
- NTOSKRNL.EXE içinde
cmp ds:word_FFDFF138, 5komutu yalnızca iki kez geçiyorKiSaveProcessorControlStateKiRestoreProcessorControlState
- Her iki konumda da word compare, byte compare olarak değiştirilmeli
- Hex editörle şu byte dizisi iki kez yamalanır
- Eski:
66 83 3D 38 F1 DF FF 05 - Yeni:
90 80 3D 38 F1 DF FF 05
- Eski:
- Bu düzeltme, özgün NT 3.1 Advanced Server dağıtımındaki NTOSKRNL.EXE’ye ve NT 3.1 SP3’e uygulanabiliyor
1 yorum
Hacker News yorumları
Bir zamanlar bir servisin ayakta olup olmadığını kontrol etmek için port kontrolü yazmıştım; makinelerde birkaç TCP portu açmakla şirketin yarısını devirmiştim
Saçma sapan zamanlardı
Gerçekten çok yol katettik
https://en.wikipedia.org/wiki/Ping_of_death
Bazı makinelerde yıllarca yamalanmamış SMB açıkları da vardı. Metasploit’in zaten var olduğu dönemdi; birkaç komutla yerel ağdaki Windows hostlarının çoğuna VNC enjekte edebiliyordunuz. Günümüzde en azından yama hızı muazzam derecede yüksek
Ah, retro computing tavşan deliği. Gerçek dünyadaki sonuçlardan zararsızca ayrılmış durumda ama yine de çok tatmin edici
Geek’ler için gerçek bir bal kapanı. Sonunda “6 yorum daha göster” genişletme düğmesine bastım
Bugün biraz iş yapabilirim belki
Ama 486 mı? Mavi ekranlar ve belleği yetmediği için diske swap yapmasını bekleyerek bitmek bilmeyen süreler geçirdiğim anılar çok fazla canlanıyor. Benim için hâlâ fazla erken gibi
“Çözüm bariz” gerçekten doğru söz
Muhtemelen trap kodunun disassembly’sini tekrar tekrar okuyup sorunu bulmuşlardır. QEMU ya da başka bir debugging aracını kullanabilmiş olduklarını sanmıyorum
Sonlardaki gizli yorumun içine gömülmüş yöntemi de mutlaka okumak gerekiyor
En az oy alan yorumları gizlemiyor, en yeni ya da en eski olanları da gizlemiyor. Rastgele gibi geliyor ve gereksiz
Sorun alansa gizlemek yerine sayfalama koymak bence daha iyi olur
Eski Abit, Asus, belki MSI anakartlarda uyumluluk için kullanılan slotket adaptörleri gibi şeylerin gerçekten overclock yeteneği vardı
RAM hızının ne olduğu ve anakartın çarpan ayarlarında ne kadar saat hızına dayanabildiği belirleyiciydi. Celeron ve Pentium II döneminin, overclock’un görece erken zamanlarıydı
Bir ara uyumluluk yüzünden Celeron 600’ü bir adaptöre takıp, onu da tekrar Slot II - Socket 370 adaptörüne takarak [1] gibi bir kurulumla 1,2 GHz’de sorunsuz çalıştırmıştım. Hatta Windows ME’de 1,4 GHz’e kadar çıkardığımı sanıyorum; sonunda o CPU’yu yaktım
[1]http://krick.3feetunder.com/370mod/
Soruya verilen yanıt gerçekten harikaydı
Konu da güzel, yanıt da çok iyiydi
Soruyu soran kişinin yanıtı da kendisinin yazmış olması güzel
Böyle şeyleri seviyorum. İnsanların retro computing ile ilgilenmesine gerçekten seviniyorum
Bu tür sorunları ve çözümlerini herkes için belgelendirmek iyi bir şey
Bu CPUID denen şeyin kötü bir fikir olduğunu biliyordum
Neden soru ile yanıtın zaman damgaları aynıydı?
Muhtemelen bu bilgiyi SO’nun soru-cevap biçiminde yayımlamanın, kimsenin bulamayacağı bir blog yazısından daha uzun ömürlü olacağını düşünmüştür
Açmadan ne olduğunu bilmiş olmam kötü mü?
Neyse, gidip şu çocuklara çimlerimden uzak durmaları için bağırmam lazım
Güvenebileceğimiz şeyler zekâmız ve gerekirse sabit hattan arayabileceğimiz ustalardı. Faydalılığı değişken yanıtlarla dolu harika bir internet falan yoktu