This month, the Old Computer Geeks Club has a conversation with one of the creators of the famous 6502 CPU, Bill Mensch! This is a free-flow talk about not only the history of the 6502 but the future as there are some exciting new developments coming soon!
https://www.youtube.com/watch?v=_8lOs1wPUn0&t=769s&ab_channel=VintageComputerCenter
7. 6. 2022, 22:32 editováno autorem komentáře
Kdyz tak ctu o tom bootu konzole pres RESET CPUcka, tak me napadlo, ze vlastne i x86-64 asi musi porad startovat v realnem rezimu a asi ma taky nejaky podobny reset vektor ne?
nasel jsem jen trosku higher level info tady https://wiki.osdev.org/System_Initialization_(x86) ale zrovna to, co se stane ihned po startu tam nemaji popsane :)
No jsou na to dvě odpovědi, jedna krátká a druhá správná :-)
V každém případě 8086 NEpoužívá koncept vektorů, což se ukázalo jako další problematický rys celé této architektury (jak se postupně rozšiřovala).
Takže krátká odpověď zní: 8086 začíná načítat instrukce od adresy ffff:0000 v reálném režimu, kde ffff je segment a 0000 offset. Procesor se nachází v reálném režimu.
7. 6. 2022, 16:08 editováno autorem komentáře
Dlouhá a snad i správná odpověď zní jinak: ona adresa ffff:0000 má dva významy:
1) na původní 8086 odpovídá ffff:0000 fyzické adrese ffff0 (segment se překrývá s offsetem, jen je posunut o 4 bity a sečten)
2) ovšem současně to z opačného pohledu znamená (posledních 16 bajtů paměti)
A další procesory používají ten druhý pohled, tedy startují na posledních 16 bajtech paměti, ať je to jakákoli velikost. Na 386 tedy FFFFFFF0, na x86-64 netuším, ale asi to bude "hodně eFek 0" :-)
No a to je problém, protože takové adresy vlastně v reálném režimu neexistují. Takže boot kód sice jakoby používá adresy ffff:0000, jenže ve skutečnosti jsou bity segmentu **všechny** nastaveny na jedničku, i ty neviditelné (vivat intel). Boot code se tedy co nejdříve přepíná do chráněného režimu, nastaví si deskriptory a další magii a poté přepne **zpět** do reálného režimu, aby najel BIOS.
(buďme rádi, že to vlastně bootuje, protože to je fakt složitější proces, než jednoduchý skok na adresu uloženou na pevně dané adrese paměti, jak to má právě 6502).
x86-64 plni 64bitovy RIP hodnotou 0x0000_0000_0000_FFF0 a co se tyce CS, tak CS Selector = 0xF000 a CS Base (Descriptor Cache, tj. kus te 'neviditelne' casti) = 0x0000_0000_FFFF_0000. Tzn., ze i x86-64 startuje v real 86 modu na fyzicke adrese 0xFFFF_FFF0 a drzi se v fyz. adresovem prostoru 0xFFFF_0000 az 0xFFFF_FFFF, tj. pouhych 64 kB, dokud se nejakou instrukci (far jump, call,...) nemodifikuje CS (tj. 16bitovy CS Selector). CS Selector se potom automaticky prepise do CS Base podle standardnich pravidel adresovani 8086 (Base = Selector << 4), a od tohoto momentu se x86-64 muze pohybovat v phy. adresovem prostoru 0x0_0000 az 0xF_FFFF (prvni MB, jako 8086, nebo i o temer 64k vyse, pokus se vypne A20 masking). Vykrocit mimo tento prostor potom jiz znamena opustit real 86.
Prave tech po resetu adresovatelnych 64k je jednim z duvodu, proc BIOSy temer okamzite prechazi do PM.
Pri POResetu se chipset postara o to (startuje v takove konfiguraci), aby byla do tohoto adresoveho prostoru namapovana pres DMI pamet BIOSu, at uz je to ve finale fyzicky skrze rozhrani LPC, nebo dnes uz snad vyhradne SPI.
Uz docela dost let se nemapuje cela Flash 1:1, ale nejprve si z ni chipset nacte tzv. descriptory (popis regionu v pameti, offset, delka), a pote namapuje pouze region BIOSu na konec prvnich 4 GB adresoveho prostoru. Fyzicky je translace delana tak, ze pri pozadavku od CPU na precteni prislusne adresy se v chipsetu pres DMI rozjede dedikovany SPI engine, ktery z Flash vycte kyzena data a umisti je na datovou sbernici. Samozrejme je to relativne pomale, ale tady se spoleha na to, ze drive ci pozdeji pomuze cache v CPU.
Na adrese 0xFFFF_FFF0 potom byva zpravidla near jump do kratkeho useku kodu, ktery pomoci instrukci lgdt/lidt natahne natahne parametry tabulky descriptoru z Flash, nahodi se bit 0 v CR0 registru (PM) a obligatnim far jumpem selektor:adresa se skoci do BIOS kodu v PM - typicky flat space 0..4 GB.
Nutno rici, ze proces bootu je pomerne komplikovana zalezitost, nebot nez vubec dojde k fetchi na adrese 0xFFFF_FFF0, tak v core probehne BIST (Built-In Self Test), pote mikrokod natahne FIT (Firmware Interface Table) na ktery ukazuje adresa 0xFFFF_FFC0, a podle zaznamu ve FITu se provedou prislusne akce - update mikrokodu, ACM, secure boot atd. atd. - ktere pri trose stesti pokracuji standardnim fetchem na 0xFFFF_FFF0.
Presne tak, ja tracoval pristupy na SPI pamet (fyzicky) u C2000, a je tam videt po resetu cteni mapovaci tabulky, software straps, a az daleko za tim je boot kod.
Zajimavy je, ze to pro tu prvni instrukci na $END-16 to nacte 64 B naraz (jakoby to emulovalo pametove pristupy ktere maji zarovnani/granularitu podle cacheline), vsechny instruction fetche se chovaji na SPI takto (nacita se to jen jednou, takze zas tak neefektivni to neni).
Ale pak kdyz se aktivuje CR0.PE=1, a zacne to pouzivat GDT, tak se ctou i mensi kousky z te SPI flash (a to opakovane), zarovnano na 4B (32 bit) adresy. U toho biosu co jsem mel, byla ta GDT podivne nezarovnana, takze se cetlo 12B namisto 8B.. no mohlo to byt o chlup rychlejsi :P
Doporučuji Kick-C kompilátor:
https://gitlab.com/camelot/kickc
cc65 je také dobrý, ale výsledný kód neoptimalizuje tak dobře jako Kick-C.