Tartalmi kivonat
Tartalomjegyzék Tartalomjegyzék Tartalomjegyzék.3 1.fejezet: Kompatibilitás az x86-os architektúrákkal 10 1.1 Hardware kompatibilitás 10 1.11 Software kompatibilitás 10 1.2 Konkurens ötödik generációs x86-kompatibilis architektúrák .12 1.21 Az INTEL Pentium processzora 12 1.211 INTEGER egység 13 1.212 Cache-ek, memória kezelés15 1.213 Programág előrejelzés 17 1.214 Beépített lebegőpontos egység18 1.215 "Bogaras" a koprocesszor ?19 1.216 Sebességnövelő technikák a Pentium osztályú számítógépeknél.19 1.217 Multiprocesszoros rendszerek22 1.218 Adatvédelem 23 1.22 A Cyrix M1-es processzor családja 24 1.221 Pipeline vagy szuperpipeline ?24 1.222 32 regiszter jobb mint 8 ! 26 1.223 Csökkentett függőség - nagyobb sebesség28 1.224 Kiegyénített terhelés -gyorsabb programfutás 29 1.225 Kiugrás lehetősége a végrehajtási sorrendből29 1.23 A NexGen Nx 586-os processzor családja 31 1.231 Hogyan lehet RISC processzorból CISC avagy
fából vaskarika ? .31 1.232 x86 - RISC86 33 1.233 Szuperskalár végrehajtás-javuló hatásfok35 1.234 Az utasítás-előrejelzési CACHE (BPC)35 1.235 Cache hierarchia36 2. fejezet: Processzor erőforrások39 Landmark 2.0040 CHECKIT 3.043 MIPS 1.20: (MIPS)46 3 Tartalomjegyzék CPUTEST 1.1 (MIPS)48 3. Fejezet: Általános CPU programozási információk 62 3.1 A memória felépítése62 3.11 Nemszegmentált vagy "lapos" modell63 3.12 Szegmentált modell 64 3.2 Regiszterek 65 3.21 Általános regiszterek 65 3.22 Szegmensregiszterek67 3.23 Utasításmutató 69 3.24 A verem felépítése és használata 69 3.25 Flagregiszter 70 3.251 Állapotbitek71 3.26 Rendszer-regiszterek73 3.261 Rendszer-flagek 74 3.262 Vezérlőregiszterek 77 3.263 Nyomkövető regiszterek 82 3.3 CPU üzemmódok84 3.31 Valós üzemmód ("valós mód")84 3.32 Védett üzemmód 84 3.33Rendszermenedzselő üzemmód84 3.4 Inicializálás és az üzemmódok közötti átkapcsolás 86 3.41 A
processzor inicializálása 86 3.411 A processzor állapota reszetelés után 87 3.412 Az első végrehajtott utasítás 90 3.413 A cache engedélyezése91 3.42 Software inicializálás valós üzemmódban92 3.421 Rendszertáblázatok 92 3.422 Az NMI megszakítás92 3.43 Software inicializálása védett üzemmódban93 3.431 Rendszertáblázatok 93 3.432 Megszakítások94 3.433 Lapozás 94 3.434 Taszkok 96 3.435 A TLB, BTB és cache tesztelése97 3.44 Üzemmódváltás 97 3.441 Átkapcsolás védett módba 97 3.442 Visszakapcsolás valós üzemmódba 98 4 Tartalomjegyzék 3.45 Példa inicializálásra és üzemmód átkapcsolásra99 3.451 A példa célja99 2.452 A memória elrendezése a reset-elést követően 100 3.453 Az algoritmus100 3.454 Eszközök használata 102 3.455 A STARTUPASM listája104 3.456 A MAINASM forráskódja 113 3.457 Állományok támogatása116 3.5 A valós üzemmód felépítése, működése 119 3.51 Címek lefordítása119 3.52 Regiszterek és
utasítások 120 2.53 Megszakítás és kivétel kiszolgálás 121 3.54 Valós üzemmódú kivételek122 3.6 A Védett üzemmód felépítése, működése 124 3.61 Memóriaszervező regiszterek 125 3.62 Rendszer utasítások 126 3.63 Védett üzemmódú memóriaszervezés 128 3.631 A szegmentálási modell kiválasztása131 3.6311 A sík modell 131 3.6312 Védett sík modell 133 3.6313 Multiszegmens modell 134 3.632 Szegmensfordítás 136 3.6321 Szegmensregiszterek 138 3.6322 Szegmensszelektorok 139 3.6323 Szegmens deszkriptorok141 3.6324 Szegmensdeszkriptor-táblázatok148 3.6325 Deszkriptortáblázat bázisregiszterek149 3.633 Lapfordítás 150 3.6331 Lapozási opciók151 3.6332 Lineáris cím152 3.6333 Laptáblázatok 152 3.6334 Laptáblázat bejegyzések153 3.6335 Lapkeret cím154 3.6336 A Present (betöltött, jelenlevő) bit 154 3.6337 Hozzáfért (accessed) és "piszkos" (dirty) bitek.156 3.6338 Írás/olvasás illetve felhasználó/felügyelő bitek.156 5
Tartalomjegyzék 3.6339 Lapszintű cache-vezérlő bitek157 3.63310 Fordítási segédpufferek 157 3.634 Szegmens- és lapfordítás keverése158 3.6341 A sík modell 158 3.6342 Több lapot átfogó szegmensek 159 3.6343 Több szegmenst átfogó lapok159 3.6344 Nem illeszkedő lap- és szegmenshatárok159 3.6345 Illeszkedő lap- és szegmenshatárok 159 3.6346 Egy laptáblázat elhelyezése szegmensenként.161 3.7 Védelemi mechanizmusok162 3.71 Szegmens szintű védelem 162 3.72 A szegmens deszkriptorok és a védelem 163 3.721 Típusellenőrzés 164 3.722 Határ (limit) ellenőrzés 167 3.73 Privilégium szintek 169 3.74 Az adathozzáférések korlátozása171 3.741 Kódszegmensekbeli adatok elérése173 3.75 Vezérlésátadások korlátozása 174 3.76 Kapudeszkriptorok176 3.761 Veremváltás 181 3.762 Visszatérés egy procedúrából 185 3.77 Az operációs rendszer számára lefoglalt utasítások 188 3.771 Privilegizált utasítások 188 3.772 Érzékeny utasítások189 3.78
Mutatók érvényességét ellenőrző utasítások 189 3.781 Deszkriptor érvényességének ellenőrzése192 3.782 Mutatók integritása és az RPL 193 3.79 Lapszinti védelem194 3.791 A laptáblázat bemenetek által tartalmazott védelmi paraméterek.194 3.7911 A megcímezhető tartományt érintő megszorítások.195 3.7912 Típusellenőrzés196 3.7913 A védelem kombinálása a laptáblázatok mindkét szintjén .197 3.7914 A lapvédelem fölülírói 197 3.792 Lap- és szegmensvédelem kombinálása 198 6 Tartalomjegyzék 3.8 Védett üzemmódú multitaszking 200 3.81 Taszk-állapot-szegmens201 3.82 A TSS deszkriptor204 3.83 Taszkregiszter 205 3.84 Taszk kapudeszkriptorok 208 3.85 Taszkkapcsolás 209 3.86 Taszkok visszafelé kapcsolása (LINKING) 214 3.861 A Busy (foglalt) bit megelőzi a hurkok kialakulását .216 3.862 A taszk visszakapcsolások módosítása 217 3.87 Taszkok címtartománya218 3.871 Taszkok által lineárisról- fizikai címre végzett leképzés.218
3.872 A taszkok logikai címtartománya 219 3.9 Védett üzemmódú kivételek és megszakítások 222 3.91 Kivétel- és megszakításvektorok 223 3.92 Utasítások újraindítása225 3.93 Megszakítások engedélyezése és letiltása 225 3.931 További NMI megszakítások maszkolása226 3.932 INTR megszakítások maszkolása 226 3.933 Debug hibák maszkolása az RF bit segítségével 227 3.934 Egyes kivételek és megszakítások maszkolása228 3.94 Szimultán kivételek és megszakítások közötti prioritás.228 3.95 A megszakításdeszkriptor-táblázat 230 3.96 IDT deszkriptorok231 3.97 Megszakítás taszkok és megszakítás-kezelő procedurák .233 3.971 Megszakítás-kezelő procedúrák233 3.9711 A megszakítás-kezelő eljárás verme 234 3.9712 Visszatérés egy megszakítás-kezelő eljárásból .235 3.9713 A megszakítás-kezelő eljárás flaghasználata 236 3.9714 Védelem a megszakítás-kezelő eljárásokban.236 3.972 Megszakítás-kezelő taszkok237 3.98
Hibakódok239 7 Tartalomjegyzék 3.99 Kivétel feltételek240 3.991 0-s számú megszakítás - Osztáshiba (Divide Error).241 3.992 1-es számú megszakítás - Debug kivétel 241 3.993 3-as számú megszakítás - Töréspont (Breakpoint) .241 3.994 4-es számú megszakítás - Túlcsordulás (Overflow) .242 3.995 5-ös számú megszakítás - Határsértés (Bounds Check) .242 3.996 6-os számú megszakítás - Érvénytelen utasítás (Invalid Opcode) .243 3.997 7-es számú megszakítás - nem elérhető eszköz (Device Not Available).243 3.998 8-as számú megszakítás - Kettős hiba, dupla hiba (Double Fault).244 3.999 9-es számú megszakítás - (az Intel által fenntartott, használata nem ajánlott).246 3.9910 10-es számú megszakítás - Érvénytelen TSS (Invalid TSS).246 3.9911 11-es számú megszakítás - Szegmens nincs jelen, (Segment Not Present) .247 3.9912 12-es számú megszakítás - verem kivétel (Stack Exception).249 3.9913 13-as számú megszakítás -
Általános védelmi hiba (General Protection).250 3.9914 14-es számú megszakítás - Laphiba (Page Fault).252 3.99141 Taszkkapcsolás alatti laphiba 253 3.99142 Laphiba összeférhetetlen veremmutatóval 254 3.9915 16-os számú megszakítás - Lebegőpontos egység hiba, Floating-Point Error) .255 3.99151 Numerikus kivételek kezelése257 3.99152 Szimultán kivételekre adott válaszok258 3.9916 17-es számú megszakítás - Illeszkedés ellenőrzés ellenőrzési hiba (Alignment Check) .259 3.9917 18-as számú megszakítás - Processzortípus ellenőrzés (Machine Check) .261 8 Tartalomjegyzék 3.910 A kivételek összefoglalása261 3.911 Hibakódok összefoglalása 263 3.10 Rendszermenedzselő üzemmód264 3.101 Az SMI megszakítás 265 3.102 Az SMM kezdeti állapota 267 3.1021 Az SMM végrehajtása268 3.103 Az SMRAM processzor-állapot tároló formátuma269 3.1031 Az SMM revízió-azonosító (FEFCH ofszet) 271 3.1032 I/O trap-újraindítás (FF00H ofszet) 272 3.1033
Felfüggesztett állapotból való automatikus újraindítás (FF02H ofszet) .273 3.1034 Az állapottároló bázisa (FEF8H ofszet)273 3.104 Az SMRAM relokációja 274 3.105 Visszatérés az SMM-ből275 3.11 8086-os virtuális üzemmód 276 3.111 8086 CPU kód végrehajtása277 3.1111 Regiszterek és utasítások 277 3.1121 Lapozás a 8086-os virtuális taszkok esetében 278 3.1122 Védelem egy 8086-os virtuális taszkon belül 279 3.113 Belépés a 8086-os virtuális üzemmódba és az abból való kilépés .279 3.1131 Taszkátkapcsolások általi tranzíciók282 3.1132 Átmenet trap- és megszakításkapukon keresztül .282 3.114 Érzékeny utasítások 285 3.115 Virtuális megszakítások támogatása286 3.116 A 8086 operációs rendszerhívások emulációja286 3.117 Virtuális I/O 287 3.1171 I/O-ra leképezett I/O 288 3.1172 Memóriába leképezett I/O288 3.1173 Különleges I/O pufferek289 3.118 Különbségek a 8086 CPU-hoz képest 289 3.119 Különbségek a 286 CPU-hoz képest
294 3.1191 Privilégiumszint 294 3.1192 A busz lezárása295 3.1110 Különbségek a 386 és 486 CPU-hoz képest 296 Ábra- és példajegyzék .297 9 Tartalomjegyzék Előzetes a második kötet tartalmából .301 10 Hardware kompatibilitás 1.fejezet: Kompatibilitás az x86-os architektúrákkal 1.1 Hardware kompatibilitás Az INTEL a Pentium processzort (80502, 80503) úgy tervezte, hogy a már meglévő x86-os architektúrákkal "felülről" kompatibilis legyen. A gyártók közötti hardware kompatibilitásra kár lenne szót vesztegetni, ugyanis a hardware felépítés szükségképpen elkell hogy térjen, a jogi viták elkerülése miatt. Azonban a fejlesztőknél, és a gyártóknál (bízzunk benne hogy nem csak ez) nem ez a fő szempont. Szeretnének minél gyorsabb, és hatékonyabb típusokat kifejleszteni e gyorsuló számítástechnikai piac korlátlan "számítási éhségének" kielégítése érdekében. 1.11 Software kompatibilitás
Nagyon lényeges kérdés azonban a software kompatibilitás. A software kompatibilitás megőrzése érdekében az alkalmazások fejlesztésekor szemelőtt kell azokat a bit-eket, Byte-okat amelyek különböző hardware architektúrák esetén változhatnak. Erre a sokféle processzor verzió, és chip-gyártó miatt kell ügyelnünk. Az ötödik generációs x86 kompatibilis processzorok gyártása terén sok gyártó és fejlesztő indult csatába. Minden egyes processzornál a kompatibilitás kérdését külön meg kell vizsgálni. Ma már vannak neves cégek, amelyek csak ezen kérdések vizsgálatára kötelezték el magukat, pl.: az XXCAL laboratórium. A továbbiakban ezen nemzetközileg elismert "laborcégek" vizsgálati eredményeire, vagy a software fejlesztőjének kompatibilitási nyilatkozatára fogunk hivatkozni. Számos regiszter és memóriaszerkezet leírásakor egyes bitek "fenntartott"-ként vannak jelölve. Abban az esetben, amikor egy bit
meghatározatlannak vagy fenntartottnak van jelölve, alapvető követelmény az, hogy az jövőbeni processzorokkal való kompatibilitás érdekében a software ezeket a biteket úgy kezelje, mintha a jövőben (bár ismeretlen) hatásuk lenne a processzor működésére. A fenntartott bitek 11 Kompatibilitás az x86-os architektúrákkal működését célszerű nemcsak meghatározatlannak, hanem kiszámíthatatlannak is tekinteni. Ajánlatos, hogy a fenntartott biteket figyelembe vevő software kövesse a következő irányvonalakat: A fenntartott biteket tartalmazó regiszterek tesztelésének eredménye ne függjön az említett bitek állapotától. Ezért tesztelés előtt ezeket a biteket maszkolni kell. A memóriába vagy regiszterbe való tárolás ne függjön egyetlen fenntartott bit állapotától sem. Ne alapozzunk a fenntartott visszanyerésének lehetőségére. Egy regiszter feltöltésekor a fenntartott biteket mindig a dokumentációban
közölt értékekkel töltsük fel. Ha ez nincs feltüntetve, akkor vissza kell tölteni az előzőleg onnan kiolvasott értékeket. 12 bitekben tárolt információ Hardware kompatibilitás 1.2 Konkurens ötödik generációs x86-kompatibilis architektúrák 1.21 Az INTEL Pentium processzora Az X86-os család legfiatalabb tagja a Pentium processzor, amelyet az INTEL úgy tervezett, hogy "lefelé" 100 %-ban kompatibilis legyen az X86-os család előző tagjaival. 64 bit 32 bit Kód-cache Utasításelôrejelzés 32 bit 256 bit Prefetch Buffer-ek 256 bit 64 bit 256 bit Pipeline-olt FPU 64 bites Busz interface ALU 64 bit ALU 64 bit 32 bit 32 bit Integer Egység Regiszter készlet 32 bit 64 bit 32 bit Hardware-es szorzás Hardware-es összeadás Hardware-es Hardware-es osztás Adat-cache 1.1 ábra: A Pentium processzor blokkvázlata A Pentium processzor szuperskalár architektúrával épül föl, tehát egyetlen órajel ciklus alatt egynél több
utasítást tud végrehajtani. Beépített lebegőpontos egységgel, a processzorlapkára integrált külön 13 Konkurens ötödik generációs architektúrák kód- és write-back adatcache-sel, 64 bit-es külső adatbusszal, az újabb 90-100MHz-es típusok integrált MP (Multi Processor) vezérlővel rendelkeznek. PREFETCH Utasítás dekódolás Utasítás dekódolás Cím generálás Cím generálás Végrehajtás Végrehajtás Write-Back Write-Back U V Pipeline Pipeline 1.2 ábra: Az INTEGER egység 14 1.211 INTEGER egység A Pentium processzor szíve a két beépített utasítás pipeline, amelyek egymástól függetlenül működnek. Ezek a pipeline-ok teszik képessé a Pentium processzort, hogy egy óraciklus alatt két integer utasítást végrehajtson. Ez közel kétszeres chip sebességet jelent az azonos frekvencián működő Intel486 chiphez képest. A Pentium processzor pipeline-jai azonosak az Intel486 CPU egyszerű pipeline-jával, de magasabb
sebességhez optimalizálták őket. Mindegyik pipeline öt utasítás végrehajtási szintre tagozódik: Prefetch Utasítás dekódolás Címgenerálás Végrehajtás WriteBack Utasítások elő-betöltése (Instruction Prefetch): Az utasítások kódjának a magasabb címekről történő előzetes beolvasása a Az INTEL Pentium processzora processzorba, a végrehajtást megelőzően; az utasítások végrehajtásának átfedésére használt technika. Amikor egy utasítás a prefetch-ből az utasításdekóderbe kerül, a pipeline kész egy másik, új utasítás végrehajtásának elkezdésére. Sok esetben a Pentium processzor két utasítást is el tud végezni egyszerre - egy utasítást mindegyik pipeline-ban - ez a módszer "utasítás párosítás" néven ismert. A párosítás feltétele, hogy mindkét utasításnak "egyszerűnek" kell lennie. Mindegyik pipeline saját ALU-val (aritmetikai logikai egység), címgeneráló
egységgel, és adatcache interface-szel rendelkezik. PIPELINE BELSÔ ADATBUSZ UTASÍTÁS DEKÓDER UTASÍTÁS SOR VEZÉRLÉS SZEKVENCIA ROM CÍMEK MIKROKÓD ROM VEZÉRLÔ VEZÉRLÉS VÉGREHAJTÓ EGYSÉG BRANCH VEZÉRLÉS LIMIT SZORZÓ EGYSÉG EGYSÉG ÖSSZEADÓ EGYSÉG ELTOLÓ REG. EGYSÉG KÉSZLET MEMÓRIA ADATBUSZ BYTE MUX. ÉS I/O REGISZTEREK MEMÓRIA MANAGER 1.3 ábra: A PIPELINE-ok belső felépítésének blokkvázlata 15 Konkurens ötödik generációs architektúrák 1.212 Cache-ek, memória kezelés Az előbb említett cache egységek 8 kByte kapacitásúak, és az egyik csak adatokat, a másik csak utasításokat tárol. Az előbb említett cache-ek kétutas csoport-asszociatív szervezésűek és támogatják a directmap eljárást. A csoport-asszociatív szervezés a cache-felépítés olyan formája, mely egy adattömb helyét a főmemóriában leszűkíti ugyan, de ennek helye a cache-ben nincs teljes mértékben meghatározva. A
csoportasszociatív felépítés a közvetlen leképezést megvalósító felépítés (melyben a főmemória egy adott címének csak egyetlen hely felelhet meg a cache-ben), és a teljes mértékben asszociatív felépítés (mely az adatot a főmemória bármelyik részéből a cache bármelyik részébe helyezheti) közt képez kompromisszumot. Egy "n-szeresen csoport-asszociatív" cache lehetővé teszi, hogy a főmemória adott címéről az adat n helyen legyen cache-elve, mely bárhol lehet a cache-ben. A cache-vonalak 32 Byte-os (256 bit) szervezésűek, így a cache áramköröknek elég csak 2* 32 Byteos vonalon keresni adatot a teljes cache helyet. Ezen 32 Byte-os vonalak (a 486DX-ben csak 16 Byte-os vonalak vannak) segítségével épül fel a Pentium processzor 64 bit széles busza. Ha a processzornak adat-, vagy utasítástárolásra van szüksége és a cache már teljesen fel van töltve, akkor a legrégebben használt információkat elhagyja, és az így
teremtett üres helyet az aktuális információval írja felül. Az adatcache-nek két interface-e van - mindegyik pipeline-hoz egy-egy, amely azt biztosítja, hogy egy óracikluson belül két különböző művelet is feltudja használni ugyanazt az adatot. Ha az adat már éppen kikerül az adatcache-ből (és csak akkor), a processzor visszaírja az adatot a fő memóriába. Ez a technika WRITE-BACK cache kezelés néven ismert. Abban az esetben ha a processzor az adatot egyidejűleg a főmemóriába és a cache-be is beírja (a Pentium processzor dinamikusan támogatja a Write-Through cache kezelést), WRITE-THROUGH cache kezelésről beszélhetünk. A fent említett eljárások biztosítják a főmemória és a cache konzisztenciáját. (A konzisztencia különösen multiprocesszoros rendszerekben fontos, és azt biztosítja hogy a processzor ne helytelen értéket kapjon meg, amikor egy másik processzor által cache-elt adatot próbál elérni. Ha a cache-elt adatot
megváltoztatja, 16 Az INTEL Pentium processzora akkor mindegyik másik processzornak a megváltoztatott adatokat kell felhasználnia.) Az előbbiekben tárgyalt cache-konzisztencia protokoll MESI szabványként ismert. (MESI= Modified, Exclusive, Shared, Invalid). A szabvány 4 állapotot definiál, amelyek mindegyike a cache vonalaihoz van rendelve, a CPU által ezen a vonalon végrehajtott művelet alapján. Multiprocesszoros rendszerekben sokszor előfordul, hogy több processzornak egyidőben van szüksége ugyanarra az adatra. Ha a fent említett protokoll szabályait betartjuk a multiprocesszoros konzisztencia problémát is megoldottnak tekinthetjük. Cache-vonal M E állapota módosított kizárólagos Ez a cachevonal igen igen érvényes ? Az adat másolata . nem aktuális érvényes Az adat megtalálható egy másik nem nem processzor cache-ében ? Írás a vonalra . nem megy ki nem megy ki a buszra a buszra S megosztott I érvénytelen igen nem érvényes --
talán talán kimegy a buszra és frissíti a cache-t közvetlenül kimegy a buszra 1.4 ábra: Cache-vonal állapotai a MESI protokoll szerint Annak meghatározására, hogy egy írásművelet során mikor kell a főmemóriát felfrissítse, a cache egy adott frissítési stratégiát kell használjon. (A frissítés stratégiája nincs hatással az olvasásműveletekre) A Pentium processzor által támogatott frissítési stratégiák a következők: Átírás (write-through) - A cache-vonalba való írásigény esetén mind a cache-memória, mind a főmemória frissítésére sor kerül. Az átírás 17 Konkurens ötödik generációs architektúrák hasznos például a grafikus pufferek esetében, ahol ahhoz hogy az adat a grafikus képernyőn megjelenjen, frissíteni kell a főmemóriát is. Visszaírás (write-back) - A cache-vonalba való írásigény csak a cache-memóriát frissíti fel. A visszaírás-stratégia csökkenti a busz forgalmát, a szükségtelen
memória-írások kiküszöbölése által. A cache-vonalakba való írások nem továbbítódnak azonnal a főmemóriába, hanem a cache-ben gyűlnek össze. A megváltoztatott cache-vonalak később, a visszaírási művelet végrehajtásakor kerülnek a főmemóriába. A visszaírási műveleteket általában a cache-vonalak felszabadításának szükségessége váltja ki, például amikor a már teljesen betelt cache-ben szükség van egy új vonal lefoglalására. A visszaíró műveleteket a cache konzisztenciáját fenntartó mechanizmusok is kiválthatják. A processzor lehetővé teszi, hogy bármely memóriaterület bármelyik stratégia segítségével kezelhető legyen. Mind a software, mind a hardware kézben tarthatja a vezérlést a használt stratégia felett; a software a laptáblázatok bejegyzéseinek PWT bitje, míg a hardware a WB/WT# jel segítségével. A Pentium processzor belső cache-ei együtt használhatók a külső cache-ekkel, melyek működhetnek
átíró, visszaíró vagy mindkét módban. A külön adat- és utasításcache előnye, hogy kizárja az utasításbetöltés és az adatelérés konfliktusának létrejöttét. Az említett konfliktus akkor jöhet létre, ha pl. az egyik pipeline prefetch állapotban van és utasítást tölt be a cache-ből, miközben a másik pipeline - szintén a cache-ből - egy adathoz szeretne hozzájutni és ugyanazokat a cachevonalakat egyidőben akarják használni. A különbontott cache-ek biztosítják a két hozzáférési művelet párhuzamosságát. 1.213 Programág előrejelzés 18 Az INTEL Pentium processzora A cache egységek felsorolásánál azonban nem hagyhatjuk ki a BTB-t sem. (Branch Target Buffer = programág-tároló) Ez egy aprócska cache, amely a dinamikus utasítás-előrejelzés (Branch Prediction) adatait tárolja. Az utasítás-előrejelzés az a technika, amely által szolgáltatott információk segítségével a pipeline-okat teljes feltöltöttséggel, azaz
teljes sebességgel lehet használni. A koncepciót egy tipikus alkalmazási példán keresztül lehet igazán megérteni: az utasítás-előrejelzés minden softwareciklus végetérésekor elvégez egy feltételes vizsgálatot, amely meghatározza, hogy a ciklus elejét kell-e ismét végrehajtani (nem ért véget a ciklus), vagy végzett a ciklus végrehajtásával, és a következő utasítással kell a programot folytatni. A fentiekben vázolt két lehetőséget vagy "útvonalat" nevezzük programágnak (Branch). Az utasítás előrejelzés pedig megjósolja, melyik programágat fogja választani a software, a már előzőleg megtett ágválasztások statisztikái alapján. Amikor a processzor egy elágazást talál, a BTB "megjegyzi" az utasítást, és a programág ugrási címét. A BTB információi alapján születik meg a "jóslat" arról, hogy az elágazás melyik programágát kell majd a következőkben felhasználni. Ha a jóslat helyes,
ezzel az eljárással az ágcím betöltési időt meg lehet takarítani. Ellenkező esetben a felhasználandó ág címét be kell tölteni, ami külön időveszteséget nem okoz, mert erre a műveletre egyébként is szükség lenne. 1.214 Beépített lebegőpontos egység A 486DX processzorokhoz képest egy teljesen újratervezett matematikai processzor került a Pentiumok lapkáira. Az újítás gyümölcse egy 8 szintű pipeline-nal felépülő meglehetősen gyors lebegőpontos egység, amely órajelenként egy, néhány esetben két (ha a második utasítás egy "Exchange") lebegőpontos számítást képes elvégezni. A lebegőpontos utasítások végrehajtása az INTEGER egység pipeline-jaiban kezdődik, és az első néhány integer pipeline-szint után 19 Konkurens ötödik generációs architektúrák PREFETCH Utasítás dekódolás Cím generálás Szám konverzió -> 80 bit Végrehajtás 1 kerül át a lebegőpontos pipeline-ba. Az FPU
pipeline-jának első négy szintje megegyezik az INTEGER egység pipeline-jában megtalálható első négy szinttel. Az utolsó négy szintet pedig következő egységek alkotják: 2 szintes lebegőpontos végrehajtó egység, kerekítő és regiszterbe író egység, hibajelző egység. Az áttervezett FPU olyan új hardware-ben megvalósított algoritmusokat használ, amelyek a közös műveletekben (pl.: összeadás, szorzás, osztás), háromszosára növelik a műveleti sebességet. 1.215 "Bogaras" a koprocesszor ? A szaksajtóban meglehetősen sok hír röppent fel a Pentiumok " hibás " lebegőpontos társprocesszoráról. Megnyugtathatom a kedves Kerekítés olvasót, a rendellenesség nem katasztrofális, és Regiszterbe írás csak a 1995 jan. 1 előtt vásárolt Pentium processzorokban található meg. Sem a hiba Hibadetektálás nagysága, sem az általános számítási műveletekre vonatkoztatott gyakorisága nem számottevő. (A gyártó 3 év
garanciát vállal a processzorokra, és bizonyos kereteken belül - ki is cseréli a 1.5 ábra: "bogaras" példányokat.) A hiba az eredmény Az FPU pipeline-ja pontosságának csökkenése. Az eltérés az egyszeres, kétszeres, és négyszeres pontosságú lebegőpontos osztási műveletekben (FDIV) fedezhető fel, az input operandusok bizonyos kombinációja esetén, a kerekítési módtól függetlenül. Az eredmény pontosságának csökkenése akkor következik be, amikor osztó utasítás ismétlőciklusának használnia kell a szétválogató táblát. A hibát okozó számpárok karakterizálása egyáltalán nem egyszerű, de a hiba bekövetkezésének valószínűsége ismert: <1:9000000. A "renitens" szám a normál alakban felírt eredmény tizedespont utáni negyedik, és tizenkilencedik helyiértéke között fordulhat elő. Végrehajtás 2 20 Az INTEL Pentium processzora 1.216 Sebességnövelő technikák a Pentium osztályú
számítógépeknél Előszöris tekintsük át miben különbözik egy ötödik generációs Pentium processzor az "elődöktől"? szuperskalár architektúra szétválasztott cache-ek Write-Back cache kezelés újra tervezett, gyorsabb FPU 64 bit széles külső adatbusz a memóriák felé (a maximális sebesség a memóriára vonatkozóan 528 MByte/s - a 486DX50-nél 160MB/s) cache kezelés burst módban (nagy 256bit-es adagok tölthetők adatcache-ből egyetlen egyszerű buszciklus alatt) a MOV, és néhány ALU utasítás harware-es megvalósítású, ezért gyorsabb működést, nagyobb teljesítményt tesz lehetővé támogatja a növelt lapméreteket így kevesebb lapozás szükséges a nagyobb alkalmazásoknál (hagyományos 4 kByte-os lapok és növelt 4 MByte-os is választhatók) Ha egy az eddigieknél gyorsabb számítógépet szeretnénk létrehozni, akkor meg kell, hogy vizsgáljuk melyek azok a részegységek, amelyekre a
többi részegységnek várnia kell. Ha a várakozásokat "kihagyjuk" a rendszer gyorsulni fog. Napjainkban a processzorok olyan műveleti sebességet értek el, hogy örökké várniuk kell, a perifériákra vagy memóriára, legyen az akár HDD, a főmemória, vagy cachememória. Hogyan növelhető a memória elérési sebesség ? Első megoldásként számításba jöhet a Pentium osztályú alaplapokon alkalmazott Pipelined Burst SRAM. Ez a másodszintű cache-elérési modell változtatásának módszere. Az alábbi táblázatból kiderül, hogy ez a módszer milyen arányú sebességnövekedést eredményez. A táblázat adatai Pentium processzorra vonatkoznak, óraciklus számban értendők. 21 Konkurens ötödik generációs architektúrák A ciklus típusa Burst Read Burst Write (Write back) Single Read Single Write Back-to -back Burst Read Aszinkron SRAM 3-2-2-2 4-3-3-3 3 4 Pipelined Burst SRAM 3-1-1-1 3-1-1-1 3 3 3-2-2-2-2 3-1-1-1-1 1.6 ábra: Cache
kezelési modellek Pl. a 3-1-1-1 adat az első adat beolvasásánál 3 óraciklust kell várni az érvényes adatra, a második azonban már egy ciklus alatt beolvasható, és így tovább. Például négy egymást követő adat beolvasása kilenc óraciklus helyett, csak hatot igényel. Pipelined Burst SRAM-mal adatátviteli sebesség maximuma 300 MByte/s fölött van. A második megoldást keressük a DRAM-ok tájékán. A normál Page-mode DRAM-oknál az adat a CAS# jel felfutóélénél érvényes. Erre "gyógyszer" EDO DRAM (Extended Data Output) használata. (Az EDO DRAM csak 72pin-es SIMM modulként kerül forgalomba. Fizikai méretkülönbség nincs a Page mode DRAM és az EDO DRAM között.) Ha EDO DRAM-ot használunk, az adat a CAS# ciklus teljes időtartama alatt érvényes. Ezzel a megoldással a (fő)memória elérési sebesség 100MB/s -ról 200MB/s fölé emelkedik. A két időzítés közötti különbséget az alábbi ábrán vehetjük szemügyre. 22 Az
INTEL Pentium processzora Page mode DRAM idôdiagram: CAS# DATA (out) érvényes érvényes érvényes EDO DRAM idôdiagram: CAS# DATA (out) érvényes érvényes érvényes 1.7 ábra: DRAM idődiagramok Ha a fizikai memórián nem csak a memória chip-eket értjük, hanem a merevlemez kapacitásának egy részét is, - pl.: MS-Windows swap területe (lásd: a szegmentált memóriamodellről szóló fejezetet, lapozás) - akkor a HDD adatátviteli sebességének növelésével szintén hatásosan növelhetjük a teljes rendszer teljesítményét. A tradícionális PIO (Programozható I/O) IDE a CPU közreműködését igényli, tehát a processzornak sokat kell várni a lassú mechanikai alkatrészekre. Minél gyorsabb processzorunk van, annál nagyobb teljesítmény kiesésével kell számolnunk. A Bus Master IDE megoldás két legyet üt egy csapásra: egyrészről a vezérléssel nem a processzornak kell vesződnie, (másik hardware elem teszi meg helyette) és
kialakítható egy új adatátviteli megoldás a már meglévő IDE buszon. E megoldás: az enhanced IDE controller. Ez a kontroller két dedikált DMA csatornát használ. (az adatok közvetlenül a memóriába kerülhetnek, és nem szükséges a processzor közreműködése). Az adatátvitel PIO mode 3, és mode 4 IDE névre hallgat. A mode 3-mal az IDE adatátviteli 23 Konkurens ötödik generációs architektúrák sebességének maximuma 11 MByte/s, a mode 4-gyel 17 MByte/s, és ha a mode 4 mellé még a DMA mode 2-t is kiválasztjuk 22 MByte/s-os sebességet is elérhetünk (Az adatok PCI IDE controllerre vonatkoznak, és a HDD-nek "ismernie" kell a fentiekben említett protokollt). A negyedik megoldást maga a Pentium processzor kínálja nekünk: a hagyományos 4 kByte-os lapméretek helyett nagyobb, 4 MByte-os lapokat is kezelhetünk. A nagyobb lapméret előnye, hogy csökken a lapcserélési frekvencia, és növekszik a lapokra vonatkoztatott találati arány.
A lapcserélgetés helyett hasznos utasításokat lehet végrehajtani komplex grafikai eljárások, keret pufferek, operációs rendszer kernelek esetében jelentős sebességnövekedés érhető el. A megoldás másik előnye, hogy transzparens (átlátszó) az alkalmazások szempontjából. 1.217 Multiprocesszoros rendszerek A 90-100MHz-es Pentium processzorok lapkái tartalmaznak egy multiprocesszoros vezérlő áramkört is. Ez a vezérlő két részre oszlik: a programozható interrupt vezérlőre (APIC= Advanced Programmable Interrupt Controller), és az arbitrátorra. Ezen vezérlő segítségével olyan nagy teljesítményű és viszonylagosan kis költségű Server architektúrák is megvalósíthatók, amelyek 256 (!) processzort tartalmaznak, mindegyiket saját cache-sel. 1.218 Adatvédelem Számos olyan technikát valósítottak meg a tervezők, amely kifejezetten az adatok védelmét szolgálja. A hibadetektálás kétszintű: a paritásvizsgálat a külső lábakon, és
a lapkára integrált memória stuktúrákon (cache, bufferek, mikrokód ROM). Akad azonban olyan szituáció amikor az adatok integritása különösen fontos. Ezekben az esetekben használható ki a Pentium által támogatott funkcionális redundancia ellenőrzés. [Functional Redundancy Checking (FRC)]. Az FRC két Pentium chip-et igényel: az egyik Master, a másik Checker. A chip-ek párhuzamosan futnak, és a Checker 24 Az INTEL Pentium processzora összehasonlítja az általa kapott eredményeket a Master eredményeivel, hogy egészen biztosan hibamentesek legyenek az eredmények. Az FRC alkalmazásával a hibadetektálás hatásfoka 99% feletti. A processzor tartalmaz néhány teszt lehetőséget a chip megbízhatóságára vonatkozóan. Az önteszt minden RESET esetén lefut, és a processzor 70%-át ellenőrzi az IEEE 1149.1 szabvány szerint Ez segít a gyártóknak a chip külső kapcsolatainak vizsgálatában, és láthatóvá teszi a regisztereket, a processzor
állapotainak pontos detektálhatósága érdekében. Ezenkívül a rendszer tartalmaz rendszerprogramozók számára egy lehetőséget a cache-ek találati arányának mérésére. Ezzel a "sebesség monitorozó" üzemmóddal felderíthetők azok az esetek, amikor a processzor hosszú ideig vár a külső buszra, és ez a funkció segít a külső memória optimalizálásában is. A Pentium processzor rendelkezik egy a 386SL-nél megismert System Management Mode-dal is, amely a teljesítmény management-ben és a biztonsági feladatok megoldásában lehet hasznos segítség. 25 Konkurens ötödik generációs architektúrák 1.22 A Cyrix M1-es processzor családja Nézzük meg, mi rejtőzik az M1-es processzor belsejében. Ha a felépítést tekintjük számos új megoldást találunk. Hogy a különbségeket megértsük, nézzük a processzor szívét, az INTEGER egységet, amelyben megközelítőleg az összes művelet zajlik. 1.221 Pipeline vagy szuperpipeline ? Az
M1-es belsejében is megtaláljuk az ötödik generációs processzoroknál már megszokott pipeline egységet. = Pipeline szint Az M1 szuperpipeline INTEGER egysége = utasítás A PENTIUM pipeline INTEGER egysége 1.8 ábra: Az M1- es és a Pentium processzorok pipelinejainak összehasonlítása 26 A Cyrix M1-es processzor családja 27 Konkurens ötödik generációs architektúrák A pipeline az az egység, amelynek belsejében az adatok és az utasítások végrehajtódnak. A Pentium chip mindegyik pipeline-ja öt végrehajtási szintre osztódik - mint ahogyan már a 80486-ban is. Ha összehasonlítjuk a két processzort az M1-es szuperpipeline, míg a Pentium pipeline adatfeldolgozási technológiát alkalmaz. Ez azt jelenti, hogy az utasítás végrehajtása hét szintre tagozódik, az M1-es esetében a két pipeline szorosabb együttműködése érdekében. Ez az M1-es processzort különlegesen magas, 100 MHz fölötti órajelek alkalmazására teszi alkalmassá
a 0,5 mikronos technológiával . 1.222 32 regiszter jobb mint 8 ! Ha a processzor más részeibe tekintünk bele, akkor az M1-es-ben 32 általános felhasználású regisztert találhatunk, szemben az x86 chipekkel, amelyek csak 8 ilyen regiszterrel rendelkeznek. A nagyobb mennyiségű regiszter flexibilisebb felhasználást tesz lehetővé. A regiszterek a működéshez szükséges részeredményeket tárolják, és ha ezek több adatot tudnak tárolni, akkor a processzor úgy dolgozhat, hogy ritkábban kell várnia, hogy az adat előkerüljön a memóriából. A 32 regiszter miatt az M1-es processzor mindig tele lehet adattal, ami magasabb sebességet eredményez. A feltételes ugrások során az ugrási címen található utasításokat feltételesen is végrehajthatja anélkül, hogy tönkretenné valódi Pentium regiszterkészlet tartalmát. Az aktuális Pentium regiszter leképezéséhez pedig a többszörös regiszterek közül a jóslat (Branch Prediction) figyelembe
vételével a legoptimálisabbat választhatja ki. Egy másik felépítésbeli különbség található a cache egységben is. Az Intel Pentium chipek elsőszintű cachee 8 kByte adat, és 8 kByte utasítás cache-re osztódik Az M1-es elsőszintű cache egysége egy 16 kByte-os duál-portos definiálatlan cache-ből (a cache tárolhat utasításokat és adatokat is vegyesen), és egy 256 Byte-os utasításvonal cache-ből épül fel. 28 A Cyrix M1-es processzor családja Utasítás adat Utasítás vonal CACHE Adat rendezõ FPU Adat busz Definiálatlan CACHE 0. készlet 1. készlet 2. készlet 3. készlet CACHE Címzés Busz Interfész Egység Utasítás vonal CACHE hiányzó adat Módosított X, Y fizikai címek 1.9 ábra: Az M1-es definiálatlan CACHE-e bármilyen arányban tartalmazhat adatot és utasítást. Az utasításvonal CACHE pedig az INTEGER egység által leginkább használt utasításokat tárolja. Nézzünk egy példát: egy adatintenzív programszegmens
túlterheli a kisebb méretű adatcache-t ( a Pentium esetében 8 kByte), és a chip lassabban fog dolgozni, mert a többi adatot a külső memóriából kell beolvasnia. Az M1-es esetében ugyanez az adatintenzív programszegmens egy nagyobb (16 kByte) definiálatlan cache-ben lelassulás nélkül hajtódhat végre, mivel a processzornak kevésbé kell a külső memóriára támaszkodnia. Az M1-es sebességi előnyének egy részét a tervezők a cache nagy sebességével érték el, egyetlen óraciklus alatt 29 Konkurens ötödik generációs architektúrák képes elérni az adatot. Ez a gyártó szerint kétszer gyorsabb a Pentium adatelérésénél. 1.223 Csökkentett függőség - nagyobb sebesség Amikor két utasítás fut párhuzamosan egy szuperskalár processzoron előtérbe kerül a két utasítás közötti függőség problémája. Ez a függés azt okozza, hogy az egyik utasításnak meg kell állnia, hogy megvárja a másik végrehajtását. Ez pl akkor fordulhat
elő ha mind a kettő ugyanazt a regisztert egyidőben szeretné használni, így az egyiknek várnia kell. Az M1-es esetében nincs szükség erre a várakozásra, mert mind a 32 regiszter mindkét pipeline felől elérhető, ezért mindegyik utasítás megkaphatja a másolatát erről a regiszterről és egyiknek sem kell várakoznia. Egy másik problémát vet fel a szuperskalár processzorokban amikor a két párhuzamos pipeline-ban valamelyik utasításnak szüksége van a másik utasítás eredményére. Az M1-es olyan adathívási technikát használ, amely biztosítja mindkét pipeline-ban végrehajtódó utasítás eredményének szimultán elérését anélkül, hogy valamelyik megállna. Azzal, hogy az egyik utasítás eredményét nem kell kiírni a memóriába és a másik utasítás ezt az eredményt mégis el tudja érni a processzor időt takarít meg, csökkennek a memória elérési ciklusok. 30 A Cyrix M1-es processzor családja 1.224 Kiegyénített terhelés
-gyorsabb programfutás Utasítás Fetch Utasítás dekódolás 1 Utasítás dekódolás 2 Utasítás dekódolás 2 Cím számítás 1 Cím számítás 1 Cím számítás 2 Cím számítás 2 Végrehajtás Végrehajtás Write-Back Write-Back X Y Pipeline Pipeline 1.10 ábra: Az M1-es processzor szuperpipelineokból felépített INTEGER egysége Ha a pipeline kiegyenlítetlenségekkel terhelt, akkor az egyik pipeline sokkal telítettebb mint a másik ezért a másiknak meg kell állnia, hogy megmaradjon a program komplexitása, ez szintén lassulást eredményez. Az M1-es tervezői ezt a kiegyenlítetlenséget úgy szüntették meg, hogy az aktuális utasítást mindig a kevésbé terhelt pipeline-on hajtatják végre, és az utasítások át tudnak kelni a két pipeline között. Az M1-es rendelkezik a becslés képességével, ez azt jelenti, hogy meg tudja jósolni, hogy melyik programág utasítását kell betölteni egy bizonyos pipeline-ba ahhoz, hogy időt
takarítson meg. (Ezt a funkciót nevezzük utasítás előrejelzésnek.) Ha az aktuális utasítás már fut valamely pipeline-on mielőtt még a pontos jóslat ismeretes lenne, már időt takarít meg. Ha a jóslat rossznak bizonyult, akkor nem vesztettünk időt, mivel a programág ugrási címének betöltésére egyébként is szükség lenne. 1.225 Kiugrás lehetősége a végrehajtási sorrendből Abban az esetben ha az egyik pipeline-ban lévő utasítás gyorsabb mint az őt megelőző másik utasítás, akkor kiléphet a pipeline sorrendből, és betöltődhet a másik pipeline-ba - anélkül, hogy a 31 Konkurens ötödik generációs architektúrák programfutás felfüggesztődne - így nem kell processzoridőt fecsérelni a lassúbb utasítás végrehajtásának kivárására. 1.11 ábra: Kiugrás a végrehajtási sorrendből Az M1-es processzorban az egyik pipeline végrehajtási sorában lévő utasításnak nem kell megvárnia a másik pipeline lassúbb
utasítását. Kiugorva a végrehajtási sorból, időt lehet megtakarítani a vérehajtás során, a program futásának megszakítása nélkül. 32 A NexGen Nx 586-os processzor családja 1.23 A NexGen Nx 586-os processzor családja 1.231 Hogyan lehet RISC processzorból CISC avagy fából vaskarika ? A NexGen kutatásainak gyümölcse X86-os processzor család, amely a 486-os meglehetősen különböző részekből épül kompatibilis" sem a 60-66MHz-es, sem a chipekkel, tehát speciális alaplap kell hozzá. egy olyan nagy sebességű és Pentiumos rendszerektől föl. A chip nem "láb 75-90-100MHz-es Pentium Ennek ellenére a Microsoft kijelentette, hogy az Nx586 Windows kompatibilis. A processzor joggal viselheti a Novell "YES It run with NetWare" logóját is. A kompatibilitási teszteket a független XXCAL laboratórium végezte el. A legnépszerűbb software-k ciklusainak trillióival tesztelték több operációs rendszer, és hálózati protokoll
alatt. Az eredmény megdöbbentő: "Platinium Certification " Ezen sorok láttán azt hiszem sokakban felmerül a gondolat: Az INTEL és a Pentium egy újabb, méltó ellenfelére akadt. No de nézzük, mit takar a tokozás. 33 Konkurens ötödik generációs architektúrák L2 CACHE SRAM 64 bit Nx 586 Processzor 64 bit Nx 587 Koprocesszor 64 bit SIMM modulok DRAM 64 bit 32-bites PCI vagy VESA busz (30-33MHz) Rendszer interface Rendszer logika 16-bites ISA busz (8MHz) 1.12 ábra: Nx586 alapú IBM PC kompatibilis számítógép felépítése NxVL vagy NxPCI rendszerinterface chip felhasználásával. A matematikai processzor külön tokban helyezkedik el, míg a másodszintű cache vezérlője a processzorlapkán kapott helyet. A chip-től elválasztva találhatjuk meg a lebegőpontos egységet (FPU) mint ahogyan a 386 - 387 -es rendszerekben. Ezzel szemben leintegrálásra került a másodszintű (L2, vagy külső) cache vezérlője, a processzorlapkán. Az
Nx586-ban egy-egy külön-külön 64 bit széles busz áll rendelkezésre a matematikai processzorral, és a külső SRAM-okkal való társalgásra. A harmadik 64 bit széles busz a rendszer többi tagjával történő kapcsolattartást biztosítja. A külön cache-busz csökkenti a memória, és az I/O ciklusok közötti konfliktusokat. Előny az is, hogy a 34 A NexGen Nx 586-os processzor családja cache-busz sebessége megegyezhet a CPU órajel frekvenciájával, amíg a rendszer-busz tetszőleges sebességgel dolgozhat. Az interface-ek elválasztásának a kivezetések száma és a tokozás gazdaságossága szab határt, ugyanis az Nx586 tokozási költsége (463 lábú PGA tok) már így is kétszerese egy Pentiuménak (296 lábú PGA tok). 1.232 x86 - RISC86 A RISC (Reduced Instruction Set Computer), egy olyan processzortípust jellemez, amely csak kevés, a fordítók által gyakran igényelt (redukált) utasítást tartalmaz hatékonyabb implementációban. Ellentéte a
CISC (Complex Instruction Set Computer), amely összetett utasításokat tartalmaz, különböző modellek szerint. Egy példa a CISC processzoroknál használható modellek közül: a Pentium Load & Store modellje. Egy Nx586-os processzor teljes mértékben implementálja az X86os utasításkészletet. Ez az implementáció a RISC86-os architektúrával történik, valós időben, dinamikusan. Hardware-esen és nem software-ből emulálva, mint ahogyan a Motorola PowrePC 603, vagy az Alpha processzorok teszik, aminek hatalmas teljesítménycsökkenés a következménye. Ezek az utasítások közvetlen leszármazottjai a normál RISC utasításkészletnek, úgy, hogy közben "örökölték" az x86-os architektúra sajátosságait. A RISC név mégis megilleti ezeket az utasításokat, mert egyszerű mikrokódként alkalmazhatóak. Az x86-os architektúra egyik szűk keresztmetszete a korlátozott regiszterkészlet: csak 8 általános felhasználású regisztere van. Itt
segít fordítás, és a RISC processzorokban már hagyományos 32 regiszter. Az Nx586, az x86 8 regiszterét 22 fizikai regiszterre képezi le. Ezt az eljárást nevezzük regiszter átnevezésnek. Mire jó a regiszter átnevezés? A pipeline-ok elakadásának elkerülése érdekében az Nx586 feltételezett eredménnyel hajtja végre a feltételes ugrásokat, és az ugrási feltételek kiértékelése után aktualizálja azokat. Ez a nem optimalizált programok esetén is fennáll 35 Konkurens ötödik generációs architektúrák A 32 regiszter többszörösen lefedi a Pentium regiszterkészletét. A pipeline folyamatos adatáramlása biztosítható a regiszterek gyors átnevezésével, így a számítási eredmények több fázisa hozzáférhető az adatok újrabetöltése nélkül, tehát a pipeline-ok nem akadnak el a lassú adatbetöltés miatt. X86 -os utasítások Utasítás fordító, és ütemezô Címzô egység RISC86-os utasítások RISC86-os utasítások
Végrehajtó egység Végrehajtó egység RISC86-os utasítások Végrehajtó egység 1.13 ábra: A NexGen szabadalmaztatott RISC86-os architektúrája dinamikusan fordítja az összetett X86-os (CISC) utasításokat RISC86-os utasításokká, így tehát kihasználhatja a RISC utasítások sebességi előnyeit. Sok X86-os utasítás egyszerűen konvertálható RISC86-os utasítássá. Vannak azonban olyan X86-os utasítások is, - amelyek a betölt-eltárol modellt használják, például a memória kezelési ciklusokamelyek csak két, vagy három RISC86-os utasítást igényelnek. 36 A NexGen Nx 586-os processzor családja 1.233 Szuperskalár végrehajtás-javuló hatásfok Azt már tudjuk, hogy egy X86-os utasítás, fordítás után ciklusonként két vagy több RISC86 utasításként is megjelenhet, minden funkcionális egységnél. A funkcionális egységeket úgy tervezték, hogy párhuzamosan több RISC86-os utasítást is végrehajthassanak. A NexGen szuperskalár
elnevezése RISC86-os szempontból értendő. A RISC86-os utasítások párhuzamosságának jobb kihasználhatósága érdekében, minden egyes funkcionális egység 14 belépési ponttal rendelkező végrehajtási sorral rendelkezik. Az Nx586-os mikroprocesszor - ahogyan a Pentiumok is - két INTEGER egységgel rendelkezik. A szokatlan azonban az, hogy ez az egység az Nx586-ban egyáltalán nem szimmetrikus. Az egyik INTEGER egység végzi a RISC86 integer utasításokat, beleértve a szorzást és osztást is, míg a másik INTEGER egység az egyszerű egyciklusos utasításokat hajtja végre. A dekóder egység rendelkezik egy "betöltés kiegyenlítő" algoritmussal, és ennek segítségével irányítja az utasításokat valamelyik INTEGER egységre. A RISC86 betöltő és tároló utasítások a CÍM-egységbe kerülnek, amely kiszámítja a cél címet, és gondoskodik az X86-os szabványról szerinti fordításról. Mivel a chip csak egy egyszerű CÍM-egységet
tartalmaz, ciklusonként csak egy betöltő, vagy tároló utasítás hajtódhat végre. 1.234 Az utasítás-előrejelzési CACHE (BPC) Az Nx586 alkalmazza az elméleti futtatás és az utasítás előrejelzés technikáját is. Ha a processzor találkozik egy programággal, először megbecsüli a végrehajtáshoz szükséges időt, és majd később kezdi el az utasítások végrehajtását. Ezt a módszert nevezzük elméleti végrehajtásnak Az 37 Konkurens ötödik generációs architektúrák Nx586 kettőnél több programág elméleti futtatására is képes. A legtöbb esetben az első programág jóslata abban az időpillanatban készül el, amikor a harmadik programág vizsgálata elkezdődik. A NexGen utasítás-előrejelzési cache-e 5 ciklusos ágbüntetéseket alkalmaz. A BPC 96 belépési ponttal rendelkezik, és az első 24 utasítás Byte-ot tartalmazza minden célcímnél. Ez a koncepció hasonlít az AMD 29000 ÁGCÉL CACHE-ében alkalmazottra, de különbözik
a Pentiumétól, mert a Pentiumé csak a célcímeket tartalmazza (256 elemű célcím puffer). Az Nx586 két bites "Smith and Lee" algoritmust használ a programág jóslatok létrehozásához. Minden egyes BPC adat 2 előrejelzés bitet tartalmaz. Ha egy ág késik, a BPC újabb 2048 adattal bővül, a processzor ellenőrzi a 2 bit széles "ágtörténet" táblázatot, és növeli a jóslási pontosságot. Ez a két struktúra pontosan megjósolja az ágfeltételeket, de nem segít, ha a kód RET utasítást tartalmaz. Ennek oka az, hogy ezek a programágak nehezen kezelhetőek, mert a célcímek változhatnak minden egyes szubrutin hívás esetén. Az Nx586 tartalmaz egy VISSZATÉRÉSI CÍM VERMET, - hasonlatosan az Alpha architektúrájára - ami 1-8 egymásba ágyazott szubrutin hívást tud kezelni. E a három struktúra kombinációja biztosítja azt, hogy a legtöbb kód esetében a sikeres előrejelzések aránya 90% fölött van. 1.235 Cache hierarchia
Azzal, hogy a lebegőpontos egység lekerült a processzor lapkájáról, elegendő hely maradt nagyobb cache-ek felépítésére. Az Nx586 16 kByte utasítás-, és 16 kByte adatcache-t tartalmaz. Ezek a memóriák éppen kétszer nagyobbak a Pentium adat- és utasításcacheénél. A NexGen négyutas csoport asszociatív cache-t alkalmaz a találati arány növelése érdekében. A Pentiummal összehasonlítva mindkét processzorban fizikailag indexelt, és címkézett cache-ek vannak, de a Pentium esetében kétutasak. 38 A NexGen Nx 586-os processzor családja Elérési sebesség: a 0.5 mikronos technológia 66MHz esetében mindegyik félperiódus alatt egy elérést engedélyez, ezért két cache-elérés zajlik le egyetlen óraciklus alatt. Az Nx586 egyetlen címző egységgel rendelkezik, ebből adódik, hogy második cache elérés csak a másodszintű (L2) cache, vagy a rendszerbusz elérésére használható. Sok processzorban felfüggesztődik az utasítás
végrehajtás amikor a fent említett események bekövetkeznek, de az Nx586 az utasítás végrehajtásának lelassulása nélkül képes kezelni ezeket az eseményeket. A beépített másodszintű cache-kontroller normál SRAM-okból felépített külső cache-re csatlakozik. A külső cache-nek azonban csak kétféle konfigurációját támogatja: 256k vagy 1M. A másodszintű cache egységes, utasításokat és adatokat is tartalmazhat, és akárcsak az elsőszintű cache, négyutas csoport asszociatív. A külsőcache elérésére a másodszintű cache-vezérlő két ciklust alkalmaz, ezért 66MHz-es órajelnél minimálisan 15ns-os SRAM-ok szükségesek. 1 66 MHz 1 66000000 1s 15ns A címkék tárolása ugyanabban a chip-ben történik, ahol az adatok tárolása, ezért az alkalmazható adatmemória 6%-kal csökken. Minden címke beolvasása két ciklust igényel, mint ahogyan a 8 Byte-os szavak (quadword-ök) is. A felhasznált adatelérési minta 4-2-2-2 Címkék
sorozatokban történő beolvasásához használható a csoport-asszociatív cache implementáció. Mivel a pontos csoport detektált, a beolvasás az adatokkal együtt sorozatokban történik. Az Nx586-os egy kicsivel hosszabb adatelérési mintákat használ mint egy 66MHz-es Pentium, amelyik ugyanazokkal a 15ns-os SRAMokkal tipikusan 3-2-2-2 -es mintákkal dolgozik. A NexGen-féle csoport asszociatív módszer nagyobb találati arányt biztosít. A fentiekben vázolt implementáció előnye, hogy azonos cache-elérési minták esetén nagyobb frekvenciákat alkalmaz, mivel a cache-busz sebessége független lehet a rendszerbuszétól. Egy 100MHz-es Nx586-os 4-2-2-2 -es cache elérési mintával 10ns-os SRAM-okat igényelne. A 100MHz-es Pentium 39 Konkurens ötödik generációs architektúrák rendszerbusza 66MHz-en "ketyeg", és 5-3-3-3 -as modellt használ. A Pentiumnak kisebb sebessége ellenére előnyére szól, hogy megtarthatjuk a kevésbé költséges 15ns-os
SRAM-jainkat. A lapkára integrált cache-k WRITE-THROUGH protokollt használnak, míg a külső cache-ek esetében a tervezők a WRITE-BACK módszert alkalmazták a rendszerbusz forgalmának csökkentése érdekében. Az adat- és utasításcache-ek támogatják az önmódosító kódokat. 40 Landmark 2.0 2. fejezet: Processzor erőforrások Az alábbiakban a Pentiumok sebességének pontos érzékeltetése céljából összevetettük néhány gyártó 32, vagy 64 bites X86-os architektúrájú processzorát. A tesztek 256 kByte külső-cache felhasználásával készültek. Az ettől eltérő eseteket külön közöljük. A belső cache méret különböző TI processzoroknál különböző lehet, a különbségekre - típusjelzés szerint az eredmények kiértékelése során kitérünk. A Texas Intruments SLC jelzésű processzorai esetében, egy valamilyen alaplapba fixen beforrasztott processzor állta a sarat a tesztek nyúzópróbái során. Ennek következménye, hogy
különböző méretű külső cache-sel, és esetleg FPU nélkül történtek meg a mérések. Az SLC33-as processzort tartalmazó alaplap 64 kByte, az SLC2-66 128 kByte külső cache-t tartalmazott. Az SLC2-50-es alaplap nem rendelkezett külső cache-foglalattal. Az ezektől eltérő esetekben 256 kByte 15ns-os cache-t használtunk fel. A DX jelzésű 486-os processzorok minden gyártó esetében tartalmazzák a lebegőpontos egységet. A táblázatokban a "+FPU" jelzés külső koprocesszort jelent. Ha az 486SX - 486SLC típusoknál nem jelöltük koprocesszor jelenlétét, a mérési eredmények lebegőpontos egység nélkül értékelendőek. Az Nx 586-os processzort fogadó alaplap NxVL rendszervezérlő chip-pel épült fel, és nem rendelkezett koprocesszor foglalattal. A *-gal jelölt processzorok nem minden esetben léteznek az aktuális típusjelzés alatt, csak a jobb összehasonlíthatóság érdekében "követtük el őket". Ezek fizikailag az
előírtnál magasabb órajellel meghajtott "tuningolt" de kifogástalanul működő példányok, pl.: az Am486DX4-120 valójában egy AmDX4-100, 120MHz-es órajel frekvenciával. Landmark 2.00 41 Processzor erőforrások Processor Típus: PENTIUM 90 PENTIUM 66 PENTIUM 60 NEXGEN Nx586 P90 Am 486DX4-120 * INTEL 486DX4-100 Am 486DX4-100 Am 486DX2-100 * INTEL 486DX2-80 * Am 486DX2-80 Cyrix 486DX2-V80 INTEL 486DX2-66 Am 486DX2-66 Cyrix 486DX2-V66 TI 486SLC2-66+FPU INTEL 486SX2-50 TI 486SLC2-50+FPU Am 486DX-40 TI 486SXLC-40 TI 486SLC-40 INTEL 486DX-33 TI 486SLC-33 INTEL 486SX-25 Am 386 DX-40 Am 386SX-40 42 CPU (MHz) 519,47 385,85 346,74 527.15 401,59 359,53 334,15 334,62 267,70 267,70 264,45 222,96 222,91 219,94 152,76 167,30 115,15 133,84 129,81 129,90 110,37 107,98 83,67 62,40 52,19 FPU (MHz) 1743,79 1299,15 1169,92 -1059,28 882,57 856,64 882,79 706,05 704,11 770,57 587,49 588,02 640,87 162,07 14,10 116,70 353,06 10,66 6,45 291,15 7,42 7,04 --- Landmark 2.00 519.47
PENTIUM 90 385.85 PENTIUM 66 346.74 PENTIUM 60 527.15 NEXGEN Nx586 P90 401.59 Am 486DX4-120 * 359.53 INTEL 486DX4-100 334.15 Am 486DX4-100 334.62 Am 486DX2-100 * INTEL 486DX2-80 * 267.7 Am 486DX2-80 267.7 264.45 Cyrix 486DX2-V80 222.96 INTEL 486DX2-66 Am 486DX2-66 222.91 Cyrix 486DX2-V66 219.94 152.76 TI 486SLC2-66+FPU 167.3 INTEL 486SX2-50 115.15 TI 486SLC2-50+FPU Am 486DX-40 133.84 TI 486SXLC-40 129.81 129.9 TI 486SLC-40 INTEL 486DX-33 110.37 TI 486SLC-33 107.98 83.67 INTEL 486SX-25 Am 386 DX-40 62.4 Am 386SX-40 52.19 0 100 200 300 400 500 600 Landmark 2.0 CPU sebességek (MHz) 43 Processzor erőforrások 1743.79 PENTIUM 90 1299.15 PENTIUM 66 1169.92 PENTIUM 60 NEXGEN Nx586 P90 1059.28 Am 486DX4-120 * 882.57 INTEL 486DX4-100 856.64 Am 486DX4-100 882.79 Am 486DX2-100 * INTEL 486DX2-80 * 706.05 Am 486DX2-80 704.11 770.57 Cyrix 486DX2-V80 INTEL 486DX2-66 587.49 Am 486DX2-66 588.02 640.87 Cyrix 486DX2-V66 162.07
TI 486SLC2-66+FPU 14.1 INTEL 486SX2-50 116.7 TI 486SLC2-50+FPU 353.06 Am 486DX-40 10.66 TI 486SXLC-40 6.45 TI 486SLC-40 291.15 INTEL 486DX-33 TI 486SLC-33 7.42 INTEL 486SX-25 7.04 Am 386 DX-40 Am 386SX-40 0 200 400 600 800 1000 1200 1400 1600 1800 2000 Landmark 2.0 FPU sebességek (MHz) 44 CHECKIT 3.0 CHECKIT 3.0 Processor Type: PENTIUM 90 PENTIUM 66 PENTIUM 60 NEXGEN Nx586 P90 Am 486DX4-120 * INTEL 486DX4-100 Am 486DX4-100 Am 486DX2-100 * INTEL 486DX2-80 * Am 486DX2-80 Cyrix 486DX2-V80 INTEL 486DX2-66 Am 486DX2-66 Cyrix 486DX2-V66 TI 486SLC2-66+FPU INTEL 486SX2-50 TI 486SLC2-50+FPU Am 486DX-40 TI 486SXLC-40 TI 486SLC-40 INTEL 486DX-33 TI 486SLC-33 INTEL 486SX-25 Am 386 DX-40 Am 386SX-40 Dhrystones 70577 52749 47474 59343 55852 43158 39211 47474 39211 39211 39211 33609 33609 33609 29759 24348 21427 19303 16999 9749 15785 11236 12054 11631 7206 Whetstones 25940900 21665700 19360100 1015400 20808800 14893800 12872800 17337700 13109500 13109500 13876500
11419900 11419900 11561800 3705600 461000 2605100 6880100 334800 201600 5703700 224000 226600 312200 114600 45 Processzor erőforrások 70577 PENTIUM 90 52749 PENTIUM 66 47474 PENTIUM 60 59343 NEXGEN Nx586 P90 55852 Am 486DX4-120 * 43158 INTEL 486DX4-100 39211 Am 486DX4-100 47474 Am 486DX2-100 * INTEL 486DX2-80 * 39211 Am 486DX2-80 39211 Cyrix 486DX2-V80 39211 INTEL 486DX2-66 33609 Am 486DX2-66 33609 Cyrix 486DX2-V66 33609 29759 TI 486SLC2-66+FPU 24348 INTEL 486SX2-50 21427 TI 486SLC2-50+FPU 19303 Am 486DX-40 16999 TI 486SXLC-40 9749 TI 486SLC-40 15785 INTEL 486DX-33 11236 TI 486SLC-33 INTEL 486SX-25 12054 Am 386 DX-40 11631 7206 Am 386SX-40 0 10000 20000 30000 40000 50000 60000 70000 Checkit 3.0: CPU összehanonlítás Dhrystone-ok alapján 46 80000 CHECKIT 3.0 25940900 PENTIUM 90 21665700 PENTIUM 66 19360100 PENTIUM 60 1015400 NEXGEN Nx586 P90 20808800 Am 486DX4-120 * 14893800 INTEL 486DX4-100 12872800 Am
486DX4-100 17337700 Am 486DX2-100 * INTEL 486DX2-80 * 13109500 Am 486DX2-80 13109500 13876500 Cyrix 486DX2-V80 INTEL 486DX2-66 11419900 Am 486DX2-66 11419900 11561800 Cyrix 486DX2-V66 3705600 TI 486SLC2-66+FPU 461000 INTEL 486SX2-50 2605100 TI 486SLC2-50+FPU 6880100 Am 486DX-40 TI 486SXLC-40 334800 TI 486SLC-40 201600 5703700 INTEL 486DX-33 TI 486SLC-33 224000 INTEL 486SX-25 226600 Am 386 DX-40 312200 Am 386SX-40 114600 0 10000000 20000000 30000000 Checkit 3.0: FPU összehasonlítás Whetstones-ok alapján 47 Processzor erőforrások MIPS 1.20: (MIPS) Processzor Típus: PENTIUM 90 PENTIUM 66 PENTIUM 60 NEXGEN Nx586 P90 Am 486DX4-120 * INTEL 486DX4-100 Am 486DX4-100 Am 486DX2-100 * INTEL 486DX2-80 * Am 486DX2-80 Cyrix 486DX2-V80 INTEL 486DX2-66 Am 486DX2-66 Cyrix 486DX2-V66 TI 486SLC2-66+FPU INTEL 486SX2-50 TI 486SLC2-50+FPU Am 486DX-40 TI 486SXLC-40 TI 486SLC-40 INTEL 486DX-33 TI 486SLC-33 INTEL 486SX-25 Am 386 DX-40 Am 386SX-40 48 Gener Intege
Mem. Reg - Reg - átlago al Inst. r Inst -mem reg mem s: (MIPS ) 13,34 23,48 17,19 29,59 28,21 22,36 9,84 17,39 13,10 21,91 21,44 16,73 8,88 15,66 11,79 19,74 19,30 15,07 7,73 27,54 4,44 31,52 13,86 16,94 11,96 27,99 16,05 34,24 25,55 23,16 10,04 27,17 13,36 34,40 21,27 21,25 9,9 23,30 13,21 28.50 21,18 19,22 10,01 23,32 13,37 28,53 21,33 19,31 8,05 18,66 10,70 22,82 17,06 15,46 7,97 18,66 10,70 22,82 17,06 15,44 9,70 22,90 14,09 29,62 19,80 19,23 6,66 15,54 8,91 19,01 14,21 12,86 6,68 15,53 8,91 19,00 14,20 12,86 8,08 19,05 11,72 24,64 16,47 15,99 7,29 13,59 10,73 15,31 14,81 12,34 5,00 11,66 6,68 14,26 10,68 9,66 5,66 10,24 8,01 11,54 11,08 9,31 4,03 9,32 5,35 11,41 8,55 7,73 4,77 11,13 6,95 14,13 9,36 9,33 4,77 11,13 6,70 14,42 9,36 9,28 3,31 7,69 4,41 9,41 7,05 6,37 3,96 9,27 5,69 12,01 7,77 7,74 2,51 5,83 3,34 7,13 5,33 4,83 3,14 6,08 4,00 8,86 5,65 5,71 2,60 5,82 3,61 8,42 4,76 5,04 MIPS 1.20 Am 386SX-40 Regiszter-memória mozgatás Am 386 DX-40 Regiszter-regiszter
mozgatás INTEL 486SX-25 TI 486SLC-33 INTEL 486DX-33 Memória-memória mozgatás TI 486SLC-40 Integer utasítások General utasítások TI 486SXLC-40 Am 486DX-40 TI 486SLC2-50+FPU INTEL 486SX2-50 TI 486SLC2-66+FPU Cyrix 486DX2-V66 Am 486DX2-66 INTEL 486DX2-66 Cyrix 486DX2-V80 Am 486DX2-80 INTEL 486DX2-80 * Am 486DX2-100 * Am 486DX4-100 INTEL 486DX4-100 Am 486DX4-120 * NEXGEN Nx586 P90 PENTIUM 60 PENTIUM 66 PENTIUM 90 0 20 40 60 80 100 120 MIPS 1.2 (MIPS) 49 Processzor erőforrások CPUTEST 1.1 (MIPS) 5.652 Am 386SX-40 7.239 Am 386 DX-40 6.571 INTEL 486SX-25 5.865 TI 486SLC-33 8.943 INTEL 486DX-33 8.305 TI 486SLC-40 8.913 TI 486SXLC-40 10.816 Am 486DX-40 9.934 TI 486SLC2-50+FPU 13.226 INTEL 486SX2-50 13.57 TI 486SLC2-66+FPU 17.193 Cyrix 486DX2-V66 Am 486DX2-66 15.867 INTEL 486DX2-66 15.781 20.666 Cyrix 486DX2-V80 Am 486DX2-80 18.938 INTEL 486DX2-80 * 18.936 23.66 Am 486DX2-100 * 17.889 Am 486DX4-100 20.31 INTEL 486DX4-100 28.432 Am
486DX4-120 * 22.803 NEXGEN Nx586 P90 17.486 PENTIUM 60 19.419 PENTIUM 66 25.182 PENTIUM 90 0 5 10 15 20 25 CPUTEST 1.1: Átlagos mûveleti sebesség (MIPS) 50 30 35 CPUTEST 1.1 17.164 Am 386SX-40 19.764 Am 386 DX-40 11.773 INTEL 486SX-25 10.875 TI 486SLC-33 15.526 INTEL 486DX-33 TI 486SLC-40 19.978 TI 486SXLC-40 19.978 18.828 Am 486DX-40 TI 486SLC2-50+FPU 23.588 INTEL 486SX2-50 23.535 27.937 TI 486SLC2-66+FPU 28.65 Cyrix 486DX2-V66 Am 486DX2-66 31.357 INTEL 486DX2-66 31.367 34.445 Cyrix 486DX2-V80 Am 486DX2-80 37.658 INTEL 486DX2-80 * 37.658 Am 486DX2-100 * 47.073 Am 486DX4-100 47.036 47.04 INTEL 486DX4-100 56.496 Am 486DX4-120 * 67.448 NEXGEN Nx586 P90 34.909 PENTIUM 60 38.766 PENTIUM 66 52.324 PENTIUM 90 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 CPUTEST1.1: Regiszter - regiszter (MIPS) 51 Processzor erőforrások 3.7 Am 386SX-40 6.37 Am 386 DX-40 9.341 INTEL 486SX-25 5.515 TI 486SLC-33
12.485 INTEL 486DX-33 10.969 TI 486SLC-40 11.609 TI 486SXLC-40 15.139 Am 486DX-40 13.733 TI 486SLC2-50+FPU 19.456 INTEL 486SX2-50 19.19 TI 486SLC2-66+FPU 23.846 Cyrix 486DX2-V66 Am 486DX2-66 19.692 INTEL 486DX2-66 19.699 28.669 Cyrix 486DX2-V80 Am 486DX2-80 23.65 INTEL 486DX2-80 * 23.65 29.563 Am 486DX2-100 * 14.526 Am 486DX4-100 19.477 INTEL 486DX4-100 35.481 Am 486DX4-120 * 25.787 NEXGEN Nx586 P90 26.272 PENTIUM 60 29.174 PENTIUM 66 39.324 PENTIUM 90 0 5 10 15 20 25 30 CPUTEST1.1: Regiszter - memória (MIPS) 52 35 40 45 CPUTEST 1.1 5.041 Am 386SX-40 9.807 Am 386 DX-40 3.964 INTEL 486SX-25 6.339 TI 486SLC-33 7.867 INTEL 486DX-33 3.761 TI 486SLC-40 2.713 TI 486SXLC-40 9.027 Am 486DX-40 4.766 TI 486SLC2-50+FPU 9.482 INTEL 486SX2-50 8.245 TI 486SLC2-66+FPU 14.573 Cyrix 486DX2-V66 9.149 Am 486DX2-66 8.056 INTEL 486DX2-66 17.521 Cyrix 486DX2-V80 Am 486DX2-80 9.671 INTEL 486DX2-80 * 9.671 12.09 Am
486DX2-100 * 6.451 Am 486DX4-100 9.126 INTEL 486DX4-100 15.195 Am 486DX4-120 * 27.389 NEXGEN Nx586 P90 32.081 PENTIUM 60 35.627 PENTIUM 66 38.979 PENTIUM 90 0 5 10 15 20 25 30 35 40 45 CPUTEST1.1: Memória - memória (MIPS) 53 Processzor erőforrások 1.617 Am 386SX-40 1.813 Am 386 DX-40 INTEL 486SX-25 1.91 TI 486SLC-33 1.777 2.65 INTEL 486DX-33 TI 486SLC-40 2.243 TI 486SXLC-40 2.243 3.163 Am 486DX-40 2.327 TI 486SLC2-50+FPU INTEL 486SX2-50 3.385 TI 486SLC2-66+FPU 3.61 4.64 Cyrix 486DX2-V66 3.54 Am 486DX2-66 3.541 INTEL 486DX2-66 5.579 Cyrix 486DX2-V80 Am 486DX2-80 4.251 INTEL 486DX2-80 * 4.251 5.314 Am 486DX2-100 * 3.058 Am 486DX4-100 3.935 INTEL 486DX4-100 6.31 Am 486DX4-120 * 8.818 NEXGEN Nx586 P90 7.237 PENTIUM 60 8.036 PENTIUM 66 10.847 PENTIUM 90 0 2 4 6 8 CPUTEST1.1: Stack mûveletek (MIPS) 54 10 12 CPUTEST 1.1 0.27 Am 386SX-40 0.579 Am 386 DX-40 0.529 INTEL 486SX-25 0.473 TI 486SLC-33
0.143 INTEL 486DX-33 TI 486SLC-40 0.48 TI 486SXLC-40 0.48 Am 486DX-40 0.479 0.634 TI 486SLC2-50+FPU 0.495 INTEL 486SX2-50 0.642 TI 486SLC2-66+FPU 0.503 Cyrix 486DX2-V66 0.226 Am 486DX2-66 0.503 INTEL 486DX2-66 0.569 Cyrix 486DX2-V80 0.535 Am 486DX2-80 0.519 INTEL 486DX2-80 * 0.553 Am 486DX2-100 * 0.259 Am 486DX4-100 0.273 INTEL 486DX4-100 0.496 Am 486DX4-120 * 0.602 NEXGEN Nx586 P90 0.355 PENTIUM 60 0.4 PENTIUM 66 0.383 PENTIUM 90 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 CPUTEST1.1: I/O mûveletek (MIPS) 55 Processzor erőforrások 1.864 Am 386SX-40 3.053 Am 386 DX-40 1.849 INTEL 486SX-25 3.279 TI 486SLC-33 2.439 INTEL 486DX-33 TI 486SLC-40 4.086 TI 486SXLC-40 4.086 2.957 Am 486DX-40 TI 486SLC2-50+FPU 3.734 INTEL 486SX2-50 3.697 4.954 TI 486SLC2-66+FPU 6.695 Cyrix 486DX2-V66 Am 486DX2-66 4.925 INTEL 486DX2-66 4.927 8.049 Cyrix 486DX2-V80 Am 486DX2-80 5.915 INTEL 486DX2-80 * 5.915 Am 486DX2-100 * 7.394 Am 486DX4-100
7.388 9.023 INTEL 486DX4-100 8.874 Am 486DX4-120 * 8.362 NEXGEN Nx586 P90 4.583 PENTIUM 60 5.09 PENTIUM 66 6.87 PENTIUM 90 0 1 2 3 4 5 6 7 8 CPUTEST 1.1: Matematikai mûveletek FPU nélkül (MIPS) 56 9 10 CPUTEST 1.1 3.525 Am 386SX-40 4.793 Am 386 DX-40 6.831 INTEL 486SX-25 6.376 TI 486SLC-33 9.118 INTEL 486DX-33 6.672 TI 486SLC-40 8.852 TI 486SXLC-40 11.057 Am 486DX-40 9.569 TI 486SLC2-50+FPU 13.478 INTEL 486SX2-50 14.035 TI 486SLC2-66+FPU 16.727 Cyrix 486DX2-V66 Am 486DX2-66 14.498 INTEL 486DX2-66 14.503 20.11 Cyrix 486DX2-V80 Am 486DX2-80 17.412 INTEL 486DX2-80 * 17.412 21.765 Am 486DX2-100 * 13.441 Am 486DX4-100 16.631 INTEL 486DX4-100 26.057 Am 486DX4-120 * 20.224 NEXGEN Nx586 P90 16.828 PENTIUM 60 18.687 PENTIUM 66 25.223 PENTIUM 90 0 5 10 15 20 25 30 CPUTEST 1.1: Logikai mûveletek (MIPS) 57 Processzor erőforrások 11.41 Am 386SX-40 Am 386 DX-40 13.04 INTEL 486SX-25 12.344 18.148 TI
486SLC-33 16.282 INTEL 486DX-33 19.085 TI 486SLC-40 22.785 TI 486SXLC-40 19.744 Am 486DX-40 20.433 TI 486SLC2-50+FPU 24.68 INTEL 486SX2-50 29.434 TI 486SLC2-66+FPU 45.92 Cyrix 486DX2-V66 31.188 Am 486DX2-66 31.2 INTEL 486DX2-66 55.208 Cyrix 486DX2-V80 Am 486DX2-80 37.456 INTEL 486DX2-80 * 37.456 46.921 Am 486DX2-100 * 26.242 Am 486DX4-100 34.951 INTEL 486DX4-100 56.128 Am 486DX4-120 * 39.115 NEXGEN Nx586 P90 35.09 PENTIUM 60 38.967 PENTIUM 66 52.595 PENTIUM 90 0 5 10 15 20 25 30 35 40 CPUTEST 1.1: Adatforgatás (Bit/s) 58 45 50 55 60 65 CPUTEST 1.1 3.85 Am 386SX-40 5.929 Am 386 DX-40 10.596 INTEL 486SX-25 1.185 TI 486SLC-33 13.973 INTEL 486DX-33 7.47 TI 486SLC-40 7.471 TI 486SXLC-40 16.945 Am 486DX-40 10.614 TI 486SLC2-50+FPU 21.101 INTEL 486SX2-50 14.081 TI 486SLC2-66+FPU 13.179 Cyrix 486DX2-V66 28.222 Am 486DX2-66 28.23 INTEL 486DX2-66 15.844 Cyrix 486DX2-V80 Am 486DX2-80 33.892 INTEL
486DX2-80 * 33.892 Am 486DX2-100 * 42.365 Am 486DX4-100 42.332 INTEL 486DX4-100 42.338 50.846 Am 486DX4-120 * 7.486 NEXGEN Nx586 P90 PENTIUM 60 0.018 PENTIUM 66 0.022 PENTIUM 90 0.041 0 10 20 30 40 50 60 CPUTEST 1.1: JMP/CALL utasítások (MIPS) Ha azt szeretnénk megtudni, hogy az egyes 486-os architektúrák mennyiben hasonlítanak, vagy térnek el egymástól, elég a mérési adatok között vizsgálódnunk. Az ugrások (JMP/CALL), matematikai műveletek koprocesszorral és anélkül - sebességi különbségéből kitűnik, hogy a 59 Processzor erőforrások Cyrix processzorok felépítése lényegesen különbözik az INTEL és az AMD által használt struktúráktól. Egy gyorsabb koprocesszort, és kicsivel gyorsabb, az INTEL-től különböző CPU-t takar a tokozás. Az INTEL és az AMD DX2-66 -os processzora esetében az is kitűnik, hogy az INTEL nem alaptalanul perlekedett: a két processzor belülről teljesen megegyezik! Mindegyik tesztprogram
a teljesen azonos eredményeket mutatott. A DX2-80 -asok esetében szintén ez a helyzet Ebben a kategóriában a Cyrix viszi a pálmát. A tesztprogramok mérő-algoritmus hosszait is érdemes megfigyelni. Az áruló a Texas SCL40 - SXLC40 párosa, ugyanis különbség a két típus között csak a belső-cache méretében van. Az SLC40-ben 1 kByte (!), az SXLC40-ben 8 kByte A mért adatokból kiderült, Landmark CPU sebesség mérése nem, FPU mérése pedig nagymértékben függ a belsőcache mérettől, egyébként azonos teljesítményű processzorok esetén. (Sokszor sajnos nem csak azt a paramétert mérjük amelyiket szeretnénk!) A Dhrystone-ok Whetstone-ok esetében az eredmény szintén nagymértékben függ a cache méretétől. A MIPS és a CPUTEST esetében azonban a helyzet sokkal jobb. Az ugrásokat összehasonlítva sokakat meglep a tény, hogy a Pentiumok, és az Nx586 esetében is meglehetősen alacsony értékeket mérünk. Csodák ebben a műfajban nincsenek A
processzorok a külső, és belsőcache-ek feltöltésével, és az utasítás előrejelzéssel foglalják el magukat, pipeline-ok pedig az ugrás után nem lehetnek tele utasítással. (A CALL utasítás esetében a helyzet még rosszabb: az előbbiekben ismertetett procedúrák kétszer - egyszer a CALL, és egyszer a RET utasítás eredményeként - hajtódnak végre.) /lásd: CPUTEST 11 JMP-CALL utasítások vérehajtásáról készült táblázat/ Érdekes dolgokra bukkanhatunk, ha az Nx586 regiszter műveleteinek sebességét vetjük össze az azonos súlycsoportba tartozó Pentiuméval: a kizárólag regiszterek között végrehajtott műveletekben mindig az Nx586 vezetett. Ennek magyarázata - az Nx586-ról szóló fejezetben már tárgyalt - 32 regiszter, és a regiszter átnevezési technológia. Sajnos az Nx586 a memória műveletek méréseinél nem szerepelt túl fényesen, ezt az alaplapra integrált 12ns-os CACHE-RAM oknak tulajdonítjuk. (A Nexgen 10ns-os cache-RAM
-okat ír elő a P90-es processzorához.) A másik összetevő, hogy PCI-buszra épülő rendszervezérlő chippel (pl.: NxPCI rendszer vezérlő) ugyanazon 60 CPUTEST 1.1 processzorral egy nyúlfarknyival (90MHz-nél kb.: 2,5-3%) nagyobb sebesség érhető el. Számunkra meglepetést okozott a Cyrix, és a DX4-es processzorok a Pentiumokhoz viszonyított meglehetősen magas INTEGER műveleti sebessége. Most nézzük milyen különbségek vannak az utasítások végrehajtásának ütemezésében néhány konkurens ötödik generációs processzorban. Kiemeltünk néhány matematikai utasítást a teljesség igénye nélkül. A táblázat az utasítás végrehajtásának idejét a végrehajtáshoz szükséges órajel ciklusok számával adja meg. A matematikai processzorra vonatkozó utasítások (FP) a kétszeres pontosságú alakok használatát feltételezik. UTASÍTÁS FP ADD késés: eredmény: FP MUL késés: eredmény: FP DIV késés: eredmény: MUL (integer)
késés: DIV (integer) késés: NEXGEN Nx586 INTEL Pentium 2 2 2 2 40 40 8 39 3 1 3 2 39 39 10 41 IBM PowerPC 601 4 1 4 2 31 29 9 36 Érdekességként nézzük meg a Pentium processzor és konkurensei UNIX operációs rendszer alatt mért INTEGER, és Floating Point teljesítményeit. Egyesek RISC processzorként hardware-sen (pl: Nx586), mások (pl.: PowerPC, R4400, Alpha) software-ből emulálva valósítják meg az x86-os architektúrát. 61 Processzor erőforrások Processzor típus Pentium 60 Pentium 66 Pentium 75 Pentium 90 Pentium 100 SPARC+ PowerPC601 PowerPC603 PowerPC604 HP7100 Alpha21064 MIPS R4400SC Cyrix M1 Gyártók: 62 Belső órajel frekvencia 60MHz 66MHz 75MHz 90MHz 100MHz 50MHz 66MHz 66MHz 100MHz 99MHz 150MHz 150MHz 100MHz Pentium PowerPC K5 M1 HP7100 R4400 Alpha21064 Nx586 SPECint92 58.3 64.5 83.8 100.9 112.7 65.2 75 55 140 80 84.4 61.7 130 SPECfp92 52.2 56.9 60.8 73.5 81.8 83 91 65 145 150 127.7 63.4 nincs adat -INTEL -IBM -AMD -CYRIX
-HEWLET-PACKARD -MIPS -DEC -NEXGEN Belső-cache méret 16 kByte 16 kByte 16 kByte 16 kByte 16 kByte 36 kByte 32 kByte 16 kByte 32 kByte -16 kByte 16 kByte 16 kByte UNIX SPECint SPECfp tesztek UNIX SPECint92 Cyrix M1 MIPS R4400SC Alpha21064 HP7100 PowerPC604 PowerPC603 PowerPC601 SPARC+ Pentium 100 Pentium 90 Pentium 75 Pentium 66 Pentium 60 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 90 100 110 120 130 140 150 UNIX SPECfp92 Cyrix M1 MIPS R4400SC Alpha21064 HP7100 PowerPC604 PowerPC603 PowerPC601 SPARC+ Pentium 100 Pentium 90 Pentium 75 Pentium 66 Pentium 60 0 10 20 30 40 50 60 70 80 63 Általános CPU programozási információk 3. Fejezet: Általános CPU programozási információk 3.1 A memória felépítése A Pentium processzor buszára kapcsolt memória neve fizikai memória, mely 8 bites Byte-okból álló sorozatnak tekinthető. Minden Byte-nak megfelel egy és csakis egy, fizikai címnek nevezett cím, amelynek érteke 0-tól
maximum 232-1-ig (4 GByte) terjedhet. A memória kezelését a megbízható és hatékony működés érdekében a hardware végzi. A memóriakezelés használata esetében a programok nem érik el közvetlenül a fizikai memóriát, hanem egy memóriamodellt címeznek, melynek virtuális memória a neve. A memória kezelése szegmentálásból és lapozásból áll. A szegmentálás egy olyan mechanizmus, mely több, független címtartományt biztosít. A lapozás mechanizmusa kevesebb RAM-ot és egy bizonyos mennyiségű lemeztároló kapacitást igénylő nagy címtartományú modelljét támogatja. Használható mindkét vagy csak az egyik módszer a kettő közül. Egy program által használt címek logikai címek. A szegmentálást végző hardware a logikai címet a nemszegmentált címtartomány címzéséhez szükséges lineáris címmé, a lapozást végző hardware pedíg a lineáris címeket fizikai címekké alakítja át. A memória tekinthető egyetlen
"lapos" címtartományként is, mint amilyen a fizikai memória; tekinthető azonban egy vagy több, egymástól független memóriarésznek is, melyek neve szegmens. Egy program legtöbb 16383 különböző fajta és méretű szegmenst használhat. A szegmensek felhasználhatók a programok és rendszerek megbízhatóságának növelése érdekében. Például megelőzhető az, hogy egy program verme, túllépve a neki szánt területet, felülírja a program kódját képező utasításokat; ez a kód és a verem két külön szegmensbe való helyezésével érhető el. Így mindegyik szegmens meghatároz egy modult. 64 A memória felépítése Mindkét, a lapos és a szegmentált modell is biztosítja a memória védelmét. E két modell közt elhelyezkedő modellek szintén kiválaszthatók. Egy memóriamodell kiválasztásának szempontjait és azt, ahogyan a rendszerprogramozók egy modellt megvalósítanak, az alkalmazási terület határozza meg. Függetlenül
attól, hogy több szegmens van használatban vagy sem, a logikai címek lineáris címekké való átalakítása a címeket egy szegmensen belüli ofszetnek értelmezve történik. Minden szegmensnek van egy szegmensdeszkriptora, mely tartalmazza a szegmens báziscímét és mérethatárát. Ha az ofszet nem haladja meg ezt a határt, és nincs más feltétel, mely megakadályozná a szegmenshez való hozzáférést, az ofszet és a báziscím összeadódik és a lineáris címet képez. Ha a CR0 regiszter 31. bitje törölve van (a CR0 regisztert lásd később), a szegmentálásból adódó lineáris cím fizikai címként lesz felhasználva. Ez a regiszterbit határozza meg hogy használatban van-e lapozás vagy sem. Ha a bit 1-re van állítva, a lineáris cím fizikai címmé való átalakítását a lapozó hardware végzi. Ha több szegmens van használatban, ezek részei az alkalmazásfejlesztő által használt programozási környezetnek. Az alkalmazásfejlesztők számára
a lapozás nem érzékelhető, részletek ezzel kapcsolatban később. 3.11 Nemszegmentált vagy "lapos" modell A legegyszerűbb memóriamodell a lapos modell. Bár nincs olyan üzemmódbit vagy vezérlőregiszter amelyik a szegmentáló mechanizmust kikapcsolná, ugyanez a hatás érhető el minden szegmensnek ugyanarra a lineáris címre való leképezésével. Ennek következtében minden memóriaművelet ugyanarra a memóriatartományra fog vonatkozni. A lapos modellben a szegmensek lefedhetik a fizikai címek egész skáláját vagy csupán azokat a részeket, melyek a fizikai memóriába vannak leképezve. A kisebb címtartomány előnye, hogy egy minimális hardware védelmet nyújt a software hibák ellen. Ha egy logikai cím egy 65 Általános CPU programozási információk nemlétező címet (melyhez nem tartozik memória) jelöl, akkor egy kivétel keletkezik (kivételeket lásd később). 3.12 Szegmentált modell A memória felépítésének szegmentált
modellje a logikai címek tartományát 16383, egyenként maximum 4 GByte méretű szegmensre osztja, melyek nagysága összesen 246 Byte (64 TByte). Ezt a 64 TByte logikai címtartományt a fizikai címtartományra a processzor a későbbiekben bemutatásra kerülő címátalakító mechanizmus segítségével képezi le. A programozóknak ezt a leképezést nem kell figyelembe venniük. A szegmentált modell előnye az, hogy a címtartományokon belüli ofszetek és minden egyes szegmenshez való hozzáférés külön ellenőrizhető. Egy, a szegmentált címtartományt címző pointer két részből áll (lásd a 3.1 ábrát). 1. 2. Szegmensszelektor - a szegmenst azonosító 16 bites mező. Ofszet - a szegmensen belüli 32 bites cím. 3.1 ábra: Szegmentált címzés 66 Regiszterek 3.2 Regiszterek A processzornak tizenhat, a programozók által használható regisztere van. Amint azt a 32 ábra is mutatja Ezek a következőképpen csoportosíthatók: 1. Általános
regiszterek. Ezt a nyolc darab 32 bites regisztert a programozó szabadon használhatja. 2. Szegmensregiszterek. Ezek a regiszterek a különböző memóriahozzáférési módokhoz hozzárendelt szegmensszelektorokat tartalmazzák. A kód- és veremterülethez való hozzáférés például külön szegmensregiszterek segítségével történik. Ez a hat regiszter a pillanatnyilag hozzáférhető memóriaszegmenseket határozza meg. 3. Állapot- és vezérlőregiszterek. Ezek a regiszterek a processzor állapotáról adnak tájékoztatást és lehetővé teszik annak megváltoztatását. 3.21 Általános regiszterek Az általános regiszterek az EAX, EBX, ECX, EDX, EBP, ESP, ESI, EDI 32 bites regiszterek. Ezek a regiszterek a programozó által szabadon választott értékeket tartalmazhatnak (logikai, aritmetikai műveletek operandusait, eredményét stb). Ezenkívül tartalmazhatják még a címszámításokhoz szükséges operandusokat is (kivéve az ESP regisztert, mely nem
használható indexoperandusként). A felsorolt regiszterek nevei a 8086 processzor AX, BX, CX, DX, BP, SP, SI, DI általános regisztereinek neveiből származnak. Ahogy a 32 ábra is mutatja, ezekkel a nevekkel lehet hivatkozni a 32 bites regiszterek alsó 16 bitjére. Az AX, BX, CX és DX 16 bites regiszterek mindkét Byte-jának saját neve is van. A Byte-regiszterek elnevezése a következő: AH, BH, CH és DH (felső Byte-ok) illetve AL, BL, CL és DL (alsó Byte-ok). 67 Általános CPU programozási információk 31 Általános regiszterek 16 15 8 7 AH DH CH BH 16-BIT 32-BIT AX DX CX BX EAX EDX ECX EBX 0 AL DL CL BL BP SI DI SP EBP ESI EDI ESP Szegmens regiszterek CS SS DS ES FS GS Státusz és vezérlõ regiszterek EFLAGS EIP 3.2 ábra: Alkalmazások számára elérhető regiszterkészlet A címszámítások és legtöbb aritmetikai illetve logikai művelet eredményei számára minden általános célú regiszter rendelkezésre áll, egyes utasítások azonban
operandusaik tárolására csak bizonyos regisztereket használnak fel. Például a füzérutasítások operandusként az ECX (ciklusszámláló), ESI (forrásindex) és EDI (célindex) regisztereket használják. Ezen műveletekhez specifikus regisztereket hozzárendelve az utasításkészlet tömörebben kódolható. A specifikus regisztereket használó 68 Regiszterek utasítások a következők: duplapontosságú szorzás és osztás-, I/O-, füzér-, transzlatáló, ciklus-, különböző eltoló- és forgató-, valamint veremműveletek. 3.22 Szegmensregiszterek A szegmentáció a rendszertervezők számára rugalmasságot nyújt a különböző memóriafelépítési modellek közti választásban. A szegmensregiszterek a 16 bites szegmensszelektorokat tartalmazzák, melyek egy, a memóriában elhelyezkedő táblázatot indexelnek. Ez a táblázat tartalmazza a szegmensek báziscímét, valamint a memóriahozzáférést illető információkat. Nem szegmentált modell minden
egyes szegmens ugyanarra a fizikai memóriatartományra való leképezésével valósítható meg. A memóriában egy adott pillanatban hat szegmens áll rendelkezésre, ezeknek szelektorait a CS, DS, SS, ES, FS és GS szegmensregiszterek tartalmazzák. Minden regiszterhez egy külön memóriaelérési mód tartozik (kód, adat, vagy verem); mindegyik regiszter egy szegmenst jelöl, a program által használtak közül (lásd a 3.3 ábrát). Más szegmensek is használhatók, ezek szegmensszelektorát be kell tölteni a megfelelő szegmensregiszterbe. Kódszegmens a neve annak a szegmensnek, mely a végrehajtandó utasításokat tartalmazza. Ennek szegmensszelektorát a CS regiszter tartalmazza. A processzor a kódszegmensben levő utasításokat olvassa be, a szegmensen belüli ofszetként az EIP regiszter tartalmát felhasználva. A CS regiszter feltöltése a megszakítások, kivételek és a vezérlést szegmensek közt átadó utasítások (például CALL, RET vagy JMP)
végrehajtása eredményeképpen történik (a számítógép autómatikusan végzi). Egy eljárás meghívása előtt szükséges egy memóriarész kijelölése a verem számára. A verem tartalmazza a visszatérési címet, a hívórutin által átadott paramétereket, valamint az eljárás által igényelt ideiglenes változókat. A veremszegmens azonosítására minden veremművelet az SS 69 Általános CPU programozási információk regisztert használja, mely a CS regiszterrel ellentétben külső módon feltölthető; így az alkalmazás saját maga építhet fel vermeket. A DS, ES, FS és GS regiszterek lehetővé teszik, hogy egyszerre négy adatszegmens álljon rendelkezésre. A négy adatszegmens biztosítja a különböző típusú adatstruktúrákhoz való hatékony és biztonságos hozzáférést. Például külön-külön adatszegmens hozható létre az aktuális modul adatstruktúrái, a magasabb szintű modulból exportált adatok, egy dinamikusan létrehozott
adatstruktúra és a más programokkal megosztott adatok számára. Ha egy programhiba következtében a program futása összezavarodik, a szegmentáló mechanizmus a hiba által okozott kárt a program által foglalt szegmensekre korlátozza. CS Kód szegmens SS Stack szegmens DS 1. adatszegmens ES 2. adatszegmens FS 3. adatszegmens Az adatok szerkezetétől függően (vagyis hogyan vannak az adatok szegmensekre osztva) a program több szegmenshez is igényelhet hozzáférést. A további szegmensek elérése érdekében a DS, ES, FS és GS regiszterek az alkalmazói program futása közben is feltölthetők. Az egyetlen teendő a megfelelő szegmensregiszter feltöltése, még mielőtt az illető szegmens adataihoz való hozzáférés megtörténne. Minden egyes szegmens báziscíme tárolva van. Egy szegmensen belüli adat 3.3 ábra: Szegmentált memória megcímzéséhez a 32 bites ofszetet hozzá kell adni a szegmens báziscíméhez. A szegmens kiválasztása (a
szegmensszelektornak a szegmensregiszterbe való betöltése által) után az utasításnak csak az ofszetet kell megadnia. Az adatszegmensen belüli operandus címzése egy regiszterben vagy maga az utasítás testében megadott ofszet segítségével történik. Azt, hogy melyik GS 70 4. adatszegmens Regiszterek szegmensregiszter használandó akkor, amikor csak egy ofszet van megadva, egyszerű szabályok határozzák meg. 3.23 Utasításmutató Az utasításmutató (EIP) regiszter levő következő végrehajtandó utasítás utasításmutató nem áll közvetlenül a kezelését a vezérlésátadó utasítások megszakítások és kivételek végzik. az aktuális kódszegmensben ofszetjét tartalmazza. Az programozó rendelkezésére, (ugrások, hívások, stb.), Az EIP regiszter egyik utasítás kezdőcíméről a következőére ugrik. Az utasítások előbetöltése miatt az EIP az utasításokat a processzorba betöltő busz aktivitásáról csak egy hozzávetőleges
tájékoztatást ad. Az utasítások előbetöltésének részletes leírása egy későbbi fejezetben található. 3.24 A verem felépítése és használata A veremműveleteket három regiszter támogatja: 1. Veremszegmens (SS) regiszter. A verem a memóriában helyezkedik el. Egy rendszerben a vermek számát a használható szegmensek maximális száma korlátozza. A verem nagysága maximálisan 4 GByte lehet, vagyis egyenlő egy szegmens maximális méretével. Egyszerre csak egy verem állhat rendelkezésre. Az, amelynek szelektorát az SS regiszter tartalmazza. Ez az aktuális verem A processzor minden veremművelethez automatikusan az SS regisztert használja. 2. Veremmutató (ESP) regiszter. Az ESP regiszter a verem tetejét (TOS - Top-Of-Stack) az aktuális veremszegmensen belüli aktuális ofszetet tartalmazza. A veremmutatót a PUSH és POP utasítások, szubrutinhívások és visszatérések, kivételek, valamint megszakítások használják. Egy adat veremre való
ráhelyezésekor (3.4 ábra) a processzor csökkenti az ESP regisztert, majd beírja az 71 Általános CPU programozási információk adatot az új TOS-ba. Amikor egy adatot kivesz a veremből, a processzor kimásolja azt a TOS-ból, majd növeli az ESP regisztert. Másképpen fogalmazva a memóriában a verem lefele nő, a kisebb címek irányába. 3. Veremkeret-bázismutató (EBP) regiszter. Az EBP regiszter jellemző felhasználási módja a vermen keresztül átadott paraméterekhez való hozzáférés. Amikor a vezérlés átadódik egy szubrutinra, a verem a visszatérési címet és az illető szubrutinnak átadott adatstruktúrákat tartalmazza. A szubrutin megnöveli a vermet, amennyiben ideiglenes lokális változói számára helyre van szüksége. Ennek eredményeképpen az ideiglenes változók veremből való ki- és behelyezése által a veremmutató nő illetve csökken. Ha a veremmutató értéke azelőtt volt a bázismutatóba másolva, mielőtt valami is a
verembe került volna, akkor a bázismutató felhasználható a rögzített ofszetű adatstruktúrák elérésére. Ha ez nem így történt, akkor egy adatstruktúrát azonosító ofszet az időszakos változók által elfoglalt hely függvényében változni fog. Az EBP regiszter által történő memóriacímzés az aktuális veremszegmenst (SS regiszter) használja. Mivel a veremszegmenst nem kell külön megadni, az utasításkód tömörebb. Az EBP regiszter más szegmensek címzésére is használható, de ekkor a szegmenst külön meg kell adni (MOV AX,GS:[EBP]). Az olyan utasítások, mint az ENTER és LEAVE, a változókhoz való könnyebb hozzáférés érdekében az EBP regisztert automatikusan beállítják. 3.25 Flagregiszter Az feltételkódokat (azaz átvitel, előjel, túlcsordulás) és állapotbiteket, (gyüjtőnevükön: flageket), az EFLAGS nevű 32 bites regiszter tartalmazza. A flagek elrendezését a regiszteren belül a 35 ábra mutatja be. Az flagek a
Pentium processzor állapotáról adnak tájékoztatást, ezenkívül egyes műveletek végrehajtását irányítják. Az állapot- és vezérlő flagbiteken kívül a flagregiszter még rendszerflageket is tartalmaz. 72 Regiszterek Régi ESP Az utoljára behelyezett adat SS Új ESP Új behelyezett adat SS 3.4 ábra: A verem működése 3.251 Állapotbitek Az EFLAGS regiszter állapotbitjei az olyan aritmetikai utasítások eredményének jellegéről adnak számot, mint az ADD, SUB, MUL vagy DIV. A MOV utasítás nincs hatással ezekre az állapotbitekre A feltételes ugrások és szubrutinhívások lehetővé teszik, hogy a program érzékelni tudja az flagek állapotát és ezektől függően cselekedjen. Amikor egy ciklusszámláló értéke a csökkentések során elérte a nullát, a ZF bit állapota 1 lesz, e változás miatt a ciklus elejére való ugrást megvalósító feltételes ugróutasítás nem hajtódik végre, és a ciklus megszakad. Az állapotbiteket a
3.6 ábra mutatja be külön 73 Általános CPU programozási információk EFLAGS 31 30 0 0 29 28 0 0 27 26 0 0 25 24 23 0 0 0 22 21 0 ID X ID FLAG 20 19 VIP VIF X LÁTSZÓLAGOS MEGSZAKÍTÁS-FELFÜGGESZTÉS X LÁTSZÓLAGOS MEGSZAKÍTÁS FLAG 18 17 16 AC VM RF X ILLESZKEDÉS ELLENÖRZŐ X 8086 VIRTUÁLIS MÓD X FOLYTATÁST JELZŐ FLAG 15 14 0 NT X BEÁGYAZOTT TASZK 13 12 11 IOPL X I/O PRIVILÉGIUM SZINT OF S TÚLCSORDULÁS FLAG 10 9 DF IF C IRÁNY FLAG X MEGSZAKÍTÁS ENGEDÉLYEZŐ FLAG 8 7 TF SF X CSAPDA FLAG S ELŐJEL FLAG 6 5 4 ZF 0 AF S ZERO FLAG 3 2 0 PF S PARITÁS FLAG 1 0 1 CF S ÁTVITEL FLAG S FÉL-ÁTVITEL FLAG S - STÁTUSZ FLAG C - VEZÉRLŐ FLAG X - RENDSZER FLAG 1,0 - NEM HASZNÁLT, INTEL ÁLLTAL FENNTARTVA 3.5 ábra: Az EFLAGS regiszter 74 Regiszterek Név OF Szándék Túlcsordulás SF ZF AF Előjel Zero Félátvitel PF Paritás CF Átvitel Kialakulási feltétel Az eredmény meghaladta a pozitív vagy negatív
határt Az eredmény negatív Az eredmény nulla Átvitel történt a 3. biten (BCD-nél használatos) Az eredmény alsó Byte-jában páros számú 1 bitek vannak A legfelső bitről átvitel történt 3.6 ábra: Állapotbitek Az EFLAGS regiszter DF vezérlőbitje a füzérutasítások irányát vezérli. (10. bit) A DF bit beállítása a füzérutasítások csökkenő memóriatartomány felé történő végrehajtását eredményezi, vagyis a füzérek feldolgozása a magasabb címek felől az alacsonyabb címek irányába tart. A DF bit törlése fordított irányú feldolgozást eredményez. 3.26 Rendszer-regiszterek A rendszerprogramozóknak szánt regisztereket a következő kategóriákba sorolhatjuk: - EFLAGS regiszter - memóriaszervező regiszterek (memory management ) - vezérlő regiszterek (control) - nyomkövető regiszterek (debug) A rendszer-regiszterek vezérlik a felhasználói programok végrehajtó környezetét. Az operációs rendszerek többsége a
felhasználói programok számára korlátozza ezen lehetőségeket. (Mindamellett 75 Általános CPU programozási információk szerkeszthetünk olyan operációs rendszereket is, amelyekben minden program a legprivilegizáltabb szinten fut, ez esetben a felhasználói programoknak megengedett e lehetőségekbe való beavatkozás.) 3.261 Rendszer-flagek Az EFLAGS regiszter rendszer-flagjei vezérlik az I/O műveleteket, a maszkolható megszakításokat, a nyomkövetést, a taszkcserét, illetve a virtuális 8086-os üzemmódot. Egy felhasználói programnak ezeket a flageket nem kell figyelembe vennie, és tilos számára az állapotuk megváltoztatását megkísérelni. Egyes operációs rendszerekben egy rendszerflag állapotának megváltoztatását célzó kísérlet kivételt idéz elő. A fent említett flageket a 35 ábra szemlélteti A 0-val illetve 1-el jelölt bitpozíciók az Intel által fenntartottak. Használatuk nem ajánlott. Mindíg a megelőző kiolvasáskor
kapott értékekre állítandók. ID - (Identification Flag) azonosító flag, (21. bit) Ha egy program képes arra, hogy az ID flaget magasra, illetve alacsonyra állítsa, azt jelenti, hogy a processzor támogatja a CPUID utasítást. Lásd cpu azonosítása VIP - (Virtual Interrupt Pending Flag) virtuális megszakításfelfüggesztés bit (20. bit) Ez a flag a VIF flaggel együtt lehetővé teszi minden egyes, multitaszkos környezetben futó felhasználói program számára, hogy a rendszer IF flagjének egy virtuális verzióját használhassa. Részletes útmutató ezen flagek virtuális 8086-os, illetve védett üzemmódú használatáról a függelékben található. VIF - (Virtual Interrupt Flag) virtuális megszakítás bit (19. bit) A VIF flag egy virtuális képe az IF (Interrupt Flag) megszakítás flagnek, a VIP-el együtt használatos. 76 Regiszterek AC - (Alignment Check Mode) illeszkedés-ellenőrzés (18. bit) Az AC flag és a CR0 regiszterbeli AM bit magasra
állításával (SET) lehetővé válik a memóriahivatkozások illeszkedésének ellenőrzése. Valahányszor egy illeszkedési hibás operandusra kerül hivatkozás, mint például egy páratlan címen elhelyezkedő 16 bites szóra, vagy egy néggyel nem osztható címen levő doublewordra, egy illeszkedési kivétel jelentkezik. Az illeszkedési kivételek csak felhasználói módban (usermode) (3. privilégium szinten) generálódnak. Azok a memóriahivatkozások, amelyek alapértelmezése a 0. privilégium szint, mint például a szegmensdeszkriptorok betöltése, nem okozzák a fenntemlített kivételt még abban az esetben sem, ha ezt egy felhasználói módbeli memóriahivatkozás okozná. Az illeszkedési kivételt fel lehet használni az adatok illeszkedésének ellenőrzésére. Ez akkor lehet hasznos, ha egy olyan processzorral cserélünk adatokat, amely megköveteli minden adat helyes illeszkedését, mint például az i860-as. Az illeszkedési kivételt az
értelmezőprogramok (interpreters) arra is felhasználhatják, hogy bizonyos mutatókat (pointereket) speciálisan megjelöljenek hibás illesztéssel. Ezáltal elkerülhetők a mutatók egyenkénti ellenőrzésének költségei, és így az alkalmazás pillanatában csak a speciális mutatókat kezelik. VM - (Virtual-8086 Mode) virtuális 8086-os üzemmódjelző bit (17. bit) Magasra állítva a VM flaget a processzort virtuális 8086-os üzemmódba hozzuk, amely nem más, mint a 8086-os processzor programozási környezetének emulálása. RF - (Resume Flag) folytatás jelző bit (16. bit) Az RF bit ideiglenesen letiltja a nyomkövetési hibákat (debug faults), annak érdekében, hogy egy debug fault után újra folytatni lehessen egy utasítást, anélkül, hogy közvetlenül egy újabb nyomkövetési hibát okozna. A hibakereső (debugger) az IRETD utasítással állítja magasra ezt a bitet, a megszakított programba való visszatérés 77 Általános CPU programozási
információk pillanatában. A POPF, POPFD, vagy IRET utasítások nem befolyásolják az RF flaget. NT - (Nested Task) egymásba ágyazott taszkokat jelző bit (14. bit) A processzor beállítja, illetve teszteli az NT flaget, hogy vezérelje a megszakított és meghívott taszkok egymásba láncolását. Az NT flag befolyásolja az IRET utasítás végrehajtását, ugyanakkor a POPF, POPFD, és IRET utasítások befolyásolják az NT flaget. Ezen flag értékének helytelen megváltoztatása váratlan kivételeket generálhat a felhasználói programokban. IOPL - (I/O Privilege Level) I/O privilegizált szintet jelző bitek (12. és 13. bit) Az I/O privilegizálási szintet a védelmi mechanizmus az I/O címtartományhoz való hozzáférés ellenőrzésére használja. Az aktuálisan végrehajtás alatt álló szegmens privilégiumszintje (CPL) és az IOPL értéke határozzák meg azt, hogy a POPF, POPFD, és IRET utasítások módosíthatják-e ezen mező értékét. További
információk a második kötetben. IF - (Interrupt-Enable Flag) megszakítás-engedélyezést jelző bit (9. bit) Ha IF magas logikai szintre van állítva, a processzor válaszol a maszkolható megszakítás kérésekre (INTR megszakítások). Alacsonyra állítva ezt a bitet letiltjuk ezeket a megszakításokat. Az IF flag nincs hatással sem a kivételekre, sem a nemmaszkolható megszakításokra (NMI megszakítások). A CPL illetve IOPL határozzák meg, hogy a CLI, STI, POPF, és IRET utasítások változtathatnak-e ezen a biten. TF - (Trap Flag) csapda bit (8. bit) A TF flag magasra állítása a processzort - a hibakeresés érdekében - lépésenkénti végrehajtás üzemmódba helyezi. Ebben az üzemmódban a processzor minden egyes utasítást követően egy hibakereső kivételt (debug excepcion) generál, ezáltal lehetővé téve egy program ellenőrzését, miközben az egyenként hajtja végre az utasításokat. A 78 Regiszterek lépésenkénti végrehajtás csak
egy a processzor által kínált számos hibakereső lehetőség közül. Ha egy felhasználói program a POPF, POPFD, vagy IRET utasítások egyikével magasra állítja a TF flaget, egy hibakereső kivétel (debug exception) generálódik. 3.262 Vezérlőregiszterek A 3.7 ábra a CR0, CR1, CR2, CR3 ÉS CR4 vezérlőregiszterek formátumát mutatja be. Az operációs rendszerek túlnyomó része meggátolja a felhasználói programokat abban, hogy a vezérlőregisztereket feltölthessék (habár ez egy védelem nélküli rendszerben megengedett). A felhasználói programok olvashatják ezeket a regisztereket, példának kedvéért a CR0-t olvasva meghatározhatják, hogy a numerikus koprocesszor jelen van-e. A MOV utasítás különböző formái lehetővé teszik, hogy ezeket a regisztereket feltölthessük vagy elmenthessük az általános regiszterekből, illetve regiszterekbe. Például: MOV EAX, CR0 MOV CR3, EBX A CR0 regiszter rendszervezérlő biteket tartalmaz, amelyek
üzemmódokat vezérelnek, vagy olyan állapotokat jeleznek, amelyek inkább általánosan a processzorra vonatkoznak, mintsem egyedi taszkok végrehajtására. Egy programnak tilos a rezervált bitek valamelyikének megváltoztatását megkísérelni. A rezervált biteket mindig az előző kiolvasásukkor kapott értékekre tanácsos állítani. PG - (Paging) lapozás bit ( CR0 31. bitje) Ha ez a bit magas, a lapozás megengedett, ha alacsony, a lapozás tiltott. Ha a lapozás alatt kivétel generálódik, a CR2-es regiszterbe kerül az a 32 bites lineáris cím, amely a kivételt előidézte. A lapozás alatt létrejött kivételek (page faults) kezelését lásd később. 79 Általános CPU programozási információk CR4 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 MCE 0 PSE DE TSD PVI VME CR3 CR2 CR1 CR0 31 30 29 28 27 26 25 FENNTARTVA 24 23 22 21 20 19 18 AM 17 16 WP 15 14 13 12
11 FENNTARTVA 10 9 8 7 6 5 NE 4 MP 3 EM 2 TS 1 ET NE 0 PG CD NW LAPCÍMTÁR BÁZIS LAPHIBA LINEÁRIS CÍME PCD PWT 3.7 ábra: A vezérlő regiszterek felépítése Ha lapozást használunk, a CR3-as regiszter tartalmazza a lapcímtár (a felső szintű laptáblázat) címének 20 legjelentékenyebb bitjét. A CR3-as regiszter a lapcímtár báziscím-regisztere (PDBR Page Directory Base Register) néven is ismert. Megjegyzendő, hogy a lapcímtárnak is lapkeret illeszkedésűnek kell lennie, ezért a regiszter alsó 12-bitje nem használható címbitként. Az 386-os processzorral ellentétben, a 486-os illetve a Pentium processzorok ezek közül két bitnek jelentőséget tulajdonítanak. Ezek: PCD - (Page-Level Cache Disable) lapszinti cache-letiltás bit (CR3 4. bitje) Ha a lapozás megengedett, a lapozást nem használó buszciklusok mint például a megszakítás elismerő ciklusok idején ennek a bitnek az 80 Regiszterek állapota megjelenik a processzor PCD vonalán.
Ha a lapozás nem engedélyezett, ez az információ minden egyes buszciklus idején megjelenik. A PCD vonalat (pin-t) egy külső cache-be történő pufferelés (caching) ciklusonkénti vezérlésére használják. PWT - (Page-Level Writes Transparent) lapszinti átlátszó átírás bit (CR3 3. bitje) Ha a lapozás megengedett, a lapozást nem használó buszciklusok mint például a megszakítás elismerő ciklusok idején ennek a bitnek az állapota megjelenik a processzor PWT vonalán. Ha a lapozás nem engedélyezett, ez az információ minden egyes buszciklus idején megjelenik. A PWT vonalat (pin-t) egy külső cachen történő átírás (writethrough) ciklusonkénti vezérlésére használják CD - (Cache Disable) cache-letiltás bit (CR0 30. bitje) Ha ez a bit 0-ra van állítva, engedélyezi a cache feltöltő mechanizmust, ha 1-re, letiltja azt. Ha ez a bit 1-es, a cache-vesztések (cache misses) nem okoznak cache feltöltést. Megjegyzendő, hogy a cache-találatok
nincsenek letiltva; ahhoz, hogy teljesen kiiktassuk a cache-t, először invalidálni kell. A cache-elésre vonatkozó információkat lásd később. NW - (Not Write-through) átírástiltás bit (CR0 29. bitje) Ha ez a bit 0-ra van állítva, engedélyezi a cache átírást (writethrough) és a cache-invalidáló ciklusokat, ha 1-re van állítva, letiltja a cache-invalidáló ciklusokat és azokat az átírásokat, amelyek cachetalálatosak. A cache-használatra vonatkozó információkért lásd később AM - (Alignment Mask) illeszkedési maszk (CR0 18. bitje) Ha ez a bit 1-es, az illeszkedés ellenőrzés engedélyezett, ha 0, letiltott. Az illeszkedés ellenőrzésre csak abban az esetben kerül sor, ha az AM bit és az AC flag is 1-es, és a CPL értéke 3 (felhasználói mód). 81 Általános CPU programozási információk WP - (Write Protect) írásvédelem bit (CR0 16. bitje) Ha 1-re van állítva, ez a bit levédi a felhasználói- szintű lapokat a
felügyelőprogram-szinti írás ellen. Ha ez a bit értéke 0, a “csak olvasható”, felhasználói-szintű lapokra a felügyelőprogram írhat is. Ez a lehetőség hasznosnak bizonyul, ha az ún. "írás közbeni másolás" megoldást (copy-on-write) akarjuk megvalósítani új, származtatott taszkok (processes) létrehozására (forking), amely egyes operációs rendszerekben (például az UNIXban) használatos. NE - (Numeric Error) numerikus hiba bit (CR0 5. bitje) Ha ez a bit magasra van állítva, a lebegőpontos numerikus hibák jelentésének standard mechanizmusa engedélyezett. Ha NE=0 és az IGNE# bemenet aktív, a numerikus hibákat a processzor nem veszi figyelembe. Abban az esetben, ha NE=0 és az IGNE# bemenet inaktív, a numerikus hibák arra késztetik a processzort, hogy megálljon, és egy megszakításra várjon. A megszakítás a FERR# vonal segítségével generálódik, amely a megszakítás kontroller egyik bemenetét hajtja meg (a FERR# vonal
emulálja az 287-es és 387-es matematikai koprocesszorok ERROR# vonalát). Az NE bitet, az IGNE# és a FERR# vonalakat külső logikával PC-típusú hibajelentések létrehozására használják. ET - (Extension Type) koprocesszorral bővítés bit (CR0 4. bitje) Ez a bit azt mutatja, hogy a processzor támogatja az 387 DX matematikai koprocesszor utasításkészletét (Pentium processzoroknál ez a bit fenntartott). TS - (Task Switched) taszkkapcsolás bit (CR0 3. bitje) A processzor minden egyes taszkkapsolás alkalmával beállítja a TS bitet, illetve teszteli azt, amikor a lebegőpontos numerikus utasításokat értelmezi. Ezzel a bittel lehetővé válik a numerikus kontextus mentésének illetve helyreállításának késleltetése mindaddig, amíg a numerikus adat 82 Regiszterek ténylegesen felhasználásra nem kerül. A CLTS utasítás 0-ra állítja (RESET) ezt a bitet. EM - (Emulation) numerikus koprocesszor emulálása (CR0 2. bitje) Mikor az EM bit magas logikai
szintre van állítva (EM=1), egy numerikus utasítás végrehajtása "nem létező koprocesszor" kivételt generál. Ha a processzornak nincs lebegőpontos egysége, az EM bitet 1-re kell állítani. MP - (Monitor coProcessor) koprocesszor monitorozó bit. Az 286-os és 386 DX processzorokban az MP bit a WAIT koprocesszorral való szinkronizálásra használatos- utasítás működését vezérli. Abban az esetben, ha 286-os vagy 386 DX processzorok programjait futtatjuk 486-os vagy Pentium processzorok FPU-ján, ez a bit kötelezően 1-re állítandó. Az MP bitet resetelni kell a 486 SX processzor estében. PE - (Protection Enable) védett üzemmód engedélyező bit (CR0 0. bitje) A PE bit magas állapota engedélyezi a szegmens-szintű védelmet. A védelemről további információk a védett üzemmódnál A CR4-es regiszterben bizonyos architektúrális kiterjesztéseket engedélyező bitek találhatók. Ez a regiszter a Pentium proceszszorban jelenik meg először VME
- (Virtual-8086 Mode Extensions) virtuális 8086-os üzemmód kiterjesztések bit (CR4 0. bitje) Ez a bit magasra állítva támogatja egy virtuális megszakítás engedélyezést jelző flag virtuális 8086-os üzemmódbeli alkalmazását. Ezen "adottság" javítani képes a virtuális 8086-os üzemmódban futó alkalmazások teljesítményén, mégpedig úgy, hogy megszünteti a költségeit egy virtuális 8086-os monitorba való fault kivétellel történő"kiugratásnak", bizonyos utasítások emulálásakor. Lásd a függelékben 83 Általános CPU programozási információk PVI - (Protected-Mode Virtual Interrupts) védett üzemmódú virtuális megszakítások (CR4 1. bitje) Ez a bit magasra állítva támogatja egy virtuális megszakítás engedélyezést jelző flag védett üzemmódbeli alkalmazását. Ezen tulajdonság lehetővé teszi a 0. privilegizálási szintre tervezett programok számára, hogy a 3-as privilégiumszinten fussanak. További
információk a függelékben. TSD - (Time Stamp Disable) time stamp-számláló olvasás tiltása (CR4 2. bitje) Ezt a bitet 1-re állítva az RDTSC utasítás (Read from Time Stamp Counter) privilegizált utasítássá válik. Részletek az RDTSC utasításról a 2. kötetben DE - (Debugging Extensions) hibakeresés kiterjesztések bitje (CR4 3. bitje) Ennek a bitnek a magasra állítása engedélyezi az I/O töréspontokat. Lásd később PSE - (Page Size Extensions) lapméret kiterjesztések bitje (CR4 4. bitje) Ennek a bitnek a magasra állítása engedélyezi a 4 MByte-os lapméretet. További információk erről a lehetőségről a függelékben találhatók. MCE - (Machine Check Enable) géptípus ellenőrzés engedélyezését jelző bit (CR4 6. bitje) Magasra állítva ezt a bitet, engedélyezzük a géptípus ellenőrző kivételt. 3.263 Nyomkövető regiszterek 84 Regiszterek A nyomkövető regiszterek fejlett hibakereső képességgel látják el a processzort,
beleértve az adat töréspontokat és annak lehetőségét, hogy a kódszegmens módosítása nélkül az utasítások közé töréspontokat (breakpoints) szúrhassunk (hasznos lehet a ROM-ra alapozott software-ek nyomkövetése esetén). Csak a legmagasabb privilégiumszinten futó programok képesek ezekhez a regiszterekhez hozzáférni. A későbbiekben egy teljeskörű leírást kaphatunk ezen regiszterek felépítéséről és használatáról. A nyomkövető regisztereket a 38 ábra illusztrálja DR7 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 LEN 3 R/W 3 LEN 2 R/W 2 LEN 1 R/W 1 LEN 0 R/W 0 0 0 GD 0 0 1 GE LE G3 L3 G2 L2 G1 L1 G0 L0 DR6 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 BT BS BD 1 1 1 1 1 1 1 1 1 B3 B2 B1 B0 DR5 DR4 FENNTARTVA FENNTARTVA DR3 3. TÖRÉSPONT LINEÁRIS CÍME DR2 2. TÖRÉSPONT LINEÁRIS CÍME DR1 1. TÖRÉSPONT LINEÁRIS CÍME DR0 0. TÖRÉSPONT LINEÁRIS CÍME 3.8 ábra: Nyomkövető regiszterek 85 31 30 29
28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Általános CPU programozási információk 3.3 CPU üzemmódok 3.31 Valós üzemmód ("valós mód") Ez az üzemmód az Intel 8086 processzor programozási környezetét valósítja meg, biztosítva egy pár kiterjesztést (ilyen például az ebből a módból való kilépés lehetősége). A reszet általi inicializálás a processzort a valós üzemmódba állítja, melyből egyetlen utasítás segítségével átkapcsolható a védett módba. 3.32 Védett üzemmód Ez a processzor natív állapota. Ebben az üzemmódban az összes utasítás és architekturális jellemző elérhető, biztosítva a legnagyobb teljesítményt és képességeket. Minden új alkalmazás és operációs rendszer számára ez az ajánlott üzemmód. A védett mód által nyújtott lehetőségek közé tartozik 8086-ra írt "valós módú" software multitaszking, védett módú környezetben történő
közvetlen végrehajtása. Ennek a lehetőségnek a neve 8086-os virtuális mód (vagy "V86 mód"). A 8086-os virtuális mód valójában nem a processzornak egy üzemmódja, hanem egy attribútum, amelyet védett módban, megfelelő software segítségével, bármely taszk számára beállítható. 3.33Rendszermenedzselő üzemmód A Pentium mikroprocesszor a rendszermenedzselő üzemmmódot (SMM - System Management Mode) is támogatja. Minden új mikroprocesszorra (kezdve az 386 SL-től) jellemző az SMM, mely egy operációs rendszer- és alkalmazásfüggetlen, ezek számára transzparens mechanizmus. Ezen mechanizmus segítségével implementálhatók a rendszerteljesítményt menedzselő és OEM megkülönböztető funkciók. Az SMM-be való belépés egy külső megszakításvonal (az SMI#) 86 CPU üzemmódok aktiválásával történik, mely a CPU-t egy különálló címtartományra kapcsolja át, lementve a CPU teljes állapotát. Ennek következtében az
SMM-specifikus kód végrehajtása transzparens. Az SMM-ból való visszatéréskor az előző műveletek fordítottja hajtódik végre. 87 Általános CPU programozási információk 3.4 Inicializálás és az üzemmódok közötti átkapcsolás A hardware reszetet követően a processzor egy jólmeghatározott alapállapotba kerül annak érdekében, hogy megkezdhesse a software végrehajtását. Inicializáláskor a processzor a modell és revíziószámmal kapcsolatos információkat nyújt annak meghatározására, hogy milyen lehetőségek állnak a software rendelkezésére. Annak módját, ahogyan az alkalmazások a rendelkezésükre álló lehetőségeket futásidőben feltérképezik, egy későbbi fejezet tárgyalja, egy példa kíséretében. Ez a rész a processzor kezdeti állapotáról nyújt információkat és tárgyalja a valós és védett üzemmód konfigurálásának követelményeit, a két üzemmód közti átkapcsolás folyamatát, mely normális esetben
része az inicializáló folyamatnak. A védett üzemmódba való átkapcsolást egy példaprogram mutatja be. 3.41 A processzor inicializálása Az inicializálást a processzor RESET bemenete idézi elő. A RESET aktiválását követően a processzor egyes regiszterei egy jól meghatározott állapotba kerülnek. Ezek a meghatározott állapotok, mint például az EBP regiszter tartalma, elegendőek ahhoz, hogy a software végrehajtása megkezdődjön. A software ezek után felépítheti a memóriában az olyan adatstruktúrákat, mint például a GDT és IDT táblázatok, melyeket a rendszer- és az alkalmazói software-ek használnak. A RESET aktiválásakor a belső cache-ek, fordítást gyorsító pufferek (TLB-k) és elágazás célpufferek (BTB-k) működése letiltódik. A gép bekapcsolásakor a RESET jelet a hardware aktiválja. E jelet a hardware más esetekben is aktiválhatja; például a reszet általi inicializálás manuálisan is előidézhető, egy billentyűgomb
segítségével. Reszetelés lehet a hardware válasza akkor is, ha jelzést kap a futás felfüggesztésére vagy a kikapcsolásra. A Pentium processzornak egy INIT bemenete is van, mely a RESET-hez hasonlít, azzal a különbséggel, hogy nem változtatja meg a belső cache-ek és modell specifikus regiszterek állapotát, valamint a 88 Inicializálás és az üzemmódok közötti átkapcsolás lebegőpontos állapotot. Az INIT lehetőséget nyújt a védettből a valós üzemmódba való átkapcsolásra úgy, hogy a cache-ek tartalma megmarad. Az INIT aktiválásakor a TLB-k és a BTB letiltódnak. 3.411 A processzor állapota reszetelés után Bekapcsoláskor öntesztelés kérhető; az önteszt-kérés megvalósítása a hardware-tervező feladata, amennyiben az öntesztre szükség van. Az önteszt elvégzése körülbelül 219 órajelnyi időt igényel (Az órajelek előbb említett száma modell-specifikus, ezért az Intel fenntartja a jogot magának az órajelek pontos
számának bejelentés nélküli megváltoztatására.) A processzorteszt hibamentes lefolyását követően az EAX regiszter tartalma nulla lesz. Ha a teszt után az EAX regiszterben nullától különböző érték van, ez azt mutatja, hogy a processzor hibás. Ha nem volt önteszt kérve, inicializálás után az EAX regiszter tartalma nulla. Inicializálás után az EDX regiszter a processzor azonosítóját és a revíziójának számát tartalmazza (3.9 ábra) A DH regiszter a 3, 4 vagy 5 értékeket tartalmazza, melyek a Intel386, Intel486 illetve a Pentium CPUt azonosítják. E családok különböző alosztályainak esetében a DH-ban más értékek is lehetnek, például az Intel386 SX CPU esetében 23H. Ezt a számot az inicializáló software kiválasztására felhasználva a bináris tárgykód kompatibilissé tehető más Intel processzorokkal is. A DL regiszter a revízió egyedi azonosítószámát tartalmazza. Reszetelés után az EDX regiszter felső szava
fenntartott. EDX DX 31 15 FENNTARTVA 7 0 DH DL ESZKÖZ AZONOSÍTÓ EGYEDI AZONOSÍTÓ 89 Általános CPU programozási információk 3.9 ábra: Az EDX regiszter tartalma reszetelés után CR0 Reszetelés után 31 30 29 PG CD NW 0 - Lapozás tiltva 1 - Cache tiltva 1- Nem át-író tiltva 28 27 26 25 24FENNTARTVA 23 22 21 20 19 18 17 16 15 AM 0 - Illeszkedés ellenőrzés tiltva WP 0 - Írásvédettség tiltva 14 13 12 11FENNTARTVA 10 9 8 7 6 5 4 3 2 1 0 NE 1 TS EM MP PE 0 - Külső FPU hiba 0 - Nincs taszk váltás 0 - ESC műveleteknél nincs c 0 - WAIT műveleteknél nincs c 0 - Valós üzemmód 3.10 ábra: A CR0 regiszter tartalma reszetelés után 90 Inicializálás és az üzemmódok közötti átkapcsolás A Pentium processzor üzembe helyezését követően a CR0 regiszter állapotát a 3.10 ábra mutatja (60000010H) Ez az állapot a processzort valós üzemmódba állítja és kikapcsolja a lapozást. A flagek és egyéb regisztereknek az
üzembehelyezés utáni állapotát a 3.11 ábra mutatja be. Regiszter EFLAG EIP CR0 CR2, CR3, CR4 CS SS, DS, ES, FS, GS EDX EAX EBX, ECX, ESI, EDI, EBP, ESP RESET - BIST nélkül 00000002h 0000FFF0h 60000010h 00000000h szelektor=0F000h bázis=0FFF0000h határ=0FFFFh elérési jogok vannak, írható, olvasható, hozzáférhrtő szelektor=0000h bázis=0000h határ=0FFFFh elérési jogok vannak, írható, olvasható, hozzáférhető 000005xxh hibátlan önteszt esetén nulla 00000000h INIT 00000002h 0000FFF0h A CD és NW biteket nem cseréli, a 4. bitet 1-be állítja, az összes többit törli. 00000000h szelektor=0F000h bázis=0FFF0000h határ=0FFFFh elérési jogok vannak, írható, olvasható, hozzáférhető szelektor=0000h bázis=0000h határ=0FFFFh elérési jogok vannak, írható, olvasható, hozzáférhető 000005xxh 0 00000000h 91 Általános CPU programozási információk LDTR GDTR, IDTR DR0, DR1, DR2, DR3 DR6 DR7 Time Stamp számláló Vezérlő és esemény
kiválasztó TR12 Minden más modell specifikus regiszter Adat és kód Cache, TLB-k szelektor=0000h bázis=00000000h határ=0FFFFh elérési jogok vannak, írható, olvasható bázis=00000000h határ=0FFFFh elérési jogok vannak, írható, olvasható 00000000h FFFF0FF0h 00000400h 0 0 szelektor=0000h bázis=00000000h határ=0FFFFh elérési jogok vannak, írható, olvasható bázis=00000000h határ=0FFFFh elérési jogok vannak, írható, olvasható 0 Nem definiált Nem cseréli Nem cseréli Érvénytelen Érvénytelen FFFF0FF0h 00000400h Nem cseréli Nem cseréli 3.11 ábra: A processzor állapota a reszetelést követően Az EFLAGS regiszter felső 10 bitjének állapota az üzembe helyezést követően meghatározatlan. A meghatározatlan bitek fenn vannak tartva, a software végrehajtása egyik említett bit állapotától sem szabad függjön. 3.412 Az első végrehajtott utasítás Egy cím generálásához a szegmensregiszter bázis része hozzáadódik a tényleges
címhez, kialakítva így a lineáris címet. Ez minden üzemmód esetében érvényes, habár a báziscím kiszámítása a védett módban másképp történik, mint a valós üzemmódban. Egy utasítás 92 Inicializálás és az üzemmódok közötti átkapcsolás beolvasásához a CS regiszter bázis része hozzáadódik az EIP tartalmához és így a kettő együtt meghatározza a lineáris címet. Valós üzemmódban, amikor a szegmensregiszter szelektorának tartalma megváltozik, akkor a bázis rész is megváltozik, ennek az értéknek a 16-szorosára. Reszetelés után azonban a CS bázisrésze másként viselkedik, nem lesz egyenlő 16-szor a szelektor értékével, ehelyett a CS szelektor értéke 0F000H és a CS bázisé 0FFFF0000H. A CS szelektor értékének a reszetelés utáni első megváltoztatása a fenti szabályt fogja követni (bázis = szelektor*16). Ennek eredményeképpen az első végrehajtandó utasítás beolvasása a CS.bázis+EIP = 0FFFFFFF0H
címről fog történni. Az EPROM-ban levő inicializáló kód ezen a címen kell elhelyezkedjen. A cím a Pentium processzor fizikai memóriájának legnagyobb címe alatt 16 Byte-tal van. Biztosítani kell, hogy az inicializálás befejezése előtt semmilyen távoli ugrás és hívás ne hajtódjon végre. Ha az első távoli ugrás vagy hívás valós üzemmódban történik, az új érték a (16 bites) CS szelektorba kerül és a CS bázisának értékét csak 20 bitesre fogja beállítani, vagyis a célként szereplő cím a 0 és 1M közti tartományban lesz. Ajánlatos meggyőződni arról, hogy ebben a tartományban érvényes memória és kód van-e. Az adatszegmensek számára a báziscím a fizikai címtartomány aljára (0 cím) állítódik, ahol a várhatóan a RAM helyezkedik el. 3.413 A cache engedélyezése A cache engedélyezése a CR0 regiszter CD és NW bitjeinek törlésével történik (a hardware reszet 1-re állítja őket). Ez engedélyezi a cache-elést
(átíró módban az Intel486 és visszaíró módban a Pentium esetében) és a cache-letiltó ciklusokat. Mivel a reszet általi inicializálást követően minden cache-vonal érvénytelen, a cache-elés engedélyezése előtt nincs szükség a cache érvénytelenítésére. A cache kezelésének részletes leírását, beleértve az átíró cache-stratégia Pentium processzoron való megvalósítását a laptáblázat-bejegyzés PWT bitjének felhasználásával, egy későbbi tartalmazza. 93 Általános CPU programozási információk Olyan körülmények közt, amikor a cache-vonalak esetleg érvényesnek vannak megjelölve, a cache engedélyezése előtt a cache-t le kell tiltani vagy ki kell üríteni. Ezt a software-inicializálás alkalmával a megbízhatósági tesztet végző rutin segítségével oldható meg, mely a tesztregisztereket felhasználva, tesztmintákat futtat keresztül a cache memórián. A cache tesztelésének modell specifikus részletei a Pentium
TM Processor Data Book dokumentációban találhatók. 3.42 Software inicializálás valós üzemmódban A processzornak több üzemmódja van. A végrehajtást a Pentium a 8086 processzorral kompatibilis üzemmódban kezdi, melynek valós üzemmód a neve. A reszet általi inicializálás után a software elő kell készítse azokat az adatstruktúrákat, melyekre a processzornak szüksége van az olyan alapvető rendszerfunkciók végrehajtásának céljából, mint például a megszakítások kezelése. Ha a processzor továbbra is valós üzemmódban marad, a software az adatstruktúrák felépítését a 8086-os által használt alakban kell elvégezze. Ha a processzor védett módban fog működni, a software az adatstruktúrákat a védett módban használatos formátumban kell felépítse, majd át kell kapcsoljon a védett üzemmódba. 3.421 Rendszertáblázatok Valós üzemmódban nincs szükség deszkriptor táblázatra. A megszakítás deszkriptor táblázatot (IDT), mely
a 0 címen kezdődik (amíg az IDTR meg nem változik), a megszakítások engedélyezése előtt fel kell tölteni a kivétel- és megszakítás-kezelőkre mutató pointerekkel. 3.422 Az NMI megszakítás Az NMI megszakítás mindig engedélyezve van (kivéve az egymásba ágyazott NMI-ket). Mivel a megszakításvektorok táblázatát és az NMI megszakítás-kezelőt be kell tölteni a memóriába, a reszet általi inicializálást követően lesz egy olyan időszak, amikor az NMI 94 Inicializálás és az üzemmódok közötti átkapcsolás megszakítás nem kezelhető. A hardware-nek biztosítania kell egy olyan módszert, mely megelőzi az NMI megszakítások generálását, amikor azokat a software még nem tudja kezelni. Például az IDT és NMI megszakításokat bele lehet tenni a ROM-ba, így lehetségessé válik az NMI megszakítás kezelése már rögtön az inicializálás után. Legtöbb rendszer az NMI engedélyezését/letiltását úgy végzi el, hogy az NMI jelet
átvezeti egy ÉS kapun, melyet egy I/O port egyik bitje vezérel. A reszeteléskor a hardware törölheti ezt a bitet, majd a software újra beállíthatja, amikor már készen áll az NMI megszakítás kezelésére. A rendszer software-ek tervezőinek ismerniük kell a hardware által használt mechanizmust, mely a software-t a reszetelést követő NMI megszakításoktól védi. 3.43 Software inicializálása védett üzemmódban A védett módban szükséges adatstruktúrákat a felhasznált memóriakezelő funkciók határozzák meg. A processzor támogatja a különböző szegmentált modellek használatát, melyek az egyetlen, folyamatos címtartománytól (lapos modell) egészen a nagyon strukturált modellekig terjednek, melyek több, minden taszk számára független és védett címtartományt biztosítanak (multiszegmentált modellek). Engedélyezhető a lapozás, mely olyan nagyméretű adatstruktúrákhoz teszi lehetővé a hozzáférést, melyeknek részben a
memóriában, részben pedig a lemezen találhatók. A címképzés mindkét formája olyan adatstruktúrákat igényel, melyeket az operációs rendszer épít fel és a memóriakezelő hardware használ. 3.431 Rendszertáblázatok A lapozást nem használó lapos modellnek legkevesebb egy GDTre van szüksége, melyben legalább egy kód- és egy adatszegmens deszkriptor van. Az első GDT bejegyzés egy nulldeszkriptort kell tartalmazzon. Egy lapozást használó lapos modellnek kód- és adatdeszkriptorokat biztosíthat a felügyelői mód és egy másik csoport kód- és adatdeszkriptort a felhasználói mód számára. (Megjegyzés: a másodszintű laptáblázat kiküszöbölhető, ha a lapcímtár egy önmagára 95 Általános CPU programozási információk mutató bejegyzést tartalmaz. Ez esetben a lapcímtár és a laptáblázat ugyanazon a lapon helyezkedik el.) A verem helyezhető egy normális írható/olvasható adatszegmensbe is, akkor a verem részére nincs
szükség deszkriptorra. A verem csak azután használható, miután a LDTR utasítás segítségével a GDT báziscíme és határa betöltődött a GDTR regiszterbe. A multiszegmentált modell esetében az operációs rendszer számára további szegmensekre, valamint az alkalmazások számára szegmensekre és LDT-ra lehet szükség. Az LDT-k szegmensdeszkriptorokat igényelnek a GDT-ben. Egyes operációs rendszerek szükség esetén újabb szegmenseket és LDT-ket foglalnak le. Ez maximális rugalmasságot biztosít az olyan dinamikus programozási környezetek kezelésében, mint például egy tervezői munkaállomás. Ennek ellenére számos operációs rendszer egyetlen LDT-t használ az összes folyamat számára és a GDT bejegyzéseket előre lefoglalja. Egy beágyazott rendszer, mint például egy folyamatvezérlés, rögzített számú alkalmazói program számára előre le kell foglaljon egy meghatározott számú LDT-t. Ez egy egyszerű és hatékony mód egy olyan
rendszer software-környezetének struktúrálására, mely valós idejű teljesítményt igényel. 3.432 Megszakítások Ha a hardware megengedi a megszakítások generálását, a megszakítás kezelő számára létre kell hozni egy IDT-t és egy kaput. Az IDT csak azután használható, miután a LIDT utasítás segítségével az IDT báziscíme és határa betöltődött az IDTR regiszterbe. 3.433 Lapozás A szegmentációtól eltérően a lapozást egy módbit vezérli. Ha a CR0 regiszter PG bitje nulla (a reszet általi inicializálás utáni állapota pontosan ez), akkor a programozó által elérhető processzor architektúrából a lapozási mechanizmus teljes mértékben hiányozni fog. 96 Inicializálás és az üzemmódok közötti átkapcsolás Ha PG bit értéke 1, akkor engedélyezve van a lapozás. A bitet a MOV CR0 utasítással lehet beállítani. A bit beállítása előtt a következő feltételeknek kell teljesülniük: 1. A software létrehozott már
legkevesebb két laptáblázatot, a lapcímtárat és 4 kByte-os lapok használata esetén legkevesebb egy másodszintű laptáblázatot. A 4 MByte-os lapokkal kapcsolatos információk a függelékben találhatók. 2. A PDBR regiszterbe (mely ugyanaz, mint a CR3) be van töltve a lapcímtár báziscíme. 3. A processzor védett módban van (a lapozás valós üzemmódban nem áll rendelkezésre). Ha minden más megszorítás teljesül, akkor a PG és PE bitek egyidejűleg 1-re állíthatók. Úgy a lefelé, mint a felfelé való kompatibilitás fenntartásának érdekében a PG bit (és a PE bit) beállításakor a következő irányelveket kell követni: 1. Közvetlenül a PG bitet beállító utasítás után egy JMP utasítás kell következzen. A MOV CR0 után következő JMP szerepe az, hogy a végrehajtás folyásának megváltoztatása által a 386 és 486 processzorokból kiürítse az addig beolvasott és dekódolt utasításokat. A Pentium processzor az elágazások
előrejelzésére egy elágazási célpuffert (BTB - Branch Target Buffer) használ, ezért szükségtelen az elő-beolvasási sor elágazási utasításokkal való kiürítése. A BTB-ről több információ a függelékben található 2. A PG bitet beállító utasítástól a JMP-ig terjedő kód egy identikusan leképezett lapon kell elhelyezkedjen (a lap JMP előtti lineáris címe megegyezik a lapozás engedélyezése utáni fizikai címével). A 32 bites x86 architektúrák a lapozás engedélyezését és a védett módba való átkapcsolását különbözőképpen valósítják meg. A 386 esetében a fenti 1. vagy 2 lépés végrehajtása szükséges A 486 esetében mindkét lépést el kell végezni. A Pentium csak a 2 lépés elvégzését 97 Általános CPU programozási információk igényli de a 386 és 486 processzorokkal a lefelé illetve felfelé való kompatibilitás megtartása érdekében ajánlatos mindkét lépést elvégezni. 3.434 Taszkok Ha a
multitaszking mechanizmus nincs használatban és a nagyobb privilégiumú szintekre való átváltás nincs engedélyezve, akkor nincs szükség a TR regiszter inicializására. Ha a multitaszking mechanizmus használatban van és a nagyobb privilégiumszintekre való átváltás engedélyezve van (a magasabb privilégiumú SS és ESP értékei a TSS-ből kaphatók meg), az inicializáló software számára létre kell hozni a TSS-t és a TSS deszkriptort. A TSS deszkriptor, létrehozásakor, nem lehet foglaltnak jelölve; a TSS deszkriptorokat a taszkátkapcsolások végrehajtásának mellékhatásaként a CPU szokta foglaltnak megjelölni. Az LDT deszkriptorjaihoz hasonlóan a TSS deszkriptorjai is a GDT-ben vannak. Az inicializáló software TSS deszkriptorja az LDT utasítás segítségével töltődik a TR regiszterbe. Ez az utasítás a TSS deszkriptort foglaltként jelöli meg, de nem hajt végre taszkátkapcsolást. Mielőtt a software az első taszkátkapcsolást végezné,
be kell tölteni a szelektort, mivel az átkapcsolás alkalmával az aktuális taszk bemásolódik a TSS-be. Az LTR utasítás használata után a taszkátkapcsolás további műveleteket hajt végre a TR regiszteren. Az LDT szegmensekhez hasonlóan a TSS-ek és TSS deszkriptorok is szükség esetén lefoglalhatók, illetve előre lefoglalhatók. Ha a magasabb privilégiumszintekre való átváltás engedélyezve van, akkor szükség van a TSS-ek és TSS deszkriptorok létrehozására. A processzor a TSS-t arra használja, hogy a vezérlésnek magasabb privilégiumszintű szegmensekre való átadásakor megszerezze a veremszegmens szelektorát és veremmutatóját. 98 Inicializálás és az üzemmódok közötti átkapcsolás 3.435 A TLB, BTB és cache tesztelése A védett módba való átkapcsolás folyamatának részeként a programozó ha úgy akarja, tesztelheti a TLB-t, a BTB-t és a cache-t. Részletes információkat a tesztelésről a függelék tartalmaz. 3.44
Üzemmódváltás A 32 bites címtartomány és utasításkészlet teljes kihasználása érdekében a processzort a natív valós üzemmódjából át kell kapcsolni védett üzemmódba. Egy rendszer szükségesnek tarthatja azt is, hogy egyes műveletek esetében visszaváltson a valós üzemmódba. Ez a rész azokat a lépéseket azonosítja, melyeket a software el kell végezzen ahhoz, hogy valósból védettbe és védettből valós üzemmódba váltson át. 3.441 Átkapcsolás védett módba A védett módba kapcsolás előtt létre kell hozni egy minimális számú adatstruktúrát és az előző részekben tárgyaltak szerint inicializálni kell a GDT, IDT és TR regisztereket. E táblázatok létrehozása után a software elvégezheti a védett módba való átkapcsolás lépéseit. A védett módba való belépés a CR0 regiszter PE bitjének 1-re állításával történik; erre a MOV CR0 utasítás használható. A PE bit beállítása során is ugyanazokat az
irányelveket kell követni, melyeket az előző rész tárgyalt a lapozás engedélyezése kapcsán. A védett módba való belépés után a szegmensregisztereknek továbbra is ugyanaz a tartalmuk, ami a valós üzemmódban volt; a software minden szegmensregisztert újra fel kell töltsön. A végrehajtás a védett módban nulla értékű CPL-lel kezdődik. 99 Általános CPU programozási információk 3.442 Visszakapcsolás valós üzemmódba Ha a software egy MOV CR0 utasítással törli a CR0 regiszter PE bitjét, a processzor visszatér a valós üzemmódba. A valós üzemmódba való visszatérést lebonyolító procedúra a következőképpen kell eljárjon: 1. Ha a lapozás engedélyezve van, a következőket végzi: A vezérlést identikusan leképezett lineáris címekre adja át (a lineáris cím megegyezik a fizikai címmel). Biztosítja, hogy a GDT és az IDT is identikusan leképezett legyen. A CR0 regiszter PG bitjét törli. Törli a TLB-t
azáltal, hogy nullázza a CR3 regisztert. 2. A vezérlést egy olyan szegmensre adja át, melynek határa 64K (0FFFFH). Ez betölti a CS regiszterbe a szegmenshatárt, melyre a valós módban szükség van. Biztosítja, hogy a GDT és az LDT a valós módban címezhető memóriában legyenek (0-1M). 3. Az SS, DS, ES, FS és GS szegmensregiszterekbe betölti a valós módnak megfelelő, a következő értékeket tartalmazó deszkriptorok szelektorjait: Szegmenshatár = 64K (0FFFFH) Byte granularitás (G=0) Kiterjesztés felfele (E=0) Írható (W=1) Jelen van (P=1) Bázis = bármilyen érték Megjegyzendő, hogy ha nem történik meg a szegmensregiszterek újrafeltöltése, akkor a végrehajtás a védett módban betöltött deszkriptorok felhasználásával folyik tovább. 4. 100 Letiltja a megszakításokat. A CLI utasítás letiltja az INTR vonalon érkező megszakításokat; az NMI megszakítások külső áramkörök segítségével tilthatók le.
Inicializálás és az üzemmódok közötti átkapcsolás 5. Törli a CR0 regiszter PE bitjét. 6. A JMP utasítás segítségével a valós módú programra ugrik. Így (a 386 és 486 processzorok esetében) kiürül az utasítássor és a megfelelő értékek a CS regiszter hozzáférési jog bitjeibe kerülnek. A Pentium processzornál erre a lépésre nincs szükség, azonban a lefele való kompatibilitás érdekében a valós üzemmódba való áttérés folyamatába ajánlatos elhelyezni egy távoli JMP utasítást. 7. A valós címzési mód a megszakításvektor-táblázat bázisának és határának betöltésére a LIDT utasítást használja. 8. Engedélyezi a megszakításokat. 9. A szegmensregiszterekbe betölti a valós címzési mód által igényelt értékeket. 3.45 Példa inicializálásra és üzemmód átkapcsolásra Ez a rész az inicializálásara és üzemmódváltásra olyan példát mutat be, amelyik belefoglalható a felhasználó által írt
alkalmazásba. Ugyanitt információk találhatók a felhasznált Intel fejlesztőeszközökről, vagyis az ASM386/486 assemblerről és a BLD386 builder-ről. 3.451 A példa célja E példa célja az, hogy rögtön a reszet után az EPROM-ban vagy flash-memóriában levő kódot felhasználva átkapcsolja a CPU-t védett üzemmódba, majd egy egyszerű alkalmazást futtasson. 101 Általános CPU programozási információk 2.452 A memória elrendezése a reset-elést követően Az előbbiekben tárgyaltak és a 3.11 ábra alapján, a 312 ábra a memória elrendezését mutatja a processzor reszetelését követően és e példa kezdeti pontján. RESZET UTÁN 0FFFF FFFFh [CS.Bázis+EIP] 0FFFF FFF0h 64K EIP=0000 FFF0 CSbázis=0 0FFFF 0000h EPROM DSbázis=0 ESbázis=0 SSbázis=0 SP=0 [SP, DS, SS, ES] 0 3.12 ábra: A processzor állapota a reszetet követően 3.453 Az algoritmus A példa főbb lépéseit a 3.13 ábra mutatja, a STARTUPASM forrásszöveg sorainak
számozásával együtt. ASM sorok Meghatározás 157 Rövid ugrás az EPROM belépési pontjára 162-169 Felépít a RAM-ban egy ideiglenes GDT-t egy bejegyzéssel: 0. null 1. irható/olvasható adat szegmens, Bázis=0 határ=4 GByte 102 Inicializálás és az üzemmódok közötti átkapcsolás 171-172 174-177 179-181 184-186 188-195 196-218 220-238 241-243 244-245 247-261 263-267 277 282-286 287 288 289 290-293 296 A GDT pointerét a GDTR regiszterbe tőlti. A CR0 regiszter védet üzemmód bitjének beállítása. Közeli ugrás a valód módot törlő sorra. DS és ES regiszterek feltöltése a GDT[1] deszkriptorral, most mindkettő a teljes fizikai memória területre mutat. Végrehajt egy specifikus tábla inicializálást amire az új védett mód miatt van szükség. Az alkalmazás GDT-jét a ROM-ból a RAM-ba másolja Az alkalmazás IDT-jét a ROM-ból a RAM-ba másolja Az alkalmazás GDTR regiszterének feltöltése Az alkalmazás IDTR regiszterének feltöltése Az
alkalmazás TSS-ét a ROM-ból a RAM-ba másolja A TSS deszkriptor felfrissítése. TR regiszter feltöltése (taszkválltás nélkül) SS és ESP feltöltése az alkalmazásban talált TSS értékekkel. Az alkalmazás TSS-ében talált EFLAG elmentése Az alkalmazás TSS-ében talált CS elmentése Az alkalmazás TSS-ében talált EIP elmentése DS és ES feltöltése az alkalmazásban talált TSS értékekkel. Végrehajt egy IRET-et, visszatölti a fenti értékeket és belép az alkalmazás kódjába. 3.13 ábra: Az algoritmus és a forrásszöveg ezzel kapcsolatos sorainak száma Megjegyzések: A védett módba való átkapcsoláskor (a távoli ugrás vagy távoli hívás által) a CS szelektor nem változik meg és az eredeti bázisérték megmarad (Ha a reszet után nem volt távoli ugrás, a bázis értéke 0FFFF0000H marad; itt található az EPROM). 103 Általános CPU programozási információk A reszet után a megszakítások le vannak tiltva és úgy is kell
maradjanak, különben távoli ugrásokat okozhatnak. Az NMI nincs letiltva, de az inicializálás ideje alatt nem aktiválódhat. A TEMP GDT használata megengedi a tömbök egyszerű mozgatását az EPROM-ból bárhova a RAM területén belül. Egy GDT bejegyzés úgy van felépítve, hogy a bázis a 0 címre mutasson és a határ 4GB legyen. Ha a DS és ES regiszterekbe betöltődik ez a deszkriptor, a TEMP GDT-re nincs többé szükség és ennek helyét elfoglalhatja az alkalmazás GDT-je. Ez a kód egyetlen TSS-t (és egyetlen LDT-t sem) feltételez. Ha az alkalmazásnak több TSS-e van, ezeket a RAM-ba kell másolni. Ugyanígy kell eljárni az alkalmazás LDT-jeivel is. Egyes implementálásoknál a korai 8086 processzorok szimulálása érdekében az A20-A31 címvonalak reszet után nincsenek dekódolva. A védett módba való átkapcsolás során ajánlatos a dekódereket úgy beállítani, hogy az összes címvonalat dekódolják. 3.454 Eszközök használata A példa az
Intel software eszközeit (ASM386 és BLD386) használja. Az inicializáló kód generálására felhasznált ASM386 és BLD386 eszközei a következőket feltételezik: Az ASM 386 a kódszegmens attribútumának megfelelő, helyes operandusméretű opkódot fog generálni. Az attribútumot vagy az ASM386 segítségkérő vezérlője vagy a kódszegmens definíciója határozza meg. A kódszegmenset, mely valós üzemmódban fog futni, USE 16 attribútumúra kell állítani. Ha a szegmensben 32 bites operandusok (MOV EAX, EBX) kerülnek felhasználásra, egy automatikus operandusprefix fog generálódni, mely a processzort 104 Inicializálás és az üzemmódok közötti átkapcsolás a 32 bites műveletekre kényszeríti annak ellenére, hogy az alapértelmezésben szereplő kódszegmens attribútum 16 bites. Az Intel ASM386 assemblere megengedi a specifikus 16 és 32 bites utasítások használatát, ilyen például a a LGDTW, LGDTD, IRETD. Egy általános
utasítás (például LGDT) használata esetén a megfelelő opkód generálásához az assembler a alapértelmezésben szereplő szegmensattribútumot fogja felhasználni. Téma Bootstrap GDT elhelyezkedés IDT elhelyezkedés RAM kezdet ASM386 és Startup.A58 public startup startup: BLD386 vezérlő és BLD file bootstrap start(startup) Hatás Közeli ugrás a 0FFFFFFF0hnál a startra public TABLE A GDT GDT EPROM GDT(location elhelyezkedése a GDT EPROM = DGT EPROM TABLE REG <> GDT EPROM pozícióra lesz ) programozva. public TABLE Az IDT IDT EPROM IDT(location= elhelyezkedése IDT EPROM IDT EPROM) az IDT EPROM TABLE REG <> pozícióra lesz programozva. RAM START memory(reser A equ 400h v= RAM START a 0.3FFFh) tábla mozgatásokhoz a ramot használja célnak Ezért szükséges egy terület kizárása az alkalmazás szegmens területéből. 105 Általános CPU programozási információk Az alkalmazás TSS-ének elhelyezkedése a GDT-ben TSS INDEX equ TABLE
GDT 10 (ENTRY=(10: PROTECTED MODE TASK )) EPROM méret és Az inicializáló SEGMENT elhelyezkedés kód mérete és startup.code elhelyezhedése. (base=0FFFF0 000h) memory (RANGE( ROM AREA = ROM(x.y)) Az alkalmazás TSS deszkriptorát a GDT 10. pontjára teszi. Az inicializált kód mérete legfeljebb 64K és a 4GB-os memória felső 64K-s területén kell elhelyezkednie. 3.14 ábra: A BLD és az ASM forrásállomány közti összefüggés 3.455 A STARTUPASM listája A CPU-t védett módba kapcsoló kód forrásszövegét a 3-1 példa tartalmazza. Ez a lista semmilyen opkód vagy ofszettel kapcsolatos információt nem tartalmaz. 3-1 példa: STARTUP.ASM OBJECT MODULE: startup.obj ASM386.EXE startupa58 pw (132) Sor Forráskód 1 2 3 4 5 6 7 NAME STARTUP ; ; ; ;Előfeltételek: ; ;1. Az alsó 64K memória az RAM és a modul 106 Inicializálás és az üzemmódok közötti átkapcsolás 8 ; használhatja azt átmeneti területek létrehozásánál. 9 ; 10 ;2. A rendszernek
van elegendő szabadon 11 ; szabadon használható RAM-ja amibe bemásolható 12 ; a GDT, IDT, TSS kezdeti értékei 13 ; 14 ; 15 ;Konfigurációs adat, meg kell hogy egyezzen a build nyelv 16 ;file-al. 17 CS BASE EQU 0FFFF0000h 18 ; 19 ;A CS BASE a STARTUP CODE lineáris címe, ami a build 20 ;nyelv file-ban van megadva. 21 ; 22 RAM START EQU 400h 23 ; 24 ;A RAM START a szabadon használható RAM kezdete a 25 ;lineáris memória területen. A GDT, IDT és a kezdeti TSS 26 ;ezen hely fölé másolódnak és egy kis adatszegmenst is 27 ;kihagy ezen a lineáris címen. A RAM STARTnál lévő 32 28 ;bites szó tartalmazza a lemásolt táblázatok fölötti első 29 ;szabad Byte lineáris címét. Ez akkor hasznos, ha memória 30 ;managert használunk. 31 ; 32 TSS INDEX EQU 10 33 ; 34 ;A TSS index az indítás után elsőként futó taszk TSS-ének 35 ;indexe. 36 ; 37 ; 107 Általános CPU programozási információk 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 108 ; ; ; ;Szerkezet a rendszer adat számára ; ;TSS szerkezet TASK STATE STRUC link DW ? link h DW ESP0 DD ? SS0 DW ? SS0 h DW ESP1 DD ? SS1 DW ? SS1 h DW ESP2 DD ? SS2 DW ? SS2 h DW CR3 reg DD ? EIP reg DD ? EFLAGS REG DD EAX reg DD ? ECX reg DD ? EDX reg DD ? EBX reg DD ? ESP reg DD ? EBP reg DD ? ESI reg DD ? EDI reg DD ? ES reg DW ES h DW ? CS reg DW CS h DW ? SS reg DW SS h DW ? DS reg DW DS h DW ? FS reg DW FS h DW ? GS reg DW GS h DW ? ? ? ? ? ? ? ? ? ? ? ? Inicializálás és az üzemmódok közötti átkapcsolás 79 LDT reg DW ? 80 LDT h DW ? 81 TRAP reg DW ? 82 IO map base DW ? 83 TASK STATE ENDS 84 ; 85 ;A deszkriptor elemi szerkezete 86 DESC STRUC 87 lim 0 15 DW ? 88 bas 0 15 DW ? 89 bas 16 23 DW ? 90 acces DB ? 91 gran DB ? 92 bas 24 31 DB ? 93 DESC ENDS 94 ; 95 ;Szerkezet az LGDT és LIDT utasítások részére 96 ;TABLE REG STRUC 97 table lim DW ? 98 tabla linear DD ? 99 TABLE REG ENDS 100 ;A GDT és IDT
deszkriptorok ofszetje a builder által generált 101 ;GDT-ben. 102 ;GDT DESC OFF EQU 1*SIZE (DESC) 103 ;IDT DESC OFF EQU 2*SIZE (DESC) 104 ; 105 ;Értékadások az átmeneti GTD felépítéséhez. 106 LINEAR SEL EQU 2*SIZE (DESC) 107 LINEAR PROTO LO EQU 00000FFFFh 108 LINEAR PROTO HI EQU 000CF9200h 109 ; 110 ;Védett mód engedélyező bit a CR0-ban 111 PE BIT EQU 1 112 ; 113 ;-----------------------------------------------------------------114 ; 109 Általános CPU programozási információk 115 ;----------------------ADAT SZEGMENS---------------------116 ; 117 ;Kezdetben ez az adatszegmens a lineáris 0 címen 118 ;kezdődik a CPU bekapcsolási állapota miatt. 119 ; 120 STARTUP DATA SEGMENT RW 121 ; 122 free mem linear base LABEL DWORD 123 TEMP GDT LABEL BYTE 124 TEMP GDT NULL DESC DESC <> 125 TEMP GDT LINEAR DESC DESC <> 126 ; 127 ;Átmeneti terület az LGDT és a LIDT utasítások számára. 128 TEMP GDT SCRATCH TABLE REG <> 129 APP GDT RAM TABLE REG
<> 130 APP IDT RAM TABLE REG <> 131 ; 132 FILL DW 133 ; 134 ;Az utolsó dolog a szegmensben ami szükséges dword illeszkedéshez. 135 end data LABEL BYTE 136 ; 137 STARTUP DATA ENDS 138 ;--------------------------------------------------------139 ; 140 ; 141 ;--------------------------------------------------------142 STARTUP CODE SEGMENT ER PUBLIC USE16 143 ; 144 ;A builder álltal feltöltve 145 PUBLIC GDT EPROM 146 GDT EPROM TABLE REG <> 147 ; 110 Inicializálás és az üzemmódok közötti átkapcsolás 148 ;A builder álltal feltöltve 149 PUBLIC IDT EPROM 150 IDT EPROM TABLE REG <> 151 ; 152 ;Belépési pont a STARTUP kódba a bootoláskor egy rövid ugrás 153 ;segítségével ide adódik át a vezérlés. Ennek a lineáris memória felső 154 ;64K-jában kell lennie. 155 ; 156 PUBLIC STARTUP 157 STARTUP: 158 ; 159 ;DS és ES a lineáris memória alsó 64K-ját címzi. 160 ASSUME DS:STARTUP DATA, ES:STARTUP DATA 161 ;Lásd a 3-15 ábrát. 162 ;A
GDTR regiszter feltöltése az átmeneti GDT-vel. 163 LEA EBX,TEMP GDT ;Felépíti a TEMP GDT-t az alsó memóriában. 164 MOV DWORD PTR [EBX],0 ;ahol címecni tudjuk. 165 MOV DWORD PTR [EBX]+4,0 166 MOV DWORD PTR [EBX]+8,LINEAR PROTO LO 167 MOV DWORD PTR [EBX]+12,LINEAR PROTO HI 168 MOV TEMP GDT scratch.table linear,EBX 169 MOV TEMP GDT scratch.table lim,15 170 ; 171 DB 66h ;32 bites LGDT végrehajtás 172 LGDT TEMP GDT scratch 173 ; 174 ;Belépés védett módba. 175 MOV EBX,CR0 176 OR EBX,PE BIT 177 MOV CR0,EBX 178 ; 179 ;Törli az utasítás előolvasó sort 180 JMP CLEAR LABEL 181 CLEAR LABEL: 111 Általános CPU programozási információk 182 ; 183 ;Elkészíti az új DS, ES regisztereket, amik a 4G-s tartományt címzik. 184 MOV CX,LINEAR SEL 185 MOV DS,CX 186 MOV ES,CX 187 ; 188 ;Elvégzi a tábla specifikus beállításokat. 189 ; 190 ; 191 ; . 192 ; 193 ; 194 ; 195 ;Lásd a 3.16 ábrát 196 ;Az EPROM GDT-t a RAM-ba másolja a 197 ;RAM START+size(STARTUP DATA) címre.
198 MOV EAX,RAM START 199 ADD EAX,OFFSET (end data) 200 MOV EBX,RAM START 201 MOV ECX,CS BASE 202 ADD ECX,OFFSET (GDT EPROM) 203 MOV SI,[ECX].table linear 204 MOV EDI,EAX 205 MOVZX ECX,[ECX].table lim 206 MOV APP GDT RAM[EBX].table lim,CX 207 INC EXC 208 MOV EDX,EAX 209 MOV APP GDT ram[EBX].table linear,EAX 210 ADD EAX,ECX 211 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] 212 ; 213 ;A GDT bázicímének rögzítése a deszkriptorban. 214 MOV ECX,EDX 215 MOV [EDX[.bas 0 15+GDT DESC OFF,CX 216 ROR ECX,16 217 MOV [EDX[.bas 16 23+GDT DESC OFF,CL 218 MOV [EDX[.bas 24 31+GDT DESC OFF,CH 219 ; 112 Inicializálás és az üzemmódok közötti átkapcsolás 220 ;Az EPROM IDT RAM-ba másolása a 221 ;RAM START+size(STARTUP DATA)+SIZE címre. 222 MOV ECX,CS BASE 223 ADD ECX,OFFSET (IDT EPROM) 224 MOV SI,[ECX].table linear 225 MOV EDI,EAX 226 MOVZX ECX,[ECX].table lim 227 MOV APP IDT RAM[EBX].table lim,CX 228 INC EXC 229 MOV APP IDT ram[EBX].table linear,EAX 230 MOV EBX,EAX 231 ADD EAX,EXC 232
REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] 233 ; 234 ;Az IDT mutató rögzítése a GDT-ben. 235 MOV [EDX[.bas 0 15+IDT DESC OFF,BX 236 ROR EBX,16 237 MOV [EDX[.bas 16 23+IDT DESC OFF,BL 238 MOV [EDX[.bas 24 31+IDT DESC OFF,BH 239 ; 240 ;GDTR és IDTR regiszterek feltöltése 241 MOV EBX,RAM START 242 DB 66h 243 LGDT APP GDT ram[EBX] 244 DB 66h 245 LIDT APP IDT ram[EBX] 246 ; 247 ;A TSS mozgatása 248 MOV EDI,EAX 249 MOV EBX,TSS INDEX*SIZE(DESC) 250 MOV ECX,GDT DESC OFF 251 MOV GS,CX 252 MOV DH,GS:[EBX].bas 24 31 253 MOV DL,GS:[EBX].bas 16 23 254 ROL EDX,16 255 MOV DX,GS:[EBX].bas 0 15 256 MOV ESI,EDX 257 LSL ECX,EBX 258 INC ECX 259 MOV EDX,EAX 113 Általános CPU programozási információk 260 ADD EAX,ECX 261 REP MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI] 262 ; 263 ;A TSS pointer rögzítése. 264 MOV GS:[EBX[.bas 0 15+IDT DESC OFF,DX 265 ROR EDX,16 266 MOV GS:[EBX[.bas 16 23+IDT DESC OFF,DL 267 MOV GS:[EBX[.bas 24 31+IDT DESC OFF,DH 268 ROL EDX,16 269 ;Elmenti a szabad
memória kezdőcímét RAM START helyzetben. 270 MOV free mem linear base+RAM START,EAX 271 ; 272 ;Feltételezzük, hogy a kezdeti taszkban nem használnak LDT-t - ha 273 ;szükséges, hozzáadhatunk egy LDT-t mozgató kódot, aminek 274 ;hasonlítania kell arra amit a TSS mozgatására használtunk. 275 ; 276 ;TR betöltése. 277 LTR BX ;Nincs taszkválltás, csak deszkriptor betöltés. 278 ;Lásd a 3.17 ábrát 279 ;A taszkválltás szimulálásához szükséges regiszterek betöltése. 280 ; 281 ; 282 ; 283 MOV AX,[EDX].SS reg 284 MOV EDI,[EDX].ESP reg 285 MOV SS,AX 286 MOV ESP,EDI 287 PUSH DWORD PTR [EDX].EFLAGS reg 288 PUSH DWORD PTR [EDX].CS reg 289 PUSH DWORD PTR [EDX].EIP reg 290 MOV AX,[EDX].DS reg 291 MOV BX,[EDX].ES reg 292 MOV DS,AX 293 MOV ES,BX 114 Inicializálás és az üzemmódok közötti átkapcsolás 294 ; 295 ;Egy távoli ugrás szimulálása a taszk inicializálásához. 296 IRETD 297 ; 298 STARTUP CODE ENDS 299 ; 300 END STARTUP, DS:STARTUP DATA, SS:STARTUP
DATA 3.456 A MAINASM forráskódja A 3-2 példában bemutatott MAIN.ASM állomány definiálja az adat- és veremszegmenseket az alkalmazás számára. Ez a rész helyettesíthető egy magasszintű nyelvben írt taszk fő moduljával, melyet a STARTUP.ASM-ban szereplő IRET utasítás hív meg 3-2 példa: MAIN.ASM 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 NAME DATA DW DATA ; STACK ; CODE main start: nop nop nop ; CODE ; END main module SEGMENT RW 1000 dup (?) ENDS STACKSEG 800 SEGMENT ER USE32 PUBLIC ENDS main start, ds:data, ss:stack 115 Általános CPU programozási információk 0FFFF FFFFh START: [CSBASE+EIP] 0FFFF 0000h -Közeli ugrás a startra -TEMP GDT felépítése -LGDT -Védett mód átkapcsolása DS, ES=GDT[1] 4GB BASE LIMIT GDT [1] BASE=0, LIMIT=4G GDT [0] 0 GDT SCRATCH TEMP GDT 3.15 ábra: A TEMP GDT létrehozása és a védett módba való átkapcsolás (a forrásszöveg 162-172 sorai) 0FFFF FFFFh -GDT, IDT, TSS ROM-ból RAM-ba mozgatása
-Másolatok rögzítése -LTR TSS IDT GDT TSS RAM IDT RAM GDT RAM RAM START 0 116 Inicializálás és az üzemmódok közötti átkapcsolás 3.16 ábra: A GDT, IDT és TSS ROM-ból RAM-ba másolása (a forrásszöveg 196-261 sorai) SS=TSS.SS ESP=TSS.ESP PUSH TSS.EFLAG PUSH TSS.CS PUSH TSS.EIP ES=TSS.ES DS=TSS.DS IRET EIP EFLAGS ESP ES CS SS DS GDT TSS RAM IDT RAM IDT ALIAS GDT ALIAS GDT RAM RAM START 0 3.17 ábra: Átkapcsolás a taszkra (a forrásszöveg 282 296 sorai) 3.457 Állományok támogatása A STARTUP.ASM és MAINASM forráskód állományok lefordítását és a végső alkalmazás létrehozását 3-3 példában mutatott parancsköteg állomány segítségével lehet elvégezni. 117 Általános CPU programozási információk ASM386 STARTUP.ASM ASM386 MAIN.ASM BLD386 STARTUP.OBJ, (EPROM.BLD) bootstrap Bootload MAIN.OBJ buildfile (STARTUP) 3-3 példa: Az alkalmazás lefordítására és felépítésére szolgáló parancsköteg-állomány E példában
a BLD386-nak több szerepe is van: A szegmensek és táblázatok számára fizikai memóriát foglal le. A bemeneti állományok és a felépítés módjának leírását tartalmazó (úgynevezett "build") állomány alapján felépíti a táblázatokat. Linkeli a tárgy állományokat és rendezi a referenciákat. Bootolható és EPROM-ba programozható állományt generál. A 3-4 példa a felépítés módjának leírását tartalmazó állományt mutatja be, melynek alapján a BLD386 a fentebb felsorolt műveletek végzi el. 3-4 példa: Build-állomány INIT BLD EXAMPLE; SEGMENT *SEGMENTS (DPL=0) , startup.startup code (BASE=0FFFF0000h) ; TASK BOOT TASK INITIAL, DPL=0, (OBJECT=startup, NOT INTENABLED) , DPL=0, 118 PROTECTED MODE TASK (OBJECT=main module, Inicializálás és az üzemmódok közötti átkapcsolás NOT INTENABLED) ; TABLE GDT ( , , , , , , LACATION=GDT EPROM ENTRY=( 10: (PROTECTED MODE TASK startup.startup code startup.startup data
main module.data main module.code main module.stack ) ), IDT ( LOCATION=IDT EPROM ); MEMORY ( RESERVE=(0.3FFFH -- terület a romból másolt IDT, GDT, TSS számára. ROM , 60000h.0FFFEFFFFH) , RANGE=(ROM AREA=ROM (0FFFF0000h.0FFFFFFFFh)) -- Eprom méret 64K , RANGE=(ROM AREA=RAM (4000h.5FFFFh)) ); END 119 Általános CPU programozási információk 3.5 A valós üzemmód felépítése, működése A Pentium processzor valós üzemmódban képes futtatni a 8086os, 8088-as, 80186-os és a 80188-as processzorokra, illetve az Intel 286, Intel 386, Intel 486-os processzorok valós üzemmódjaira írt programokat. Ebben az üzemmódban a processzor felépítése megközelítőleg azonos a 8086, 8088, illetve 80188-as processzorokéval. A programozó számára a valós üzemmódban dolgozó 32 bites proceszszor egy gyors 8086-os, vagy egy valós üzemmódú, bővített utasításkészletű Intel 286-os processzornak tűnhet. Ebben a részben bizonyos kiegészítő fogalmakról esik majd
említés, amelyek az operációs rendszer programozók valós üzemmódról alkotott képét hivatottak kibővíteni, mint például : címek képzése megszakítások és kivételek kezelése valós üzemmódú kivételek. 3.51 Címek lefordítása Valós üzemmódban a processzor a szelektorokat nem deszkriptorok mutatójaként értelmezi, hanem lineáris címeket állít elő, akárcsak egy 8086-os. A szelektort négy bittel balra forgatva képezi a 20 bites báziscímet. Az effektív (ofszet) cím négy 0-s bittel egészítődik ki a felső helyértékű bitek fölött, és a báziscímmel összeadódva alkotja a lineáris címet, ahogyan azt a 3.18 ábra szemlélteti Minthogy fenn áll az átvitel (carry) lehetősége, a keletkezett lineáris címeknek 21 szignifiáns bitje lehet. Egy 8086-ra írt program a 0-tól 10FFEFh-ig terjedő (1 MByte és megközelítőleg 64 kByte-nyi) lineáris címtartomány bármely lineáris címét előállíthatja. ( Ugyanakkor
megjegyzendő, hogy az Intel 486-os illetve Pentium processzorok esetében az A20M# jel valós üzemmódban felhasználható az A20-as címvonal maszkolására, utánozva ezáltal a 8086-os processzor 20 bitet átfogó viselkedését). Minthogy a lapozás valós üzemmódban nem megengedett, a lineáris cím fizikai címként kerül felhasználásra. 120 A valós üzemmód felépítése, működése 20 16 bites Szegmens szelektor 4 BÁZIS 16 bites effektív cím + 20 OFSZET 0 00 00 4 0 4 0 00 0 0 = 20 LINEÁRIS CÍM XX XX XX XX XX XX XX XX XX XX 3.18 ábra: Címek lefordítása Ellentétben a 8086-os és 286-os processzorokkal, akárcsak a 386os illetve 486-os processzorok, a Pentium képes 32 bites effektív címek előállítására egy cím-fölülíró prefix segítségével. Ugyanakkor valós üzemmódban a 32 bites címek értéke nem haladhatja meg a 65535-öt anélkül, hogy egy kivételt ne okozna. A 286-os valós üzemmódjával való teljes kompatibilitás
érdekében pszeudo védelmi hibák (12-es vagy 13-as, hibakód nélküli megszakítások) jelentkeznek, ha egy effektív cím a 0-tól 65535-ig terjedő tartományon kívül esik. 3.52 Regiszterek és utasítások A valós üzemmódban érvényes regiszter szett magába foglalja az összes 8086-os processzor esetében definiált regisztert és ezenfelül, a 386-os processzornál és 387-es koproceszszornál bevezetett új regisztereket: FS, GS, nyomkövető regiszterek, kontroll regiszterek, teszt regiszterek és a lebegőpontos egység (NDP) regiszterei. Új utasítások jelentek meg, amelyek expliciten az FS illetve GS szegmensregiszterekkel hivatottak műveleteket végezni, ezenkívül használhatók az új szegmensfölülíró prefixek is annak érdekében, hogy a címek kiszámításához az utasításokat késztetni lehessen az FS és GS regiszterek használatára. 121 Általános CPU programozási információk Érvénytelen utasítás (invalid-opcode) kivételt
előidéző utasítás kódok közé azon védett üzemmódú utasítások tartoznak, amelyek védett üzemmódú szegmens szelektorokat illetve szegmens deszkriptorokat mozgatnak vagy tesztelnek, mint például: a VERR, VERW, LAR, LSL, LTR, STR, LLDT, és az SLDT utasítások. A valós üzemmódban futó programok képesek kihasználni azon új, alkalmazás-orientált utasítások előnyeit, amelyek a 8086-os, 80186-os, 80188-as, 286-os, 386-os, 486-os illetve Pentium processzorok bevezetésével egészítették ki az architektúrát. Ellentétben a 8086-os és 286-os processzorokkal, hasonlóan a 386-os illetve 486-os processzorokhoz, a Pentium felkínálja egy operandus hossz fölülíró prefix használatának lehetőségét, amely lehetővé teszi 32 bites operandusok hozzáférését. Ennek ellenére ezen prefix használatától óvakodjunk, ha célunk a 8086-os vagy 286-os processzorokkal való kompatibilitás megőrzése. 2.53 Megszakítás és kivétel kiszolgálás Valós
üzemmódban a megszakítások és kivételek nagyjából úgy működnek, mint egy 8086-os processzoron. A megszakítások és kivételek megszakítás kezelő rutinokat hívnak meg egy megszakításvektor táblázaton keresztül. A processzor néggyel beszorozza a megszakítás vagy kivétel azonosítóját, hogy megkapja a megfelelő indexet a megszakításvektorok táblázatában. A megszakításvektorok táblázatának bejegyzései "far" (távoli) típusú mutatók a megszakítást vagy kivételt kiszolgáló procedúrák bemenőpontjaira. Egy megszakítás megjelenésekor a processzor eltárolja a CS, illetve IP regiszterek aktuális értékét a verembe (push), letiltja a megszakításokat, törli a TF flaget és átadja a vezérlést a megszakítás-vektorok táblázatából kiolvasott címre. A kiszolgáló rutin végén egy RET utasítás visszapörgeti az előbbi lépéseket, mielőtt a megszakított eljárásnak visszaadná a vezérlést. A kivételek valós
üzemmódban nem szolgáltatnak hibakódokat. Az elsődleges különbség a valós üzemmódú 32 bites processzorok és a 8086-os megszakításkezelése között az, hogy a megszakításvektorok táblázatának helye és mérete az IDTR regiszter tartalmától függ. 122 A valós üzemmód felépítése, működése Általános esetben ez nem nyilvánvaló a programozó számára, mert egy reset inicializálást követően az IDTR regiszterben a bázis cím 0 és a határ értéke 3FF, ami kompatibilis a 8086-os processzorral. Ugyanakkor, valós üzemmódban a LIDT utasítást használhatjuk az IDTR regiszterbeli báziscím illetve határ (limit) értékeinek megváltoztatására. További részleteket az IDTR regiszterről, valamint a LIDT és SIDT utasításokról az előbbi rész szolgáltat. Ha egy befutó megszakítás táblázatbeli bemenőpontja meghaladja az IDTR regiszter által tárolt határ értékét, egy kettős hiba kivételt (double-fault exception) eredményez.
3.54 Valós üzemmódú kivételek A processzor némely kivételt eltérő módon jelez attól függően, hogy valós vagy védett üzemmódban dolgozik-e. A 319 ábra a valós üzemmódú kizárásokat részletezi. Meghatározás Vekto r Osztási hiba Nyomkövetés NMI Töréspont Túlcsordulás Határ ellenörzés Hibás műveleti kód 0 1 2 3 4 5 6 Eszköz nem elérhető Dupla hiba 7 8 Fenntartva 9 A kivétel forrása Hibamutató pointer visszatérés után DIV és IDIV utasítások van Akármi (1.megj) Nem maszkolható megszakítás van INT utasítás nincs INTO utasítás nincs BOUND utasítás van Fenntartott műveletkódok és van helytelen LOCK prefix használat ESC vagy WAIT utasítások van Interrupt tábla túl kicsi, hiba van előfordulása egy másik hiba kezelése közben 123 Általános CPU programozási információk Érvénytelen TSS (3.megjegyzés) Szegmens nincs jelen (3.megjegyzés) Stack kivétel CS, DS, ES, FG, GS szegmens túlfutás Laphiba
(3.megjegyzés) Fenntartva Lebegőpontos hiba Illeszkedés ellenörzés (3.megjegyzés) Fenntartva Software megszakítás Maszkolható megszakítás 10 11 12 13 14 JMP, CALL, IRET utasítások, megszakításik és kivételek Akármilyen művelet, amelyik cseréli a szegmenseket Stack ofszet túl nagy Ofszet túlnyúlik a 64K-s határon, kód végrehajtási kísérlet a CS határán túl Akármilyen művelet, amelyik hivatkozik a memóriára 15 16 ESC vagy WAIT utasítások 17 Akármilyen adat hivatkozás 18-31 0-255 INT n utasítások 32-255 van van van van van van van (2.megj) nincs nincs van 3.19 ábra: Kivételek és megszakítások Megjegyzések: 1. Egyes nyomkövető kivételek a hibát okozó utasításra mutatnak, mások az azt követő utasításra. A kivétel kezelő tesztelheti a DR6-os regiszter tartalmát, hogy megállapítsa, melyik helyzet áll fennt. 2. A lebegőpontos hibákat az első olyan ESC illetve WAIT utasítás alatt jelenti, amely a kivételt
előidéző ESC utasítást követi. 3. A 10-es, 11-es, 14-es és 17-es kivételek valós üzemmódban nem jelentkeznek, viszont virtuális 8086-os módban előfordulhatnak. 124 A védett üzemmód felépítése, működése 3.6 A Védett üzemmód felépítése, működése A processzor architektúrális tulajdonságainak jelentős hányadát kizárólag rendszer programozók veszik igénybe. Ebben a részben ezen tulajdonságok áttekintésére kerül sor. A felhasználói programok írói számára szükségesnek bizonyulhat e fejezet átolvasása, csakúgy mint az ezt követő fejezeteké, amelyekben a fenntemlített tulajdonságok felhasználási módjai kerülnek bemutatásra, annak érdekében, hogy megérthessék a rendszer programozók rendelkezésére álló hardware kínálta lehetőségeket, amelyekkel az alkalmazói programok számára megbízható és biztonságos környezeteket (environment) hozhatnak létre. Ezenkívül, a rendszerszinti architektúra hatékony
hibaelhárító (debugging) lehetőségeket is támogat, amelyeket az alkalmazói programírók valószínűleg szívesen beépítenének fejlesztés alatt álló programjaikba. Az architektúra rendszerszinti lehetőségei közé tartoznak a következők: memóriaszervezés védelem multitaszking kivételek és megszakítások ki- és beviteli műveletek (Input/Output) inicializálás és üzemmódváltás a lebegőpontos egység (FPU) menedzsmentje hibaelhárítás, nyomkövetés cache szervezés multiprocesszálás A felsorolt tulajdonságokat regiszterek és utasítások támogatják, ezek sorra bemutatásra kerülnek a következő részben. A jelen rész célja nem annyira a részletes bemutatásuk, mint inkább a későbbi, védett üzemmódról és rendszer-programozásról szóló információk előrevetítése. Valahányszor egy regiszterről illetve utasításról kerül említés, azt vagy magyarázat kíséri, vagy utalás egy
későbbi fejezetre. 125 Általános CPU programozási információk 3.61 Memóriaszervező regiszterek A processzor négy regisztere határozza meg azon adatstruktúrák helyét, amelyek a szegmentált memória szervezését szabályozzák, amint azt a 3.20 ábra mutatja Speciális utasítások állnak rendelkezésre ezen regiszterek feltöltésére és elmentésére. A GDTR és IDTR regiszterek feltölthetők bizonyos utasításokkal, amelyek a memóriából egy 6-Byte hosszúságú adatblokkot vesznek ki. AZ LDTR és TR regisztereket olyan utasításokkal tölthetjük fel, amelyek operandusai 16 bites szegmens szelektorok. A regiszterek fennmaradó Byte-jait a processzor automatikusan feltölti az operandus által kijelölt deszkriptorokból. RENDSZER CÍMZÕ REGISZTEREK 47 32 BIT LINEÁRIS BÁZISCÍM 16 15 0 GDTR IDTR RENDSZER SZEGMENS REGISZTEREK 15 0 TR SZELEKTOR LDTR SZELEKTOR DESZKRIPTOR REGISZTEREK (AUTÓMATIKUSAN TÖLTÕDNEK) 32 BIT LINEÁRIS BÁZISCÍM 32
BIT SZEGMENS HATÁR JELLEMZŐK 3.20 ábra: Memória kezelő regiszterek Az operációs rendszerek többsége levédi a felhasználói program elől azokat az utasításokat, amelyek a memóriaszervező regisztereket töltik fel (bár elképzelhető olyan rendszer is, amelyben egyáltalán nincs védelem). GDTR Global Descriptor Table Register - globális deszkriptortáblázat regiszter A GDTR regiszter tartalmazza a globális deszkriptortáblázat (GDT) 32 bites báziscímét és a 16 bites határt (limit). Valahányszor hivatkozás történik egy memóriában levő adatra, egy szegmensszelektort használunk egy GDT- vagy LDT-beli szegmensdeszkriptor megkeresésére. A szegmensdeszkriptor a szegmens báziscímét tartalmazza. 126 A védett üzemmód felépítése, működése LDTR Local Descriptor Table Register - helyi deszkriptortáblázat regiszter Ez a regiszter tartalmazza a helyi deszriptortáblázat (LDT) 32 bites báziscímét, a 32 bites szegmens határt, a deszkriptor
attribútumokat és a 16 bites szegmensszelektorát. Az LDT-t tartalmazó szegmensnek van egy szegmensdeszkriptora a GDT-ben. A GDT-nek nincs szegmensszelektora. Valahányszor hivatkozás történik egy memóriában levő adatra, egy szegmensszelektort használunk egy GDT- vagy LDT-beli szegmensdeszkriptor megkeresésére. A szegmensdeszkriptor a szegmens báziscímét tartalmazza. IDTR Interrupt Descriptor Table Register - megsz.-dt reg Az IDTR regiszter tartalmazza a megszakítás deszkriptortáblázat (IDT) 32 bites báziscímét és a 16 bites határát (limit). Valahányszor befut egy megszakítás, a megszakításvektor e táblázaton belüli indexként meghatároz egy kapudeszkriptort. A kapudeszkriptor egy mutatót tartalmaz, amelyet a megszakítás kiszolgáló rutin elindítására alkalmaznak. TR Task Register - taszkregiszter Ez a regiszter tartalmazza az éppen végrehajtás alatt álló taszk 32 bites báziscímét, a 32 bites szegmens határt, a deszkriptor
attribútumokat és a 16 bites szegmensszelektorát. Egy GDT-beli taszk-állapotszegmens deszkriptorra (TSS) mutat. Lásd: multitaszking 3.62 Rendszer utasítások A redszer utasítások a következő funkciókat látják el: 1. 2. 3. 4. 5. mutatók paraméterellenőrzése deszkriptortáblázatok címzése multitaszking lebegőpontos műveletek ki- és beviteli műveletek 127 Általános CPU programozási információk 6. 7. 8. 9. megszakítás-vezérlés nyomkövetés, hibakeresés cache-szervezés rendszervezérlés Az SMSW és az LMSW utasításokat a 16 bites 286-os proceszszorral való kompatibilitás érdekében vezették be. A 32 bites processzorokra, mint például a Pentiumra írt programokban nem ajánlott a használatuk. Helyette inkább a vezérlőregiszterekhez kell a MOV utasítás különböző formáival hozzáférni. Az LMSW utasítás nem befolyásolja a PG, CD, NW, AM, WP, NE vagy ET biteket, ugyanakkor nem használható fel a PE bit törlésére sem. A HLT
utasítás mindaddig leállítja a processzort, amíg egy engedélyezett megszakítás vagy egy RESET jel nem érkezik be. (jegyezzük meg, hogy az NMI illetve SMI megszakítások mindíg engedélyezettek.) A processzor egy speciális buszciklust generál a halt üzemmódra való váltás jelzésére. A hardware sokféleképpen válaszolhat erre a jelre. A gép elülső paneljén például bekapcsolhat egy fényjelzést, esetleg generálhat egy diagnosztizáló NMI-t, vagy akár inicializálást (reset) is kezdeményezhet. A software íróknak tisztában kell lenniük a hardware halt üzemmódbeli válaszával. A LOCK utasításprefix célja, hogy lehetővé tegye egy védett olvasás-módosítás-írás művelet kezdeményezését egy memóriában lévő operandus értékének módosításakor. A LOCK# jel aktiválódik, és a processzor a levédett ("lezárt") utasítás alatt nem válaszol a buszvezérlés átadását célzó kérésekre. Ezt a mechanizmust
multiprocesszoros rendszerekben használják a proceszszorok közti biztonságos kommunikáció érdekében. Minden egyes utasításról részletes információt kaphatunk a könyv második kötetéböl. 128 A védett üzemmód felépítése, működése 3.63 Védett üzemmódú memóriaszervezés A memóriaszervezés egy olyan hardware mechanizmus, amely lehetővé teszi az operációs rendszerek számára, hogy egy leegyszerűsített környezetet hozzanak létre a futtatott programok részére. Például abban az esetben, ha több program fut párhuzamosan, mindegyiknek független címtartományt kell biztosítani. Ha mindannyian ugyanazon címtartományon osztoznának, egyenként kéne nehézkes és időpazarló ellenőrző műveleteket elvégezniük, hogy elkerülhessük az összeütközést a többi programmal. A memóriaszervezés szegmentálásból illetve lapozásból áll. A szegmentálás célja, hogy minden egyes program részére számos, egymástól független és
védett címtartományt biztosítson. A lapozás olyan környezetek kialakítását támogatja, amelyekben egy kis méretű RAM és egy bizonyos mennyiségű lemezterületet felhasználásával kiterjedt címtartományok szimulálhatók. Az operációs rendszerek tervezői választhatnak a két mechanizmus közül. Ha egyszerre több program is szalad, az említett két eljárás közül bármelyiket felhasználhatjuk arra, hogy egy programot megvédjünk más programok beavatkozásától. A szegmentálás megengedi a teljesen strukturálatlan, egyszerű memória modellek (mint amilyen a 8 bites processzoroké), vagy az erőteljesen strukturált, címfordításos illetve védelemmel ellátott modellek használatát. A memóriaszervezés a "szegmenseknek" nevezett egységekre vonatkozik. Minden egyes szegmens egy önálló, védelemmel ellátott címtartomány. A szegmensekhez való hozzáférést olyan adatok vezérlik, amelyek meghatározzák a szegmens hosszát, a
hozzáféréshez szükséges privilégiumszintet, a szegmensre történő memóriahivatkozások típusait (utasítás elérése, veremre vonatkozó push vagy pop, olvasási vagy írási műveletek, stb.), illetve azt, hogy a szegmens a memóriában található-e A szegmentálást a memória hozzáférések ellenőrzésére használják, ami a fejlesztés alatt álló program hibáinak felderítésében és a "végtermék" megbízhatóságának növelésében igencsak hasznosnak bizonyulhat. A tárgynyelvi modulok összekapcsolásának (link) leegyszerűsítésére is használatos. Nincs értelme helyfüggetlen kódot írni, ha a szegmentáló mechanizmust teljes mértékben kihasználjuk, ugyanis 129 Általános CPU programozási információk minden egyes memóriahivatkozást a modul kód, illetve adatszegmensének báziscíméhez viszonyíthatunk. A szegmentálást ugyanakkor ROM-ra alapuló software modulok létrehozására is felhasználhatjuk, amelyekben a fix
címek (abban az értelemben fixek, hogy nem lehet őket megváltoztatni) egy szegmens báziscíméhez viszonyított ofszetek. Különböző rendszereknek eltérő fizikai címen lehetnek a ROM-moduljai, mivelhogy a szegmentáló mechanizmus minden egyes memóriahivatkozást a megfelelő helyre irányít. Egy egyszerű memória felépítés esetén minden cím ugyanarra a címtartományra hivatkozik. Ezt a memória modellt használják a 8 bites mikroprocesszorok, mint például a 8080-as processzor, amelynél a logikai cím egyben fizikai cím is. A 32 bites processzorok védett üzemmódban is működtethetők ezzel a memória modellel, ha a szegmenseket ugyanabba a címtartományba képezzük le (mapping), a lapozást pedig letiltjuk. A software-ek meghibásodásának igen gyakori oka az, hogy a verem "belenő" az utasításkódba vagy a program adataiba. Ennek megelőzésére biztos módszer a szegmentálás. A vermet a kód vagy adat részére fenntartott
címtartományon kívül eső tartományba tehetjük. Így a verem címek mindíg a veremszegmensbeli, az adatcímek pedig az adatszegmensbeli memóriarészre vonatkoznának. A verem-szegmensnek hardware által meghatározott maximális hossza van. Bármely olyan próbálkozás, amely a verem maximális méretének túlhaladását célozná, kivételt generálna. Egy komplex programrendszer teljes mértékben kihasználhatja a szegmentálást. Például egy olyan operációs rendszer, amelyben a programok valós időben osztják meg az adatokat, precízen ellenőrizheti a hozzáférést ezekhez az adatokhoz. A "program-gubancok" (bugs), mint a program által végrehajtott szabálytalan hozzáféréssel generált kivételek jelentkeznek. Ez hasznos lehet a programírás stádiumában, mint hibakereső segédlet, illetve a végfelhasználónak leszállított rendszerben, mint a hiba helyreállító procedúrák vezérlője. A szegmentáló hardware egy szegmentált (logikai)
címet fordít le egy folytonos, nem szegmentált címtartományra ún. "lineáris" címre Ha a lapozás megengedett, a lapozó mechanizmus lefordítja a lineáris címet 130 A védett üzemmód felépítése, működése fizikai címre. Ha a lapozás nem engedélyezett, a lineáris cím fizikai címként kerül felhasználásra. A fizikai cím a processzorból kijövő címbuszra kerül, engedélyezett lapozás esetén esetleg a háttértárolóról lapozódik be. A lapozás mechanizmust arra használható, hogy egy jelentős méretű, nem szegmentált címtartományt lehessen szimulálni egy kis méretű, fragmentált címtartomány és némi lemezterület segítségével. Lapozással a szabad memóriaterületnél nagyobb adatstruktúrákhoz lehet hozzáférni, azáltal, hogy részint a memóriaban, részint a lemezen tároljuk őket. A lapozást 4 kByte-os, lapoknak nevezett egységekre alkalmazzák. Ha egy program megpróbál hozzáférni egy lemezen levő laphoz,
különleges eljárással szakítódik meg. Más kivételekkel és megszakításokkal ellentétben, a címek lefordításakor keletkezett kivétel visszaállítja a processzor regisztereinek tartalmát olyan értékekre, amelyek lehetővé teszik a kivételt előidéző utasítás megismételt végrehajtását. Ez a speciális eljárás megengedi az utasítás újraindítását, azaz képesíti az operációs rendszert arra, hogy kiolvassa a lapot a lemezről, felfrissítse a lap lineáris címeinek fizikai címekre való leképezéseit, és újraindítsa a programot. A program számára ez a folyamat áttetsző. A lapozás opcionális. Ha egy operációs rendszer soha nem engedélyezi a lapozás mechanizmusát, a lineáris címek fizikai címekként kerülnek felhasználásra. Ez akkor volna lehetséges, ha egy 16 bites processzorra írt alkalmazást 32 bites processzorra adaptálunk. Egy 16 bites processzorra írt operációs rendszer nem alkalmaz lapozást, mivel a címtartománya
annyira rövid (64 kByte), hogy sokkal inkább gazdaságosabb egész szegmenseket átcserélni (swap) a RAM és a lemez között, mint egyedi lapokat. Az olyan operációs rendszerekben mint az UNIX, amelyek támogatják az igényeknek megfelelően lapozható (demand-paged) virtuális memóriát, engedélyezett a lapozás. A felhasználói software részére a lapozás áttetsző, tehát a 16 bites processzorokra írt alkalmazásokat támogató operációs rendszer képes futtatni azokat a 131 Általános CPU programozási információk lapozás engedélyezése mellett is. A lapozással elletétben, a szegmentálás nem áttetsző a felhasználói programoknak. Szegmentálást használó programokat azokkal a szegmensekkel kötelező futtatni, amelyek használatára eredetileg meg voltak tervezve. 3.631 A szegmentálási modell kiválasztása A memória szegmentálásának modelljét a megbízhatóság és teljesítmény kritériuma alapján választják meg. Például, ha egy
operációs rendszerben több program osztja meg valós időben adatait, maximális teljesítményt egy olyan modell nyújthatna, amely hardware-ileg ellenőrzi a memória hivatkozásokat. Ehhez egy multiszegmens modellre lenne szükség. A másik oldalról viszont, egy olyan operációs rendszer, amely csak egyetlen programot futtat, magasabb teljesítményt érne el egy szegmentálás nélküli, ún. "sík" modellel A "far" típusú mutatók és a szegmens-felülíró prefixek kiküszöbölésével lecsökken a kód hossza és megnő a végrehajtás sebessége. A kontextusváltás is gyorsabb, mivel a szegmensregiszterek tartalmát nem kell többé elmenteni vagy visszaállítani. A szegmentálás egyes előnyeit a lapozás is képes biztosítani. Például az adatok megoszthatók (share), ugyanazon lapok minden egyes program címtartományba való betérképezésével. 3.6311 A sík modell A legegyszerűbb modell a sík modell. Ebben a modellben minden szegmens
a teljes fizikai címtartományra van rátérképezve. Egy szegmensen belüli ofszet vonatkozhat úgy kód, mint adat területre. Ez a modell a lehető legtökéletesebben eltörli a szegmentálás mechanizmusát, akár a rendszerprogramozó, akár a felhasználói programiró szemszögéből látott architektúrából. E megoldás lehetséges volna egy olyan programozási környezet esetében, mint az UNIX, amely támogatja a lapozást, ellenben a szegmentálást nem. 132 A védett üzemmód felépítése, működése Egy szegmenst egy szegmensdeszkriptor határoz meg. A sík modellben legalább két szegmensdeszkriptort kell létrehozni: egyet a kód hivatkozásoknak, egy másikat pedig az adat hivatkozásoknak. Mindkét deszkriptornak ugyanaz kell legyen a báziscíme. Valahányszor memóriahozzáférés történik, a szegmens regiszterek egyikét a szegmensdeszkriptor kiválasztására használják. A szegmens deszkriptor szolgáltatja a szegmens báziscímét és a határ
(limit) értékét, valamint a hozzáférést ellenörző információkat. (Lásd a 321 ábrát) Általában a ROM-ot a fizikai címtartomány tetejére helyezik, mivel a processzor az FFFF FFF0H címen kezdi végrehajtani az utasításokat. A RAM a címtartomány alján foglal helyet, ugyanis a reset után a DS adatszegmens báziscíme 0. A sík modellben minden deszkriptor báziscíme 0, és a szegmenshatár értéke 4 GByte. A szegmenshatárt 4 GByte-ra állítva a szegmentáló mechanizmust meggátoljuk abban, hogy kivételt generáljon a szegmenshatáron kívülre eső memória hivatkozásokkor. Ugyanakkor még fennáll annak lehetősége, hogy a lapozó illetve szegmentáló védelmi mechanizmusok kivételeket generáljanak, de ezeket is ki lehet iktatni a memória modellből. SZEGMENS KÓD ÉS ADATSZEGMENS FIZIKAI REGISZTEREK DESZKRIPTOR MEMÓRIA CS EPROM 4G SS DS ES HOZZÁFÉRÉS HATÁR BÁZISCÍM FS GS DRAM 0 3.21 ábra: Sík modell 133 Általános CPU
programozási információk 3.6312 Védett sík modell A védett sík modell hasonlít az egyszerű sík modellre, azzal a különbséggel, hogy a szegmenshatár értékek csak akkorára vannak beállítva, amekkora a tulajdonképpeni memória címtartománya. Egy általános védelmi hiba kivétel generálódik valahányszor megkísérelünk nem implementált memória területhez hozzáférni. Ez a lehetőség olyan operációs rendszerekben használható, amelyekben a lapozás mechanizmus ki van kapcsolva. E modellben a szegmentáló hardware meggátolja a programokat abban, hogy nem létező memóriarekeszeket címezzenek meg. Ezen rekeszek címezhetőségének következményei hardware függők. Például, ha a processzorhoz nem érkezik be a READY# jel (amely egy buszciklus tudomásulvételezésére és befejezésére használatos), a buszciklus nem fejeződik be, és a program végrehajtása leáll. Bár egyetlen programnak sem volna megengedett ezeket a memória cellákat
megcímezni, mégis adódhat ilyen nemű kísérlet, programozási hibák eredményeképpen. A címek hardware-es ellenőrzése nélkül megtörténhet, hogy egy gubanc hirtelen leállíthatja a programot. Hardware-es ellenőrzés esetén a programok ellenőrzött módon "omlanak össze". Ilyenkor egy diagnózis üzenetet lehet megjeleníteni, illetve helyreállító eljárásokat (recovery procedure) lehet kezdeményezni. A 3.22 ábra egy védett sík modellre ad példát Ebben a szegmensdeszkriptorok úgy voltak beállítva, hogy csak a fizikailag létező memória tartományát takarják. A fizikai memóriának EPROM és DRAM részét egy kód- illetve adatszegmens takarja. A kódszegmens báziscíme és szegmenshatára opcionálisan beállítható úgy, hogy a DRAM tartományhoz is engedélyezzen hozzáférést. Az adatszegmens határát az EPROM és a DRAM méreteinek összegére kell beállítani. Ha memóriába leképezett I/O tartományt is használunk, ez
megcímezhető lehet közvetlenül a DRAM terület határán túl. 134 A védett üzemmód felépítése, működése SZEGMENS REGISZTEREK SZEGMENS DESZKRIPTOROK FIZIKAI MEMÓRIA 4G HOZZÁFÉRÉS CS HATÁR EPROM BÁZISCÍM SS MEMÓRIA I/O DS ES HOZZÁFÉRÉS HATÁR BÁZISCÍM FS DRAM GS 0 3.22 ábra: Védett sík modell 3.6313 Multiszegmens modell A legbonyolultabb modell a multiszegmens modell. Itt a szegmentáló mechanizmus teljeskörű lehetőségeit használjuk. Minden egyes programnak megvan a saját szegmensdeszkriptor táblázata és a saját szegmensei. A szegmensek lehetnek teljes mértékben a program "magántulajdonában", vagy bizonyos más programkal lehetnek megosztva. A programoknak bizonyos szegmensekhez való hozzáférése egyenként ellenőrizhető. Maximum hat szegmens állhat rendelkezésre azonnali használatra. Ezek azok a szegmensek, amelyeknek a szegmens-szelektorai a szegmensregiszterekbe vannak betöltve. Más szegmensekhez a
szegmens szelektoraik szegmens regiszterbe való betöltésével lehet hozzáférni. (Lásd a 3.23 ábrát) Minden egyes szegmens egy különálló címtartomány. Mindamellett, hogy megengedett a fizikai memória egymással szomszédos blokkjaiba betölteni őket, a szegmentáló mechanizmus meggátolja, hogy egy szegmens tartalmához hozzáférhessünk egy másik szegmens határát átlépő olvasással. Minden memóriát érintő műveletnél ellenőrizve van annak a szegmensnek a határa (limit), amelyet a művelet 135 Általános CPU programozási információk használ. A szegmens határát túllépő memóriacímzési próbálkozás általános védelmi hiba kivételt eredményez. A szegmentáló mechanizmus csak a szegmens deszkriptorban meghatározott címtartomány betartását követeli meg. Az operációs rendszer feladata minden egyes szegmensnek különálló címtartományokat lefoglalni. Elképzelhető olyan eset is, amelyben szükséges lehet közös
címtartományt megosztó szegmensek használata. Például, egy rendszer ROM-jában tárolva lehet kód is, adat is. Kódszegmens deszkriptort használunk, ha a ROM-ban utasításelérést végzünk. Ha a ROM-ot adatként olvassuk, adatszegmens deszkriptort használunk. SZEGMENS REGISZTEREK CS SS SZEGMENS DESZKRIPTOROK HOZZÁFÉRÉS HOZZÁFÉRÉS ES FS GS HATÁR BÁZISCÍM HOZZÁFÉRÉS DS HATÁR BÁZISCÍM HATÁR BÁZISCÍM HOZZÁFÉRÉS HATÁR BÁZISCÍM HOZZÁFÉRÉS HATÁR BÁZISCÍM HOZZÁFÉRÉS HATÁR BÁZISCÍM HOZZÁFÉRÉS HATÁR BÁZISCÍM HOZZÁFÉRÉS HATÁR BÁZISCÍM HOZZÁFÉRÉS HATÁR BÁZISCÍM HOZZÁFÉRÉS HATÁR BÁZISCÍM 3.23 ábra: Multiszegmens modell 136 FIZIKAI MEMÓRIA A védett üzemmód felépítése, működése 3.632 Szegmensfordítás Egy logikai cím a szegmenst jelölő 16 bites szegmens szelektorból, valamint a szegmensen belüli 32 bites ofszetből áll. A logikai címek a hozzáférési jog és a tartomány
szempontjából kerülnek ellenőrzés alá. Ha megfelel ezeknek a teszteknek, a logikai címeket a processzor lineáris címekre fordítja le, az ofszetet hozzáadva a szegmens báziscíméhez. A báziscím a szegmensdeszkriptorból származik, ami egy memóriában tárolt adatstruktúra, és a szegmens méretéről, helyzetéről és hozzáférési adatairól szolgáltat információt. A szegmensdeszkriptort két táblázat valamelyikéből kaphatjuk meg. Vagy a globális deszkriptor táblázatból (GDT), vagy a lokális deszkriptor táblázatból (LDT). A rendszerbeli összes programnak egyetlen GDT táblázata van, és egy-egy különálló LDT táblázata minden egyes futó programnak. Ha az operációs rendszer megengedi, különböző programok osztozhatnak ugyanazon LDT-n. A rendszert úgy is konfigurálhatjuk, hogy egy LDT táblázatot se tartalmazzon. Ebben az esetben minden program a GDT-t fogja használni Minden logikai címhez egy szegmens van rendelve (még akkor is, ha
az operációs rendszer minden szegmenst ugyanabba a címtartományba képez le). Annak ellenére, hogy egy programnak sok ezer szegmense lehet, azonnali alkalmazásra csak hat szegmens áll rendelkezésére. Ez az a hat szegmens, amelyeknek a szegmens szelektora fel van töltve a processzorba. A szegmens szelektor a logikai cím megfelelő lineáris címmé alakítására használatos információkat tartalmazza. Minden memória hivatkozás típusnak (kód tartományra, verem tartományra és adat tartományra), külön szegmensregisztere van a processzorban. Ezek az aktuálisan használat alatt álló szegmensek szegmensszelektorjait tartalmazzák. Más szegmensekhez való hozzáférés szükségessé teszi a szegmensregiszterek feltöltését a MOV utasítás különböző formáinak segítségével. Legtöbb négy adat tartományt lehet egyszerre elérni, ami tehát összesen hat szegmensregisztert jelent. Mikor egy szegmensszelektor betöltésre kerül, a báziscím, a
szegmenshatár és a hozzáférési jogot ellenörző információk is betöltődnek a szegmensregiszterbe. A processzor addig nem nyúl a memóriában levő deszkriptor táblázathoz, ameddig egy új szegmens szelektor nem kerül betöltésre. A processzorban eltárolt információk 137 Általános CPU programozási információk lehetővé teszik számára a címek lefordítását anélkül, hogy plusz buszciklusokra lenne szüksége. Az olyan rendszerekben, amelyekben több processzornak van hozzáférési lehetősége ugyanazon deszkriptortáblázatokhoz, a software köteles a szegmensregisztereket újratölteni, valahányszor a deszkriptor táblázatokat módosítástja. Ha ez nem így történik, fennáll az a lehetőség, hogy egy szegmens regiszterben eltárolt régi szegmens deszkriptor kerül alkalmazásra, miután a memóriarezidens változata már megváltozott. A szegmensszelektor a deszkriptortáblázatok egyikének egy 13 bites indexét tartalmazza. Az index, egy
nyolcas skálatényezővel való beszorzás után (ennyi Byte található egy szegmensdeszkriptorban) a deszkriptor táblázat 32 bites báziscímével adódik össze. A báziscím vagy a globális deszkriptortáblázat regiszterből (GDTR), vagy a lokális deszkriptortáblázat regiszterből (LDTR) származik. Ezek a regiszterek tartalmazzák a deszkriptortáblázatok kezdetének lineáris címét. Amint azt a 3.24 ábra is mutatja, a szegmensszelektor egyik bitje határozza meg, hogy a processzor melyik táblázatot használja. SZEGMENS SZELEKTOR GLOBÁLIS DESZKRIPTOR LOKÁLIS DESZKRIPTOR TÁBLÁZAT TÁBLÁZAT TI=0 TI=1 T I SZELEKTOR HATÁR BÁZISCÍM 138 GDTR HATÁR BÁZISCÍM LDTR A védett üzemmód felépítése, működése 3.24 ábra: TI BIT - A deszkriptor tábla kiválasztása A lefordított cím a lineáris cím, amint az a 3.25 ábrán is látható Ha nem használunk lapozást, ez egyben a fizikai cím is. Ha a lapozás megengedett, egy második szintű
címfordítás adja meg a fizikai címet. Ezzel a típusú fordítással a fejezet későbbi részében foglalkozunk. Logokai cím 0 15 Szelektor 0 31 Ofszet Deszkriptor tábla Szegmens deszkriptor 31 0 Lineáris cím 3.25 ábra: Szegmens fordítás 3.6321 Szegmensregiszterek Bármely memóriahozzáférés típushoz egy szegmensregiszter van rendelve. A kódra, veremre, illetve adatra vonatkozó hivatkozások mindegyike a szegmensregisztereik tartalma által kijelölt szegmenseket címezik meg. További szegmensek tehetők elérhetővé, ha a program végrehajtása közben a szegmens-szelektorjaikat betöltjük ezekbe a regiszterbe. A 326 ábrának megfelelően, minden egyes regiszternek van egy "látható" és egy "láthatatlan" része. A szegmensregiszterek látható részének feltöltésére a MOV utasítás különböző formái ismeretesek. A láthatalan részt a processzor tölti fel. 139 Általános CPU programozási információk Látható
rész Láthatatlan rész Szelektor Bázis cím, határ, stb. CS SS DS ES FS Azok a műveletek, amelyek ezeket a regisztereket feltöltik, utasítások a felhasználói programok számára. Két fajta ilyen utasítás létezik: 1. közvetlen betöltő utasítások, mint amilyenek a MOV, POP, LDS, LES, LSS, 3.26 ábra: Szegmens regiszterek LGS és LFS utasítások. Ezek az utasítások expliciten a szegmensregiszterekre vonatkoznak. GS 2. közvetett betöltő utasítások, mint amilyenek a CALL és JMP utasítások "far" változatai. Ezek az utasítások a CS regiszter tartalmát működésük implicit részeként módosítják. Amikor a fenti utasítások egyike végrehajtódik, egy szegmensszelektor betöltődik a szegmensregiszter látható részébe. A processzor automatikusan feltölti a szegmens regiszter láthatatlan részét a deszkriptor táblázatból kiolvasott információkkal (például a báziscímmel). Minthogy az utasítások legnagyobb része azokra a
szegmensekre vonatkozik, amelyek szelektorai már be vannak töltve a szegmens regiszterekbe, a processzor teljesítmény veszteség nélkül képes a logikai cím ofszetjét a szegmens báziscímével összeadni. 3.6322 Szegmensszelektorok A szegmensszelektor egy szegmens deszkriptornak nevezett, szegmens definiáló információra mutat. Egy programnak lehet több szegmense azon a haton kívül, amelyek szegmensszelektorai a szegmensregisztereket foglalják el egy adott pillanatban. Ez azt jelenti, tehát, hogy a program a MOV utasítás különböző formáinak segítségével lecserélheti ezen regiszterek tartalmát, mikor új szegmensre van szüksége. Egy szegmensszelektor meghatároz egy szegmens deszkriptort, egy deszkriptortáblázat és a táblázaton belüli deszkriptor megjelölésével. 140 A védett üzemmód felépítése, működése A felhasználói programok számára a szegmens szelektorok egy pointer változó részeként jelennek meg, de a szelektorok
értékeit általában a kapcsolóprogram (link editor) vagy kapcsoló töltőprogramok (linking loaders) határozzák meg, illetve módosítják, és nem a felhasználói programok. A 327 ábra egy szelektor formátumát mutatja be 15 14 13 12 11 10 9 8 7 INDEX Tábla kijelölő 0=GDT 1=LDT 6 5 4 3 2 1 0 T RPL I Privilégium szint kérő 00 = Legmagasabb szint 11 = Legalacsonyabb szint Index: 8192 deszkriptor közül kiválaszt egyet a deszkriptortáblázatból. A processzor beszorozza az index értékét egy 8-as skálatényezővel (egy szegmensdeszkriptorban ennyi Byte van) és az eredményt összeadja a deszkriptortáblázat báziscímével (amelyet a GDTR vagy az LDTR regiszter tárol). 3.27 ábra: Szegmens szelektor Táblázat mutató bit: Meghatározza, hogy melyik táblázat kerül alkalmazásra. 0-ás bit a GDT-t, 1-es bit az aktuális LDT-t szelektálja. Ígényelt privilegizálási szint (RPL): Ha ez a mező egy nagyobb értékű privilégium szintet
jelöl, mint a program szintje (tehát kevésbé privilegizált), akkor egyszerűen felülírja a program privilegium szintjét minden olyan hozzáférés esetén, amely ezt a szelektort használja. Ha egy program egy kevésbé privilegizált szegmensszelektort alkalmaz, a memória hozzáférések az alacsonyabb privilegizálási szinten mennek végbe. Ezt az eljárást annak a védelem sértésnek az elhárítására használják, amely akkor lépne fel, amikor egy kevésbé privilégizált program egy privilégizáltabb programot próbálna arra felhasználni, hogy levédett adatokhoz férjen hozzá. Például a rendszer kezelő programok vagy a periféria meghajtók (device driver) magas privilégium szinten kell fussanak ahhoz, hogy elérhessék a védelemmel ellátott területeket, mint például a periféria interfészek kontroll regisztereit. Ugyanakkor elkerülendő más, levédett területtel az összeakadás, még akkor is, ha egy kevésbé privilegizált program ezt kérné.
Ha egy program inditványozza egy lemezen tárolt 141 Általános CPU programozási információk szektor memóriába töltését egy privilegizáltabb program, például az operációs rendszer által elfoglalt helyre, az RPL felhasználható egy általános védelmi hiba kiváltására a kevésbé privilegizált szegmensszelektor használatának pillanatában. Ez a kivétel még akkor is létrejönne, ha a szegmens szelektort használó program privilégium szintje elégséges volna ahhoz, hogy a műveletet egymagában elvégezze. Mivel a GDT legelső bejegyzését a processzor nem használja, egy 0-ás indexel és 0-ás táblázat mutatóval ellátott szelektort (tehát a GDT első bejegyzésére mutató szelektort) "null szelektorként" használhatunk. A processzor nem generál kivételt, ha egy (CS-től illetve DS-től különböző) regiszterbe egy null szelektort töltünk. Ugyanakkor, ha egy null szelektort tartalmazó regiszterrel végzünk memória
hozzáférést, kivétel keletkezik. Ezt a lehetőséget használaton kívüli szegmens regiszterek inicializálására lehet alkalmazni. 3.6323 Szegmens deszkriptorok A szegmens deszkriptorok a memóriában elhelyezkedő adatstruktúrák, amelyek a szegmens méretét, helyét illetve a vezérlő- és státusinformációkat szolgáltatják a processzor számára. A deszkriptorokat általában a fordítóprogramok, kapcsolóprogramok, betöltőprogramok vagy az operációs rendszer hozzák létre, de semmi esetre sem a felhasználói programok. A deszkriptorok általános formátumát a 328 ábra mutatja be. Bármely típusú deszkriptor ennek az alapformátumnak a változatait használja. 142 A védett üzemmód felépítése, működése 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Báziscím 31-24 A D G 0 V B L Báziscím 15-0 Szegmens határ 19-16 P DPL S Típus Báziscím 23-16 Szegmens határ 15-0 +4 +0 31 30 29 28 27 26
25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 G - Szemcsézettség D/B - Alap szegmens operandus méret (0 - 16 bites, 1 - 32 bites) AVL - Rendszer program számára engedélyezett a használat P - A szegmens jelen van DPL - Deszkriptor privilégium szint S - Deszkriptor típus (0 - rendszer, 1 - alkalmazás) 0 - Fenntartva 3.28 ábra: Szegmens deszkriptorok Báziscím: Meghatározza a szegmens 4 GByte-os fizikai címtartománybeli helyzetét. A processzor összeteszi a három báziscím mezőt és így képezi az egy, 32 bites értéket. A szegmensek báziscím értékei 16 Byte-os keretekhez kell illeszkedjenek annak érdekében, hogy a programok teljesítményét maximalizálják az adatok, illetve a kód 16 Byte-os keretekbe történő illesztésével. Felbontás (Granularity) bit: A szegmenshatár (Limit) mező értékének 4096-os (212) tényzővel való skálázását engedélyezi. Ha a bit értéke 0, a szegmenshatár értéke egy Byte-os egységekben,
ellenkező esetben 4 kByte-os egységekben van értelmezve. Megyjegyzendő, hogy a skálázás alkalmazása esetén a címek 12 legkevésbé értékes bitje nem kerül ellenőrzésre. Például, ha a G bit magas, egy 0-ás szegmenshatár a 0-4095 közötti tartományba helyezi a megengedett eltolási címeket. Fontos azt is megjegyeznünk, hogy ez kizárólag a szegmenshatár mezőre érvényes. A báziscím mindig Byte-os felbontású marad. 143 Általános CPU programozási információk Szegmenshatár (Limit): A szegmens méretét határozza meg. A processzor összeteszi a két szegmenshatár mezőt, így kapja meg a 20 bites értéket. A szegmens hosszát a processzor kétféleképpen értelmezi, a felbontás (G) bit állapotának függvényében: 1. Ha G=0, a szegmens hossza egy Byte-tól egy MByte-ig terjed, 1 Byte-os növekménnyel. 2. Ha G=1, a szegmens hossza 4 kByte-tól 4 GByte-ig terjed, 4 kByte-os növekménnyel. A felfele bővülő szegmensek esetén a logikai címek
ofszetjei 0-tól a szegmenshatár értékéig terjedhetnek. Más ofszetek kivételt generálnak A lefele bővülő szegmensek megváltoztatják a limit mező értelmét. Bármely ofszettel megcímezhetők, kivéve azokkal, amelyek a 0-tól a szegmenshatárig terjednek (lásd a szegmenstípus mezőt a következőkben). Ennek az az értelme, hogy lehetővé tegye olyan szegmensek képezését, amelyeknél a szegmenshatár értékének növelésével a szegmens címtartományának alján foglalódik le új memóriaterület, és nem a szegmens tetején. A lefele bővülő szegmensek célja a verem befogadása, de használatuk nem kötelező. Ha a stack-et egy olyan szegmensbe helyezzük, amely nem kell méretet változtasson, akkor ez egy közönséges adatszegmens is lehet. S bit, deszkriptor típusát lelző bit: Meghatározza, hogy egy adott szegmens rendszer szegmens vagy kód- illetve adatszegmens. Ha S=1, a szegmens vagy kódszegmens, vagy adatszegmens. Ha S=0, a szegmens egy
rendszer szegmens. D bit / B bit: Kódszegmensek esetében ennek a bitnek a neve D bit, és az operandusok és effektív címek alapértelmezés szerinti hosszát jelöli. Ha a D bit 1-re van állítva, 32 bites operandusokat és 32 bites effektív címzésmódot határoz meg. Ellenkező esetben 16 bites operandushosszt és 16 bites címzésmódot jelöl. Adatszegmensekben a bit neve B bit, és a veremmel végzett műveletek két aspektusát ellenőrzi: 144 A védett üzemmód felépítése, működése 1. A veremmutató regiszter méretét Ha B=1, a PUSH, POP és CALL típusú műveletek mindegyike a 32 bites ESP regisztert használja; ha B=0, a verem műveletek a 16 bites SP regisztert használják. 2. Egy lefelé bővülő verem felső korlátját Lefelé terjedő szegmensek esetén a szegmenshatár (limit) mező határozza meg a verem szegmens alsó korlátját. Ha B=1, a felső korlát FFFF FFFFH; ha B=0, a felső korlát FFFFH. Szegmenstípus mező: ennek a mezőnek az
értelmezése attól függ, hogy a szegmens deszkriptor egy felhasználói szegmens vagy egy rendszer szegmens deszkriptora. A rendszer szegmenseknek kissé eltérő a deszkriptor formátuma, lásd később. Egy momória deszkriptor típus mezője meghatározza az engedélyezett szegmens hozzáférés típusát, és a szegmens növekedési irányát (lásd 3.29 ábra) Adatszegmensek esetén a szegmenstípus mező legalsó három bitjének a következő az értelme: lefele terjedő (E - expand-down), írás engedélyezés (W write enable), illetve elért (A - accessed). Kódszegmensek esetén az említett három bit értelme: illeszkedő (C - conforming), olvasás engedélyezés (R - read enable), illetve elért (A - accessed). Az adatszegmensek lehetnek csak olvasható, illetve írható/olvasható típusuak. A veremszegmensek olyan adatszegmensek, amelyek kötelezően írható/olvasható típusuak. Ha az SS regiszterbe bármilyen más típusú szegmens szelektora kerül betöltésre,
általános védelmi hiba kivétel generálódik. Ha a verem szegmens mérete változó kell legyen, akkor ez egy lefele bővülő adatszegmens lehet. A szegmenshatár értelme megváltozik a lefele bővülő szegmens esetében. A lefele bővülő szegmensekben azok a szabályos ofszet címek, anelyek a felfele növekvő szegmensekben kivételeket idéznek elő. A felfele bővülő szegmenseket csak olyan eltolási címekkel lehet megcímezni, amelyek értéke kisebb vagy egyenlő a szegmenshatárnál. A lefele terjedő szegmensekbe mutató ofszeteknek minden esetben nagyobbnak kell lennie a szegmens limit értékénél. A szegmenshatár ezen értelmezésének megfelelően a szegmenshatár csökkenése a szegmens alján eredményez memória foglalást, ami a veremszegmens esetében helyes, ugyanis a verem az alacsonyabb címek irányába terjed. Ha a veremnek egy fix 145 Általános CPU programozási információk méretü szegmenst foglalunk le, ez a szegmens nem kell
feltétlenül lefele növekvő legyen. 146 A védett üzemmód felépítése, működése Típus 11 10 9 8 Deszkriptor Meghatározás E W A típus 0 0 0 0 0 Adat Csak olvasható 1 0 0 0 1 Adat Csak olvasható, hozzáférhető 2 0 0 1 0 Adat Írható - olvasható 3 0 0 1 1 Adat Írható - olvasható, hozzáférhető 4 0 1 0 0 Adat Csak olvasható, lefelé növekvő 5 0 1 0 1 Adat Csak olvasható, hozzáférhető, lefelé növekvő 6 0 1 1 0 Adat Írható, olvasható, lefelé növekvő 7 0 1 1 1 Adat Írható, olvasható, hozzáférhető, lefelé növekvő Típus 11 10 9 C R 0 1 0 0 1 1 0 0 2 3 1 1 0 0 1 1 4 5 1 1 1 1 0 0 6 1 1 1 7 1 1 1 8 Deszkriptor Meghatározás A típus 0 Kód Csak végrehajtható 1 Kód Csak végrehajtható, hozzáférhető 0 Kód végrehajtható, olvasható 1 Kód végrehajtható, olvasható, hozzáférhető 0 Kód Csak végrehajtható, illeszkedő 1 Kód Csak végrehajtható, hozzáférhető, illeszkedő 0 Kód végrehajtható, olvasható,
illeszkedő 1 Kód végrehajtható, olvasható, hozzáférhető, illeszkedő 3.29 ábra: Alkalmazási szegmens típusok A kódszegmensek lehetnek végrehajtható/olvasható, illetve csak végrehajtható típusuak. Egy végrehajtható/olvasható szegmens hasznos 147 Általános CPU programozási információk lehet például abban az esetben, ha egy ROM-ba az utasításkóddal együtt konstansokat is elhelyeztek. Ebben az esetben a konstansok kiolvashatók vagy egy CS fölülíró prefixel ellátott utasítással, vagy egy kódszegmensre vonatkozó szegmens szelektornak egy adatszegmens regiszterbe történő betöltésével. A kódszegmens lehet illeszkedő (conforming), vagy nem illeszkedő (non-conforming). A vezérlés átadása egy privilegizáltabb, illeszkedő szegmensnek megtartja a CPL értékét. Egy nem illeszkedő szegmensnek eltérő privilégium szinten átadott vezérlés általános védelmi hibát eredményez, ha nem használunk taszkkaput. Azok a rendszer kezelő
programok, amelyek nem férnek hozzá levédett területekhez, mint amilyenek az adat konverziót végző eljárások (pld. EBECDIC/ASCII fordítás, Huffman kódolás/dekódolás, matematikai könyvtár) és egyes kivételtípusok (például: Osztási hiba, INTO által detektált túlcsordulás és BOUND típusú tartomány átlépés) tölthetők csak az illeszkedő kódszegmensekbe. A szegmenstípus (Type) mezőbeli A (accessed) bitet a processzor állítja be azzal a céllal, hogy jelezze egy szegmens szegmensregiszterbe való töltését. Az A bitet 0-ás kezdeti értékre állítva, majd később letesztelve a software követni tudja a szegmens felhasználást. Például, egy programfejlesztő rendszer kitörölheti egy alkalmazás összes szegmensének A bitjeit. Ha az alkalmazás kiakad, lehetővé vállik ezen bitek állapota alapján az alkalmazás által elért összes szegmens feltérképezése. A hibakereső mechanizmus által biztosított töréspontokkal ellentétben
(lásd 2. kötet), a felhasználtsági információ inkább a szegmensek használatára vonatkozik, mintsem a lineáris címek helyességére. A processzor aktualizálhatja a Type mezőt a szegmens elérésekor, még akkor is, ha a hozzáférés egy olvasási ciklus. Ha a deszkriptor táblázatok a ROM-ban vannak elhelyezve, szükségessé vállhat a hardware részére, hogy az írási ciklus ideje alatt megelőzze a ROM adatbuszra való csatlakozásának engedélyezését. Ugyanakkor egy ROM-ba író ciklus esetén szükség lehet a READY# jel processzorba történő visszajuttatására, különben a ciklus soha sem fejeződne be. A hardware ezen tulajdonságai szükségesek, ha ROM-ra alapozott deszkriptor táblázatokat használunk a 386-os processzorban, amely beállítja az A bitet valahányszor egy szegmens deszkriptor. betöltésre kerül A 486 és 148 A védett üzemmód felépítése, működése Pentium processzorok ellenben csak akkor állítják 1-re az A bitet, ha az
előzőleg még nem volt beállítva. A ROM-ba elhelyezett deszkriptortáblázatokba való írás megelőzhető, beállítva minden egyes deszkriptor A bitjét. DPL (Descriptor Priviledge Level) a deszkriptor privilégiumszintje. A szegmens privilégiumszintjét határozza meg, a már leírt védelmi mechanizmus alkalmazásával. A szegmens jelenlétét jelző bit: Ha ez a bit értéke 0, a processzor egy "betöltetlen szegmens" kivételt generál, amikor a deszkriptor szelektora betöltődik egy szegmens regiszterbe. Ezt az időközben elérhetetlenné vállt szegmensekhez való hozzáférés felismerésére használják. Egy szegmens akkor vállhat elérhetetlenné (unavailable), mikor az operációs rendszernek szabad memória területet kell létrehoznia. A memóriában helyet foglaló, alkalmazáson kívüli struktúrák, mint például a fontok vagy periféria meghajtók által elfoglalt hely felszabadításra kerül. Egy struktúra helye a szegmens
"betöltetlen" megjelölésével szabadítható fel (ezt a szegmens jelenlétét jelző bit 0-ra állításával lehet elérni). Ezt követően a szegmens által eddig lefoglalt területet felhasználhatjuk más célra. A legközelebbi alkalommal, mikor a felszabadított struktúrára szükség van, a "betöltetlen szegmens" kivétel fogja jelezni, hogy a szegmenst újra be kell tölteni a memóriába. A memszervezés ezen a felhasználói programok számára áttetsző formáját virtuális memóriának nevezzük. Egy operációs rendszer a fizikai memóriánál sokkal nagyobb mennyiségü virtuális memóriát képes fenntartani azzal, hogy minden pillanatban csak néhány szegmenst tárol egyszerre a fizikai memóriában. A 3.30 ábrán egy olyan deszkriptor formátumát láthatjuk, amelyben a szegmens jelenlétét jelző bit törölve van. Ha ez a bit 0, az operációs rendszernek engedélyezve van az "Elérhető" (Available) mezőben eltárolni a
saját adatait, mint például a hiányzó szegmens helyét tekintő információkat. 149 Általános CPU programozási információk 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Elérhető P DPL S Típus Elérhető Elérhető +4 +0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 3.30 ábra: Szegmens deszkriptor (a szegmens nincs jelen) 3.6324 Szegmensdeszkriptor-táblázatok Két fajta deszkriptortáblázat létezik: a globális deszkriptortáblázat (GDT) a lokális deszriptortáblázat (LDT) A taszkoknak van egyetlen egy, közös GDT-je, illetve minden egyes aktív taszknak külön-külön van egy LDT-je. A deszkriptor táblázat egy szegmens deszkriptorokból álló tömb, amint azt a 3.31 ábra mutatja Egy deszkriptor táblázat hossza változó, és legtöbb 8192 (213) deszkriptort tartalmazhat. A processzor nem használja a GDT legelső deszkriptorát. Erre a "null
deszkriptorra" mutató szegmens szelektor, adat szegmens regiszterekbe (DS, ES, FS vagy GS-be) töltve, nem generál kivételt, viszont minden olyan esetben kivételt eredményez, amelyben megkísérelünk egy memória hozzáférést ezzel a deszkriptorral. Inicializálva a szegmensregisztereket ezzel a szegmensszelektorral, garantálhatjuk, hogy a használaton kívüli szegmensregiszterekre való véletlen hivatkozások kivételt idézzenek elő. 150 A védett üzemmód felépítése, működése GLOBÁLIS LOKÁLIS DESZKRIPTOR TÁBLÁZAT DESZKRIPTOR TÁBLÁZAT Az első deszkriptor a GDT-ben nem használt HATÁR BÁZISCÍM GDTR regiszter +56 +56 +48 +48 +40 +40 +32 +32 +24 +24 +16 +16 +8 +8 +0 +0 HOZZÁFÉRÉS HATÁR BÁZISCÍM LDT deszkriptor (GDT belépési pont #2) 3.31 ábra: Deszkriptor táblázatok 3.6325 Deszkriptortáblázat bázisregiszterek A processzor a GDTR és IDTR regiszterek alapján találja meg a globális deszkriptor táblázatot
(GDT), illetve a megszakítások deszkriptorát (IDT). Ezek a regiszterek tartalmazzák a táblázatok 32 bites lineáris címtartománybeli címeit. Ezenkívül tárolják még a táblázatok méreteinek 16 bites határ értékét. Valahányszor az IDTR és GDTR regiszterek betöltésére vagy elmentésére kerül sor, egy - a 3.32 ábrán látható - 48 bites "pszeudódeszkriptor"-ra történik memóriahivakozás. A felhasználómódbeli (3. privilégiumszint) illeszkedési hibák elkerülése végett ajánlatos a pszeudódeszkriptort páratlan szó címre elhelyezni (vagyis egy olyan címre, amelynek 4-el való osztási maradéka 2). Így a processzor egy illesztett szót, és azt követően egy illesztett duplaszót tárol. A felhasználó-módbeli programok normális esetben nem tárolnak pszeudó-deszkriptorokat, de egy illeszkedés-ellenőrzési hiba kiváltásának lehetősége elkerülhető a pszeudódeszkriptorok ilyen típusú illesztésével. 151 Általános
CPU programozási információk 47 16 15 0 A cache vonal feltöltés teljesítményének maximalizálása érdekében célszerű a GDT és IDT 3.32 ábra: Pszeudó deszkriptor báziscímeit egy nyolc Byte-os kerethez illeszteni. A GDT, illetve formátum IDT határértékei Byte-okban vannak kifejezve. Csakúgy, mint a szegmensek estében, itt is a határ (limit) értékét a báziscímmel összeadva kapjuk meg az utolsó, érvényes Byte címét. Ha a határ értéke 0, pontosan egy érvényes Byte-ot határoz meg Minthogy a szegmens deszkriptorok hossza minden esetben nyolc Byte, a határ értéke mindíg eggyel kevesebb kell legyen mint nyolc egész számú sokszorosa (tehát 8N-1). Az LGDT és SGDT utasítás feltölti, illetve kiolvassa a GDTR regisztert, a LIDT és SLDT utasítás pedig az IDTR regisztert tölti fel, illetve olvassa ki. Báziscím Határ A harmadik deszkriptor tábla a lokális deszkriptortáblázat (LDT). Egy 16 bites szegmens szelektor azonosítja, amelyet
az LDTR regiszter tárol. Az LDTR regiszter ezen kívül tartalmazza az LDT báziscímét és határértékét, de ezeket a processzor tölti be automatikusan az LDT (GDTből kiolvasott) szegmens deszkriptorából A cache vonal feltöltés (cache line fill) teljesítményének maximalizálása érdekében ajánlatos az LDT-t egy nyolc Byte-os kerethez illeszteni. 3.633 Lapfordítás Lineáris cím alatt egy egyenletes, szegmentálás mentes címtartománybeli 32 bites címet értünk. Ez a címtartomány lehet egy kiterjedt fizikai címtartomány (például több GByte-nyi RAM-ból képezett), ugyanakkor a lapozás segítségével szimulálható ez a címtartomány, egy kis mennyiségű RAM és némi lemezterület segítségével. Ha lapozást használunk, a lineáris cím vagy a neki megfelelő fizikai címre fordítódik, vagy egy kivétel generálódik. A kivétel biztosítja az operációs rendszernek azt a lehetőséget, hogy beolvassa a lapot a lemezről (valószínűleg egy
másik lap lemezreküldésének kíséretében), majd újraindítsa a kivételt előidéző utasítást. 152 A védett üzemmód felépítése, működése A lapozás abban tér el a szegmentálástól, hogy fix méretű lapokat használ. A szegmensekkel ellentétben, amelyeknek hossza általában megegyezik a bennük foglalt kód- vagy adatstruktúrák méretével, a lapoknak rögzített méretük van. Abban az esetben, ha a szegmentálás a címfordítás egyedüli felhasznált módja egy, a fizikai memóriában jelen levő adatstruktúrának minden része a memóriában található. Ha lapozást használunk, az adatstruktúra egy része a memóriában, másik része a lemezen lehet. Az az információ, amely vagy a lineáris címeket térképezi le fizikai címekre, vagy kivételeket vált ki, egy memóriában tárolt, laptáblázat néven ismert adatsruktúra. Csakúgy, mint a szegmentálás esetében, ez az információ is egy processzoron belüli gyorsítótárba (cache)
kerül, a címfordításra szükséges buszciklusok számának minimizálása érdekében. A szegmentálással ellentétben, a címfordító gyorsítótárak teljesen áttetszőek a felhasználói programok részére. A processzor által címfordításra felhasznált információkat tároló gyorsítótárak a "fordítási segédpuffer" (TLB - Translation Lookaside Buffer) nevet viselik. A TLB a legtöbb laptáblázat olvasásra irányuló kérésnek eleget tesz. A felesleges buszciklusok csak akkor jelennek meg, amikor a TLB-ben nincs találat. Ez általában akkor történik, amikor egy laphoz hosszú ideje nem volt hozzáférés. 3.6331 Lapozási opciók A lapozás megengedett, ha a CR0 regiszter 31. bitje magasra van állítva. Ezt a bitet általában az operációs rendszer állítja be a software inicializálás idején. Ha a lapozás engedélyezett, a fizikai címek lineáris címekké alakításához a címfordításnak egy második szintjét alkalmazzuk. Ha a
lapozás nem engedélyezett, a lineáris cím egyben fizikai cím is. A PG bit 1 kell legyen, ha az operációs rendszer egynél több programot futtat virtuális 8086-os üzemmódban, vagy az igényeknek megfelelően lapozható (demand-page) virtuális memóriát használunk. 153 Általános CPU programozási információk 3.6332 Lineáris cím A 3.33 ábrán egy 4 kByte-os lap lineáris címének formátumát láthatjuk 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 Lapcímtár Táblázat 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 1 0 Ofszet 7 6 5 4 3 2 3.33 ábra: A lineáris cím formátuma A 3.34 ábra bemutatja, hogy a processzor a laptáblázatokat vizsgálva, miként fordítja le egy lineáris cím lapcímtár, táblázat, és ofszet mezőit fizikai címre. A címzőmechanizmus a lapcímtár mezőt használja indexként egy lapcímtárban. A táblázat mezőt indexként használja a lapcímtár
által kijelölt laptáblázatban. Az ofszet mezőt a laptáblázat által meghatározott lapon belüli operandusok címzésére hasznája. 3.6333 Laptáblázatok A laptáblázat egy 32 bites bejegyzéseket tartalmazó tömb. Maga a laptáblázat is egy lap, és 4096 Byte-nyi adatot tartalmaz, vagy legtöbb 1 kByte 32 bites bejegyzést. A négy kilóByte-os oldalak, beleértve a lapcímtárakat és a laptáblázatokat is, 4 kByte-os keretekhez illeszkednek. Két szinten elhelyezett táblázatokat alkalmazunk egy memória lap megcímzéséhez. A legkülső szinten a lapcímtár helyezkedik el Egy lapcímtár maximum 1024 bejegyzést tárol, amelyek a második szintű laptáblázatokat címezik meg. Egy laptáblázat legtöbb 1 kByte-nyi lapot címez meg a fizikai memóriában. Tehát egyetlen lapcímtár által megcímzett laptáblázatok összesen 1 MByte (220) 4 kByte-os lapot képesek megcímezni. Ha minden egyes lap 4 kByte (212) Byte-ot tartalmaz, egyetlen címlaptár
laptáblázatai 4 GByte-nyi (220x212=232) lineáris címtartományt képes átfogni. A 4 kByte-nál nagyobb méretű lapok használatának támogatásáról a függelékben olvashatunk. 154 A védett üzemmód felépítése, működése Lapcímtár Táblázat Ofszet Lap keret Lap directory Lap táblázat Fizikai cím Lapcímtár bejegyzés Lap táblázat bejegyzés 3.34 ábra: Lapfordítás Az aktuális lapcímtár fizikai címe a CR3-as regiszterben van eltárolva, amelyet még a lapcímtár báziscím regiszterének (PDBR) is nevezünk. A memóriaszervező software dönti el, hogy az összes taszk egy lapcímtárat használ-e, vagy minden egyes taszk rendelkezik egy külön lapcímtárral, esetleg a két megoldás valamilyen kombinációját használja. 3.6334 Laptáblázat bejegyzések A laptáblázatok és lapcímtárak bemenőpontjai, 4 kByte-os lapok esetén, a 3.35 ábrán látató formátumok egyikével rendelkeznek A 4 kByte-nál nagyobb lapok laptáblázat- és
lapcímtár formátumáról további információk a függelékben találhatók. 155 Általános CPU programozási információk Laptáblázat bejegyzés 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 Hozzáférhető 11 a programozó 10 9 számára 0 8 0 7 6 Piszkos Hozzáférhető 5 4 Cache tiltott 3 Átíró 2 Felhasználó 1 Írható 0 Jelen van Lapkeret cím 31-12 Lapcímtár bejegyzés 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 Hozzáférhető 11 a programozó 10 9 számára 0 8 Lapméret (0=4k) 7 6 0 Hozzáférhető 5 4 Cache tiltott 3 Átíró 2 Felhasználó 1 Írható 0 Jelen van Lapkeret cím 31-12 3.35 ábra: A lapcímtár formátuma és a laptáblázatok elemei a 4K-s lapokhoz. 3.6335 Lapkeret cím A lapkeret cím a lap fizikai kezdőcímét határozza meg. A
lapcímtárakban a lapkeret cím egy laptáblázat címe. Egy második szintű laptáblázatban a lapkeret cím annak a négy kByte-os lapnak a címe, amely a keresett operandust, illetve utasítást tartalmazza. 3.6336 A Present (betöltött, jelenlevő) bit A P bit megmutatja, hogy egy lapkeret a fizikai memóriában jelenlevő lapra mutat-e. Ha a Present bit törölve van, a lap nincs betöltve a memóriába, és a laptáblázat bejegyzés fennmaradó része az operációs rendszer rendelkezésére áll, hogy abba tárolhassa például a hiányzó lap hollétéről 156 A védett üzemmód felépítése, működése szóló információt. A 336 ábrán látható a laptáblázat bejegyzés formátuma abban az esetben, ha a Present bit értéke 0. 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 H o z z á f é r h e t ő 0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 3.36 ábra: Laptáblázat
bejegyzés formátuma nem jelenlévő lapoknál Ha a laptábálzatok bármely szintjén a P bit törölve van, egy laptáblázat bejegyzés használatát célzó kisérlet laphiba kivételt eredményez. Az igényeknek megfelelően lapozható (demandpage) virtuális memóriát támogató rendszerekben,a tárgyalt esetben a következő eseménysorozat jelentkezik: 1. Az operációs rendszer betölti a lapot a lemezről a fizikai memóriába 2. Az operációs rendszer bejegyzi a lapkeret címét a laptáblázatba és beállítja annak P bitjét. Más bitek, mint például a piszkos (dirty) illetve a hozzáfért (accessed) bitek is beállítódhatnak. 3. Minthogy egy fordítási segédpuffer (TLB) még mindég tartalmazhatja a régi laptáblázat bejegyzés másolatát, az operációs rendszer érvényteleníti azokat. A fordítási segédpufferek (TLB-k) érvénytelenítésének mikéntjét a fejezet későbbi része tárgyalja. 4. A kivételt előidéző program ezek után
újraindítódik Megjegyzendő, hogy a lapcímtárnak mint olyannak, nincs Present bitje a CR3-ban. A lapcímtár betöltetlen is lehet, amíg a hozzárendelt taszk felfüggesztett állapotban van, de az operációs rendszernek biztosítania kell azt, hogy a CR3-nak egy folyamat TSS-ében levő képe által kijelölt lapcímtár, jelen legyen a fizikai memóriában, még mielőtt a folyamat megkapná a vezérlést. A lapcímtárnak ezenkívül mindaddig a memóriában kell maradnia, amíg a taszk aktív. 157 Általános CPU programozási információk 3.6337 Hozzáfért (accessed) és "piszkos" (dirty) bitek Ezen bitek szolgáltatnak adatokat a laphasználatról a laptáblázatok mindkét szintjén. Az Accessed bit a lapokhoz, vagy egy második szintü laptáblázathoz történő olvasási vagy írási hozzáférések jelzésére használt. A Dirty bit egy lapba való írási hozzáférés jelzésére használatos. Ezeket a biteket a hardware állítja be, bár a
processzor impiciten egyik bitet sem törli ezek közül. A processzor az A bitet a laptáblázatok mindkét szintjén beállítja, még a lapot olvasó illetve író műveletek előtt. A processzor még egy, az illető laptáblázat bejegyzés által megjelölt címre író művelet előtt beállítja a D bitet. Kizárólag a második szintü laptáblázat Dirty bitje kerül felhasználásra, a processzor nem használja a lapcímtár D bitjét. Az operációs rendszer felhasználhatja az Accessed bitet, amikor némi szabad tárterületet kell létrehoznia egy lap vagy egy második szintü laptáblázat lemezre küldésével. A laptáblázatok A bitjének periódikus törlésével ellenőrizheti, hogy melyek az utoljára használt lapok. A használatlan lapok esélyesek a lemezreküldésre. Az operációs rendszer felhasználhatja a Dirty bitet, amikor egy lapot visszaküld a lemeztárra. A lap memóriába töltésének pillanatában törölve a Dirty bitet, az operációs rendszer
ellenőrizheti, hogy a laphoz volt-e írás-hozzáférés. Ha a lapnak létezik a lemezen egy másolata, és nem történt írás-hozzáférés a memóriában levő példányhoz, nem szükséges a diszk memória szerinti frissítése. A könyv második kötetéből megtudhatjuk, hogy a multiprocesszoros rendszerekben a processzor hogyan újítja fel az Accessed és Dirty biteket. 3.6338 Írás/olvasás illetve felhasználó/felügyelő bitek A Read/Write és User/Supervisor biteket a processzor lapvédelem ellenőrzésre használja fel, amit a címfordítással egyidőben végez. A védelemről bővebb információ a fejezet későbbi részében található. 158 A védett üzemmód felépítése, működése 3.6339 Lapszintű cache-vezérlő bitek A PCD és PWT biteket lapszintű cache szervezésre alkalmazzák. A software-ek ezen bitek segítségével kontrolálhatják az önálló lapok vagy a második szintű laptáblázatok cache használatát. A cache használatról bővebb
információ egy későbbi fejezetben található. 3.63310 Fordítási segédpufferek A legutoljára használt laptáblázat bemeneteket a processzor a chip-be épített cache tárakban, az úgynevezett fordítási segédpufferekben, (más néven TLB) tárolja. A Pentium mikroprocesszorban az adat- és utasítás cache memóriáknak különálló fordítási segédpufferei vannak. A lapozások legjelentősebb hányada a TLB-k tartalmát használja fel. A memóriában található laptáblázatok elérésére csak abban az esetben hajtódnak végre buszciklusok, amikor a fordítási segédpufferek nem tartalmazzák a kért lap fordítási információit. A TLB-k áttetszőek a felhasználói programok számára (amelyeknél PL>0), de az operációs rendszerek számára (PL=0) nem. Az operációs rendszerek programozóinak azonnal érvényteleníteni kell a fordítási segédpuffereket (elvetve ezekből a laptáblázat bemenőpontokat) valahányszór a laptáblázat bemenetek
módosúlnak (akkor is, ha a Present bit értéke 0). Ha ez nem így történik, akkor címfordításkor felhasználásra kerülhetnek olyan régebbi adatok, amelyek nem tartják számon a változásokat, és ennek következtében az ezt követő laptáblázathivatkozások helytelenek lehetnek. Az operációs rendszer a CR3-as regiszter feltöltésével érvénytelenítheti a TLB-ket. A CR3-as regiszter a következő két eljárás egyikével tölhető fel: 1. Explicit feltöltés a MOV utasítás alkalmazásával, mint pld: MOV CR3,EAX 159 Általános CPU programozási információk 2. Implicit feltöltés taszkkapcsolással, amely megváltoztatja a CR3as regiszter tartalmát (Lásd később, taszkkapcsolás) Amikor egy önálló lap leképezése (mapping) operációs rendszernek az INVLPG utasítást kell lehetséges, az INVLPG utasítás csak egyetlen érvénytelenít; bár egyes esetekben az INVLPG érvényteleníti az utasítás-cache TLB-t. változik meg, az használnia. Ha
TLB bemenetet teljes egészében 3.634 Szegmens- és lapfordítás keverése A 3.37 ábra egyesíti a 336 és 334 ábrákat, és összefoglalja a logikai címek fizikai címekre való fordításának mindkét stádiumát, a lapozás engedélyezése esetében. A címfordítás mindkét stádiumában létező opciók számtalan különböző memória szervezési mód támogatására alkalmazhatók. 3.6341 A sík modell Ha a 32 bites processzor szegmensek nélkül megírt software-eket futtat, szükséges lehet a processzor szegmentáló képességének kikapcsolása. A 32 bites processzoroknak nincs szegmentálás letiltó üzemmódot kapcsoló bitje, de ugyanaz a hatás érhető el a verem-, kód- és adattartományok ugyanazon lineáris címtartományra való leképezésével. A 32 bites processzorutasítások által használt 32 bites ofszetek 4 GBytenyi lineáris címtartományt takarnak le. Ha lapozást használunk, a szegmensek a teljes lineáris címtartományra leképezhetők.
Ha egyszerre, egynél több program fut, a lapozómechanizmus segítségével minden egyes programnak önálló címtartomány biztosítható. 160 A védett üzemmód felépítése, működése 3.6342 Több lapot átfogó szegmensek A processzor architektúrája megengedi olyan szegmensek használatát, amelyek hossza meghaladja egy lap méretét. Például egy kiterjedt adatsruktúra lapok ezreit foghatja át. Ha a lapozás nem lenne engedélyezett, az adatstruktúra bármely részéhez való hozzáférés megkövetelné a teljes adatstruktúra jelenlétét a fizikai memóriában. Lapozás esetén csak a hozzáfért részt tartalmazólapnak kell a memóriában lennie. 3.6343 Több szegmenst átfogó lapok A szegmensek ugyanakor lehetnek a lapoknál rövidebbek is. Ha egy ilyen szegmens egy, más szegmensekkel nem megosztott lapon kap helyet, a fennmaradó tárterület "parlagon marad". Például egy kis méretű adatstruktúra, mint amilyen egy 1 Byte-os szemafor,
elfoglal 4 kByte-nyi helyet, ha egy lapra egyedül kerül elhelyezésre. Ha több szemafort használunk, sokkal gazdaságosabb ugyanarra az egy lapra pakolni őket. 3.6344 Nem illeszkedő lap- és szegmenshatárok Az architektúra nem tesz kötelezővé a lapok és a szegmensek határa közt semmilyen megfeleltetést. Egy lap tartalmazhatja egyik szegmens végét, illetve egy másik szegmens elejét. Hasonlóan, egy szegmens tartalmazhatja egy lap végét, illetve egy másik lap elejét. 3.6345 Illeszkedő lap- és szegmenshatárok A memória szervező software egyszerűbb és hatékonyabb lehet, ha bizonyos mértékben megköveteli a lapok illetve a szegmenshatárok közti illeszkedést. Például, ha egyetlen lapra elférő szegmens két lapra kerül elhelyezésre, kétszer több lapozási műveletre lehet szükség a szegmens eléréséhez. 161 Általános CPU programozási információk LOGIKAI CÍM 0 31 15 Szelektor 0 Ofszet Deszkriptor táblázat Szegmens deszkriptor
Lineáris cím (4k-s lapoknál) OR Tartalomjegyzék Táblázat Ofszet 4k-s Lapkeret Operandus Laptáblázat Lapcímtár Laptáblázat bejegyzés 4k-s tartalomjegyzék bejegyzés 4M-s Lapkeret 4M-s tartalomjegyzék bejegyzés Operandus CR3 Tartalomjegyzék Ofszet Lineáris cím (4M-s lapoknál) 3.37 ábra: Kombinált szegmens- és lapcím fordítás 162 A védett üzemmód felépítése, működése 3.6346 Egy laptáblázat elhelyezése szegmensenként A lapozás és szegmentálás együttes használatának egyik lehetséges megközelítése - amely leegyszerűsíti a memória szervező software-t - az, hogy minden egyes szegmensnek saját laptáblázata legyen biztosítva, ahogyan azt a 3.38 ábra mutatja Ez a megoldás a szegmensnek egyetlen lapcímtár bejegyzést biztosít, amely a szegmens lapozásához szolgáltatja a hozzáférést ellenőrző információkat. Lokális deszkriptor táblázat Lapkeretek Lapcímtár Laptáblázatok Laptáblázat bejegyzés
Laptáblázat bejegyzés Laptáblázat bejegyzés Deszkriptor Deszkriptor Lapcímtár bejegyzés Lapcímtár bejegyzés Laptáblázat bejegyzés Laptáblázat bejegyzés Laptáblázat bejegyzés 3.38 ábra: minden egyes szegmensnek biztosítani kell saját laptáblázatot 163 Általános CPU programozási információk 3.7 Védelemi mechanizmusok A védelem egy megbízható multitaszking számára elengedhetetlen. A védelem célja az, hogy a taszkok egymásba történő beavatkozását kiküszöbölje. Például, a védelem megakadályozhatja az egyik taszkot abban, hogy egy másik taszk utasításait vagy adatait felülírja. Programírás közben a védelmi mechanizmus egy tisztább képet adhat a program összeakadásairól. Ha egy program váratlan hivatkozást tesz egy nem megfelelő tárterületre, a védelmi mechanizmus meggátolhatja az eseményt, illetve visszajelezheti annak megjelenését. A végfelhasználói rendszerekben a védelmi mechanizmus megóvhat a
felderítetlen program hibák által okozott hiba lehetőségétől (a rejtett hibák sosem maradnak rejtve). Az operációs rendszert meg lehet védeni a sérülésektől, ezáltal lehetővé válik a diagnosztizálás és megkísérelhető az automatikus helyreállítás. A védelem lapokra és szegmensekre alkalmazható. A processzor egyik regiszterében található két bit meghatározza az aktuálisan futó program privilegizálási szintjét (más néven aktuális privilégium szint, vagy CPL). A CPL ellenőrzése a szegmentálási és lapozási címfordítás ideje alatt történik. Annak ellenére, hogy nem létezik egy vezérlőregiszter vagy egy üzemmód meghatározó bit, amellyel a védelmi mechanizmust ki lehetne kapcsolni, ugyanaz a hatás érhető el azzal, hogy minden egyes szegmens szelektorhoz, szegmens deszkriptorhoz, illetve laptáblázat bejegyzéshez nullás privilégium szintet (a legmagasabb privilegizáltsági szintet) rendelünk 3.71 Szegmens szintű
védelem A védelem biztosítja annak lehetőséget, hogy egy helytelenül működő program más programokra, illetve azok adataira gyakorolt beavatkozásának mennyiségét korlátozni lehessen. A védelem egy értékes 164 Védelmi mechanizmusok segítőeszköze a software írásnak, mivel megengedi különböző software eszközök (operációs rendszer, hibakereső, stb.) számára, hogy sértetlenül megmaradjanak a memóriában. Mikor egy felhasználói program elakad, a rendszer képes diagnózis üzeneteket megjelenteni, illetve a hida esetleges helyreállítására. A gyártási fázisban a védelem megbízhatóbbá teszi a software-eket azzal, hogy lehetőséget biztosít az operációs rendszer számára a helyreállító eljárások elindítására. Minden egyes memóriahivatkozás esetén ellenőrződik, hogy eleget tesz-e a védelmi feltételeknek. Minden ellenőrzés a memóriaciklus kezdete előtt indul be; bármely szabálytalanság meggátolja a ciklus
elkezdését és kivételt eredményez. Minthogy az ellenőrzések a címfordítással párhuzamosan történnek, nincs teljesítménykiesés. Öt védelmi ellenőrzés típus létezik: 1. 2. 3. 4. 5. Típus ellenőrzés Határ (limit) ellenőrzés A megcímezhető tartományt érintő megszorítások Az procedúrák bemenőpontjait érintő megszorítások Az utasításkészletet érintő megszorítások A védelem megszegése kivételt eredményez. A kivétel mechanizmus magyarázatát lásd a fejezet későbbi részében Ezen rész azokat a védelem megszegéseket írja le, amelyek kivételekhez vezetnek. 3.72 A szegmens deszkriptorok és a védelem A 3.39 ábra a szegmens deszkriptor azon mezőit mutatja be, amelyeket a védelmi mechanizmus használ. A "Típus" mező különböző bitjei az általuk ellátott funkciókkal vannak elnevezve. Amikor az operációs rendszer létrehoz egy deszkriptort, beállítja annak védelmi paramétereit is. Általános esetben a
felhasználói programok íróinak nem szükséges a védelmi paraméterekkel törődniük. Amikor egy program betölt egy szegmensregiszterbe egy szegmens szelektort, a processzor betölti mind a szegmens báziscímét, 165 Általános CPU programozási információk mind a védelmi információkat. Minden szegmensregiszter láthatalan részében hely van biztosítva a báziscím, limit, típus és privilégium szint tárolására. Amíg ez az információ a szegmensregiszterben rezidens, az ugyanarra a szegmensre irányuló, egymást követő védelmi ellenőrzések teljesítmény kimaradás nélkül végezhetők. 3.721 Típusellenőrzés A felhasználói kód- és adatszegmensek deszkriptorain kívül, a processzornak rendszerszegmens- és kapudeszkriptorai is vannak. Ezek olyan adatstruktúrák, amelyek taszkok, illetve kivételek és megszakítások szervezésére használatosak. A 340 ábra felsorolja a rendszer szegmensek és kapuk minden definiált típusát.
Megjegyzendő, hogy nem minden deszkriptor határoz meg egy szegmenst; a kapudeszkriptorok a procedúrák bemenőpontjaira mutató pointereket tartalmaznak. Típus Decimális 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Meghatározás Bináris 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 Fenntartva Hozzáférhető 16 bites TSS LDT Foglalt 16 bites TSS 16 bites Call kapu Taszk kapu 16 bites megszakítás kapu 16 bites csapda kapu Fenntartva Hozzáférhető 32 bites TSS Fenntartva Foglalt 32 bites TSS 32 bites Call kapu Fenntartva 32 bites megszakítás kapu 32 bites csapda kapu 3.40 ábra: Rendszer szegmens- és kapu típusok 166 Védelmi mechanizmusok Az adat- és kódszegmens deszkriptorok típus mezői olyan biteket tartalmaznak, amelyek meghatározzák a továbbiakban a szegmens célját (lásd 3.39 ábra) Az Írható (Writable) bit egy adatszegmens deszkriptorban meghatározza, hogy a programok írhatnak-e a szegmensbe. Az Olvasható
(Readable) bit egy kódszegmens deszkriptorban meghatározza, hogy a programok olvashatnak-e egy szegmensből (például a kódtartományban tárolt konstansokat). Egy olvasható kódszegmens kétféleképpen olvasható: 1. A CS regiszter segítségével, a CS fölülíró prefixet használva 2. Az adatszegmens regiszterbe (DS, ES, FS, vagy GS regiszterekbe) olvasva a deszkriptor egy szelektorát. A típusellenőrzés felhasználható olyan programozási hibák felderítésére, amelyek megkísérelnék a szegmenseket a programíró számára nemkívánatos módon alkalmazni. A processzor két alkalommal ellenőrzi a típusinformációt: 1. Mikor egy deszkriptor szelektora betöltődik szegmensregiszterbe. Bizonyos szegmensregiszterek meghatározott deszkriptorokat tartalmazhatnak; például: egy csak A CS regisztert csak végrehajtható szegmens szelektorával szabad feltölteni. A végrehajtható de nem olvasható szegmensek szelektorai nem tölthetők be az
adatszegmens regiszterekbe. Csak írható adatszegmensek szelektorai tölthetők az SS regiszterbe. 167 Általános CPU programozási információk 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Báziscím 31-24 A G B 0 V L Szegmens határ 19-16 1 DPL 1 0 E W A Báziscím 23-16 Szegmens határ 15-0 Báziscím 15-0 +4 +0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Báziscím 31-24 A G D 0 V L Szegmens határ 19-16 1 DPL 1 1 C R A Báziscím 23-16 Szegmens határ 15-0 Báziscím 15-0 +4 +0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Báziscím 31-24 G Báziscím 15-0 0 Szegmens határ 19-16 1 DPL 0 Típus Báziscím 23-16 Szegmens határ 15-0 31 30 29
28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 A - Hozzáférhető B - Nagy C - Illeszkedő D - Alapbeállítás DPL - Deszkriptor privilégium szint E - lefelé növekvő G - Szemcsézettség R - Olvasható W - Írható 3.39 ábra: Védett módban használt deszkriptor mezők 168 +4 +0 Védelmi mechanizmusok 2. Mikor az utasítások olyan szegmensekhez férnek hozzá, amelyek deszkriptorai már be vannak töltve a szegmensregiszterekbe. Egyes szegmenseket az utasítások csak bizonyos előre meghatározott módon használhatnak; például: Egyetlen utasítás sem írhat egy végrehajtható szegmensbe. Egyetlen utasítás sem írhat egy adatszegmensbe ha az Írható (Writable) bit nincs beállítva. Egyetlen utasítás sem olvashat egy végrehajtható szegmensből, ha az Olvasható (Readable) bit nincs beállítva. 3.722 Határ (limit) ellenőrzés Egy szegmens deszkriptor limit mezője meggátolja a programokat abban, hogy a
szegmensen kívülre címezhessenek. A határ gyakorlati értéke függ a G (Granularity) bit állapotától. Adatszegmensek esetén a határ függ az E (Expansion) bit értékétől is. Az E bit a Típus mező egyik bitjének megnevezése, ha adatszegmens deszkriptorra vonatkozik. Ha a G bit törölve van, a határ a deszkriptor 20 bites Limit mezőjének értéke. Ebben az esetben a határ a 0-tól F FFFFH értékig terjed (220 - 1 vagy 1 MByte). Ha a G bit értéke 1, a processzor beszorozza a limit mező értékét egy 212 skálatényezővel. Ebben az esetben a határ a 0FFFH-tól (212- 1 vagy 4 kByte) egészen FFFF FFFFH-ig (232-1 vagy 4 GByte) terjed. Jegyezzük meg, hogy a skálatényező használatakor a cím alsó tizenkét bitje nem kerül limit ellenőrzés alá; ha a G bit 1-re van állítva és a szegmenshatár értéke 0, a szegmensen belüli érvényes ofszetek 0-tól 4095-ig terjednek. Minden szegmenstípus esetén, kivéve a lefele bővülő szegmenseket, a limit
értéke egyel kevesebb mint a szegmens Byte-okban 169 Általános CPU programozási információk kifejezett hossza. A processzor általános védelmi hibát idéz elő a következő esetek bármelyikében: Egy olyan memóriabeli Byte elérésére tett kísérlet, amelynek a címe > limit Egy olyan memóriabeli szó elérésére tett kísérlet, amelynek a címe > (limit-1) Egy olyan memóriabeli duplaszó elérésére tett kísérlet, amelynek a címe > (limit-3) Egy olyan memóriabeli négyes szó elérésére tett kísérlet, amelynek a címe > (limit-7) A lefele bővülő adatszegmensek esetében a határnak ugyanaz a funkciója van, csak másképpen van értelmezve. Ebben az esetben az érvényes ofszetek tartománya a (limit+1)-től a 232-1 -ig terjed, ha B=1, illetve 216-1-ig, ha B=0. Egy lefele bővülő szegmensnek akkor van maximális hossza, ha a szegmenshatár értéke 0. A limit ellenőrzés olyan programhibákat "fedez fel",
mint amilyenek a "kiszaladó" indexek, illetve az érvénytelen mutató számítások. Ezek a hibák a megjelenésük pillanatában detektálódnak, ezáltal a kiváltó ok megtalálása egyszerűbb. Limit ellenőrzés nélkül ezek a hibák felülírhatnának kritikus tárterületeket egy másik modul belsejében, és az említett hibák létezése mindaddig nem lenne kimutatható, amíg a sérült modul össze nem esne, ez egy olyan esemény lévén, amely jóval a tulajdonképpeni hiba után következne be. A védelem képes ezeket a hibákat elhárítani, és jelezni forrásukat. A szegmenshatár ellenőrzés mellett létezik még a deszkriptortáblázatok limit ellenőrzése is. A GDTR, LDTR, és az IDTR regiszterek tartalmaznak egy-egy 16 bites limit értéket. Ezeket a processzor arra használja, hogy meggátolja a programokat abban, hogy egy deszkriptortáblázaton kívül eső szegmens deszkriptort szelektáljanak. A deszkriptortáblázat határértéke a táblázat
utolsó érvényes Byte-ját határozza meg. Minthogy minden deszkriptor 8 Byte-nyi hosszú, egy N deszkriptort tartalmazó táblázat határértéke 8N-1 kéne legyen. Egy szelektornak az értéke lehet 0 is. Ez a deszkriptor a GDT legelső elemére vonatkozik, amely nem használatos. Annak ellenére, hogy ezt a 170 Védelmi mechanizmusok deszkriptort be lehet tölteni egy szegmensregiszterbe, bármely olyan próbálkozás, amely ezzel a deszkriptorral hivatkozna a memóriára, általános védelmi hibát váltana ki. 3.73 Privilégium szintek A védelmi mechanizmus négy privilégium szintet ismer, számozásuk 0-tól 3-ig történik. A nagyobb számok alacsonyabb privilégiumszintet jelentenek. Ha minden egyéb védelmi ellenőrzés ki van elégítve, egy általános védelmi hiba generálódik, valahányszor egy program megkísérel egy szegmenshez hozzáférni a szegmenshez rendelt privilégium-szintnél kevésbé privilegizált szinten (nagyobb privilégium számmal). Annak
ellenére, hogy nem létezik a védelmi mechanizmus kikapcsolását szolgáló vezérlőregiszter vagy üzemmód-váltó bit, ugyanaz a hatás érhető el minden privilegizálási szintnek 0-s értéket rendelve. (A CR0 regiszter PE bitje nem csak a védelmi mechanizmust engedélyező bit; a védett üzemmód engedélyezésére használt, vagyis a programvégrehajtás egy olyan módjának, amelyben a teljes 32 bites architektúra elérhető. Ha a védett üzemmód nem engedélyezett, a processzor valós üzemmódban dolgozik, amelyben egy gyors, kiterjesztett 8086-os processzornak tűnik.) A privilégium-szinteket az operációs rendszerek megbízhatóságának javítására lehet felhasználni. Az operációs rendszernek a legmagasabb privilegizáltságot (számozás szerinti legkisebb privilegizálási szintet) biztosítva megvédhető attól, hogy más programokban előforduló gubancok által megsérüljön. Ha egy program összeomlik, az operációs rendszernek megadatik ezáltal
a lehetőség arra, hogy diagnózis-üzenetet generálhasson, illetve helyreállító eljárásokat kíséreljen meg. Egy újabb privilegizálási szint állapítható meg a rendszersoftware egyéb részei, mint például a periféria-eszközöket kezelő programok számára. Abban az esetben, ha egy kezelőprogram (device driver) fagyna le, az operációs rendszer képes kell, hogy legyen egy diagnózis-üzenetet küldeni, tehát van értelme az operációs rendszert megvédeni a kezelőprogramok gubancaitól. Egy kezelőprogram 171 Általános CPU programozási információk ugyanakkor fontos perifériát kezelhet, mint például egy lemezegységet. Ha a felhasználói program akad el, a kezelőprogramnak nem szabad a lemez könyvtárstruktúráját módosítania. A kezelőprogram számára célszerű egy köztes privilegizálási szintet biztosítani az operációs rendszer és a felhasználói programok között. A felhasználói programok a legalacsonyabb privilegizálási
szintet (számozás szerinti legnagyobb szintet) kapják. A 3.41 ábra bemutatja, hogy miként értelmezhetők ezek a privilegizálási szintek mint védelmi gyűrűk A középpont jelképezi a legkritikusabb software-t, általában egy operációs rendszer magját (kernel) tartalmazó szegmenseket. A külső gyűrűk a kevésbé kritikus software-eket jelképezik. A következő adatstruktúrák tartalmaznak privilegizálási szinteket: A CS szegmens-regiszter legalsó két bitje tartalmazza az aktuális privilégium-szintet (CPL). Ez az aktuálisan futó program privilegizálási szintje. Az SS regiszter legalsó két bitje is tárolja a CPL egy másolatát. Normális esetben a CPL értéke megegyezik annak a kódszegmensnek a privilegizálási szintjével, amelyből az utasításelérés történik. A CPL értéke megváltozik, valahányszor a vezérlés átadódik egy eltérő privilegizálási szinttel rendelkező kódszegmensnek. A szegmens-deszkriptorok tartalmaznak
egy "deszkriptorprivilegizálási szint"-nek nevezett mezőt (DPL). A DPL a szegmenshez rendelt privilegizálási szint. A szegmens-szelektorok tartalmaznak egy "szükséges privilegizálási szint"-nek nevezett mezőt (RPL). Az RPL célja, hogy a szelektort létrehozó procedúra privilegizálási szintjét jelképezze. Ha az RPL kevésbé privilegizáltabb a CPL-nél, akkor fölülírja a CPL-t. Amikor egy privilegizáltabb program egy kevésbé privilegizált programtól kap egy szegmens-szelektort, az RPL teszi azt, hogy a memóriahozzáférés a kevésbé privilegizált szinten menjen végbe. 172 Védelmi mechanizmusok A privilegizálási szintek akkor kerülnek ellenőrzés alá, amikor egy deszkriptor szelektora betöltődik egy szegmens-regiszterbe. Az adathozzáférés esetén alkalmazott ellenőrzések eltérnek a végrehajtható szegmensek közötti vezérlésátadáskor alkalmazott ellenőrzésektől; ebből kifolyólag az elkövetkező
alfejezetekben a két hozzáférés-típus különkülön kerül bemutatásra. Operációs rendszer KERNEL Op. rendszer kezelõprogramok Eszközmeghajtók, stb. Alkalmazások 0. szint 1. szint 2. szint 3. szint 3.41 ábra: Védelmi gyűrűk 3.74 Az adathozzáférések korlátozása Ahhoz, hogy a memóriában levő operandusokat megcímezzük, egy adatszegmens szelektorát be kell tölteni egy adatszegmensregiszterbe. (a DS, ES, FS, GS, vagy SS regiszterekbe) A proceszszor ellenőrzi a szegmens privilegizálási szintjeit. Az ellenőrzés a szegmensszelektor betöltésének pillanatában történik Amint azt a 342 ábra mutatja, három különböző privilegizálási szint kerül ilyen típusú ellenőrzés alá. 173 Általános CPU programozási információk A három ellenőrzött privilegizálási szint a következő: 1. A program CPL-je (aktuális privilegizálási szintje). Ezt a CS regiszter két legalsó helyértékű bitje tárolja. 2. Az operandust tartalmazó
szegmens deszkriptorának DPL-je (deszkriptor-privilegizálási szintje). 3. Az operandust tartalmazó szegmens megjelölésére használt szelektor RPL-je (szükséges privilegizálási szintje). Ezt az operandus elérésére felhasznált szegmensregiszter (az SS, DS, ES, FS, vagy GS regiszterek) két legalsó bitje tárolja. Ha az operandus a veremszegmensben van, az RPL megegyezik a CPL értékével. 174 Védelmi mechanizmusok Operandus szegmens deszkriptor 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +4 DPL +0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Aktuális kódszegmens regiszter CPL Operandus szegmens szelektor RPL CPL - Aktuális privilégium szint Privilégium ellenőrzés DPL - Deszkriptor privilégium szint RPL - Igényelt privilégium szint 3.42 ábra: Privilégium ellenőrzés adathozzáféréseknél Az utasítások csak abban az esetben tölthetnek fel egy
szegmensregisztert, ha a szegmens DPL-je kisebb vagy egyenlő privilegizálási szintű (nagyobb privilégium szám) mint a CPL és a szelektor RPL-je közül a legkevésbé privilegizáltnál. Egy taszk által megcímezhető tartomány a CPL változásával módosul. Ha a CPL=0, bármely privilegizálási szintű adatszegmens hozzáférhető; ha a CPL=1, csak az 1-től 3-ig terjedő privilégiumszintű 175 Általános CPU programozási információk adatszegmensek érhetők el; ha a CPL=3, csak a 3-as privilegizálási szintű adatszegmensek érhetők el. Azok a rendszerek, amelyek a lehetséges négy privilegizálási szint közül csak kettőt használnak, a 0-s és a 3-as szinteket kell alkalmazzák. 3.741 Kódszegmensekbeli adatok elérése Szükséges lehet a kódszegmensben adatokat tárolni, például abban az esetben, ha a kód és az adatok is ROM típusú tárban vannak megadva. A kódszegmensek szabályszerűen tárolhatnak konstansokat; nem lehetséges
kódszegmensként definiált szegmensbe írni, csak akkor, ha ugyanarra a címtartományra egy adatszegmenst is leképezünk. A kódszegmensekbeli adatok elérésére a következő módszerek lehetségesek: 1. Egy adatszegmens-regiszter feltöltése egy nemilleszkedő (nonconforming), olvasható, végrehajtható szegmens szelektorával. 2. Egy adatszegmens-regiszter feltöltése egy illeszkedő (conforming), olvasható, végrehajtható szegmens szelektorával. 3. Egy kódszegmens-fölülíró prefix alkalmazása egy olyan olvasható, végrehajtható szegmens írása céljából, amelynek szelektora már a CS regiszterbe van töltve. Az első esetre az adatszegmens hozzáférésre vonatkozó, ugyanazon szabályok érvényesek. A második eset mindig érvényes, mivel egy olyan kódszegmens privilegizálási szintje, amelynek Conforming (illeszkedő) bitje 1-re van állítva, a DPL értékétől függetlenül, gyakorlatilag megegyezik a CPL értékével. A harmadik eset mindig
érvényes, minthogy a CS regiszter által kijelölt kódszegmens DPL-je maga a CPL. 3.75 Vezérlésátadások korlátozása 176 Védelmi mechanizmusok A vezérlésátadásokat a JMP, CALL, RET, INT, és IRET utasítások, valamint a kivétel- és megszakítás-mechanizmusok biztosítják. A kivételek és a megszakítások speciális esetek, amelyeket egy későbbi fejezet tárgyal. Ez a rész csak a JMP, CALL és RET utasításokkal foglalkozik. A JMP, CALL és RET utasítások "near" formái a program vezérlését az aktuális kódszegmensen belül adják át, ezért ezek csak a limit-ellenőrzésnek vannak kitéve. A processzor ellenőrzi, hogy a JMP, CALL illetve RET utasítások rendeltetési helyei nem haladják-e meg az aktuális kódszegmens határát. Ez a limit a CS regiszterbe van "cacheelve", így a "near" típusú vezérlésátadások esetén a védelmi ellenőrzések nem rontják a teljesítményt. A JMP és CALL utasítások
"far" változatainak operandusai más szegmensekre vonatkoznak, ezért a processzor privilégium-ellenőrzést végez. A JMP és CALL utasítások kétféleképpen vonatkozhatnak egy másik szegmensre: 1. Az operandus egy másik végrehajtható szegmens deszkriptorát szelektálja. 2. Az operandus egy call-kapu deszkriptorát szelektálja. Amint azt a 3.43 ábra mutatja, az olyan vezérlésátadások esetén, amelyek nem használnak call-kaput, két különböző privilegizálási szint lesz alávetve a privilégium-ellenőrzésnek: 1. A CPL (aktuális privilegizálási szint). 2. A cél kódszegmens deszkriptorának DPL-je. 177 Általános CPU programozási információk Cél kód-szegmens deszkriptor 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Típus DPL +4 1 1 C R A +0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Aktuális kódszegmens regiszter CPL Operandus szegmens
szelektor RPL CPL - Aktuális privilégium szint Privilégium ellenőrzés DPL - Deszkriptor privilégium szint C - Illeszkedés bit 3.43 ábra: Privilégium ellenőrzés taszkkapu nélküli vezérlésátadásoknál Normális esetben a CPL megegyezik annak a szegmensnek a DPL értékével, amelyet a processzor éppen végrehajt. Ennek ellenére a CPL lehet a DPL értékénél nagyobb (kevésbé privilegizált), ha az aktuális kódszegmens egy illeszkedő (conforming) szegmens (amint azt a szegmensdeszkriptorának típusmezője mutatja). Egy illeszkedő (conforming) szegmens a hívó procedúra privilegizálási szintjén szalad. A processzor a CS regiszterben tárolja a CPL egy másolatát; ez az érték eltérhet az aktuális kódszegmens deszkriptorában tárolt DPL értékétől. 178 Védelmi mechanizmusok A processzor csak abban az esetben engedélyezi a JMP és CALL utasításokkal egy másik szegmensbe történő direkt hívást, ha a következő két privilégium
szabály közül valamelyik teljesítve van: A szegmens DPL-je egyenlő a CPL-el. A szegmens egy illeszkedő (conforming) kódszegmens, és a DPLje kisebb (privilegizáltabb) a CPL-nél. Az illeszkedő szegmensek olyan programok esetén használatos, mint például a matematikai könyvtárak, illetve néhány kivétel kiszolgáló procedúra esetén, amelyek támogatják ugyan az alkalmazásokat, de nincs szükségük hozzáférni védett rendszer-szolgáltatásokhoz. Amikor a vezérlés egy "conforming" típusú szegmensnek kerül átadásra, a CPL értéke nem változik meg, még akkor sem, ha a szegmens megcímzésére használt szelektornak eltérő az RPL-je. Ez az egyedüli olyan feltétel, amely esetében a CPL különbözhet az aktuális kódszegmens DPL értékétől. A kódszegmensek legtöbbje nem illeszkedő (nonconforming). Ezen szegmensek esetén a kapu nélküli vezérlésátadás csak ugyanazzal a privilegizálási szinttel rendelkező
kódszegmensek között lehetséges. Ugyanakkor néha szükséges a vezérlés átadása magasabb privilegizálási szintekre. Ez a CALL utasítás segítségével megy végbe, callkapudeszkriptorok alkalmazásával, amelyek a későbbiek folyamán lesznek elmagyarázva. A JMP utasítás soha nem adhatja át a vezérlést egy olyan nem illeszkedő (nonconforming) szegmensnek, amelynek DPL értéke nem egyenlő a CPL értékével. 3.76 Kapudeszkriptorok A különböző privilegizálási szinten levő végrehajtható szegmensek közötti vezérlésátadás védelmének biztosítása érdekében a processzor kapudeszkriptorokat használ. Négy fajta kapudeszkriptor létezik: 179 Általános CPU programozási információk - call-kapuk - trapkapuk - megszakításkapuk - taszkkapuk A call-kapuk a védett üzemmódbeli vezérlésátadás egyik formája. Eltérő privilegizálási szintek közötti vezérlésátadásra vannak alkalmazva. Csak azokban a rendszerekben szükséges a
használatuk, amelyekben egynél több privilegizálási szint kerül alkalmazásra. A 344 ábra egy callkapu formátumát illusztrálja 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Ofszet a szegmensben 31-16 Szegmens szelektor P DPL 0 1 1 0 0 0 0 0 DWORD +4 számláló Ofszet a szegmensben 15-0 +0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 3.44 ábra: Call kapu Egy call-kapunak két fő funkciója van: 1. Megjelölni egy procedúra bemenőpontját. 2. Meghatározni a procedúrába privilegizálási szintet. való belépéshez szükséges A CALL és JMP utasítások ugyanolyan módon használják a callkapudeszkriptorokat, mint a kódszegmens deszkriptorokat. Amikor a hardware felismeri, hogy a cél szegmens-szelektora egy kapudeszkriptorra utal, az utasítás által végrehajtott művelet a call-kapu tartalma által lesz meghatározva. Egy call-kapudeszkriptor a GDT-ben vagy az LDT-ben
foglalhat helyet, de a megszakításdeszkriptortáblázatban (IDT-ben) nem. 180 Védelmi mechanizmusok Egy kapu szelektor és ofszet mezői egy procedúra bemenőpontjára mutató pointert képeznek. A call-kapu garantálja azt, hogy minden egyes más szegmensnek történő vezérlésátadás egy érvényes bemenőpontra történik, és nem a procedúra közepébe (vagy még rosszabb esetben egy utasítás közepébe ). A vezérlésátadást végrehajtó utasítás argumentuma nem a szegmens-szelektor illetve procedúra bemenőpontját mutató szegmensen belüli ofszet. Ehelyett, a szegmens-szelektor egy kapudeszkriptorra mutat, és az ofszet használaton kívül marad. A 345 ábra bemutatja a címzésnek ezen formáját. Cél cím 15 0 Szelektor 31 Nem használt 0 A szegmensen belüli ofszet Deszkriptor táblázat Ofszet Szelektor Bázis Bázis DPL Száml. Ofszet DPL Bázis Kapu deszkriptor Kód szegmens deszkriptor Eljárás Belépési pont 3.45 ábra: A call kapu
mechanizmusa 181 Általános CPU programozási információk Amint azt a 3.46 ábra mutatja, egy call-kapun keresztül történő vezérlésátadás érvényességének ellenőrzésére négy különböző privilegizálási szint van felhasználva. Egy call-kapun keresztül történő vezérlésátadás alkalmával ellenőrzött privilegizálási szintek a következők: 1. 2. 3. 4. A CPL (az aktuális privilegizálási szint) A call-kapu megjelölésére használt szegmens-szelektor RPL (szükséges privilegizálási szint) értéke. A kapudeszkriptor DPL (deszkriptor privilegizálási szint) értéke. A cél kódszegmensdeszkriptorának DPL értéke. A kapudeszkriptor DPL mezője határozza meg, hogy milyen privilegizálási szintekről használható a kapu. Egy kódszegmensen belül számos olyan eljárás lehet, amelyek különböző privilegizálási szintről történő felhasználásra vannak rendeltetve. Például, egy operációs rendszernek lehet néhány olyan
szolgáltatása, amelyeknek az a rendeltetése, hogy úgy az operációs rendszer, mint a felhasználói program által alkalmazva legyenek, mint például a karakter ki- és bevitelt kezelő rutinok, miközben más szolgáltatások csak az operációs rendszer általi használatra vannak tervezve, mint például a kezelőprogramokat inicializáló rutinok. A kapukat magasabb, vagy ugyanazon privilegizálási szintre történő vezérlésátadásra lehet felhasználni (bár az ugyanarra a szintre történő vezérlésátadásokkor nem szükségesek). Kizárólag a CALL utasítások képesek a kapukat magasabb privilegizálási szintre való vezérlésátadásra felhasználni. A JMP utasítás csak egy ugyanolyan privilegizáltság kódszegmensnek való vezérlésátadásra képes a kaput alkalmazni, vagy egy ugyanakkora, illetve nagyobb privilegizáltsággal rendelkező illeszkedő (conforming) kódszegmensnek történő vezérlésátadásra. 182 Védelmi mechanizmusok Call kapu
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +4 DPL +0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Cél kód-szegmens deszkriptor 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +4 DPL +0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Aktuális kódszegmens regiszter CPL Operandus szegmens szelektor RPL CPL - Aktuális privilégium szint DPL - Deszkriptor privilégium szint Privilégium ellenőrzés RPL - Igényelt privilégium szint 3.46 ábra: Privilégium ellenörzés call kapuval történő vezérlésátadásnál 183 Általános CPU programozási információk Egy nem illeszkedő szegmensre ugró JMP utasítás esetén az itt következő mindkét privilégium-szabály be kell legyen tartva; különben általános védelmi hiba kivétel generálódik. - MAX(CPL,RPL) <= a kapu DPL-je -A cél
kódszegmensének DPL-je = CPL Egy CALL utasítás (vagy egy illeszkedő szegmensre ugró JMP utasítás) esetén az itt következő mindkét privilégium-szabály be kell legyen tartva, különben általános védelmi hiba kivétel generálódik. - MAX(CPL,RPL) <= a kapu DPL-je -A cél kódszegmensének DPL-je <= CPL 3.761 Veremváltás Egy privilegizáltabb szintre történő procedúra-hívás a következőket végzi el: 1. 2. 3. Megváltoztatja a CPL-t. Átadja a vezérlést (a végrehajtást) Taszkkapcsolást végez Mindegyik belső védelmi gyűrűnek (a 0-s 1-es és 2-s privilegizálási szintek) megvan a saját veremtára, a kevésbé privilegizált szintekről történő kérések fogadására. Ha a veremterületet a hívó biztosítaná, és a verem túl kicsi lenne, a meghívott procedúra elakadhatna, a nem elégséges veremterület miatt. Ehelyett a processzor megakadályozza a kevésbé privilegizált programokat abban, hogy privilegizáltabb programokat
megsérthessenek, mégpedig egy új verem létrehozásával a privilegizáltabb szintre való kérés pillanatában. Az új verem létrejön, a régi stack-ből átmásolásra kerülnek a paraméterek, a regiszterek tartalma elmentődik, és az utasítás-végrehajtás normálisan folytatódik tovább. Mikor a processzor visszatér (return), az elmentett regiszterek tartalma visszaállítják az eredeti vermet. 184 Védelmi mechanizmusok A processzor a taszk-állapot-szegmens (TSS) segítségével találja meg a vermek létrehozásának szükséges helyet, amint azt a 3.47 ábra mutatja. Minden taszknak megvan a saját TSS-e A TSS a belső védelmi gyűrűk kezdeti veremmutatóit tartalmazza. Az operációs rendszer a felelős azért, hogy minden egyes TSS-t létrehozzon és inicializálja azok veremmutatóit. (Ha az operációs rendszer nem használ TSS-eket a multitaszking megvalósításához, még akkor is le kell foglalnia legalább egy TSS-t az említett, veremmel
összefüggő cél érdekében). Egy kezdeti veremmutató egy szegmens-szelektorból és az ESP regiszter egy kezdeti értékéből (egy szegmensen belüli kezdeti ofszetből) áll össze. A kezdeti veremmutatók szigorúan csak olvasható típusú értékek lehetnek. A processzor nem módosítja őket a taszk futása közben. Ezeket a veremmutatókat kizárólag azzal a céllal használja, hogy egy magasabb privilegizálási szintre történő hívás esetén új veremtárakat hozzon létre. Ezek a vermek a meghívott procedúra visszatérése pillanatában eltűnnek. A következő alkalommal, amikor a procedúra újra meghívásra kerül, a kezdeti veremmutató segítségével új verem lesz létrehozva. 32 bites Taszk állapot szegmens 31 0 100 SS2 24 20 SS1 16 12 SS0 8 4 ESP2 ESP1 ESP0 0 3.47 ábra: Kezdeti stack pointerek egy TSS-ben 185 Általános CPU programozási információk Valahányszor a privilégium-szint megváltoztatása egy callkapuval történik, a
TSS-ből egy cím betöltésével új verem kerül létrehozásra. A processzor a cél kódszegmens DPL értékét (az új CPL-t) használja fel arra, hogy a 0-s, 1-es vagy 2-es privilegizálási szint kezdeti veremmutatóját kiválassza. Az új veremszegmens DPL-je egyenlő kell legyen az új CPL értékével; ha ez nem így van, egy TSS-hiba generálódik. Az operációs rendszer feladata, hogy minden alkalmazott privilegizálási szintnek létrehozza a veremét, illetve a verem-szegmensdeszkriptorát. A vermek a szegmensdeszkriptoruk típusmezőjében feltüntetett módon írható/olvasható típusúak kell legyenek. Elegendő helyet kell tartalmazzanak, a Limit mezőknek megfelelően, hogy magukba foglalhassák az SS és ESP regiszterek tartalmát, a viszszatérési címet, illetve a meghívott procedúrának szükséges paramétereket és ideiglenes változókat. Ami pedig az ugyanazon a privilegizálási szinten történő hívásokat illeti, a procedúra paraméterei a verembe
kerülnek elhelyezésre. A paraméterek átmásolódnak az új verembe. A meghívott procedúrán belül a paraméterek ugyanazon relatív címeket használva érhetők el, mint amelyeket a veremváltás nélkül kéne alkalmazni. Egy call-kapu számláló (count) mezője jelzi a proceszszornak, hogy hány duplaszót (maximum 31-et) másoljon át a hívó vereméből a meghívott procedúra veremébe. Ha a számláló értéke 0, egy paraméter sem lesz átmásolva. Ha 31-nél több duplaszót kell a meghívott procedúrának átadni, a paraméterek egyike egy adatstruktúra mutatója lehet, vagy az SS és ESP regiszterek elmentett értékeit a régi veremterületről való paraméterhozzáféréshez lehet felhasználni. A különböző privilegizálási szintek közötti procedúrahíváskor a processzor a következő veremmel kapcsolatos műveleteket végzi: 1. 186 Ellenőrzi, hogy a meghívott procedúra veremének mérete elég nagy legyen ahhoz, hogy befogadja a paramétereket
és a Védelmi mechanizmusok regiszterek elmentett veremkivételt generál. tartalmát; ha ez nincs teljesítve, 2. Az SS és ESP regiszterek régi tartalmát két duplaszóként lenyomja a meghívott procedúra veremébe (a 16 bites SS regiszter 0-s bitekkel van 32 bitre kiegészítve, a legfelső, 0-s kitöltésű kiegészítő szó az Intel által lefoglalt; használata nem ajánlott). 3. A paramétereket a hívó procedúra vereméből a meghívott procedúra veremébe másolja át. 4. A CALL utasítást követő utasításra mutató pointert (A CS és EIP regiszterek régi értékeit) lenyomja az új verembe. A hívás után az SS és ESP regiszterek a veremben erre a viszszatérési pointerre mutatnak. A 3.48 ábrán látható a veremkeret egy sikeres szintek közti procedúrahívás és visszatérés előtt, közben és után. Régi stack RET FAR N-el való visszatérés után (N=3) Új stack hívás után, visszatérés előtt Régi stack hívás előtt Régi
SS Parm1 Régi ESP Parm2 Parm1 Parm3 ESP ESP Parm2 Parm3 Régi CS Régi EIP ESP 3.48 ábra: Stack keret szintek közötti hívás alatt A TSS-ben a 3-as privilegizálási szintnek nincs veremmutatója, ugyanis egy 3-as privilegizálási szintű procedúrát nem hívhat meg egy kevésbé privilegizált procedúra sem. A 3-as privilegizálási szint verme az 187 Általános CPU programozási információk SS és EIP regiszterek tartalma által van eltárolva, amelyek a 3-as szintről meghívott privilegizálási szint veremében vannak elmentve. Egy call-kapus hívás nem ellenőrzi az új verembe másolt szavak értékeit. A meghívott procedúrának kell ellenőriznie minden paraméter helyességét. Egy későbbi részben található magyarázat arra, hogy miként lehet az ARPL, VERR, VERW, LSL, és LAR utasítások segítségével a mutatók értékeit ellenőrizni. 3.762 Visszatérés egy procedúrából A RET utasítás "near" formái csak az aktuális
kódszegmensen belül végeznek vezérlésátadást, ezért csak a limit-ellenőrzésnek vannak alávetve. A CALL utasítást követő parancs ofszetje a veremből lesz leemelve és az EIP-be töltve. A processzor ellenőrzi, hogy ez az ofszet nem haladja-e meg az aktuális kódszegmens határát. A RET utasítás "far" formája egy korábbi "far" típusú CALL utasítás által a veremre lenyomott visszatérési címet emeli le (pop). Normális körülmények között, a visszatérési mutató érvényes, mivelhogy egy CALL vagy INT utasítás hozta létre. Mégis a processzor elvégzi a privilégium-ellenőrzést, mivel fennáll az a lehetőség, hogy az aktuális procedúra megváltoztathatta a mutató értékét, vagy nem sikerült megtartania helyesen a vermet. A viszszatérési utasítás által a veremről leemelt kódszegmens-szelektor RPL értéke meg kell egyezzen a hívó procedúra privilegizálási szintjével. Egy másik szegmensbe való visszatérés
megváltoztathatja a privilegizálási szintet, de csakis a kevésbé privilegizáltabb szintek irányába. Ha a RET utasítás talál egy olyan elmentett CS értéket, amelynek az RPL-je számszerint nagyobb (kevésbé privilegizált) mint a CPL, privilegizálási szintek közötti visszatérés (return) megy végbe. Egy ilyen típusú visszatérés a következő lépéseket teszi meg: 1. 188 A 3.49 ábrán bemutatott ellenőrzéseket végzi el, és a CS, EIP, SS és ESP regisztereket feltölti a verembe elmentett előző értékeikkel. Védelmi mechanizmusok 2. Az SS és ESP regiszterek régi tartalmát (az aktuális verem tetején) a RET utasítás által meghatározott számú Byte-tal kiigazítja. A keletkező ESP értéket nem veti alá veremszegmens határ ellenőrzésnek. Az a tény, hogy az ESP értéke a határon kívülre esik, nem vevődik észre mindaddig, amíg a következő veremműveletre sor nem kerül. ( A visszatérő procedúra SS és az ESP regisztereinek
tartalma nincs eltárolva; normális esetben ezek értékei megegyeznek a TSS által tartalmazott értékekkel.) 3. A DS, ES, GS szegmensek tartalmát ellenőrzi. Ha ezen regiszter közül bármelyik egy olyan szegmensre vonatkoznak, amelynek DPL-je kisebb mint az új CPL (kivéve az illeszkedő szegmenseket), a szegmensregiszterbe a nullás szelektor töltődik be (Index=0, TI=0). A RET utasítás egymagában ilyen esetben nem jelez kivételeket; ugyanakkor bármely következő memóriahivatkozás, amely nullás szelektort tartalmazó szegmensregisztert alkalmaz, általános védelmi hiba kivételt eredményez. Ez meggátolja a kevésbé privilegizált kódot abban, hogy egy privilegizáltabb procedúra által a szegmensregiszterben hagyott szelektorok segítségével privilegizáltabb szegmensekhez férjen hozzá. Az ellenőrzés típusa A kivétel típusa Stack Hibakód A visszatérő kódszegmens RPL-je nagyobb kell legyen mint a CPL Védelmi CS A visszatérő kódszegmens
szelektora nem lehet a nullás szelektor Védelmi CS A visszatérő kód szegmensdeszkriptorának a deszkroptor-táblázat határán belül kell lennie Védelmi CS A verem teteje + 7 a veremszegmens határán belül kell legyen 0 189 Általános CPU programozási információk A visszatérést végző szegmensdeszkriptor kódszegmensre kell vonatkozzon A visszatérő kódszegmens jelen kell legyen a memóriában (present) A visszatérő, nem illeszkedő (nonconforming) kódszegmens DPL-je egyenlő kell legyen a visszatérő kód szegmensszelektorának RPL értékével, illetve a visszatérő, illeszkedő (conforming) kódszegmens DPL-je kisebb vagy egyenlő kell legyen a visszatérő kód szegmensszelektorának RPL értékével. Védelmi CS Szegmens nincs jelen CS Védelmi CS ESP + N + 15 * a veremszegmens határán belül Stack hiba kell legyen 0 Az ESP + N + 12 * helyen található szegmensszelektor nem lehet nullás szelektor Védelmi SS Az ESP + N + 12 *
helyen található szegmensdeszkriptornak a deszkriptor-táblázat határán belül kell lennie Védelmi SS A veremszegmensdeszkriptor írható/olvasható kell legyen Védelmi SS Stack hiba SS A régi veremszegmens DPL-je egyenlő kell legyen a régi kódszegmens RPL értékével Védelmi SS A régi veremszegmens-szelektor RPL-je egyenlő kell legyen a régi veremszegmens DPL értékével Védelmi SS A veremszegmens jelen kell legyen a memóriában (present) 190 Védelmi mechanizmusok * N a RET utasítást követő közvetlen operandus 3.49 ábra: Szintek közötti visszatérés ellenőrzés 3.77 Az operációs rendszer számára lefoglalt utasítások Azokat az utasításokat, amelyek a védelmi mechanizmust érinthetik, vagy amelyek befolyásolhatják a rendszer általános teljesítményét, csak megbízható procedúrák használhatják. A proceszszornak két ilyen utasításcsoportja van: 1. 2. Privilegizált utasítások - amelyek a rendszer vezérlésére
használatosak Érzékeny (sensitive) utasítások - amelyek az I/O, illetve az I/Ofüggő műveletekre használatosak 3.771 Privilegizált utasítások Azok az utasítások, amelyek a védett szolgáltatásokat érinthetik, csak akkor hajthatók végre, ha a CPL értéke 0 (legprivilegizáltabb). Ha ezen utasítások közül bármelyik 0-tól eltérő CPL mellett hajtódik végre, általános védelmi hiba kivétel generálódik. Ezen utasítások közé tartoznak a következők: CLTS HLT INVD INVLPG LGDT LIDT LLDT LMSW LTR Clear Task-Switched Flag - taszkváltásjelző bit törlése Halt Processor - leállás Invalidate Cache - belső cache érvénytelenítése Invalidate TLB Entry - TLB bejegyzés érvénytelenítése Load GDT Register - a globális deszkriptortáblázat-regiszter betöltése Load IDT Register - a megszakítás deszkriptortáblázatregiszter betöltése Load LDT Register - a lokális deszkriptortáblázat-regiszter betöltése Load Machine Status Word - a gépi
állapotszó betöltése Load Task Register - taszkregiszter betöltése 191 Általános CPU programozási információk MOV to/from CRn - Move to Control Register n - adatmozgatás a CRn vezérlőregiszterbe MOV to/from DRn - Move to Debug Register n - adatmozgatás a DRn nyomkövetőregiszterbe WBINVD Write Back and Invalidate Cache - Cache-be való visszaírás és érvénytelenítés 3.772 Érzékeny utasítások Az I/O műveletekkel foglalkozó utasítások számára szükséges, hogy védve legyenek, ugyanakkor az is szükséges, hogy az olyan procedúrák is használják őket, amelyek a 0-tól eltérő privilegizálási szinten futnak. Az I/O műveletek védelmi mechanizmusát a második kötet részletezi. 3.78 Mutatók érvényességét ellenőrző utasítások A mutatók érvényességét ellenőrző utasítások. a privilegizálási szintek közötti szigeteltség fenntartására szükséges. A következő lépésekből áll: 1. 2. 3. Annak ellenőrzése, hogy a
mutatót szolgáltatónak van-e joga a szegmenshez hozzáférni. Annak ellenőrzése, hogy a szegmens típusa kompatibilis-e a felhasználási céljával. Annak ellenőrzése, hogy a mutató ofszetje nem haladja-e meg a szegmenshatárt. Bár a processzor a 2. és 3 ellenőrzést automatikusan elvégzi az utasítás végrehajtása pillanatában, az első ellenőrzés elvégzéséhez a software segítsége szükséges. E cél érdekében adott az ARPL utasítás A software is alkalmazhatja inkább a 2. és 3 lépést, ahelyett, hogy egy kivétel megjelenésére várakozna. Ezen célt szolgálják a LAR, LSL, VERR, és VERW utasítások. LAR (Load Access Rights) - hozzáférési jogot tartalmazó Byte betöltése 192 Védelmi mechanizmusok A LAR utasítás annak ellenőrzésére használatos, hogy a mutató kompatibilis privilegizálási szintű és típusú szegmensre vonatkozik-e. A LAR utasításnak egyetlen operandusa van: azon deszkriptor szegmensszelektora, amelynek a
hozzáférési jogát vizsgálja. Az illeszkedő (conforming) kódszegmensek bármely privilegizálási szintről hozzáférhetők. Bármely más szegmensdeszkriptor olvasható kell legyen a CPL-nél, illetve a szelektor RPL értékénél számszerint nagyobb (kevésbé privilegizált) privilégiumszinten. Ha a deszkriptor olvasható, a LAR utasítás kiválasztja a deszkriptor második dupla-szavát, lemaszkolja ezt az értéket 00FxFF00H-val, eltárolja az eredményt a meghatározott 32 bites célregiszterbe, és magasra állítja a ZF bitet. (Az x azt mutatja, hogy a tárolt érték megfelelő négy bitje határozatlan.) A betöltés után a hozzáférési jogok azonnal tesztelhetők. Bármely érvényes deszkriptortípust lehet a LAR utasítással tesztelni. Ha az RPL vagy CPL nagyobb mint a DPL értéke, vagy ha a szegmensszelektor átlépné a deszkriptortáblázat határát, a visszaadott érték 0 lesz és a ZF bit törlődik. LSL (Load Segment Limit) a szegmenshatár
betöltése Az LSL utasítás lehetővé teszi a software számára, hogy egy szegmensdeszkriptor határát tesztelje. Ha egy (memóriában vagy egy regiszterben levő) szegmens-szelektor által meghatározott deszkriptor a CPL mellett olvasható, az LSL utasítás feltölti a megadott 32 bites regisztert egy 32 bites, Byte-felbontású határral, amelyet az összeillesztett limit mezők és a deszkriptor G bitje alapján számít ki. Ez csak azokkal a deszkriptorokkal lehetséges, amelyek szegmenseket írnak le (adat, kód, taszk-állapot, és lokális deszkriptortáblázat); a kapudeszkriptorok nem érhetők el. (A 350 ábra részletesen felsorolja, hogy melyek az érvényes típusok, és melyek nem.) A limit értelmezése a szegmens típusától függ Például, a lefele bővülő adatszegmensek (veremszegmensek), más típusú szegmensektől eltérő módon kezelik a határt. Úgy a LAR, mint a LSL utasítások esetén a ZF bit akkor van magasra állítva, ha a betöltés sikeres,
ellenkező esetben a ZF bit törlődik. Típus kód 0 1 Deszkriptor típus fenntartva fenntartva Érvényes? nem nem 193 Általános CPU programozási információk 2 3 4 5 6 7 8 9 A B C D E F LDT fenntartva fenntartva Taszk kapu fenntartva fenntartva fenntartva Lehetséges 32 bites TSS fenntartva Foglalt 32 bites TSS 32 bites call kapu fenntartva 32 bites megszakítás kapu 32 bites trap kapu igen nem nem nem nem nem nem igen nem igen nem nem nem nem 3.50 ábra: Érvényes deszzkriptor típusok LSL műveletekhez Egy újabb ellenőrzés, az illeszkedés-ellenőrzés (alignment check) alkalmazható a CPL=3 esetén. Amikor úgy a CR0-beli AM bit, mint az AC flag is 1-re van állítva, a nem illesztett (unaligned) memóriahivatkozások kivételeket generálnak. Ez azon programok számára hasznos, amelyek a mutatók alsó két bitjét használják az általuk megcímzett adatstruktúra típusának azonosítására. Például, egy matematikai könyvtár szubrutinja elfogadhat
numerikus adatstruktúrákra mutató pointereket. Ha e struktúra típusához az 10 (bináris) kódot társítjuk az erre a típusra mutató pointer legalsó két bitjén, a matematikai szubrutinok kijavíthatják a típuskódot -10 (bináris) eltolás hozzáadásával. Abban az esetben, ha a szubrutin helytelen mutatótípust kapna, egy illesztetlen (unaligned) hivatkozás jönne létre, amely kivételt generálna. Az illeszkedés-ellenőrzés felgyorsítja a szimbolikus feldolgozású (azaz a mesterséges intelligencia) nyelvekben megírt programok feldolgozását, mint amilyen a Lisp, Prolog, Smalltalk és a C++. A pointer-végek típusellenőrzésének felgyorsítására lehet használni 194 Védelmi mechanizmusok 3.781 Deszkriptor érvényességének ellenőrzése A processzor két olyan utasítással rendelkezik, a VERR és VERW utasításokkal, amelyek megállapítják, hogy a szegmens-szelektor a jelenlegi CPL mellett írható vagy olvasható szegmensre mutat. Egyikük sem
okoz védelmi hibát, ha a szegmens nem hozzáférhető. VERR (Verify for Reading) a szegmens olvashatóságának ellenőrzése A VERR utasítás olvasásra ellenőrzi a szegmenst és ha a CPL mellett a szegmens olvasható, beállítja a ZF bitet. A VERR utasítás a következőket ellenőrzi: Hogy a szegmens-szelektor a GDT vagy az LDT határain belüli szegmensdeszkriptorra mutat-e. Hogy a szegmens-szelektor egy kód- vagy adatszegmens deszkriptort indexel. Hogy a szegmens olvasható, és egy kompatibilis privilegizálási szintje van-e. Az adatszegmensek és a nem illeszkedő (nonconforming) kódszegmensek privilégium-ellenőrzése azt vizsgálja, hogy a DPL kevésbé privilegizált szint legyen akár a CPL-hez, akár a szelektor RPL értékéhez viszonyítva. Az illeszkedő (conforming) szegmensek nem kerülnek privilégiumszint-ellenőrzés alá. VERW (Verify for Writing) a szegmens írhatóságának ellenőrzése A VERW utasítás ugyanazokat a képességeket
nyújtja a szegmens írásra ellenőrzéséhez, mint a VERR utasítás Akárcsak a VERR utasítás, a VERW parancs is beállítja a ZF bitet, ha a szegmens írható. Az utasítás azt vizsgálja, hogy az deszkriptor a határok között van-e, hogy szegmensdeszkriptor legyen, írható-e, illetve hogy a DPL-je kevésbé privilegizált szint legyen akár a CPL-hez, akár a szelektor RPL értékéhez viszonyítva. Attól függetlenül, hogy illeszkedők (conforming) vagy sem, a kódszegmensek soha sem írhatók. 195 Általános CPU programozási információk 3.782 Mutatók integritása és az RPL A szükséges privilegizálási szint (RPL) megelőzheti az olyan mutatók balesetszerű használatát, amelyek kevésbé privilegizált szintről omlasztanák össze a privilegizáltabb kódot. Erre egy közönséges például az FREAD (fájl azonosító, Byte-ok száma, puffer mutató) rendszerprocedúra. Ez a képzeletbeli procedúra egy lemezen levő fájlból adatokat olvas be egy
pufferbe, fölülírva bármit, ami már benne található. Az alkalmazások szintjén futó programok kéréseit szolgálja ki, de privilegizált módon kell szaladjon annak érdekében, hogy olvashasson a rendszer I/O pufferéből. Ha a felhasználói program egy hibás puffermutatót adna át ennek a procedúrának - egy olyat, amely privilegizált címtartományban levő kritikus kódra vagy adatra mutatna - a procedúra a rendszer összeomlásához vezető kárt okozhatna. Az RPL használata képes megelőzni ezt a problémát. Az RPL megengedi egy privilégium-fölülíró hozzárendelését egy szelektorhoz. Ez a privilégium-fölülíró annak a kódszegmensnek a privilegizálási szintje kell legyen, amely a szegmens-szelektort létrehozta. A fennemlített példában az RPL annak a felhasználói programnak a CPL-je volna, amelyik meghívta a rendszerszintű procedúrát. A processzor automatikusan ellenőriz minden szegmensregiszterbe betöltött szegmensszelektort, hogy
megállapítsa: az RPL je megengedi-e a hozzáférést. Annak érdekében, hogy ki legyen használva a processzor által elvégzett RPL-ellenőrzés előnye, a meghívott procedúrának csak azt kell ellenőriznie, hogy minden neki átadott szegmens-szelektornak az eredeti hívó CPL-jének megfelelő, vagy annál kevésbé privilegizált RPL értéke van. Ez garantálja azt, hogy a szegmens-szelektorok nem privilegizáltabbak a forrásaiknál. Ha a szelektor egy olyan szegmenshez való hozzáférésre van használva, amelyet a forrás nem lenne képes közvetlenül elérni, tehát az RPL a szegmens DPL értékénél kevésbé privilegizált, általános védelmi hiba kivétel keletkezik amikor a szelektor a szegmensregiszterbe kerül. ARPL (Adjust Requested Privilege Level) - a szelektor RPL mezőjének beállítása 196 Védelmi mechanizmusok Az ARPL utasítás egy szegmens-szelektor RPL értékét beállítja az eredeti érték, és egy általános regiszterben tárolt
szegmensszelektor RPL mezőjének értéke közül a nagyobbik (kevésbé privilegizált) értékre. Az RPL mező a szegmens-szelektor és a regiszter két legjelentéktelenebb bitje. Az utóbbi általában a hívó CS regiszterének verembeli másolata Ha a beállítás megváltoztatja a szelektor RPL-jét, a ZF bit beállítódik (set); ellenkező esetben a ZF bit törlődik. 3.79 Lapszinti védelem A védelem úgy szegmensekre, mint lapokra is vonatkozik. Ha a memóriaszegmentálás sík modelljét használjuk, a lapszinti védelem meggátolja a programokat abban, hogy egymást zavarják. Minden egyes memóriahivatkozás megvizsgálás alá kerül annak érdekében, hogy meg lehessen állapítani: eleget tesz-e a védelmi feltételeknek. Minden ellenőrzés a memóriaciklus elindítása előtt kerül elvégzésre; bármely szabálysértés meggátolja a ciklus elkezdését és kivételt eredményez. Minthogy az ellenőrzések a címfordítással párhuzamosan történnek, nincs
teljesítmény-kiesés. Két lapszintű védelmi ellenőrzés létezik: 1. 2. A megcímezhető tartományt érintő megszorítások Típusellenőrzés A védelem megsértése kivételt eredményez. A védett üzemmódú kivétel-mechanizmus magyarázatárol majd később lesz szó. Ez a rész azokat a védelem-megszegéseket írja le, amelyek kivételekhez vezetnek. 3.791 A laptáblázat bemenetek által tartalmazott védelmi paraméterek A 3.51 ábra a laptáblázat bemenet azon mezőit emeli ki, amelyek a laphozzáférést kontrollálják. A védelmi ellenőrzések mind az első-, mind a második szintű laptáblázatokra is hivatkoznak. 197 Általános CPU programozási információk 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 P Lapkeret cím 31-12 hozzáf. 0 0 D A C D 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 P W T 3 2 1 0 U R P S W 2 1 0 R/W - Írható/olvasható U/S - User/supervisor 3.51
ábra: Egy laptáblázat bejegyzés védelmi mezői 3.7911 A megcímezhető tartományt érintő megszorítások A privilégium lapok esetében a szegmensekhez képest eltérő módon értelmezett. A szegmensek esetében négy privilegizálási szintet különböztetünk meg, a 0-tól 3-ig. A lapok esetében két privilegizálási szint létezik: 1. Felügyelő-szint (U/S=0) - az operációs rendszer, más rendszersoftware-ek (mint például az eszközmeghajtó kezelőprogramok), illetve védett rendszeradatok (mint amilyenek a laptáblázatok) részére. 2. Felhasználói szint (U/S=1) - az alkalmazások kódja és adatai számára. A szegmentálásra használt privilegizálási szintek a lapozásnál használt privilegizálási szintre vannak leképezve. Ha a CPL értéke 0, 1, vagy 2, a processzor felügyelő-szinten dolgozik. Ha a CPL=3, a processzor felhasználói szinten működik. Amikor a processzor felügyelőszinten dolgozik, minden lap hozzáférhető Ha a processzor
felhasználói szinten fut, csak a felhasználói szint lapjai érhetők el. 198 Védelmi mechanizmusok 3.7912 Típusellenőrzés A védelmi mechanizmus csak két típusú lapot ismer fel: 1. 2. Csak-olvasási hozzáférésű (R/W=0) Írási/olvasási hozzáférésű (R/W=1). Amikor a processzor felügyelőszinten szalad és a CR0-s regiszter WP bitje 0-s (a reset inicializálást követő állapota), minden lap írható és olvasható is egyben (az írás-védettség figyelmen kívül marad). Ha a processzor felhasználói szinten fut, csak azok a felhasználói szinthez tartozó lapok írhatók, amelyek írási/olvasási hozzáférésre vannak megjelölve. Az írható/olvasható, illetve a csak-olvasható felhasználói szintű lapok olvashatók. A felügyelő-szintű lapok sem nem írhatók, sem nem olvashatók felhasználói szintről. Egy általános védelmi hiba kivétel generálódik bármely védelmi szabály megsértésére tett kísérlet esetén. A 386-os
processzorral ellentétben, a 486-os és Pentium processzorok megengedik, hogy a felhasználói szintű lapok írásvédettek legyenek a felügyelő módbeli hozzáférések ellen. A CR0 regiszter WP bitjének magasra állítása engedélyezi a felügyelő-szintnek a felhasználói szint lapjainak írásvédettsége iránti " fogékonyságát". A felügyelő-ellenes írásvédelem lehetősége az ún. "írás közbeni másolás" (copy-on-write) stratégiájának implementálása esetén is hasznos lehet, amelyet némely operációs rendszer, mint például a UNIX, használ fel új taszkok létrehozására. Egy új taszk létrehozásakor lehetséges a szülő szegmens címtartományának teljes lemásolása. Ez a származtatott taszk számára egy komplett másolatát nyújtja a szülő szegmens- és lapszettjének. Egy alternatív stratégia, az "írás közbeni másolás" (copyon-write) tárterületet és időt takarít meg azzal, hogy a gyermek taszk
szegmenseit és lapjait ugyanazokra a szegmensekre és lapokra képezi le, mint amelyeket a szülő taszk is használ. A lapnak egy egyedi másolata csak akkor kerül megteremtésre, amikor a taszkok egyike a lapra ír. A WP bit alkalmazásával a felügyelőprogram detektálhatja a felhasználói-szintű lapra való írási kísérletet, és ugyanakkor átmásolhatja is a lapot. 199 Általános CPU programozási információk 3.7913 A védelem kombinálása a laptáblázatok mindkét szintjén Bármely lap esetén, a lapcímtárbeli bejegyzésének (első szintű laptáblázat) védelmi attribútumai különbözhetnek a második szintű laptáblázat bemeneteinek attribútumaitól. A processzor úgy ellenőrzi egy lap védelmét, hogy a lapcímtárban (első szintű laptáblázat), mint a második szintű laptáblázatban megadott védelmi információt is tanulmányozza. A 352 ábra bemutatja a védelmi attribútumok lehetséges kombinációiból adódó védelmet, akkor, ha a
WP bit törölve van. 3.7914 A lapvédelem fölülírói Némely hozzáférés úgy van leellenőrizve, mintha a 0-s privilegizálási szinten végbemenő hozzáférések volnának, a CPL bármely értéke esetén: Hozzáférés a szegmensdeszkriptorokhoz (LDT, GDT, TSS és IDT). Hozzáférés a belső veremhez, egy CALL utasítás, vagy kivételek és megszakítások közben, ha a privilegizálási szint megváltozik. Lapcímtár bejegyzés Priviléhozzáférgium hetőség User Csak olvasható User Csak olvasható User Írható/ olvasható User Írható/ olvasható User Csak olvasható User Csak olvasható 200 Laptáblázat bejegyzés Priviléhozzáférgium hetőség User Csak olvasható User Írható/ olvasható User Csak olvasható User Írható/ olvasható Supervisor Csak olvasható Supervisor Írható/ olvasható Kombinált effektus Priviléhozzáférgium hetőség User Csak olvasható User Csak olvasható User Csak olvasható User Írható/ olvasható Supervisor
Írható/ olvasható Supervisor Írható/ olvasható Védelmi mechanizmusok User User Supervisor Supervisor Supervisor Supervisor Supervisor Supervisor Supervisor Supervisor Írható/ olvasható Írható/ olvasható Csak olvasható Csak olvasható Írható/ olvasható Írható/ olvasható Csak olvasható Csak olvasható Írható/ olvasható Írható/ olvasható Supervisor Supervisor User User User User Supervisor Supervisor Supervisor Supervisor Csak olvasható Írható/ olvasható Csak olvasható Írható/ olvasható Csak olvasható Írható/ olvasható Csak olvasható Írható/ olvasható Csak olvasható Írható/ olvasható Supervisor Supervisor Supervisor Supervisor Supervisor Supervisor Supervisor Supervisor Supervisor Supervisor Írható/ olvasható Írható/ olvasható Írható/ olvasható Írható/ olvasható Írható/ olvasható Írható/ olvasható Írható/ olvasható Írható/ olvasható Írható/ olvasható Írható/ olvasható 3.52 ábra: Kombinált lapcímtár
és laptáblázat védelem 3.792 Lap- és szegmensvédelem kombinálása Ha a lapozás engedélyezett, a processzor először a szegmens-, majd a lapvédelmet értékeli ki. Ha a processzor védelemsértést fedez fel akár a szegmensek, akár a lapok szintjén, a művelet nem hajtódik végre, ehelyett egy kivétel keletkezik. Ha a szegmentálásnál kivétel generálódik, a művelet nem vált ki laphiba kivételt. Például, lehetőség van egy olyan kiterjedt adatszegmenst definiálni, amelynek vannak egyes csak-olvasható, illetve más, írható/olvasható részei is. Ebben az esetben, a csak-olvasható részek lapcímtár- (vagy laptáblázat) bejegyzéseinek U/S és R/W bitjei az írási hozzáférés letiltását határoznák meg, a lapcímtár-bemenet által kijelölt 201 Általános CPU programozási információk lapok számára (vagy a második szintű laptáblázatban megadott egyedi lapok számára). Ezt a technikát fel lehetne használni például, egy olyan
kiterjedt adatszegmens definiálására, amelynek bizonyos részei csakolvasható típusúak (közös adatok, vagy ROM-ban tárolt konstansok esetén). Ez, egy sík adattartományt, egyetlen, óriási szegmensként definiál, amely sík tartomány hozzáféréséhez sík mutatók szükségesek, ugyanakkor védelem alá helyezve a közös adatokat, a megosztott, virtuális címterületre leképezett állományokat, illetve a felügyelőprogram területeit. 202 Védett üzemmódú multitaszking 3.8 Védett üzemmódú multitaszking A Pentium processzor biztosítja a multitaszking számára szükséges hardware támogatást. A taszk egy olyan program, amely éppen fut, vagy amely arra vár, hogy fusson, miközben egy másik program van végrehajtás alatt. Egy taszkot egy megszakítás, egy kivétel, egy ugrás, vagy egy call utasítás hív meg. Két különböző típusú, taszkokra vonatkozó deszkriptor létezik, amelyek egy deszkriptor-táblázatban megjelenhetnek:
taszk-állapot-szegmens deszkriptorok és a taszkkapuk. Amikor a vezérlés átadódik a két deszkriptortípus bármelyikének, taszkkapcsolás keletkezik. A taszkkapcsolás olyan, mint egy procedúrahívás, csak több processzor-állapotinformációt tárol el. A taszkkapcsolás átadja a vezérlést egy teljesen új környezetnek, egy taszk környezetének. Ehhez szükség van a processzor majdnem összes regiszterének elmentésére, ideértve az EFLAGS regisztert és a szegmensregisztereket is. A procedúrákkal ellentétben a taszkok nem újraindíthatók (re-entrant). A taszkkapcsolás nem nyom le semmit a verembe. A processzor állapotinformáció a memóriában tárolt adatsruktúrába, az ún. taszkállapot-szegmensbe lesz elmentve A multitaszkingot támogató regiszterek és adatstruktúrák a következők: taszk-állapot-szegmens taszk-állapot-szegmensdeszkriptor taszkregiszter taszkkapudeszkriptor A felsorolt struktúrák segítségével, a processzor
átadhatja a vezérlést egyik taszktól a másiknak, elmentve az eredeti taszk állapotát annak érdekében, hogy a taszkot folytatni lehessen. A processzor ezenkívül két további taszk-szervező lehetőséget is felkínál: 1. A megszakítások és kivételek taszkkapcsolásokat okozhatnak (ha ez szükséges a rendszerben). A processzor nemcsak a megszakítások és kivételek kezelésére képes taszkkapcsolást végrehajtani, hanem automatikusan vissza is tud kapcsolni, amikor a megszakítás vagy kivétel visszatér (return). Ez a mechanizmus képes a megszakítás-taszkok alatt megjelenő megszakítások kezelésére. 203 Általános CPU programozási információk 2. Minden egyes taszkkapcsoláskor, a processzor egy új LDT-re is képes váltani. Ez arra használható, hogy minden taszknak egy különálló logikai cím - fizikai cím megfeleltetést lehessen biztosítani. Ez egy plusz védelmi lehetőség, ugyanis így a taszkokat el lehet egymástól szigetelni,
és meg lehet előzni azt, hogy egymással ősszeakadjanak. A PDBR regiszter is újratöltődik Ez a tény megengedi, hogy a lapozómechanizmust is fel lehessen használni a taszkok egymás közötti elszigetelésének biztosítására. A multitaszking-mechanizmus használata opcionális. Egyes alkalmazások esetén lehet, hogy nem a legjobb módja a programvégrehajtás megszervezésének. Ahol a megszakításokra különösen gyors válaszra van szükség, ott a processzor állapotának elmentésére szükséges idő túl hosszú lehet. Az ilyen helyzetekben egy lehetséges kompromisszum az, hogy használjuk a taszkokra vonatkozó adatstruktúrákat, de a taszkkapcsolást software úton valósítsuk meg. Ez lehetővé teszi egy kisebb terjedelmű processzor állapotinformáció elmentését. Ez a technika egyike lehet azon optimizálásoknak, amelyek a teljesítmény növelésére alkalmazhatók. 3.81 Taszk-állapot-szegmens Egy taszk visszaállításához szükséges
processzorállapotinformációk egy bizonyos típusú szegmensbe vannak elmentve, amelyet taszk-állapot-szegmensnek, vagy TSS-nek nevezünk. A 353 ábra a 32 bites CPU-kra írt taszkok TSS formátumát mutatja be (a 16 bites, 80286-os processzor taszkjaival való kompatibilitást egy más típusú TSS biztosítja, de erről a második kötetben lesz részletesebben szó). Egy TSS mezői két fő kategóriába oszthatók: 1. Dinamikus mezők, amelyeket a processzor minden taszkkapcsoláskor felfrissít. Ezek a mezők a következőket tárolják: 204 Az általános regisztereket (EAX, ECX, EDX, EBX, ESP, EBP, ESI, és EDI). Védett üzemmódú multitaszking 2. A szegmensregisztereket ( ES, CS, SS, DS, FS, és GS). A flag regisztert ( EFLAGS) Az utasításmutatót (EIP) Az előző taszk TSS-ének szelektorát (csak akkor frissíti fel, amikor egy return várható). Statikus mezők, amelyeket a processzor olvas, de nem módosít. Ezek a mezők a taszk
létrehozásakor lesznek beállítva. Ezen mezők a következőket tárolják: A taszk LDT-jének szelektorát. A taszk PDBR-jét (CR3). A 0-s, 1-es és 2-es privilegizálási szintek vermeinek logikai címét. A T bitet (debug trap bit), amely ha 1-re van állítva, arra készteti a processzort, hogy valahányszor egy taszkkapcsolás jelenik meg, debug-kivételt hozzon létre. ( A hibakeresésről több információ található a második kötetben.) Az I/O engedélyező bittérkép és a megszakítás átírányitó bit-térkép báziscímét. Ha jelen vannak, ezek a bittérképek a TSS magasabb címeire kerülnek eltárolásra. A báziscím az I/O térkép elejére, illetve a 32 Byte-os megszakítás térkép végére mutat. (A megszakítás-átirányításról további információk szintén a második kötetben találhatók). 205 Általános CPU programozási információk 31 I/O térkép bázis cím 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 T 100 96 0 0 0 0 A taszk LDT szelektora 92 0 0 0 0 GS 88 0 0 0 0 FS 84 0 0 0 0 DS 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SS 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 CS 80 76 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ES 72 EDI ESI 68 64 EBP 60 ESP EBX 56 52 EDX 48 44 ECX EAX 40 36 32 EFLAGS EIP CR3 (PDBR) 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ESP2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ESP1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ESP0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 SS2 24 20 SS1 16 12 SS0 8 4 LINK (régi TSS szelektor) 0 3.53 ábra: 32 bites taszk állapot szegmens Ha a lapozás használt, fontos megelőzni a laphatároknak a TSS azon részébe történő elhelyezését, melyekből a processzor olvas a taszkkapcsolás idején (az első 104 Byte). Ha egy laphatár a TSS ezen részébe kerül, a határ mindkét oldalán található lapoknak egyidőben kell jelen lenniük. Azonfelül, ha a lapozás engedélyezett, a
kimenő taszk TSS- 206 Védett üzemmódú multitaszking ének megfelelő lapokat, az új taszk TSS-ét, és mindezek deszkriptortáblázat bemenetét jelenlévőnek, illetve írható/olvashatónak kell megjelölni. Visszaállíthatatlan hiba, ha azután érkezik be egy laphiba, vagy egy általános védelmi hiba kivétel, miután a processzor megkezdte a TSS olvasását. 3.82 A TSS deszkriptor Mint minden más szegmenst, a taszk-állapot-szegmenst is egy deszkriptor határoz meg. A 354 ábra bemutatja a TSS deszkriptor formátumát TSS Deszkriptor 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Típus Báziscím 31-24 A G 0 0 V L Szegmens határ 19-16 P DPL 0 1 0 B 1 Báziscím 23-16 Szegmens határ 15-0 Báziscím 15-0 +4 +0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 AVL B DPL G P - A rendszer software számára elérhető - Foglaltság bit - Deszkriptor privilégium szint -
Szemcsézettség - A szegmens jelenlétét jelző bit 3.54 ábra: TSS Deszkriptor A típusmező Foglalt (Busy) bitje jelzi, hogy a taszk foglalt-e. Egy foglalt taszk éppen fut, vagy arra vár, hogy futhasson. Ha a típusmező értéke 9, inaktív taszkot jelöl, a 11-es (decimális) érték foglalt taszkot jelent. A taszkok nem rekurzívak A processzor arra használja a Foglalt bitet, hogy a megszakított taszkok hívására tett kísérleteket detektálja. 207 Általános CPU programozási információk A Bázis, Limit, és DPL mezőknek, illetve a Felbontás (Granularity) és Jelenlevő (Present) biteknek az adatszegmens deszkriptorokbeli szerepükkel azonos funkciójuk van. A Limit mezőnek 67H-nál nagyobb vagy egyenlő értéke kell legyen, ami egy Byte-tal kevesebb egy taszk-állapot minimális méreténél. Egy olyan taszkra való áttérés, amelynek a TSS deszkriptor-limitje kevesebb mint 67H, kivételt generál. Egy I/O engedélyező bittérkép használatakor nagyobb
limitre van szükség. Az operációs rendszernek akkor is szüksége lehet egy nagyobb limit értékre, ha a TSS-ben a rendszer kiegészítő adatokat tárol. Egy TSS deszkriptorhoz hozzáférő procedúra kiválthat egy taszkkapcsolást. A rendszerek többségében a TSS deszkriptorok DPL mezőinek értéke 3-nál kisebbnek kell lennie, hogy csak a privilegizált software-ek végezhessenek taszkkapcsolást. A TSS deszkriptorhoz való hozzáférés nem adja meg a procedúrának azt a képességet, hogy olvashassa vagy módosíthassa a deszkriptort. Az olvasás vagy a módosítás csak az ugyanarra a memóriaterületre leképezett adat deszkriptor alkalmazásával lehetséges. A TSS deszkriptornak egy szegmensregiszterbe való töltése kivételt generál. A TSS deszkriptorok csak a GDT-ben tartózkodhatnak Egy TSS hozzáférésére tett olyan kísérlet, amely egy magasra állított TI bittel rendelkező szelektort alkalmaz (ami az aktuális LDT-t jelöli), kivételt eredményez.
3.83 Taszkregiszter A taszkregiszter (TR) az aktuális TSS megtalálását szolgálja. A 3.55 ábra azt az utat mutatja, amit a processzor megtesz a TSS eléréséhez. A taszkregiszternek van egy látható része (tehát egy olyan része, amelyet a software olvasni és módosítani képes), és egy láthatatlan része (azaz egy olyan része, amelyet a processzor tárol, illetve amely a software számára elérhetetlen). A látható részben levő szelektor egy TSS deszkriptor GDT-beli indexe. A processzor a TR láthatatlan részét a TSS 208 Védett üzemmódú multitaszking deszkriptorból származó báziscím és limit értékének tárolására használja. Ezeknek az értékeknek a megtartása a taszk végrehajtását sokkal hatékonyabbá teszi, mivel a processzornak nem kell ezeket az értékeket a memóriából elérnie, azért, hogy az aktuális taszk TSS-ét megcímezze. Az LTR és STR utasítások a taszkregiszter látható részének módosítására és olvasására
használatosak. Mindkét utasításnak egyetlen operandusa van, egy memóriában elhelyezett 16 bites szegmens-szelektor, vagy egy általános regiszter. Az LTR (Load Task Register) utasítás feltölti a taszkregiszter látható részét az operandussal, amely a GDT-ben levő egyik TSS deszkriptorhoz kell index legyen. Az LTR utasítás ugyanakkor feltölti a láthatatlan részt is a TSS deszkriptorból vett információkkal. Az LTR utasítás egy privilegizált utasítás, csak akkor hajtható végre, ha CPL=0. Az LTR utasítást általában a rendszerinicializálás alkalmával használják arra, hogy egy kezdeti értéket tegyenek a taszkregiszterbe. Ezt követően, a TR regiszter tartalma a taszkkapcsolást előidéző események által módosul. Az STR (Store Task Register) utasítás egy általános regiszterbe, vagy a memóriába menti el a taszkregiszter látható részét. Az STR utasítás szintén privilegizált. A taszk kapudeszkriptor egy taszkhoz biztosít indirekt,
védett referenciát. A 356 ábra egy taszkkapu formátumát illusztrálja A taszkkapu szelektor mezője index egy TSS deszkriptorhoz. Ennek a szelektornak az RPL értéke nem használt. A taszkkapu DPL-je szabályozza a taszkkapcsolás deszkriptorhoz való hozzáférését. Egy procedúra nem szelektálhat egy taszkkapu deszkriptort anélkül, hogy a szelektor RPL-je és a procedúra CPL-je numerikusan kisebbek, vagy egyenlők lennének a deszkriptor DPL értékével. Ez meggátolja a kevésbé privilegizált procedúrákat abban, hogy taszkkapcsolást idézzenek elő. Amikor egy taszkkapu kerül alkalmazásra, a cél TSS deszkriptor DPL értéke nem lesz felhasználva. 209 Általános CPU programozási információk Taszk állapot szegmens Látható rész Szelektor Láthatatlan rész Bázis cím Szegmens határ TR Globális deszkriptor táblázat N TSS Deszkriptor 0 3.55 ábra: Taszk regiszter Egy taszkkapuhoz hozzáférő procedúra taszkkapcsolást válthat ki
ugyanúgy, mint egy TSS deszkriptorhoz hozzáférő procedúra. Úgy a taszkkapuk, mint a TSS deszkriptorok célja az, hogy három követelményt elégítsenek ki: 1. Egy taszknak csupán egyetlen Foglalt (Busy) bitje legyen. Minthogy a Foglalt bit tárolva van a TSS deszkriptorban, minden taszknak csak egyetlen ilyen deszkriptora lehet. Ennek ellenére, létezhet számtalan olyan taszkkapu, amely ugyanazt az egy TSS deszkriptort szelektálja. 2. A taszkokhoz szelektív hozzáférést biztosítsanak. A taszkkapuk teljesítik ezt az elvárást, ugyanis helyet foglalhatnak egy LDT-ben és a TSS deszkriptor DPL értékétől eltérő DPL-jük lehet. Egy 210 Védett üzemmódú multitaszking olyan procedúra, amelynek nincs meg a kellő privilegizálási szintje a GDT-beli TSS deszkriptor használatához (amelynek a DPL értéke általában 0), még mindég meghívhat egy másik taszkot, ha hozzáférhet annak LDT-jében levő taszkkapuhoz. A taszkkapuk segítségével az
operációs rendszer leszűkítheti a taszkkapcsolást bizonyos taszkokra. 3.84 Taszk kapudeszkriptorok TSS Kapudeszkriptor 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Típus Fenntartva P DPL 0 TSS szegmens szelektor 0 1 0 1 Fenntartva Fenntartva +4 +0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 DPL - Deszkriptor privilégium szint P - A szegmens jelenlétét jelző bit 3.56 ábra: Taszk kapudeszkriptor 3. Egy megszakítás vagy kivétel taszkkapcsolást eredményezzen. A taszkkapuk az IDT-ben is lehetnek, amely lehetővé teszi a megszakítások és kivételek számára, hogy taszkkapcsolás eredményezzenek. Amikor egy megszakítás vagy egy kivétel egy taszkkapura mutató vektort szolgáltat, a proceszszor átkapcsol a jelzett taszkra. 211 Általános CPU programozási információk A 3.57 ábra bemutatja azt a módot, ahogyan mind az LDT-ben levő taszkkapu, mind pedig az IDT-ben
helyet foglaló taszkkapu azonosítja ugyanazt a taszkot. Lokális deszkriptor táblázat Globális deszkriptor táblázat Taszk kapu TSS deszkriptor Taszk státusz szegmens Megszakítás deszkriptor táblázat Taszk kapu 3.57 ábra: Taszkokra jellemző taszk kapuk 3.85 Taszkkapcsolás A processzor átadja a vezérlést egy másik taszknak a következő négy eset bármelyikében: 212 Védett üzemmódú multitaszking 1. Az aktív taszk egy JMP vagy CALL utasítást hajt végre egy TSS deszkriptorra. 2. Az aktív taszk egy JMP vagy CALL utasítást hajt végre egy taszkkapura 3. Egy megszakítás vagy egy kivétel az IDT-ben levő egyik taszkkapura mutat. 4. Az aktív taszk egy IRET utasítást hajt végre, miközben az NT flag magasra van állítva. A JMP, CALL és IRET utasítások, csakúgy mint a megszakítások és kivételek, a processzor közönséges mechanizmusai, melyeket olyan körülmények között is használni lehet, amelyekben nem jön létre
taszkkapcsolás. A deszkriptor típusa (amikor a taszk call hívást kap), illetve az NT bit (ha a taszk visszatér) különböztetik meg a standard mechanizmust attól a formától, amely egy taszkkapcsolást okoz. A JMP vagy CALL utasítások, annak érdekében, hogy taszkkapcsolást hozzanak létre, átadhatják a vezérlést akár egy TSS deszkriptornak, akár egy taszkkapunak. Mindkét esetben az eredmény ugyanaz: a processzor átadja a vezérlést a megadott taszknak. Egy megszakítás vagy egy kivétel akkor vált ki taszkkapcsolást, ha az IDT-ben levő egyik taszkkapura mutat. Ha egy IDT-beli megszakítás vagy trap kapura indexel, taszkkapcsolás nem megy végbe. Egy megszakítás kiszolgáló rutin mindíg visszaadja a vezérlést a megszakított procedúrának, amely esetenként más taszkban is lehet. Ha az NT bit törölve van, normális visszatérés következik. Ha az NT magasra van állítva, taszkkapcsolás jön létre. A taszkkapcsolást fogadó taszk a
megszakításkezelő rutin TSS-ében levő TSS szelektor által van meghatározva. Egy taszkkapcsolás a következő lépések szerint történik: 213 Általános CPU programozási információk 1. Ellenőrzi azt, hogy az aktív taszk átkapcsolhat-e az új taszkra. Az adat-hozzáférési privilégiumszabályok a JMP és CALL utasításokra vonatkoznak. A TSS deszkriptor és a taszkkapu DPLje számszerint nagyobb (tehát alacsonyabb privilegizálási szinten) vagy egyenlő kell legyen a kapuszelektor CPL és RPL értékével. A megszakítások, kivételek és az IRET utasítás számára megengedett a taszkkapcsolás, függetlenül a cél taszkkapu, vagy a TSS deszkriptor DPL értékétől. 2. Ellenőrzi azt, hogy a bejövő taszk TSS deszkriptora jelenlevőként van-e megjelölve, illetve érvényes limitje van-e (nagyobb mint 67H). A hibák visszaállítják a processzor állapotában végzett bármely változtatást, ha kísérlet történik a hiba-generáló utasítás
végrehajtására. Ez a tény megengedi a kivétel-kiszolgáló rutin számára, hogy a visszatérési cím a hiba-kiváltó utasításra mutasson, és nem az ezt követő utasításra. A kivétel-kiszolgáló rutin kijavíthatja azt az okot, amely a hibát előidézte, és újraindíthatja a taszkot. A kivétel-kiszolgáló rutin beavatkozása teljesen áttetsző lehet a felhasználói program számára. 3. Elmenti az aktuális taszk állapotát. A processzor megtalálja a taszkregiszterben az aktuális TSS báziscímét. A processzor regiszterek átmásolásra kerülnek az aktuális TSS-be (az EAX, ECX, EDX, EBX, ESP, ESI, EDI, ES, CS, SS, DS, FS, GS és EFLAGS regiszterek, valamint az utasításmutató). 4. A TR regisztert feltölti a bejövő taszk TSS deszkriptorára vonatkozó szelektorral, beállítja a bejövő taszk Foglalt bitjét, illetve a CR0 regiszter TS bitjét. A szelektor vagy egy CALL, illetve JMP utasítás operandusa, vagy egy taszkkapuból származik. 5.
Betölti az új taszk állapotát a megfelelő TSS-ből, és folytatja a végrehajtást. A betöltött regiszterek a következők: az LDTR regiszter; a PBDR (CR3); az EFLAGS regiszter; az általános regiszterek EIP, EAX, ECX, EDX, EBX, ESP, ESI, EDI és a szegmensregiszterek ES, CS, SS, DS, FS valamint a GS. Az ebben a lépésben detektált bármely hiba, megjelenik a bejövő taszk 214 Védett üzemmódú multitaszking környezetében. Egy kivétel-kiszolgáló rutin számára úgy tűnik, mintha az új taszk első utasítása nem lett volna végrehajtva. Fontos, hogy taszkkapcsolás esetén a kimenő taszk állapota mindig elmentődik. Ha a taszk folytatódik, a vezérlés azzal az utasítással kezdődik, amely normális esetben következett volna. A regiszterek azokra az értékekre lesznek visszaállítva, amelyeket a megállásuk pillanatában tartalmaztak. Minden taszkkapcsolás magasra állítja a CR0 regiszter TS (Task Switched) bitjét. A TS bit a rendszersoftware
számára hasznos az integer és a lebegőpontos egységek műveleteinek koordinálására. A TS bit azt mutatja, hogy a lebegőpontos egység környezete eltérhet az aktív taszk környezetétől. A taszkkapcsolások által okozott kivételeket (a 3.58 ábra 5-től 17.-ig terjedő pontjaiból adódó kivételeket) kezelő rutinok rekurzív hívások alanyai lehetnek, ha megkísérelik a kivételt létrehozó szegmensszelektort újra betölteni. A kivétel okát (vagy a többszörös okok közül az elsőt) meg kell szüntetni, mielőtt a szelektor újratöltődne. A kimenő taszk privilegizálási szintje és a bejövő taszk privilegizálási szintje között nincs összefüggés. Minthogy a taszkokat elszigetelik egymástól a független címtartományaik és taszkállapotszegmenseik, és mivel a TSS-hez való hozzáférést privilégium szabályok ellenőrzik, a taszkkapcsoláshoz nincs szükség a privilégium vizsgálatára. A bejövő taszk a CS regiszter új tartalmának RPL
értéke által mutatott privilegizálási szinten kezd végrehajtódni, amelyet a TSS-ből tölt be. Lépés 1 2 Állapot ellenörzés A TSS deszkriptor jelen van a memóriában A TSS deszkriptor nem foglalt Kivétel1 NP TS, GP Hibakód hivatkozás Az új taszk TSS-e A taszk visszakapcsolt TSS-e 215 Általános CPU programozási információk 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 A TSS szegmens határ TS Az új taszk TSS-e nagyobb vagy egyenlő mint 108 A regiszterek feltöltve a TSS értékeivel Az új érvényes taszk LDT TS Az új taszk LDTszelektora2 je A kódszegmens DPL értéke TS Új kódszegmens megegyezik a szelektor RPL értékével Az SS szelektor érvényes2 TS Új veremszegmens A veremszegmens jelen SF Új veremvan a memóriában szegmens A veremszegmens DPL TS Új veremértéke megegyezik a CPL szegmens értékkel Az új taszk LDT-je jelen TS Az új taszk LDTvan a memóriában je A CS szelektor érvényes2 TS Új kódszegmens A kódszegmens jelen van a NP
Új kódszegmens memóriában A veremszegmens DPL TS Új veremértéke megegyezik a szegmens szelektor RPL értékével TS Új adatszegmens A DS, ES, FS és GS 2 szelektorok érvényesek A DS, ES, FS és GS TS Új adatszegmens szegmensek olvashatók A DS, ES, FS és GS NP Új adatszegmens szegmensek jelen vannak a memóriában A DS, ES, FS és GS TS Új adatszegmens szegmensek DPL értéke nagyobb vagy egyenlő a CPL értékével 3.58 ábra: Taszkváltás alatti ellenörzés 216 Védett üzemmódú multitaszking Megjegyzések: A jövőbeli Intel processzorok az ellenőrzéseket eltérő sorrendben végezhetik. 1. NP= a szegmens nincs jelen kivétel, GP= általános védelmi hiba kivételek, TS= "érvénytelen TSS" kivétel, SF= veremhiba kivétel. 2. Egy szelektor akkor érvényes, ha egy kompatibilis típusú táblázatban van (például egy LDT szelektor nem lehet bármilyen más táblázatban a GDT-n kívül), a táblázat szegmenshatárán belüli címet foglal
el, és egy kompatibilis típusú deszkriptorra utal (például a CS regiszterben levő szelektor csak abban az esetben érvényes, ha egy kódszegmens deszkriptorra mutat, a deszkriptor típusa a típusmezőben van megadva). 3.86 Taszkok visszafelé kapcsolása (LINKING) A TSS Link mezője és az NT jelzőbit célja, hogy az előző taszknak visszaszolgáltassa a vezérlést. Az NT flag megmutatja, hogy az éppen végrehajtás alatt álló taszk be van-e ágyazva egy másik taszkba, és az aktív taszk TSS-ének Link mezője a magasabb szinten levő taszk TSS szelektorát tárolja, ha létezik ilyen. (lásd a 359 ábrát) 217 Általános CPU programozási információk Legfelső szintű taszk TSS Beágyazott taszk TSS Mélyebben beágyazott taszk TSS Jelenleg futó taszk EFLAGS NT=1 NT=0 LINK NT=1 LINK NT=1 LINK TR regiszter 3.59 ábra: Beágyazott taszkok Amikor egy megszakítás, kivétel, jmp vagy call taszkkapcsolást eredményez, a processzor bemásolja az
aktuális taszk-állapot-szegmens szelektorát az új taszk TSS-ébe, és beállítja az NT bitet. Az NT flag azt jelzi, hogy a TSS Link mezőjébe egy elmentett TSS szelektor került betöltésre. Az új taszk egy IRET utasítás végrehajtásával adja vissza a vezérlést. Az IRET utasítás végrehajtásakor az NT bit ellenőrzés alá kerül. Ha ez 1-re van állítva, a processzor taszkkapcsolást végez az előző taszkra. A 360 ábra összefoglalja azon TSS mezők szerepét, amelyeket a taszkkapcsolás érint. Mező Az ugrás hatása A CALL utasítás Az IRET vagy utasítás hatása megszakítás hatása Az új taszk Busy A bit beállítva A bit beállítva Nem változik, bitje (előtte töröltnek (előtte töröltnek 1-nek kell lennie kell lennie) kell lennie) A régi taszk A bit törölt Nem változik A bit törölt Busy bitje Az új taszk NT Nem változik A flag Nem változik flagje beállítódik 218 Védett üzemmódú multitaszking A régi taszk NT flagje Az új
taszk Link mezője A régi taszk Link mezője Nem változik Nem változik A flag törölt Nem változik A szelektorral betöltve Nem változik Nem változik Nem változik Nem változik 3.60 ábra: A taszkváltások hatása a Busy, NT és LINK mezőkre Megjegyzendő, hogy az NT flaget bármely privilegizálási szinten futó software módosíthatja. Egy program számára adott az a lehetőség, hogy beállítsa az NT bitet és végrehajtson egy IRET utasítást, aminek az volna a következménye, hogy meghívásra kerülne az aktuális taszk TSSének Link mezője által megjelölt taszk. Annak érdekében, hogy a hamis taszkkapcsolások ne járjanak sikerrel, az operációs rendszernek inicializálnia kell minden egyes általa létrehozott TSS Link mezőjét. 3.861 A Busy (foglalt) bit megelőzi a hurkok kialakulását A TSS deszkriptorának B (foglalt) bitje megakadályozza az újraindított taszkkapcsolást. Csak egyetlen egy elmentett taszk-környezet létezik, a TSS-ben
eltárolt környezet, ezért egy taszkot csak egyszer szabad meghívni mielőtt befejeződne. A felfüggesztett taszkok lánca bármilyen hosszúra megnőhet, a többszörös megszakításoknak, kivételeknek, ugrásoknak és hívásoknak köszönhetően. A B bit megakadályozza, hogy a taszkot meg lehessen hívni, ha ebben a láncban található. Egy újrahívott taszkkapcsolás felülírná a taszk régi TSS-ét, ami felbontaná a láncot. A processzor a következőképpen kezeli a Busy bitet: 1. Mikor átkapcsol egy taszkra, a processzor beállítja a bejövő taszk B bitjét 219 Általános CPU programozási információk 2. Mikor visszakapcsol egy taszkról, a processzor letörli a kimenő taszk B bitjét, ha azt a taszkot nem kell a láncba helyezze (ha tehát a taszkkapcsolást előidéző utasítás egy JMP vagy CALL utasítás). Ha a taszk a láncba kerül, a B bitje továbbra is 1-re marad állítva. 3. Ha az új taszk Busy bitje már be van állítva,
taszkkapcsolás esetén a processzor egy általános védelmi hiba kivételt generál. Eképpen a processzor meggátolja, hogy egy taszk saját magára kapcsolhasson, vagy a lánc bármely más taszkjára, ezzel megakadályozva az újraindított (re-entrant) taszkkapcsolást. A B bitet multiprocesszoros konfigurációban is lehet használni, mivel a processzor buszlezárást (bus lock) indítványoz amikor beállítja, vagy törli a B bitet. Ez megakadályozza, hogy két processzor ugyanazt a taszkot hívhassa meg. 3.862 A taszk visszakapcsolások módosítása Annak érdekében, hogy a megszakított taszkokat, az őket megszakító taszkok előtt folytatni lehessen, szükségessé válhat a felfüggesztett taszkok láncának módosítása. Ennek egy megbízható módja a következő: 1. A megszakítások letiltása. 2. Elsőként, a megszakító taszk TSS-ének Link mezőjét kell megváltoztatni, majd a láncból kiemelt taszk TSS deszkriptorának B bitjét kell törölni. 3.
A megszakítások engedélyezése. 220 Védett üzemmódú multitaszking 3.87 Taszkok címtartománya Az LDT szelektor és a TSS PDBR (CR3) mezője felhasználható arra, hogy minden taszkhoz saját LDT és laptáblázat legyen rendelve. Minthogy a lokális deszkriptor-táblázatokban (LDT) levő szegmensdeszkriptorok képezik a taszkok és a szegmensek közötti kapcsolatot, minden egyes taszknak önálló LDT-t lehet biztosítani, ezen kapcsolatok fölötti egyéni kontroll létrehozása érdekében. Bármely meghatározott szegmenshez való hozzáférés hozzárendelhető bármely egyéni taszkhoz, a szegmens szegmens-deszkriptorának a megfelelő taszk lokális deszkriptor-táblázatába való helyezésével. Ha a lapozás engedélyezett, minden taszknak lehet egy saját laptáblázat gyűjteménye, a lineáris címeknek fizikai címekre való leképezése végett. Az is lehetséges, hogy a taszkoknak ugyanaz az LDT-je legyen. Ez egy egyszerű és memóriatakarékos módja
annak, hogy bizonyos taszkoknak engedélyezni lehessen, hogy egymás között kommunikáljanak, illetve egymást vezéreljék, anélkül, hogy a teljes rendszer védelmi korlátait ejteni kéne. Mivel mindegyik taszk hozzáférhet a GDT-hez, az a lehetőség is adott, hogy ezen táblázaton belüli szegmensdeszkriptorokkal elérhető megosztott szegmenseket hozzunk létre. 3.871 Taszkok által lineárisról- fizikai címre végzett leképzés A taszkok lineáris-fizikai leképzései (linear-to-physical mapping) két általános kategóriába sorolhatók: 1. Minden taszk által megosztott, egyetlen lineáris-fizikai leképzés. Ha a lapozás nincs engedélyezve, ez az egyedüli lehetőség. Lapozás hiányában minden lineáris cím az identikus fizikai címekre van leképezve. Ha engedélyezett a lapozás, a lineárisfizikai leképzés e formája úgy valósítható meg, hogy minden taszk egyetlen közös lapcímtárat használ. A lineáris tartomány meghaladhatja a rendelkezésre
álló fizikai tartományt, ha 221 Általános CPU programozási információk támogatott az igényeknek megfelelően lapozható (demand-paged) virtuális memória használata. 2. Független lineáris-fizikai leképzés minden egyes taszknak. A leképezés e formája abból adódik, hogy minden egyes taszk különálló lapcímtárat használ. Mivel minden taszkkapcsoláskor a PDBR (a lapcímtár bázisregisztere) a TSS-ből kerül betöltésre, mindegyik taszknak különálló lapcímtára lehet. A különböző taszkok lineáris címtartománya teljesen eltérő fizikai címekre képezhető le. Ha a különböző lapcímtárak bemenetei különböző laptáblázatokra mutatnak, és a laptáblázatok a fizikai memória különböző lapjaira mutatnak, akkor a taszkok egyetlen közös fizikai címen sem osztoznak. A taszk-állapot-szegmensnek egy minden taszk számára elérhető tartományban kell helyet foglalnia, azért, hogy a TSS címek leképezése taszkkapcsolás közben
ne változzon, mialatt a proceszszor a TSS-ét olvassa, illetve újraírja. A GDT által leképzett lineáris tartomány egy megosztott fizikai tárterületre is le kell legyen képezve, ellenkező esetben a GDT célját veszti. A 361 ábra bemutatja, hogy laptáblázatok közössé tételével két taszk lineáris tartománya miként fedi át egymást a fizikai tárterületben. 3.872 A taszkok logikai címtartománya Egymagában az átfedett, lineárisról-fizikai tartományba való leképezés (mapping) nem engedi meg a taszkok közötti adatmegosztást. Ahhoz, hogy adatokat tehessenek közössé, a taszkoknak egy közös logikairól-lineáris tartományba való leképezésre is szükségük van. Magyarán olyan deszkriptorokhoz is hozzá kell férhessenek, amelyek egy megosztott (közössé tett), lineáris címtartományra mutatnak. Három módja van a megosztott, logikairól fizikai címtartományba való leképezések megteremtésének: 1. 222 A GDT szegmensdeszkriptorain
keresztül. Minden taszk hozzá tud férni a GDT-ben levő deszkriptorokhoz. Ha ezek a deszkriptorok Védett üzemmódú multitaszking egy olyan lineáris címtartományra mutatnak, amely az összes taszk számára közös fizikai címtartományra van leképezve, akkor a taszkok közössé tehetnek adatokat, illetve utasításokat. 2. Közössé tett LDT-ken keresztül. Két, vagy több taszk használhatja ugyanazt a lokális deszkriptor-táblázatot (LDT-t), ha a TSS-ükben található LDT szelektorok ugyanazt a LDT-t szelektálják a címfordításhoz. Az LDT-beli szegmensdeszkriptorok, amelyek átfedett (overlapping) fizikai tartományra leképezett lineáris tartományt címeznek meg, megosztott (shared) fizikai memóriát szolgáltatnak. 3. Ugyanarra a lineáris címtartományra leképező LDT-beli szegmensdeszkriptorokon keresztül. Ha a szóban forgó taszk lapleképezése a lineáris címtartományt ugyanarra a fizikai címtartományra képzi le, ezen deszkriptorok
lehetővé teszik a taszkok számára, hogy címterületeket tegyenek közössé. Ezeknek a deszkriptoroknak a közönséges neve: alias. A jelen eljárás még inkább szelektívebb, mint a fentebb felsoroltak, ugyanis az LDT többi deszkriptora független, nem megosztott, lineáris címtartományokra mutathat. 223 Általános CPU programozási információk A taszk TSS-e Lapcímtárak Laptáblázatok Lapkeretek A taszk lapja PTE A taszk lapja PTE PDBR PDE PTE PDE Megosztott Laptáblázatok A taszk lapja Megoszt. lap PTE PTE B taszk TSS-e Megoszt. lap B taszk lapja PDBR PDE PTE PDE PTE 3.61 ábra: Lineáris átfedés a fizikai memóriában 224 B taszk lapja Védett üzemmódú kivételek és megszakítások 3.9 Védett üzemmódú kivételek és megszakítások A kivételek és megszakítások egy taszknak vagy egy procedúrának történő erőltetett vezérlésátadása. A taszkot, vagy a procedúrát "kiszolgáló rutinnak" nevezzük
(handler). A megszakítások véletlenszerűen jelennek meg egy program végrehajtása közben, a hardware-jelzésekre adott válaszként. A kivételek akkor jelennek meg, amikor kivételeket előidéző utasítások hajtódnak végre. Általános esetben, a megszakítások és kivételek szervizelése a felhasználói programok számára áttetsző módon megy végbe. A megszakítások, a processzoron kívüli események, mint például a periféria-eszközök kiszolgálási kéréseinek kezelésére használatosak. A kivételek, a processzor által az utasítások végrehajtása alatt észlelt feltételeket kezelnek, mint például a nullával való osztást. A megszakításoknak és a kivételeknek két-két forrása van: 1. Megszakítások Maszkolható megszakítások, amelyeket a CPU az INTR bemenetére kap. A maszkolható megszakítások addig nem keletkeznek, amíg a megszakítás-engedélyező flag (IF) nincs 1-re állítva. Nem maszkolható megszakítások, amelyek a
processzor NMI (NonMaskable Interrupt) vonalán érkeznek be. A processzor nem rendelkezik egy olyan mechanizmussal, amelyik meggátolná a nem maszkolható megszakításokat. 2. Kivételek A processzor által detektált kivételek. Ezek tovább bonthatók hibákra (faults), csapdákra (traps) és abortokra. Programozott kivételek. Az INTO, INT 3 , INT n és BOUND utasítások kivételeket generálhatnak. Ezeket az utasításokat gyakran nevezik "software- 225 Általános CPU programozási információk megszakításoknak", de a processzor kivételekként kezeli őket. A jelen rész a processzor azon adottságait mutatja be, amelyek kontrollálják a megszakításokat, és válaszolnak azokra. 3.91 Kivétel- és megszakításvektorok A processzor minden egyes megszakítás- vagy kivételtípushoz rendel egy azonosító számot. Ezt a számot "vektor"-nak nevezzük Az NMI megszakításhoz és a kivételekhez a 0-tól 31-ig terjedő tartományból
vannak a vektorok rendelve. A processzor jelenleg nem használja mindegyiket közülük. E tartomány szabad vektorai egy esetleges jövőbeli felhasználásra fenntartottak ezért ne használjuk a hozzárendeletlen vektorokat. A maszkolható megszakítások vektorait a hardware determinálja. A külső megszakítás-vezérlők, (mint például az 8258A jelzésű programoztó megszakítás-vezérlő) a processzor buszára helyezik a vektort, ennek megszakítás-elismerő ciklusa idején. A 32-től 255-ig terjedő tartományból bármely vektorok alkalmazhatók. A 362 ábra a kivétel- és megszakítás-vektorok kirendelését mutatja. Vektorszám 0 1 2 3 4 5 6 7 8 9 10 226 Meghatározás Osztási hiba Debug kivétel Nem maszkolható megszakítás Töréspont INTO túlcsordulást talált BOUND határ túllépés Nem megengedett op. kód Eszköz nem elérhető Dupla hiba Koprocesszor szegmens túlfutás Érvénytelen taszk státusz szegmens Védett üzemmódú kivételek és
megszakítások 11 12 13 14 15 16 17 18 19-31 32-255 Szegmens nincs jelen Verem hiba Általános védelmi hiba Laphiba Intel által fenntartva Lebegőpontos hiba Illeszkedés ellenőrzés Géptípus ellenőrzés Intel által fenntartva Maszkolható megszakítások 3.62 ábra: Kivételek és megszakításvektorok * Megjegyzés: A processzortípus ellenőrzés modell-specifikus kivétel, amely csak a Pentium processzorokon létezik. A kivételeket hibákra, trapokra és abortokra oszthatjuk, annak függvényében, hogy miként vannak jelentve, illetve, hogy a kivételt előidéző utasítás újraindítását támogatják-e. Hibák (faults): A hiba egy olyan kivétel, amelyet a processzor az utasításhatáron jelent, azon utasítást megelőzően, amelyben a kivétel észlelve volt. A hiba jelentése a gépnek egy olyan helyreállított állapotában történik, amely megengedi az utasítás újraindítását. A hibakezelő rutin visszatérési címe a hibát kiváltó utasításra
mutat, nem pedig az ezt követő utasításra. Csapdák (traps): A trap egy olyan kivétel, amelyet a processzor az utasításhatáron jelent, rögtön azon utasítást követően, amelyben a kivétel észlelve volt. Abort-ok (aborts): Az abort egy olyan kivétel, amely nem jelenti minden esetben a kivételt előidéző utasítás helyét, és amely nem engedélyezi a kivételt kiváltó program újraindítását. Az abortok komoly hibák jelentésére használatosak, mint amilyenek a hardware-hibák, vagy a rendszer táblázatokban talált összeférhetetlen, vagy szabálytalan értékek. 227 Általános CPU programozási információk 3.92 Utasítások újraindítása A megszakítások és kivételek legnagyobb része esetén, a vezérlésátadásra mindaddig nem kerül sor, amíg az aktuális utasításnak nincs vége. Ennek az az eredménye, hogy az EIP regiszter a kivétel vagy megszakítás megjelenésének pillanatában, éppen a végrehajtás alatt álló utasítást
közvetlenül követő utasításra mutat. Ha az utasításnak van egy ismétlési prefixe, a vezérlés átadása az aktuális művelet végén történik, a következő művelet elvégzésére beállított regiszterekkel. Ellenben, ha a kivétel egy hiba, a processzor regiszterei visszaállítódnak azokra az állapotokra, amelyeket az utasítás elkezdése előtt tartalmaztak. Ez lehetővé teszi az utasítások újraindítását. Az utasítás újraindítást olyan kivételek kezelésére lehet felhasználni, amelyek lezárják az operandusokhoz való hozzáférést. Például, egy felhasználói program hivakozhat egy olyan szegmensben levő adatra, amely nincs betöltve a memóriába. Amikor a kivétel megjelenik, a kivétel-kiszolgáló rutinnak be kell töltenie a szegmenst (valószínűleg a lemezről), és folytatnia kell a végrehajtást a kivételt előidéző utasítással kezdődően. A kivétel megjelenésének pillanatában, az utasítás már megváltoztathatta a
processzor egyes regisztereinek tartalmát. Ha az utasítás egy operandust olvasott ki a veremből, kötelező a veremmutatót a megelőző értékre visszaállítani. A processzor mindezen visszaállító műveleteket a felhasználói programok számára teljesen átlátszó módon végzi el. Mikor egy hiba jelenik meg, az EIP regiszter úgy lesz helyreállítva, hogy a kivételt kiváltó utasításra mutasson. Amikor a kivétel-kiszolgáló handler visszatér, a végrehajtás ezzel az utasítással folytatódik. 3.93 Megszakítások engedélyezése és letiltása Bizonyos feltételek és jelzőbit-beállítások arra késztetik a processzort, hogy egyes megszakítás- és kivételtípusokat letiltson. 228 Védett üzemmódú kivételek és megszakítások 3.931 További NMI megszakítások maszkolása Amíg egy NMI megszakításkezelő rutin fut, a processzor letiltja a megszakítást kiszolgáló procedúrához vagy taszkhoz intézett további hívásokat, mindaddig, amíg a
következő IRET utasítás nem kerül végrehajtásra. Ezzel megelőzi azt, hogy a megszakításkezelőhöz intézett hívások felgyűljenek a veremben. Ajánlott, megszakítás kapuk alkalmazása a nem maszkolható megszakításokra (NMI), az egymásbaágyazott maszkolható megszakítások letiltása céljából, ugyanis egy maszkolható-megszakítást kiszolgáló eljárásból származó IRET utasítás újra engedélyezné az NMI-t. 3.932 INTR megszakítások maszkolása Az IF flag kikapcsolhatja a processzor INTR vonalán beérkező megszakítások szervizelését. Ha az IF bit törölve van, az INTR megszakítások figyelmen kívül maradnak. Ha az IF magasra van állítva, az INTR megszakítások ki lesznek szolgálva. Egy RESET jelre válaszolva, a processzor, a többi flag-hez hasonlóan, törli az IF bitet is. Az STI és CLI utasítás magasra állítja (set), illetve letörli (clear) az IF bitet. A CLI (Clear Interrupt-Enable Flag - megszakítés engedélyező bit
törlése) utasítás és az STI (Set Interrupt-Enable Flag - megszakítás engedélyező bit beállítása) utasítás egy ismert állapotba hozza az IF flaget (az EFLAGS regiszter 9. bitjét) Ezek az utasítások csak akkor hajthatók végre, ha a CPL szint megegyezik az IOPL értékével, vagy annál privilegizáltabb. Az IF bitet még a következő műveletek is befolyásolják: A PUSHF utasítás eltárol minden flag-et a verembe, ahol ezek vizsgálhatók, illetve módosíthatók. A POPF utasítással lehet a megváltoztatott formát az EFLAGS regiszterbe visszatölteni. 229 Általános CPU programozási információk A taszkkapcsolások, illetve a POPF és IRET utasítások feltöltik az EFLAGS regisztert, tehát felhasználhatók az IF bit beállításának megváltoztatására. A kapuzott megszakítások automatikusan törlik az IF bitet, letiltva ezzel a megszakításokat. 3.933 Debug hibák maszkolása az RF bit segítségével Az EFLAGS regiszterben
található RF bit alkalmazásának célja, hogy meggátolja egy utasítás-töréspont hiba többszörös kiszolgálását. Az RF a következőképpen működik: Mielőtt a processzor belépne bármely hibakezelő rutinba, előbb beállítja az RF bitet az EFLAGS másolatában, amelyet aztán a kiszolgáló rutin veremébe helyez (push). Normális esetben, az RF verembeli képét a software-ek nem kell módosítsák. Magát az RF bitet a hibakezelő rutin állítja be, amikor az IRETD utasítást hajtja végre a hiba-generáló utasításra való visszatéréshez. Az IRETD utasítás átmozgatja az EFLAGS képét a veremből az EFLAGS regiszterbe. (A POPF és POPFD utasítások nem viszik át az RF másolatát az EFLAGS regiszterbe.) A processzor törli az RF bitet, ha minden utasítást sikerült befejeznie, kivéve az IRET utasítást, illetve a taszkkapcsolást előidéző JMP, CALL vagy INT utasításokat. Tehát az RF flag beállítva marad, de nem több, mint
egy, - az IRET után közvetlen következő - utasítás idejére. Ha RF be van állítva, arra készteti a processzort, hogy beszüntesse az utasítás-töréspont hibák jelentését. Mivel az utasítás-töréspont hibák a legnagyobb prioritással rendelkező hibák, ugyanahhoz az utasításhoz kapcsolódó bármely más hibát megelőzően kerülnek bejelentésre. Az utasítás végrehajtására tett legelső kísérlet esetén RF=0, illetve RF =1 minden olyan próbálkozás 230 Védett üzemmódú kivételek és megszakítások esetén, amely egy utasítás-töréspont hibát, vagy bármilyen más hibát követően, újraindítaná az utasítást. Ez azt biztosítja, hogy minden utasítás-töréspont hiba csak egyszer lesz jelentve. 3.934 Egyes kivételek és megszakítások maszkolása Azok a software-ek, amelyek gyakran kell veremszegmenst váltsanak, egy utasítás párt használnak, például: MOV MOV SS, AX ESP, StackTop Ha egy megszakítás vagy kivétel
jelenik meg miután a szegmensszelektor már fel van töltve, de még mielőtt az ESP regiszter be lenne töltve, a megszakítás- vagy kivétel-kiszolgáló rutin idejére, a veremtartományba mutató logikai címnek ezen két része összeférhetetlen. Ennek a helyzetnek az elkerülése végett, egy MOV SS-be, vagy POP SS-be típusú utasítást követően, a processzor letiltja a megszakításokat, a debug-kivételeket és az egylépéses nyomkövető trap kivételeket, amíg a következő utasítás mögötti utasításhatárt el nem éri. Általános védelmi-hibák még ekkor is generálódhatnak. Ha az SS regiszter tartalmának módosítására az LSS utasítást használjuk, ez a probléma nem jelenik meg. 3.94 Szimultán kivételek és megszakítások közötti prioritás Ha egy utasításhatáron egynél több kivétel, vagy megszakítás van függőben (pending), a processzor egy előre meghatározható sorrendben szolgálja ki őket. A megszakítás- és kivétel források
osztályai közti prioritásokat a 3.63 ábra mutatja be Amíg ezen osztályok közötti prioritás konzisztens az architektúra egészén, addig minden egyes osztályon belüli kivételek alkalmazás-függők, és processzoronként eltérők lehetnek. A processzor először a legmagasabb prioritással rendelkező osztályba tartozó, függőben levő kivételt, vagy megszakítást szolgál ki, 231 Általános CPU programozási információk átadván a vezérlést a kezelő rutin első utasításának. Az alacsonyabb prioritású kivételeket elveti. Az alacsonyabb prioritású megszakítások függőben maradnak. Az elvetett kivételek újra aktualizálódnak, amikor a megszakítás kezelő visszaadja a vezérlést a megszakítási pontra. Prioritás Osztály Magas 1. osztály 2. osztály 3. osztály 4. osztály Alacsony 5. osztály Meghatározás Trap az előző műveleten -Töréspont -Debug trap kivétel Külső megszakítás -NMI megszakítás -Maszkolható
megszakítás Hiba a következő utasításnál -Kód töréspont hiba -Kódszegmens határ túllépés -Laphiba az előolvasásnál Hiba a következő utasítás dekodolásánál -Érvénytelen op. kód -Műveleti kód hosszabb 15 Byte-nál -Koprocesszor nem áll rendelkezésre Hiba egy utasítás végrehajtásakor -Általános detektálás -Koprocesszor hiba -Túlcsordulás -Határellenörzés -Érvénytelen TSS -Szegmens nincs jelen -Verem kivétel -Általános védelmi hiba -Adat laphiba -Illeszkedés ellenőrzés 3.63 ábra: Kivételek és megszakítások egymás közötti prioritása 232 Védett üzemmódú kivételek és megszakítások 3.95 A megszakításdeszkriptor-táblázat A megszakításdeszkriptor-táblázat (IDT) minden kivételhez és megszakításhoz, a hozzárendelt eseményt kiszolgáló procedúra vagy taszk deszkriptorát rendeli. Akárcsak a GDT, vagy az LDT-k, az IDT is egy 8 Byte-os deszkriptorokat tartalmazó tömb. Az IDT-be mutató indexek
formálásához a processzor beszorozza egy 8-as skálatényezővel (a deszkriptorban levő Byte-ok számával) a kivétel-, vagy megszakításvektort. Mivel mindössze 256 vektor van, az IDT nem tartalmazhat több mint 256 deszkriptort. Kevesebb, mint 256 deszkriptort viszont tartalmazhat, mert deszkriptorokra csak azoknak a megszakításvektoroknak van szükségük, amelyek előfordulhatnak. Az IDT a fizikai memória bármely részén rezidens lehet. Amint azt a 3.64 ábra mutatja, a processzor az IDTR regisztert felhasználva lokalizálja az IDT-t. Ez a regiszter tartalmazza az IDT 32 bites báziscímét, valamint a 16 bites határt. A LIDT és SIDT utasítások töltik fel, illetve mentik el az IDTR regiszter tartalmát. Mindkét utasításnak egy operandusa van, amely a memóriában levő hat Byte címe. IDTR regiszter IDT báziscím IDT határ Megszakítás deszkriptor táblázat Kapu az N. megszakításhoz Kapu az 3. megszakításhoz Kapu az 2. megszakításhoz Kapu az 1.
megszakításhoz 3.64 ábra: IDT lokalizálása a memóriában az IDTR segítségével 233 Általános CPU programozási információk Abban az esetben, ha egy vektor a határon kívülre eső deszkriptorra mutat, a processzor átmegy "shutdown" módba. Ebben az üzemmódban a processzor megszünteti az utasítás-végrehajtást, mindaddig, amíg nem észlel egy NMI megszakítást, vagy amíg egy reset inicializálás nincs kezdeményezve. A processzor egy speciális buszciklust generál a "shutdown" állapotba való belépés jelzésére. A softwarefejlesztők tisztában kell legyenek a hardware-nek erre a jelzésre adott válaszával. Például, a hardware ilyenkor kigyújthat egy fényjelzést a gép fő paneljén, generálhat egy diagnosztika-információkat felvevő NMI megszakítást, vagy kezdeményezhet reset inicializálást. A LIDT (Load IDT Register - a megszakításdeszkriptor-táblázat regisztert betöltő utasítás) feltölti az IDTR
regisztert a memóriában levő operandusban tárolt báziscímmel és limit-tel. Ezt az utasítást csak akkor lehet végrehajtani, ha CPL=0. Általában az operációs rendszerek inicializáló kódja használja az IDT létrehozásához. Az operációs rendszer arra is felhasználhatja, hogy egyik IDT-ről a másikra váltson. SIDT (Store IDT Register - a megszakításdeszkriptor-táblázat regisztert eltároló utasítás) átmásolja az IDTR-ben tárolt báziscímet és limit értéket a memóriába. Ez az utasítás bármely privilégium szinten végrehajtható. 3.96 IDT deszkriptorok Az IDT a következő három típusú deszkriptor közül bármelyiket tartalmazhatja: 1. taszkkapukat 2. megszakítás kapukat 3. trap kapukat A 3.65 ábra bemutatja a taszkkapuk, megszakítás kapuk, és trap kapuk formátumát. 234 Védett üzemmódú kivételek és megszakítások 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Fenntartva P DPL 0 0 1 0
Fenntartva 1 +0 Fenntartva TSS szegmens szelektor +4 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Ofszet 31-16 P DPL 0 1 1 1 0 0 0 0 Fenntartva +0 Ofszet 15-0 Szegmens szelektor +4 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Ofszet 31-16 Szegmens szelektor P DPL 0 1 1 1 1 0 0 0 Fenntartva Ofszet 15-0 +4 +0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 3.65 ábra: IDT kapudeszkriptor 235 Általános CPU programozási információk 3.97 Megszakítás taszkok és megszakítás-kezelő procedurák Amint a CALL utasítás képes egy procedúrát, vagy egy taszkot meghívni, úgy egy kivétel, vagy megszakítás is képes egy kezelőrutint, akár mint procedúrát,
akár mint taszkot "meghívni". A kivételre vagy megszakításra válaszolva, a processzor a kivétel, vagy megszakításvektort alkalmazza egy IDT-ben levő deszkriptor indexelésére. Ha a processzor egy megszakítás-, vagy trap kapura indexel, a call-kapura irányuló CALL utasításhoz hasonló módon hívja meg a kiszolgáló rutint. Ha a processzor egy taszkkaput talál, a taszkkapura irányuló CALL utasításhoz hasonló módon végez taszkkapcsolást. 3.971 Megszakítás-kezelő procedúrák Amint azt a 3.66 ábra mutatja, egy megszakítás-, vagy trap kapu közvetett módon címez meg egy olyan procedúrát, amely az aktív taszk kontextusában fut. A kapu szelektora egy végrehajtható szegmens GDTbeli, vagy az aktuális LDT-ben levő deszkriptorára mutat A kapudeszkriptor ofszet mezője a kivételt vagy megszakítást kiszolgáló procedúra elejére mutat. 236 Védett üzemmódú kivételek és megszakítások IDT Cél kódszegmens Eljárás Ofszet
Megszakítás vektor Megszakítás vagy trap kapu Szegmens szelektor GDT vagy LDT Bázis cím Szegmens deszkriptor 3.66 ábra: Megszakítás procedura hívás A processzor, egy procedúrahívással majdnem azonos módon hív meg egy kivételt, vagy megszakítást kiszolgáló procedúrát. 3.9711 A megszakítás-kezelő eljárás verme Akárcsak egy CALL utasítással történő vezérlésátadás esetén, a kivételt, vagy megszakítást kiszolgáló procedúrának való vezérlésátadás 237 Általános CPU programozási információk is alkalmazza a vermet, a processzor állapotának elmentésére. Amint azt a 3.67 ábra mutatja, egy megszakítás, a megszakított utasítás címének stack-be való eltárolását megelőzően, lenyomja az EFLAGS regiszter tartalmát a verembe. Nem privilégizált szint csere hibakód nélkül Nem privilégizált szint csere hibakóddal Régi ESP Régi EFLAG Régi CS Régi EIP Új ESP Privilégizált szint csere hibakód nélkül Nem
használt Régi SS Régi ESP Régi EFLAG Régi CS Régi EIP Régi ESP Régi EFLAG Régi CS Régi EIP Hibakód Új ESP Privilégizált szint csere hibakóddal ESP a TSS-ből Új ESP Nem használt Régi SS Régi ESP Régi EFLAG Régi CS Régi EIP Hibakód ESP a TSS-ből Új ESP 3.67 ábra: Verem keret egy megszakítás vagy kivétel után Némely kivétel típus egy hibakódot is lenyom a verembe. A kivételt kiszolgáló rutin felhasználhatja a hibakódot a kivétel diagnosztikájára. 3.9712 Visszatérés egy megszakítás-kezelő eljárásból A megszakítás-kezelő eljárás a normális eljárásoktól az eljárásból való kilépés metódusában különbözik. Az IRET utasítás a megszakításkezelő procedúra elhagyására használatos Az IRET utasítás hasonlít a RET utasításra, azzal a különbséggel, hogy négy további Byte-tal növeli az ESP regisztert, és visszaállítja az elmentett flageket az EFLAGS regiszterbe. Az EFLAGS regiszter IOPL mezőjét csak
abban az esetben 238 Védett üzemmódú kivételek és megszakítások állítja vissza, ha a CPL=0. Az IF bit csak akkor módosul, ha CPL<= IOPL. 3.9713 A megszakítás-kezelő eljárás flag-használata A megszakítás kapukat vagy trap kapukat használó megszakítások a TF bit törlését okozzák, miután annak aktuális értékét, az EFLAGS regiszter elmentett tartalmának részeként, elmentik a verembe. Ezzel, a processzor megelőzi azt, hogy az utasítás nyomkövetés a megszakításra adott választ befolyásolhassa. Egy következő IRET utasítás visszaállítja a TF bitet az EFLAGS regiszter verembe elmentett tartalmának értékére. Egy megszakítás kapu és egy trap kapu közti különbség az IF flagre gyakorolt hatásukból adódik. Egy megszakítás kaput alkalmazó megszakítás törli az IF bitet, megakadályozva ezzel, hogy más megszakítások beavatkozzanak az aktuális megszakításkezelő rutinba. Egy következő IRET utasítás visszaállítja
az IF bitet az EFLAGS regiszter verembe elmentett tartalmának értékére. Egy trap kaput használó megszakítás nem változtat az IF biten. 3.9714 Védelem a megszakítás-kezelő eljárásokban Azok a privilégium szabályok, amelyek a megszakítás-kezelő procedúrákat irányítják, azonosak a procedúra hívásra érvényes szabályokkal: a processzor nem teszi lehetővé egy megszakításnak, hogy átadja a vezérlést egy kevésbé privilegizált (számszerint nagyobb privilegizálási szintű) szegmensben levő procedúrának. E szabály megsértésére tett kísérlet általános védelmi hiba kivételt eredményez. Minthogy a megszakítások általában nem szabályos időközönként jelennek meg, az említett privilégium szabály gyakorlatilag azokra a privilegizálási szintekre kényszeríti a megszorításokat, amelyeken a kivételt-, vagy megszakítást kiszolgáló rutinok képesek futni. A következő technikák bármelyikét fel lehet használni a privilégium
szabályok megsértésének megelőzésére: 239 Általános CPU programozási információk A kivételt-, vagy megszakítás-kezelő rutinokat illeszkedő (conforming) kódszegmensbe lehet elhelyezni. Ezt a technikát bizonyos kivételeket (például az osztáshiba kivételt) kezelő rutinok alkalmazhatják. Ezek a kiszolgáló rutinok csak a veremben elérhető adatokat szabad használják. Ha a megszakítás-kezelőnek szüksége lenne egy adatszegmensben található adatokra, akkor az adatszegmensnek kötelezően 3-as privilegizálási szintje kéne legyen, ami védtelenné tenné azt. A megszakítást kiszolgáló rutin 0-s privilegizálási szintű kódszegmensbe is elhelyezhető. Ez a handler a program CPL-jétől függetlenül, mindig futhatna. 3.972 Megszakítás-kezelő taszkok Egy IDT-beli taszkkapu közvetetten határoz meg egy taszkot, ahogyan azt a 3.68 ábra illusztrálja A taszkkapuban található szegmensszelektor egy GDT-beli TSS deszkriptort címez
meg 240 Védett üzemmódú kivételek és megszakítások IDT TSS Megszakítás vektor Taszk kapu TSS szelektor GDT TSS bázis cím TSS szegmens deszkriptor 3.68 ábra: Megszakítás taszkkapcsolás Amikor egy kivétel, vagy megszakítás meghív egy IDT-ben levő taszkkaput, taszkkapcsolás keletkezik. Egy megszakításnak különálló taszkkal való kiszolgálása két előnyt kínál fel: A teljes kontextus automatikusan elmentődik 241 Általános CPU programozási információk A megszakítás-kezelő elszigetelhető a többi taszktól, egy különálló címtartomány hozzárendelésével. Ez, a megszakításkezelő részére egy külön LDT biztosításával valósítható meg. Egy megszakítás okozta taszkkapcsolás ugyanúgy működik, mint a többi taszkkapcsolás. A megszakítás-kezelő taszk visszatér a megszakított taszkba, egy IRET utasítást végezve. Egyes kivételek egy hibakódot szolgáltatnak. Ha a taszkkapcsolást egy ilyen kivétel
eredményezte, a processzor lenyomja a hibakódot a megszakítás-kezelő privilegizálási szintjének megfelelő verembe. Hogyha egy operációs rendszer megszakítás-kiszolgáló taszkokat használ, tulajdonképpen két taszk-elosztó mechanizmus létezik: a software ütemező (az operációs rendszer része), illetve a hardware ütemező (a processzor megszakítási mechanizmusának része). A software ütemező olyan megszakításkiszolgáló taszkokat kell készenlétbe helyezzen (accomodate), amelyek eloszthatók (dispatched), ha a megszakítások engedélyezve vannak. 3.98 Hibakódok Egy bizonyos szegmenshez kapcsolódó kivételek esetén, a processzor eltárol egy hibakódot a kivételkezelő vermébe (függetlenül attól, hogy az procedúra, vagy taszk). A hibakódoknak a 369 ábrán látható formátuma van. A hibakód hasonlít egy szegmens-szelektorhoz, ugyanakkor, az RPL mező helyett a hibakód két, egybites mezőt tartalmaz: 1. A processzor beállítja az EXT
bitet, ha a programon kívüli esemény eredményezte a kivételt. 2. A processzor beállítja az IDT bitet, ha a hibakód index része egy IDTbeli deszkriptorra vonatkozik 242 Védett üzemmódú kivételek és megszakítások 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 I T Szelektor index Fenntartva D I T 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 E X T 0 3.69 ábra: Hibakód Ha az IDT bit nincs beállítva (set), a TI bit mutatja meg, hogy a hibakód egy GDT-re (TI=0), vagy az LDT-re (TI=1) vonatkozik-e. A megmaradt 13 bit a szegmens szelektorának felső bitjei. Egyes esetekben a hibakód nulla (tehát az alsó szó minden bitje 0-s). A hibakód duplaszóként van a veremre helyezve. Ez azért történik így, hogy a verem olyan címekhez maradjon illesztett (aligned), amelyek négy többszörösei. A duplaszó felső része fenntartott 3.99 Kivétel feltételek A következő alpontok
felsorolják azokat a feltételeket, amelyek kivételeket generálnak. Mindegyik leírás hiba-, trap-, vagy abort-ként osztályozza a kivételeket. E kategorizálás azon procedúrák újraindításához szükséges információt szolgáltatja a rendszerprogramozóknak, amelyekben a kivételek megjelennek: Hibák - A CS és EIP regiszterek elmentett tartalma a hibát kiváltó utasításra mutat. Csapdák - A CS és EIP regisztereknek a trap megjelenésekor elmentett tartalma a trap-et kiváltó utasítás után végrehajtandó utasításra mutat. Ha egy vezérlést átadó utasítás ideje alatt egy trap detektálódik, a CS és EIP regiszterek elmentett tartalma tükrözi a vezérlésátadást. Például, ha egy JMP utasításban trap van detektálva, a CS és EIP regiszterek elmentett tartalma a JMP utasítás rendeltetési helyére mutat, és nem - JMP fölötti következő címen levő utasításra. Abortok - Az abort egy olyan kivétel, amely nem engedi meg sem
a kivételt okozó utasítás helyének pontos behatárolását, sem a kivételt 243 Általános CPU programozási információk kiváltó program újraindítását. Az abortok komoly hibák jelentésére használatosak, mint amilyenek a hardware-hibák, vagy a rendszertáblázatokban talált összeférhetelen, vagy szabálytalan értékek. 3.991 0-s számú megszakítás - Osztáshiba (Divide Error) Az osztáshiba egy DIV, vagy IDIV utasítás esetén jelenik meg, ha az osztó nulla. 3.992 1-es számú megszakítás - Debug kivétel A processzor debug kivételt generál egy sor feltétel esetén. Az, hogy a kivétel hiba, vagy trap, a feltételtől függ, ahogy következik: Utasítás cím töréspont Adat cím töréspont Általános detektálás Lépésenkénti végrehajtás Taszkkapcsolás töréspont hiba trap hiba trap trap A processzor nem nyom le hibakódot ennél a kivételnél. A kivételkezelő rutin megvizsgálhatja a nyomkövető regisztereket, hogy
megállapítsa, melyik feltétel váltotta ki a kivételt. A debugolásról és a nyomkövető regiszterekről részletes információ található a 2. kötetben 3.993 3-as számú megszakítás - Töréspont (Breakpoint) Az INT 3 utasítás töréspont trap-et generál. Az INT 3 utasítás egy Byte-nyi hosszú, ami leegyszerűsíti egy RAM-ban levő kódszegmensbeli műveletkód (opcode) kicserélését a töréspont műveletkódra. Az operációs rendszer, vagy egy nyomkövető eszköz alkalmazhat egy, a kódszegmens 244 Védett üzemmódú kivételek és megszakítások fizikai címtartományára leképezett adatszegmenst, az INT 3 utasítás azon pontokra való elhelyezésére, amelyekben a debugoló meghívása szükséges. A nyomkövetők a program felfüggesztésére töréspontokat használnak, a regiszterek, változók, stb. vizsgálatához A CS, illetve EIP regiszterek elmentett tartalma a töréspontot követő Byte-ra mutatnak. Ha a debugoló engedélyezi a
felfüggesztett program végrehajtásának folytatását, a töréspont helyén az INT 3 utasítást visszacseréli az eredeti műveletkódra, és mielőtt visszaadná a vezérlést, dekrementálja az EIP regiszter elmentett tartalmát. 3.994 4-es számú megszakítás - Túlcsordulás (Overflow) A túlcsordulás trap akkor jelenik meg, ha a processzor beállított OF flag mellett egy INTO utasítást hajt végre. Mivel úgy az előjeles, mint az előjel nélküli aritmetika ugyanazon néhány utasítást használja, a processzor nem tudja meghatározni, hogy a túlcsordulás tulajdonképpen mikor jelenik meg. Ehelyett, magasra állítja az OF bitet, ha az előjeles számokként értelmezett eredmények a tartományon kívülre esnének. Előjeles operandusokon végzett aritmetikai műveletek esetén az OF flag közvetlenül tesztelhető, vagy az INTO utasítás alkalmazható. 3.995 5-ös számú megszakítás - Határsértés (Bounds Check) A határsértés (bounds-check) hiba akkor
jön létre, amikor a processzor egy BOUND utasítás végrehajtása közben azt észleli, hogy az operandus meghaladja a megadott határértékeket. A program a BOUND utasítást annak ellenőrzésére használhatja fel, hogy egy előjeles tömbindex nem lépi-e túl egy memóriablokkban definiált előjeles határértékeket. 245 Általános CPU programozási információk 3.996 6-os számú megszakítás - Érvénytelen utasítás (Invalid Opcode) Az érvénytelen utasítás (invalid op-code) hiba akkor keletkezik, amikor egy érvénytelen műveletkódot detektál a végrehajtó egység. ( A kivétel addig nem detektálódik, amíg az érvénytelen utasítás végrehajtására nem történik kísérlet. Tehát egy érvénytelen műveletkód előzetes elérése (prefetch) nem váltja ki ezt a kivételt.) A verembe nem kerül hibakód. A kivétel ugyanazon taszk keretén belül kezelhető Ez a kivétel akkor is jelentkezik, ha az operandus típusa az adott utasítás számára
érvénytelen. A példák közé sorolható egy regiszteroperandust alkalmazó szegmensek közötti JMP utasítás, vagy egy regiszter forrásoperandust használó LES utasítás. A harmadik feltétel, amely ezt a kivételt generálja, a LOCK prefix használata egy olyan utasítással, amely nem zárható le. Csak bizonyos utasításokra alkalmazható a busz lezárása, és ezeknek az utasításoknak csak azon formái használhatók, amelyek a memóriába írnak. A LOCK prefix minden eltérő használata érvénytelen utasítás hibát generál. 3.997 7-es számú megszakítás - nem elérhető eszköz (Device Not Available) A "numerikus koprocesszor nem elérhető" hibát a következő két feltétel egyike hozza létre: A processzor végrehajt egy ESC utasítást, és a CR0 regiszter EM bitje 1-re van állítva. A processzor végrehajt egy WAIT (MP=1 esetén) utasítást, vagy egy ESC utasítást, és a CR0 regiszter TS bitje 1-re van állítva. Tehát a 7-es
megszakítás akkor jelentkezik, amikor a programozó azt akarja, hogy az ESC utasítás software úton legyen kezelve (EM=1 esetén), illetve akkor, amikor a processzor egy WAIT, vagy ESC 246 Védett üzemmódú kivételek és megszakítások utasítással találkozik, és a lebegőpontos egység kontextusa eltér az aktuális taszk kontextusától. Az Intel286-os és Intel386-os processzorokban a CR0 regiszter MP bitje és a TS bit annak megállapítására szolgál, hogy a WAIT utasítás kivételt kell-e generáljon. A Pentium, Intel486 DX és Intel487 SX processzorokon futó programok esetén az MP bit 0 kell legyen. 3.998 8-as számú megszakítás - Kettős hiba, dupla hiba (Double Fault) Ha a processzor, miközben egy előző kivétel kiszolgáló rutinját próbálja behívni, egy újabb kivételt detektál, normális esetben a két kivételt sorban, egymás után szolgája ki. Osztály Jóindulatú kivételek és megszakítások Járulékos kivételek Laphibák
Vektorszám 1 2 3 4 5 6 7 16 0 10 11 12 13 14 Meghatározás Debug kivétel NMI megszakítás Tőréspont Túlcsordulás Határellenörzés Érvénytelen op. kód Eszköz nem elérhető FPU hiba Osztási hiba Érvénytelen TSS Szegmens nincs jelen Verem hiba Ált. védelmi hiba Laphiba 3.70 ábra: Megszakítás és kivétel osztályok 247 Általános CPU programozási információk Első kivétel Jóindulatú Járulékos Laphiba Jóindulatú ok ok ok Második kivétel Járulékos ok Dupla hiba Dupla hiba Laphiba ok ok Dupla hiba 3.71 ábra: Dupla hiba viszonyok Ha mégsem képes őket sorosan kezelni, kettős hiba kivételt jelez. Annak eldöntésére, hogy a processzor milyen esetben kell két kivételt "dupla hiba"-ként megjelöljön, a kivételeket a következő három osztályba sorolja: "szelíd" (benign) kivételek, "hozzájáruló" (contributory) kivételek, illetve laphiba kivételek. Ezt a felosztást a 370 ábra ábrázolja Az első
kivétel osztályát összevetve a második kivétel osztályával, a processzor a 3.71 ábrán megjelölt esetekben jelent kettős hibát Egy utasítás előzetes elérése (prefetch) idején észlelt kezdeti szegmens- vagy laphiba a 3.71 ábrán kívül esik Ugyanakkor bármely további hiba, amely akkor generálódik, amikor a processzor megkíséreli átadni a vezérlést a megfelelő hibakezelőnek, továbbra is dupla hiba szekvenciához vezethet. A processzor minden alkalommal lenyom egy hibakódot a kettős hibát kiszolgáló rutin vermébe, viszont ennek a hibakódnak az értéke mindig 0. A hibát kiváltó utasítás nem indítható újra Ha a kettős hiba kivételkezelő meghívására tett kísérlet közben újabb kivétel is előfordul, a processzor átmegy leállított (shutdown) módba. Ez a mód hasonlít egy HLT utasítást követő állapothoz. Egyetlen utasítás sem kerül végrehajtásra, amíg egy NMI megszakítás, vagy egy RESET jel nem fut be. Ha a leállás
akkor jön létre, miközben a processzor egy NMI megszakítást hajt végre, csak a RESET jel képes újraindítani a processzort. A "shutdown" állapot jelzésére a processzor egy speciális buszciklust generál. 248 Védett üzemmódú kivételek és megszakítások 3.999 9-es számú megszakítás - (az Intel által fenntartott, használata nem ajánlott) A 9-es megszakítás, a "koprocesszor-operandus szegmenshatár sértés "abort a 386-os CPU-ra alapuló, 387-es numerikus koprocesszorral ellátott rendszerekben generálódik, amikor a 386-os processzor egy lapvagy szegmens sértést detektál, miközben a 387-es numerikus koprocesszor operandusának középső részét transzferálja. Ezt a megszakítást nem generálja sem a Pentium, sem a 486-os processzor, helyette a 13-as számú megszakítás jön létre. 3.9910 10-es számú megszakítás - Érvénytelen TSS (Invalid TSS) Az érvénytelen TSS hiba akkor generálódik, ha egy érvénytelen TSS-el
rendelkező szegmensre történik taszkkapcsolási kísérlet. A TSS a 3.72 ábrán felsorolt esetekben érvénytelen A kivételkezelő vermébe lenyomódik egy hibakód, a hiba okának felderítését elősegítendő. Az EXT bit megmutatja, hogy a kivételt a program ellenőrzési területén kívülre eső feltétel okozta-e (például, ha egy taszkkaput alkalmazó külső megszakítás egy érvénytelen TSS-re kísérelt meg taszkkapcsolást végrehajtani). Hibakód index TSS szegmens LDT szegmens Verem szegmens Verem szegmens Verem szegmens Verem szegmens Kódszegmens Kódszegmens Meghatározás A TSS szegmenshatár kisebb mint 67h Érvénytelen LDT, vagy LDT nincs jelen A veremszegmens szelektor túllépi a deszkriptor tábla határt A verem szegmens nem írható A veremszegmens DPL-je nem kompatibilis a CPL-el A veremszegmens szelektor RPL-je nem kompatibilis a CPL-el A kódszegmens szelektor túllépi a deszkriptor tábla határt A kódszegmens nem végrehajtható 249
Általános CPU programozási információk Kódszegmens Kódszegmens Adatszegmens Adatszegmens A nem illeszkedő kódszegmens DPL-je nem egyenlő a CPL-el Az illeszkedő kódszegmens DPL-je nagyobb a CLP-nél Az adatszegmens szelektor túllépi a deszkriptor tábla határt Az adatszegmens nem olvasható 3.72 ábra: Érvénytelen TSS állapotok Ez a hiba megjelenhet akár az eredeti taszk, akár a bejövő taszk kontextusában. Amíg a processzor nem ellenőrizte le teljesen az új taszk TSS-ének jelenlétét, a kivétel az eredeti taszk kontextusában jön létre. Abban a pillanatban, hogy az új TSS jelenléte detektálva van, a taszkkapcsolás befejezettnek lesz nyilvánítva. Vagyis a TR regiszterbe az új TSS-re mutató szelektor töltődik be, és ha a taszkkapcsolást kiváltó ok egy CALL hívás vagy egy megszakítás volt, az új TSS Link mezője a régi TSS-re mutat. Bármely hiba, amelyet a processzor ezen a ponton túlmenően fedez fel, az új taszk kontextusában lesz
kezelve. Annak érdekében, hogy biztosítva legyen egy TSS elérhetősége a kivétel kiszolgálásához, az "érvénytelen TSS" kivételt kiszolgáló rutin egy taszkkaput alkalmazó taszk kell legyen. 3.9911 11-es számú megszakítás - Szegmens nincs jelen, (Segment Not Present) A "szegmens nincs jelen" hiba akkor generálódik, amikor a processzor észleli, hogy a deszkriptor P bitje 0-s. A processzor a következő esetek bármelyikében generálhatja ezt a hibát: Miközben megkíséreli a CS, DS, ES, FS, vagy GS regisztereket feltölteni, az SS regiszter feltöltése viszont, veremhibát okoz. Miközben megkíséreli az LDT regisztert az LLDT utasítás segítségével feltölteni, az LDT regiszter egy taszkkapcsolás közbeni feltöltése viszont, egy "érvénytelen TSS" kivételt okoz. 250 Védett üzemmódú kivételek és megszakítások Miközben megkíséreli egy olyan kapudeszkriptor alkalmazását, melynek P bitje
betöltetlen szegmenst jelöl. Ez a hiba újraindítható. Ha a kivételkezelő betölti a szegmenst, majd ezt követően visszatér (return), a megszakított program végrehajtása folytatódik. Ha egy taszkkapcsolás közben "szegmens nincs jelen" kivétel keletkezik, a taszkváltás nem minden lépése lesz befejezve. Egy taszkkapcsolás alatt a processzor előszőr feltölti az összes szegmensregisztert, majd ellenőrzi ezek tartalmának helyességét. Amikor egy "betöltetlen szegmens" kivétel kerül felfedezésre, a hátramaradó szegmensregiszterek még nincsenek leellenőrizve, ezért ezek memóriahozzáférésre alkalmatlanok lehetnek. A "betöltetlen szegmens" kivételkezelő rutinja nem "számíthat" arra, hogy a CS, SS, DS, ES, FS, illetve GS regiszterekben található szegmens-szelektororokat felhasználhatja anélkül, hogy egy újabb kivételt ne okozna. A kivételkezelő minden egyes szegmensregisztert meg kell vizsgáljon,
mielőtt megpróbálná folytatni a bejövő taszkot, különben a későbbiekben általános védelmi hibák keletkezhetnek, olyan feltételek mellett, amelyek a diagnosztizálást még nehezebbé teszik. Ezen eset kezelésére három lehetőség kínálkozik: 1. Taszk segítségével kezelni a "betöltetlen szegmens" kivételt A megszakított taszkra való visszakapcsolás arra készteti a processzort, hogy ellenőrizze a regisztereket, miközben a TSS-ből betölti őket. 2. PUSH és POP utasításokat alkalmazni az összes szegmensregiszterre Minden POP utasítás arra készteti a processzort, hogy ellenőrizze a szegmensregiszter új tartalmát. 3. Minden egyes szegmensregnek a TSS-ben eltárolt tartalmát ellenőrizni, szimulálva azt a tesztelést, amelyet a processzor a szegmensregiszter betöltésekor végez. Ez a kivétel lenyom egy hibakódot a verembe. A hibakód EXT bitje magasra állítódik, ha egy programon kívüli esemény idézte elő a 251 Általános
CPU programozási információk megszakítást, amely a továbbiakban egy betöltetlen szegmensre mutatott. Az IDT bit akkor lesz beállítva, ha a hibakód egy IDT bemenetre utal (például, egy jelen nem levő kapura vonatkozó INT utasítás). Az operációs rendszer, a virtuális memória szegmensszintű alkalmazására, tipikusan a "betöltetlen szegmens" kivételt alkalmazza. Ennek ellenére, egy kapudeszkriptorbeli "nincs jelen" jelölés általában nem azt jelzi, hogy a szegmens nincs jelen (mivel a kapuknak nem felelnek meg feltétlenül szegmensek). A jelen nem levő kapukat az operációs rendszer, a számára különös jelentőséggel bíró kivételek jelzésére használhatja fel. 3.9912 12-es számú megszakítás - verem kivétel (Stack Exception) A veremhiba két feltétel mellett jön létre: Bármely olyan műveletben történő határsértés eredményeként, amely az SS regiszterre vonatkozik. Ide tartoznak az olyan verem-orientált
utasítások, mint a POP, PUSH, ENTER, és a LEAVE, valamint egyéb olyan memóriahivatkozások, amelyek impliciten, vagy expliciten alkalmazzák az SS regisztert (például MOV AX, [BP+6] vagy MOV AX, SS:[EAX+6]). Az ENTER utasítás akkor váltja ki ezt a kivételt, amikor túl kevés hely van a lokális változók lefoglalására. Mikor kísérlet történik az SS regiszternek egy olyan deszkriptorral való feltöltésére, amely a "szegmens nincs jelen" megjelölést viseli, de egyébként érvényes. Ez megjelenhet egy taszkkapcsoláskor, egy eltérő privilegizálási szintre történő CALL híváskor, egy eltérő privilegizálási szintre való visszatéréskor, egy LSS utasítás esetén, illetve egy SS regiszterbe történő MOV vagy POP utasítás esetén. Amikor a processzor észleli a veremhibát, a hibakezelő vermébe lenyom egy hibakódot. Ha a kivétel oka egy betöltetlen veremszegmens, vagy az új veremnek, privilegizálási szintek közti CALL
hívás alatt létrejött túlcsordulása, akkor a hibakód a kivételt előidéző szegmens szelektorát tartalmazza (a kivételkezelő tesztelheti a deszkriptor P bitjét annak megállapítására, hogy ezek közül melyik kivétel jött létre), ellenkező esetben a hibakód értéke 0. 252 Védett üzemmódú kivételek és megszakítások Ezt a kivételt kiváltó utasítás minden esetben újraindítható. A kivételkezelő vermébe eltárolt visszatérési cím arra az utasításra mutat, amelyet újra kell indítani. Általában, ez maga a kivételt okozó utasítás Ugyanakkor, azon veremhiba esetén, amely egy "nincs jelen" jelzésű veremszegmens deszkriptor taszkkapcsolás közbeni betöltésekor jelentkezik, a mutatott utasítás a bejövő taszk első utasítása. Ha a veremhiba egy taszkkapcsolás közben lép fel, a szegmensregisztereket nem lehet a memória megcímzésére felhasználni. Egy taszkkapcsolás alatt, a szelektorértékek hamarabb kerülnek
betöltésre a deszkriptorok ellenőrzésénél. Abban az esetben, ha veremkivétel generálódik, a fennmaradt szegmensregiszterek még nem lévén leellenőrizve, a használatuk kivételt okozhat. A veremhiba kivételkezelő rutinja nem "számíthat" arra, hogy a CS, SS, DS, ES, FS, illetve GS regiszterekben található szegmensszelektororokat felhasználhatja anélkül, hogy egy újabb kivételt ne okozna. A kivételkezelő minden egyes szegmensregisztert meg kell vizsgáljon, mielőtt megpróbálná folytatni a bejövő taszkot, különben a későbbiekben általános védelmi-hibák keletkezhetnek, olyan feltételek mellett, amelyek a diagnosztizálást még nehezebbé teszik. 3.9913 13-as számú megszakítás - Általános védelmi hiba (General Protection) Minden olyan védelemsértés, amely nem okoz egy másik kivételt, általános védelmi hiba kivételt eredményez. Ezek közé tartoznak: A szegmens határ átlépése, a CS, DS, ES, FS, vagy GS szegmensek
használata közben. A szegmens határ átlépése, egy deszkriptor-táblázat megcímzése esetén. Egy nem végrehajtható szegmensnek átadott vezérlés. Egy csak-olvasható típusú adatszegmens vagy kódszegmens írása 253 Általános CPU programozási információk Egy csak-végrehajtható típusú kódszegmens olvasása Az SS regiszternek egy csak-olvasható szegmens szelektorával való feltöltése (ha taszkkapcsolás alatt a szelektor egy TSS-ből származik, amely esetben egy érvénytelen TSS kivétel jelentkezik.) Egy rendszerszegmens szelektorának betöltése az SS, DS, ES, FS, vagy GS regiszterekbe. Egy csak-végrehajtható kódszegmens szelektorának betöltése a DS, ES, FS, vagy GS regiszterekbe. Egy végrehajtható szegmens szelektorának betöltése az SS regiszter be. A DS, ES, FS, vagy GS regiszterkel történő memória-hozzáférés, ha azok a nullás deszkriptort tartalmazzák. Egy foglalt
(busy) taszkra való kapcsolás. A privilégiumszabályok megsértése. Az utasításhossz 15 Byte-nyi korlátjának túlhaladása (ez csak abban az esetben történhet meg, ha egy utasítás elé redundáns prefixek kerülnek). A CR0 regiszter betöltése, ha a PG=1 (a lapozás engedélyezve van) és PE=0 (a védelem le van tiltva). Virtuális 8086-os üzemmódból, trap-kapuzott megszakítás vagy kivétel, egy 0-tól eltérő privilegizálási szintű kezelő rutinra. A CR4 regiszter fenntartott bitjeinek 1-re való átírása. Az általános védelmi kivétel egy hiba (fault). Egy általános védelmi hiba kivételre adott válaszként, a processzor lenyom a kivételkezelő vermére egy hibakódot. Ha a kivételt egy deszkriptor 254 Védett üzemmódú kivételek és megszakítások betöltése okozta, a hibakód ennek a deszkriptornak egy szelektorát tartalmazza. Különben a hibakód nulla Egy hibakódon belüli szelektor forrásai a
következők lehetnek: Az utasítás egy operandusa. Egy olyan kapu szelektora, amelyik az utasítás operandusa. Egy taszkkapcsolásban résztvevő TSS-beli szelektor 3.9914 14-es számú megszakítás - Laphiba (Page Fault) Laphiba akkor jelenik meg, ha a lapozás engedélyezett (a CR0 regiszter PG bitje 1-es) és a processzor egy lineáris címnek fizikai címre való fordításakor, a következő feltételek egyikét észleli: A címfodításhoz szükséges lapcímtár- vagy laptáblázat bejegyzés P bitje 0-s, ami azt jelzi, hogy a laptáblázat, vagy az operandust tartalmazó lap nincs jelen a fizikai memóriában. A procedúra nem rendelkezik a kellő privilégiummal ahhoz, hogy a megadott lapot elérhesse. Ha a laphiba oka egy lapszintű védelemsértés, a lapcímtárbeli hozzáférést jelző "A" bitek a hiba megjelenésével egyidőben lesznek beállítva. A laptáblázat hozzáférést jelző bitjei csak akkor kerülnek
beállításra, ha nem lép fel lapszintű védelemsértés. A processzor két olyan információt biztosít a laphiba kezelőnek, amelyek segítik a kivétel diagnosztizálását, illetve helyreállítását (recover): Egy verembeli hibakódot. A laphibákra adott hibakódoknak eltérő formátumuk van, a többi kivétel hibakódjaihoz képest (lásd 3.73 ábra). A hibakód három dolgot közöl a kivételkezelővel: 255 Általános CPU programozási információk 1. A kivételt egy betöltetlen (not-present) lap, egy hozzáférési jog megsértése, vagy egy fenntartott bit használata okozta-e. 2. A processzor felügyelőszinten működött-e a kivétel megjelenése közben. 3. A kivételt előidéző memória-hozzáférés írás, vagy olvasás volt-e A CR2 regiszter tartalmát. A processzor feltölti a CR2 regisztert azzal a 32 bites lineáris címmel, amely a kivételt előidézte. A kivételkezelő ezt a címet arra használhatja, hogy lokalizálja a megfelelő
lapcímtár, illetve laptáblázat bemeneteket. Ha a laphibakezelő végrehajtása közben egy újabb laphiba jön létre, a hibakezelő rutinnak el kell tárolni a CR2 regiszter tartalmát a verembe (push). 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 R S Fenntartva V 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 P 0 1 W/R 0 1 U/S 0 1 RSV 0 1 2 1 0 U R P S W 2 1 0 A hiba oka egy nem jelenlévő lap volt A hiba oka egy lapszint védelem megszegés volt A hibát okozó memória hozzáférés egy olvasás volt A hibát okozó memória hozzáférés egy írás volt A hiba keletkezésekor a végrehajtás supervisor módban történt. A hiba keletkezésekor a végrehajtás user módban történt. A hibát egy beállított bit okozta a laptáblázat vagy a lapcímtár egy fenntartott pozícióján Egyéb 3.73 ábra: Laphiba hibakódok 3.99141 Taszkkapcsolás alatti laphiba Egy taszkkapcsolás alatt a következő
műveletek idéznek elő memória hozzáférést: 256 Védett üzemmódú kivételek és megszakítások A kimenő taszk állapotának a taszk állapot-szegmensébe (TSS) való írása. A bejövő taszk TSS-deszkriptorának lokalizálása a GDT olvasásával. A bejövő taszk TSS-ének olvasása, a benne levő szegmensdeszkriptorok típusának ellenőrzése végett. A bejövő taszk LDT-jének esetleges olvasása, az új TSS-ben tárolt szegmensregiszterek ellenőrzése végett. Laphiba származhat bármely fentemlített művelet végrehajtásából. A két utolsó alpont esetén, a kivétel a bejövő taszk kontextusában jelenik meg. Az utasításmutató az új taszk következő utasítását jelöli ki, nem a taszkkapcsolást előidéző utasítást (vagy az utoljára végrehajtás alatt álló utasítást, mint a megszakítások esetében). Ha az operációs rendszer struktúrája megengedi, hogy a taszkkapcsolások idején laphibák jelenjenek meg, a
laphibakezelőt taszkkapun keresztül kell meghívja. 3.99142 Laphiba összeférhetetlen veremmutatóval Különös figyelmet kell fordítani annak biztosítására, hogy a laphiba ne késztesse a processzort egy érvénytelen veremmutató (SS:ESP) alkalmazására. A 16 bites processzorokra írt software-ek gyakran használnak egy utasítás-párt egy új veremre való áttéréshez, például: MOV SS, AX MOV SP, StackTop (verem teteje) Minthogy a második utasítás hozzáfér a memóriához, a 32 bites processzorok esetén lehetséges, hogy laphiba keletkezzen, miután az SS regiszterben levő szelektor megváltozott, de még mielőtt az SP regiszter tartalma elszenvedte volna a megfelelő módosításokat. Ebben a stádiumban, az SS:SP (vagy 32 bites programokban az SS:ESP) 257 Általános CPU programozási információk veremmutató két része, összeférhetetlen. Az új veremszegmenssel a régi veremmutató kerül alkalmazásra. A processzor nem alkalmaz összeférhetetlen
veremmutatót, ha a laphiba kiszolgálása egy helyesen definiált veremre történő átváltást (stack switch) idéz elő, (tehát a kivételkezelő rutin egy taszk, vagy egy privilegizáltabb procedúra). Ugyanakkor, ha a laphiba ugyanazon a privilegizálási szinten van, és ugyanabban a taszkban található, mint a kivételkezelő rutin, a processzor megkíséreli alkalmazni az inkonzisztens veremmutató által kijelölt vermet. Azokban a lapozást használó rendszerekben, amelyek a laphibákat a hibázó taszk keretén belül (trap-, vagy megszakítás kapukkal) kezelik, a laphiba-kezelő rutinnal megegyező privilegizálási szinten futó softwareek számára ajánlott, hogy inkább az LSS utasítás segítségével inicializáljanak egy új vermet, mintsem a fentemlített utasításpárral. Ha a laphiba-kezelő rutin a 0-s privilegizálási szinten fut (normális esetben), a probléma csak a 0-s szinten szaladó programokra szűkül le, vagyis tipikusan az operációs
rendszer kerneljére. 3.9915 16-os számú megszakítás - Lebegőpontos egység hiba, Floating-Point Error) A numerikus koprocesszor hiba egy lebegőpontos aritmetikai utasítás által kiváltott hibát jelez. A 16-os számú megszakítás csak akkor jöhet létre, ha a CR0 regiszterbeli NE bit 1-re van állítva. Ha NE=1, egy nem maszkolható lebegőpontos kivétel a 16-os megszakítást váltja ki, azonnal a következő nemvezérlő (non-control) lebegőpontos utasítás, vagy WAIT utasítás előtt. A 16-os megszakítás egy operációs rendszer-hívás, amely meghívja a kivételkezelő rutint. Ha NE=0 (és az IGNE# bemenet inaktív), egy nem maszkolt koprocesszor hiba azonnal a következő nemvezérlő (non-control) lebegőpontos utasítás, vagy WAIT utasítás előtt, lefagyásra (freeze) kényszeríti a processzort. A lefagyott processzor egy külső megszakításra vár, amelyet a külső hardware kell szolgáltasson, válaszként a 486-os, 258 Védett üzemmódú
kivételek és megszakítások vagy Pentium processzor FERR# vonalán kimenő jelre ( a FERR# hasonlít az 387-es numerikus koprocesszor ERROR# vonalára). Az NE értékétől függetlenül, egy maszkolatlan numerikus kivétel aktiválja a 486os és a Pentium processzorok FERR# vonalát. Ebben az esetben a külső megszakítás hívja meg a kivételkezelő rutint. Ha de az IGNE# bemenet aktív, a processzor figyelmen kívül hagyja a kivételt, és folytatja feladatát. A külső megszakítások általi hibajelentés a DOS-al való kompatibilitás érdekében támogatott. A numerikus hibák kezelésekor a processzornak két feladata van: Amikor egy hibát (error) észlel, nem szabad megsértenie a numerikus kontextust. Törölnie kell a hibát, és meg kell kísérelnie a hiba helyreállítását (recovery). Bár az eljárás, amellyel a programozók ezen feladatokat elláthatják, alkalmazásonként változik, mégis a kivételkezelők többsége magába foglalja a
következő lépéseket: Az FPU környezetének (vezérlő-, állapot-, és toldalék szók, operandus- és utasítás mutatók) elmentése úgy, ahogyan az a kivétel pillanatában volt. Az állapotszó kivételt jelző bitjeinek törlése. Az INTR, NMI, vagy SMI által letiltott megszakítások engedélyezése. A kivétel identifikálása, az elmentett környezetbeli állapot-, és vezérlőszó vizsgálata segítségével. Néhány rendszer-függő művelet elvégzése, a kivétel helyreállítása (rectify) érdekében. Visszatérés a megszakított programba, és a normális vezérlés folytatása. 259 Általános CPU programozási információk 3.99151 Numerikus kivételek kezelése A numerikus kivételeket kezelő rutinoknak számos formája létezhet. Ezek megváloztathatják az FPU aritmetikai és programozási szabályait. Ezek a módosítások újradefiniálhatják egy hiba (error) alapértelmezés szerinti kijavításának módját,
megváltoztathatják az FPU megjelenését a programozók számára, vagy módosíthatják az FPU aritmetikai szabályainak definícióját. kivételekre adott válaszok módosításának egyike az volna, hogy a denormális aritmetika a memóriából betöltött denormálisokon legyen elvégezve. Egy megjelenésbeli változást a regiszterveremnek a memóriába való kiterjesztése jelentené, "végtelen" számú numerikus regiszter biztosításának érdekében. Az FPU aritmetikája átváltoztatható arra, hogy automatikusan kiterjessze a változók pontosságát és a tartományát, amikor ez túlhaladódik. Néhány lehetséges, alkalmazás-függő lehetőség: Egy kivétel számláló inkrementálása, a későbbi kijelzés, vagy kinyomtatás végett. Diagnosztika-információk kinyomtatása, vagy kijelzése (például az FPU környezete és regiszterei). A további végrehajtás abortolása. Egy diagnosztika érték (egy NaN) elmentése az
eredményben, majd a számítások folytatása. Fontos, hogy egy kivétel, az alkalmazástól függően, nem jelent minden esetben hibát (error). Amint a kivételkezelő kijavítja a kivételt előidéző feltételt, a kivételt okozó lebegőpontos utasítás újraindítható, ha ez megfelelő. Ugyanakkor, az IRET utasítást használva ez nem lehetséges, mert a trap a "vétkes" ESC utasítást követő ESC vagy WAIT utasításnál jelenik csak meg. A kivételkezelő meg kell szerezze a "vétkes" utasítás címét azon taszk belsejében, amely kezdeményezte azt, másolatot kell készítenie róla, a másolatot végre kell hajtania a "vétkes" taszk 260 Védett üzemmódú kivételek és megszakítások kontextusában, majd egy IRET utasítással vissza kell térjen az aktuális utasításláncba. A numerikus kivételt okozó feltétel kijavítása érdekében, a kivételkezelő fel kell ismerje pontosan az FPU azon állapotát, amelyben a
kivételkezelő meghívásának pillanatában volt, majd képes kell legyen az FPU arra az állapotára visszakövetkeztetni, amely a kivétel kezdetén volt aktuális. Az FPU állapotának visszafejtéséhez a programozóknak tudniuk kell, hogy a különböző osztályú kivételek eltérő pillanatokban lesznek felismerve, a numerikus utasítás végrehajtása előtt, vagy azt követően. Az érvénytelen művelet, zéróval való osztás és denormális operandus kivételek egy művelet megkezdése előtt lesznek detektálva, míg a túlcsordulás, alulcsordulás, és a pontosság kivételek addig nem jelennek meg, amíg egy valódi eredmény nincs kiszámítva. Ha egy műveletkezdés előtti kivétel detektálódik, az FPU regiszterverme és memóriatára még nincs felújítva, és úgy tűnik, mintha a "vétkező" utasítás még nem lett volna végrehajtva. Amikor egy műveletkezdés utáni kivétel detektálódik, a regiszterverem és memória úgy néznek ki, mintha
az utasítás befejeződött volna, tehát fölújíthatók. Ugyanakkor, egy store, vagy store-andpop típusú műveletben, a maszkolatlan túl/alulcsordulás műveletkezdés előtti kivételként van kezelve, a memória nem lesz felfrissítve, és a veremből semmi sem lesz kiemelve. 3.99152 Szimultán kivételekre adott válaszok Az olyan estekben, amelyekben szimultán, többszörös kivételek keletkeznek, az FPU az alábbiakban következő elsőbbségi-lista alapján jelzi az egyik kivételt. Ez annyit jelent, hogy például egy SNaN zéróval való osztása "érvénytelen műveletet" eredményez, és nem "nullával való osztási hibát" ; a maszkolt eredmény a QNaN valódi végtelen (real infinite), és nem a végtelen . Egy denormális, vagy pontosság kivétel ugyanakkor, kísérhet egy numerikus alulcsordulást, vagy túlcsordulást. A numerikus kivételek közti sorrend a következő: 261 Általános CPU programozási információk 1.
Érvénytelen művelet kivétel, a következőképpen tovább osztva: verem alulcsordulás verem túlcsordulás nem támogatott formátumú operandus SNaN operandus 2. QNaN operandus Bár ez nem egy kivétel, ha egy operandus egy QNaN, kezelése előnyt élvez az alacsonyabb prioritású kivételek előtt. 3. Bármely, fentebb nem említett kivétel, vagy nullával való osztás 4. Denormális operandus Ha le van maszkolva, a művelet végrehajtása folytatódik, és ugyanakkor egy alacsonyabb prioritású kivétel is megjelenhet. 5. Numerikus alulcsordulás, vagy túlcsordulás A pontatlan eredmény (pontosság) flag is bejelölhető. 6. Pontatlan eredmény (pontosság-) kivétel 3.9916 17-es számú megszakítás - Illeszkedés ellenőrzés ellenőrzési hiba (Alignment Check) Az illeszkedés ellenőrzési hiba kivétel a nem illesztett (unalign) operandusokhoz való hozzáférés esetén generálódhat. Például, egy páratlan Byte-címen tárolt szó, vagy egy
duplaszónak egy olyan címen való tárolása, amelyik nem négynek többszöröse. A 374 ábra az adattípusok által igényelt illeszkedési feltételeket sorolja fel. Az illeszkedés ellenőrzés engedélyezéséhez a következő feltételek teljesítése szükséges: a CR0 regiszterbeli AM bit magasra legyen állítva az AC flag magasra legyen állítva a CPL értéke 3 legyen (felhasználói mód) 262 Védett üzemmódú kivételek és megszakítások Adat típus WORD DWORD rövid REAL hosszú REAL TEMPREAL Szelektor 48 bites szegmentált mutató 32 bites lap mutató 32 bites szegmentált mutató 48 bites pszeudo deszkriptor FSTENV/FLDENV mentési terület FSAVE/FSTOR mentési terület Bit sztring A címnek oszthatónak kell lennie: 2 4 4 8 8 2 4 4 2 4 2 vagy 4, az operandusmérettől függően. 2 vagy 4, az operandusmérettől függően. 4 3.74 ábra: Adattípusok által igényelt illeszkedési feltételek Az illeszkedés ellenőrzés azon programok számára
hasznos, amelyek a mutatók alsó két bitjét használják az általuk megcímzett adatstruktúra típusának azonosítására. Például, egy matematikai könyvtár szubrutinja elfogadhat numerikus adatstruktúrákra mutató pointereket. Ha e struktúra típusához az 10 (bináris) kódot társítjuk az erre a típusra mutató pointer legalsó két bitjén, a matematikai szubrutinok kijavíthatják a típuskódot -10 (bináris) eltolás hozzáadásával. Abban az esetben, ha a szubrutin helytelen mutatótípust kapna, egy illesztetlen (unaligned) hivatkozás jönne létre, amely kivételt generálna. Az illeszkedés ellenőrzés hiba kivételek csak felhasználói módban (3. privilégium szinten) generálódnak Azok a memóriahivatkozások, amelyek alapértelmezése a 0. privilégium szint, mint például a szegmensdeszkriptorok betöltése, nem okozzák a fentemlített kivételt még abban az esetben sem, ha ezt egy felhasználói módbeli memóriahivatkozás okozná. Egy 48 bites
pszeudo-deszkriptor (egy deszkriptor-táblázat bázisregisztertartalmának memóriabeli másolata) tárolása felhasználói módban, illeszkedés ellenőrzés hiba kivételt generálhat. Bár a felhasználói 263 Általános CPU programozási információk programok normális esetben nemigen tárolnak pszeudo-deszkriptorokat, a hiba mégis elkerülhető, a pszeudo-deszkriptornak egy páratlan szó címre való illesztésével (tehát egy olyan címre, amelynek 4-el való osztási maradéka 2). Az FSAVE és FRSTOR utasítások illesztetlen referenciákat (hozzáféréseket) állítanak elő, amelyek illeszkedésellenőrzés-hiba kivételeket okozhatnak. Ezekre az utasításokra a felhasználói programoknak ritkán van szükségük. 3.9917 18-as számú megszakítás - Processzortípus ellenőrzés (Machine Check) A processzortípus ellenőrzés modell-specifikus kivétel, amely csak a Pentium processzorokon létezik. 3.910 A kivételek összefoglalása A 3.75ábra
összefoglalja a Pentium processzor által felismert kivételeket. Meghatározás Osztás nullával Vektor Visszatérési szám cím a hibára mutat? 0 Igen Kivétel típus A kivétel forrása Hiba DIV és IDIV művelet Akármilyen kód vagy adat hivatkozás INT 3 művelet INTO művelet BOUND művelet Fenntartott műveleti kódok Debug kivétel 1 *1 *1 Töréspont Túlcsordulás Határsértés 3 4 5 Nem Nem Igen Trap Trap Hiba Érvénytelen op. kód 6 Igen Hiba 264 Védett üzemmódú kivételek és megszakítások Eszköz nem elérhető Dupla hiba Érvénytelen TSS 7 Igen Hiba 8 10 Igen Igen2 Abort Hiba Szegmens nincs jelen 11 Igen2 Hiba Verem hiba Általános védelmi hiba 12 13 Igen Igen Hiba Hiba/ trap3 Laphiba 14 Igen Hiba FPU hiba 16 Igen Hiba4 Illeszkedés ellenőrzés Géptípus ellenőrzés Software megszakítás 17 Igen Hiba 18 - 0-255 Nem Trap ESC és WAIT művelet Bármi JMP, CALL, IRET művelet, megszakítások és
kivételek Akármilyen művelet ami szegmenst vált Verem művelet Akármilyen kód vagy adat hivatkozás Akármilyen kód vagy adat hivatkozás ESC és WAIT művelet Akármilyen adat hivatkozás Modellfüggő INT n művelet 3.75 ábra: Kivételek összefoglalása Megjegyzések: 1. A nyomkövető kivételek trap-ek, vagy hibák lehetnek Ez a kivétel a DR6 regiszter tartalmát vizsgálja meg ahhoz, hogy megkülönböztesse a trap-eket a hibáktól. 2. A taszkkapcsolások közbeni újraindíthatóság feltételhez kötött 265 Általános CPU programozási információk 3. Minden általános védelmi hiba újraindítható Ha a hiba a kivételkezelő meghívására tett kísérlet közben jelentkezik, a megszakított program újraindítható, de a megszakítás maga elveszhet. 4. A lebegőpontos hibák nem lesznek jelentve, csak a hibát generáló ESC utasítást követő első ESC vagy WAIT utasítás beérkezésekor. 3.911 Hibakódok összefoglalása A 3.75 ábra összesíti
minden egyes kivételt követő hiba információt. Meghatározás Osztási hiba Debug kivétel Töréspont Túlcsordulás Határellenörzés Érvénytelen op. kód Eszköz nem elérhető Dupla hiba Érvénytelen TSS Szegmens nincs jelen Verem hiba Ált. védelmi hiba Laphiba FPU hiba Illeszkedés ellenőrzés Modell ellenőrzés Software megszakítás Vektor szám 0 1 3 4 5 6 7 8 10 11 12 13 14 16 17 18 0-255 Hibakód van ? Nincs Nincs Nincs Nincs Nincs Nincs Nincs Van, mindíg nulla Van Van Van Van Van, spec. formátum Nincs Van, mindíg nulla Modellfüggő Nincs 3.75 ábra: Hibakódok összefoglalása 266 Rendszermenedzselő üzemmód 3.10 Rendszermenedzselő üzemmód A rendszermenedzselő üzemmód (SMM - System Management Mode) segíti a rendszerfejlesztőket az olyan rendkívül magas szintű rendszerfunkciók kialakításában, mint a fogyasztásmenedzsment vagy a biztonság, nemcsak az alkalmazói software, hanem maga az operációs rendszer számára is átlátszó
módon. Az SMM a védett, valós, és 8086-os virtuális módokkal egyszinten levő, egyik fő üzemmód. Az SMM azonban úgy volt tervezve, hogy az alkalmazói software-ek és általános célú operációs rendszersoftware-ek nem, csak a firmware tudja használni. A 376 ábra azt mutatja be, hogy más üzemmódokból a processzor hogyan léphet be az SMM üzemmódba, illetve hogyan léphet ki abból. A külső SMI# jel a processzort arra kényszeríti, hogy az átkapcsoljon az SMM üzemmódba. Az SMM üzemmódból az RSM utasítással lehet kilépni. Az SMI# jel aktiválását egy hordozható számítógép esetében például a gép fedelének lecsukása okozhatja. Az SMM átlátszó az alkalmazói programok és az operációs rendszer számára, mivel: Az SMM üzemmódba való belépés egyetlen útja egy külső jel által kiváltott, nem maszkolható megszakítás. A processzor egy különálló címtartományban levő SMM kód végrehajtását kezdi meg, mely
címtartomány neve rendszermenedzsment-RAM (SMRAM). Az SMM üzemmódba való belépéskor a processzor a megszakított program regiszter-állapotát az SMRAM-nak egy SMM állapottároló rekord nevezetű részébe menti. A normális esetben az operációs rendszer vagy az alkalmazások által kezelt minden megszakítás az SMM üzemmódba való belépéskor letiltódik. 267 Általános CPU programozási információk Egy speciális RSM utasítás az SMM állapot-rekordból viszszaállítja a processzor regisztereinek állapotát és a vezérlést visszaadja a megszakított programnak. Az SMM abban hasonlít hasonlít a valós üzemmódhoz, hogy nincsenek privilégiumszintjei és nem végez címleképzést. Egy SMM program végrehajthat I/O és más rendszerutasításokat, és négy GBytememóriát címezhet. 3.101 Az SMI megszakítás Amikor egy utasításhatáron az SMI# jelet felismeri, a processzor előbb kivárja, hogy minden tárolási művelet
befejeződjön (a külsőleg függőben levőket is ide értve). Ezután elmenti a regiszterek állapotát az SMRAM-ba és megkezdi az SMM kezelő végrehajtását. Az SMI#-nek a debug kivételek és külső megszakításoknál nagyobb prioritása van. Ez azt jelenti, hogy ha az utasításhatáron e kivételek közül több mint egy jelenik meg, akkor csak az SMI lesz kiszolgálva, a debug kivétel vagy külső megszakítás nem. Az újabb SMI# vagy NMI kéréseket az SMM-ben levő processzor már nem veszi figyelembe. A CR4 regiszter gépellenőrzést engedélyező bitje szintén törlődik. Az SMM-ban megjelenő SMI# és NMI megszakítások betöltődnek ugyan, de csak akkor hajtódnak végre, amikor a processzor az RSM utasítás által kilép az SMM-ból. 268 Rendszermenedzselő üzemmód RESET Valós címzési mód RSM RESET PE=0 PE=1 SMI SMI Védett mód RSM Megszakítás, kivétel Taszkváltás, IRET Rendszer menedzselő mód RSM SMI Virtuális 8086 mód 3.76
ábra: Az üzemmód-állapotok közti átmenetek Az SMM-ba való belépéskor a kezelőket igénylő külső megszakítások letiltódnak (az EFLAGS regiszter IF bitje törlődik). Erre azért van szükség, mert az SMM-ban levő processzor egy külön címtartományt használ. Emiatt a megszakítás deszkriptor-táblázatban (IDT) tárolt vektorok nem alkalmazhatóak. A kivételek engedélyezéséhez az SMM program új megszakítás/kivétel vektorokat kell felépítsen. Az SMM megszakításvektor-táblázatának formátuma megegyezik a valós üzemmódban használtéval. Amíg a megszakításvektor-táblázatot helyesen fel nem építi, addig az SMM kezelőprogram nem generálhat kivételeket. Kivételek azonban még letiltott megszakítások esetén is keletkezhetnek. A belső megszakítások megjelenését csak a helyesen megírt software előzheti meg. Az új kivételvektorok beállítása után a belső kivételek kiszolgálhatók. 269 Általános CPU programozási
információk Ugyancsak az SMM-be való belépéskor az lépésenkénti végrehajtás (az EFLAGS TF bitjének értéke nulla) és címtöréspont (a DR7 törölve van) kivételek is törlődnek. A processzor debuglehetőségeinek maga az SMM-ben való hibakeresésre felhasználása érdekében az SMM kezelőnek előbb biztosítania kell, hogy az IDT-be egy megfelelő, elérhető kezelő legyen installálva, majd a debug regiszterekbe illetve az EFLAGS-be be kell töltenie a megfelelő értékeket. 3.102 Az SMM kezdeti állapota Miután a processzor felismerte az SMI# jelet és elmentette a regiszterek állapotait, saját állapotát a 3.77 ábrán bemutatott értékekre változtatja. Regiszter EFLAG EIP CS szelektor DS, ES, FS, GS, SS szelektorok DS, ES, FS, GS, SS határ DS, ES, FS, GS, SS jellemzők CR0 CR4 CR6 CR7 GDTR, LDTR, IDTR, TSSR Modell specifikus regiszter Tartalom 2 8000h 3000h, ez az érték a 30000h báziscím inicializáló utasítását adja 0 0FFFFFFFFh 16 bites,
felfelé növekvő 0, 2, 3 és 31. bitek törölve (PE, EM, TS, PG) 0 Nem definiált 400h Nem definiált Nincs módosítva 3.77 ábra: Az SMM kezdeti állapota 270 Rendszermenedzselő üzemmód Az adatcache-ek kiürítéséért, az adat- valamint utasításcache-ek érvénytelenítéséért és ezeknek az SMM alatti letiltásáért a külső hardware felel. 3.1021 Az SMM végrehajtása Az SMM kezelő végrehajtását a processzor a CS szegmens 8000H ofszetjétől kezdi. A kódszegmens báziscíme kezdetben 30000H, ez a cím azonban megváltoztatható. Az SMM kezelőjének meghívásakor a processzor CR0 regiszterének PE (védelem) és PG (lapozás) bitjei törlődnek, így a processzor a valós üzemmódhoz hasonló környezetbe kerül. Mivel a (CStől különböző) szegmens-bázis törlődik és a szegmenshatárok 0FFFFFFFFH értékűre állítódnak, a címtartomány egyetlen lapos, nem szegmentált, 4GB-os lineáris tartományként kezelhető, a processzor azonban a
címeket a valós üzemmódban használttal megegyező módon generálja. Amikor a szegmensszelektorba egy 16 bites érték töltődik, az érték 4 bittel balra tolódik és betöltődik a szegmens-bázisba. Az SMMben egy szegmensregiszter betöltése során a deszkriptor regiszterek rejtett részeiben a határ mező és az attribútumok nem módosulnak. Az operandusméret és címméret alapértelmezése 16 bit, a 4 GByte-os logikai címtartományban bárhol, az adatok közvetlen elérésére használhatók az operandusméret- és címméret-fölülíró prefixek. Az operandusméret-fölülíró prefixekkel együtt az SMM kezelő a vezérlésnek a négy GByte-os címtartomány bármelyik pontjára való átadására használhat ugrásokat, hívásokat és visszatéréseket. Megjegyzendők azonban a következő korlátozások: Bármely vezérlésátadás, melynek nincs operandusméret-fölülíró prefixe, az EIP regisztert annak alsó 16 bitjére csonkítja. A valós
üzemmódban használthoz hasonló báziscím-képzés miatt a hosszú ugrások, hívások, megszakítások vagy kivételek a vezérlést 271 Általános CPU programozási információk nem adhatják át egy 20 bitesnél nagyobb méretű (azaz egy MByte-nál nagyobb) báziscímű szegmensre. Egy kivétel vagy megszakítás nem adhatja át a vezérlést egy 16 bitesnél (64 kByte-nál) nagyobb méretű szegmensre. Ha a kivételek és megszakítások engedélyezve vannak, akkor a visszatérési címeknek csak az alsó 16 Byte-ja kerül a veremre. Ha a megszakított procedúra ofszetje nagyobb, mint 64 kByte, akkor a megszakításkezelő, a vermen levő visszatérési címnek a software általi bizonyos módosítása nélkül, nem tudja visszaadni a vezérlést az illető procedúrának. 3.103 Az SMRAM processzor-állapot tároló formátuma Az SMRAM terület állapottároló rekordjának szerkezetét a 3.78 ábra mutatja be. A regiszterek fizikai helye ahhoz a
CS-bázisba töltött értékhez képest relatívak, mely kezdetben 30000H, de megváltoztatható. A regiszterek abszolút helye: (CSbázis + RegiszterOfszet). Az FFA8H-FFFFH ofszeteken levő mezők az SMM# megszakítás pillanatában a processzor regiszter-állapotát tárolják. A fennmaradó biteket a következő részek mutatják be. Regiszter ofszet 0FFFC 0FFF8 0FFF4 0FFF0 0FFEC 0FFE8 0FFE4 0FFE0 0FFDC 0FFD8 0FFD4 272 Regiszter CR0 CR3 EFLAG EIP EDI ESI EBP ESP EBX EDX ECX Rendszermenedzselő üzemmód 0FFD0 0FFCC 0FFC8 0FFC4 0FFC0 0FFBC 0FFB8 0FFB4 0FFB0 0FFAC 0FFA8 0FFA7-0FF04 0FF02 0FF00 0FEFC 0FEF8 0FEF7-0FE00 EAX DR6 DR7 TR* LDTR* GS* FS* DS* SS* CS* ES Fenntartva Leállás automatikus újraindítása I/O trap újraindítása SMM reviziószám Állapot tároló bázisa Fenntartva 3.78 ábra: Az állapottároló formátuma Megjegyzések: A FENNTARTOTT-ként bejelölt területeket az SMM kezelő nem használhatja. E területekre való írás a processzor hibás
működését eredményezheti. Az a software, amelyik ezeknek a területeknek a tartalmára alapoz, az elkövetkező processzor generációkkal inkompatibilis lehet. * A felső 2 Byte FENNTARTOTT. A 3.78 ábrán megnevezett regiszterek láthatók, tehát az SMM kezelő kiolvashatja értéküket az állapottároló rekordból. Ezek közül az adattételek közül az SMM egyeseket megváltoztathat és a megváltozott értékük a processzor regisztereibe az RSM utasítással tölthető be. A 379 ábra bemutatja, hogy mely adattételek változtathatók meg, és melyek nem. A táblázat még azt is megmutatja, hogy egyes regiszterértékek az 273 Általános CPU programozási információk állapottárolóba mentődnek, azonban nem láthatók. E tételek a fenntartott részeken tárolódnak, de helyük és formátumuk különböző processzorverziók esetén más és más. A 379 ábra utolsó sora azokat a regisztereket mutatja, melyeket az SMI# és RSM nem tárol illetve
állít vissza automatikusan. Ha az SMM kezelő megváltoztatja ezeket a regisztereket, akkor implicit módon el is kell tárolja, illetve vissza is kell állítsa őket. Állapot adat Mentett és Olvasható? Írható? visszatöltött? EDI, ESI, ESP, EBX, EDX, ECS, Igen Igen Igen EAX, EFLAG, EIP CR0, CR3, DR6, DR7, TR, Igen Igen Nem LDTR, GS, FS, DS, SS, CS, ES CR1, CR2, CR4, A GDT Igen Nem Nem láthatatlan deskriptor regiszterei, LDT, IDT, CS, DS, ES, FS, GS DR0-DR7, FP regiszterek STn, Nem Nem Nem FCS, FSW, címző szó, FP utasítás mutató, FP op. kód és operandus mutató 3.79 ábra: Állapot-beosztás 3.1031 Az SMM revízió-azonosító (FEFCH ofszet) A 32 bites SMM revízió-azonosító megadja verziószámát és a processzor által nyújtott lehetőségeket. az SMM 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Fenntartva, értéke 0 SMM revizió szint 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4
3 2 1 0 I/O trap kiterjesztés SMM bázis relokáció 3.80 ábra: SMM revízió-azonosító 274 Rendszermenedzselő üzemmód Az SMM revízió-azonosító mezőit a 3.81 ábra mutatja Az 1-re állított 16. vagy 17 bitek azt mutatják, hogy a processzoron az illető lehetőségek implementálva vannak. Bitek 0-15 16 17 Megjegyzés Alap SMM verzió azonosító A processzor támogatja az I/O trap újraindítást A processzor támogatja az SRAM áthelyezését 3.81 ábra: SMM revízió-azonosító táblázat Megjegyzés: Minden más bit fenntartott. 3.1032 I/O trap-újraindítás (FF00H ofszet) Az I/O trap-újraindító slot lehetővé teszi az SMM számára, hogy az az RSM utasítást egy megszakított I/O utasítás automatikus újra történő végrehajtására bírja. Ha az RSM utasítás végrehajtásakor az I/O trap-újraindító slot az FFH értéket tartalmazza, akkor a processzor az SMI# által megszakított I/O utasítást automatikusan újra végrehajtja. Ha az RSM
utasítás végrehajtásakor az I/O trap-újraindító slot a 00H értéket tartalmazza, akkor a processzor az SMI# által akkor a processzor nem hajtja végre újra az I/O utasítást. Az I/O trap-újraindító slot-ot az SMI# feldolgozásakor a processzor automatikusan nullával inicializálja. Az SMM kezelő csak akkor kell az I/O trap-újraindító slotot a 0FFH értékre állítsa, amikor az SMI# egy I/O utasításhatáron szakad meg egy trap által. Ha az RSM utasítás végrehajtásakor a processzor az I/O trap-újraindító slotban a 0FFH értéket találja, de a megszakított utasítás nem egy I/O utasítás, akkor a művelet eredménye kiszámíthatatlan. 275 Általános CPU programozási információk 3.1033 Felfüggesztett állapotból való automatikus újraindítás (FF02H ofszet) Ha felfüggesztett állapotában a processzor felismeri az SMI#-t, akkor a processzor a felfüggesztett állapotból való automatikus újraindítás Byte-ját 1-re állítja, egyébként
törli azt. Ha ez a mező 1, akkor az SMM kezelő megváltoztathatja értékét annak érdekében, hogy ellenőrizze a processzornak a kezelőből az RSM utasítással való, a HLT utasítást folytató visszatérését. A lehetőségeket a 382 ábra mutatja Érték a belépésnél Érték a kilépésanél 0 0 0 1 1 0 1 1 CPU működés a kilépésnél Visszatér a megszakított program következő utasítására Kiszámíthatatlan Visszatér a HLT utáni utasításra Visszatés a megszakított HLT utasításra 3.82 ábra: Felfüggesztett állapotból való automatikus újraindítás 3.1034 Az állapottároló bázisa (FEF8H ofszet) A processzornak egy olyan láthatatlan belső regisztere van, amelyik megadja az állapottároló rekord és az SMM kezelő első utasításának fizikai báziscímét. Az SMRAM relokációját támogató processzorok (a Pentium is ilyen) e regiszter tartalmát az SMI# jel feldolgozása alatt az állapottároló-bázisba mentik. Az RSM utasítás
végrehajtásakor a Pentium processzor viszszatölti belső regisztereinek tartalmát az állapottároló-bázisból. Így lehetővé válik e regiszter tartalmának megváltoztatása. Az állapottárolóbázis és a processzor belső, fenntartott regiszterében tárolt kezdeti érték 030000H. 276 Rendszermenedzselő üzemmód Ez a már meglévő SMM rendszerekkel való kompatibilitás érdekében van így, melyeknél az alapértelmezésben szereplő SMRAM terület minimálisan a 38000H címnél kezdődő 32 kByte-nyi részként van definiálva. Most, hogy az SMRAM helye változó lehet, az SMRAM terület egy minimálisan 32 kByte méretű, az [8000H + SCbázis] címen kezdődő területként van definiálva. 3.104 Az SMRAM relokációja Az SMM revízió-azonosító megadja, hogy a processzor támogatja az SMRAM relokációját vagy sem. Az SMRAM nem cache-elhető címekre való relokálása megelőzheti azt, hogy az SMI# feldolgozása megzavarja a cache tartalmát. Az
SMRAM-relokáció megvalósítása az SMRAM állapottárolójának egy lokációja és egy láthatatlan belső regiszter felhasználásával történik. A 4 Byte-os állapottároló-bázis a processzor által az SMM-be való belépéskor felhasznált láthatatlan belső regiszternek felel meg. Az SMM állapottároló és az SMM kezelő első utasításának helyét határozza meg. Egy SMI# kiszolgálásakor a processzor láthatatlan belső regiszterének tartalma az állapottároló-bázis mezőben lesz tárolva. Egy RSM utasítás végrehajtásakor a processzor a láthatatlan regisztert az állapottároló-bázisból tölti fel. Az SMM kezelő megváltoztathatja az állapottároló-bázis mező értékét az állapottároló rekordban. Ezután, amikor újabb SMI#-k generálódnak, az SMM állapottároló és a kódszegmens-bázisok számára generált lokációk számára a processzor az új értéket használja. Megjegyzendő, hogy az INIT vonal aktiválása a belső
állapottároló-bázisregiszter tartalmát nem változtatja meg. Ugyancsak megjegyzendő, hogy amikor a processzor az új állapottároló-bázist feltölti, a változtatás nincs hatással a CS szelektorra. 277 Általános CPU programozási információk 3.105 Visszatérés az SMM-ből Az RSM utasítás kilép az SMM-ből és visszaadja a vezérlést a megszakított programnak. Az RSM utasítás csak az SMM-ben hajtható végre. Végrehajtására az SMM-en kívül tett kísérlet érvénytelen-opkód kivételt okoz. Az RSM utasítás végrehajtásakor a processzor előzőleg (az SMMbe való belépéskor) elmentett állapota visszaállítódik és a vezérlés visszakerül a megszakított programra. Ha a processzor egy érvénytelen állapot-információt detektál, akkor a lekapcsolt állapotba vált át. Ez csak a következő esetekben történhet meg: Az állapottároló bázis mezőben tárolt érték nem egy 32 kByte-hoz illesztett cím. A CR4 regiszter egyik
fenntartott bitjének értéke 1. A CR0 valamelyik bitkombinációja illegális, pontosabban (PG=1 és PE=0) vagy (NW=1 és CD=0). Lekapcsolt állapotban a processzor egy NMI megszakítás megjelenéséig vagy a reszetelésig megszakítja az utasítások végrehajtását. Hogy a lekapcsolt állapotba való belépését jelezze, a processzor egy speciális buszciklust generál. Ha az SMM kezelő a rendszernek olyan állapotát változtatta meg, amelyet az RSM nem állít vissza (ilyenek például a lebegőpontos regiszterek), akkor azt az állapotot még az RSM végrehajtása előtt vissza kell állítsa. 278 8086-os virtuális üzemmód 3.11 8086-os virtuális üzemmód A Pentium processzor támogatja egy vagy több 8086 vagy 8088 program védett módú környezetben való végrehajtását. Ebben a környezetben egy 8086 program egy 8086-os virtuális taszk részeként fut. A 8086-os virtuális üzemmód kihasználja a védett mód által a multitaszking számára nyújtott
támogatást. A 8086-os programokat futtató 8086-os virtuális taszkokból nemcsak hogy több is lehet, hanem ezek a Pentium processzor más taszkjaival is multitaszkolhatók. A 8086-os virtuális taszkok célja az, hogy a 8086 proceszszorra írt program számára egy "virtuális gép"-et emuláljanak. Egy teljes virtuális gép hardware-ből és rendszersoftware-ből áll. A 8086 processzor emulációját a software által felhasznált hardware valósítja meg, a következőképpen: A hardware egy virtuális regiszterkészletet (a TSS-en keresztül), virtuális memóriát (a taszk lineáris címtartományának első MByteját), és a megszakítások virtuális támogatását biztosítja, ezenkívül közvetlenül végrehajt minden olyan utasítást, mely az előbbiekben említett regisztereket és címtartományt használja. A software a virtuális gép külső interfészét (I/O, megszakítások és kivételek) a tágabb környezettel (amelyben maga is fut)
konzisztens módon vezérli. A software választhat azon lehetőségek között, hogy a I/O-t, a megszakításokat és a kivételkezelést maga emulálja, vagy ezeknek a software közbelépése nélküli végrehajtását a hardware-re bízza. A 8086-os virtuális gépeket támogató software neve 8086-os virtuális felügyelőprogram. A Pentium processzor saját 8086-os virtuális működési módjának olyan kiterjesztéseit tartalmazza, melyek az alkalmazások teljesítményét azáltal növelik meg, hogy kiküszöbölik az egyes műveletek emulálása miatt keletkező, a felügyelőprogramnak jelentett hibákat. A virtuális mód kiterjesztéséről a Pentium processzoron több információ a függelékben található. 279 Általános CPU programozási információk 3.111 8086 CPU kód végrehajtása A processzor akkor müködik 8086-os virtuális üzemmódban, ha az EFLAGS regiszter VM (virtual machine) bitje 1-re van állítva. E flaget a processzor két alkalommal teszteli:
1. Egy szegmensregiszter feltöltésekor annak kiderítése érdekében, hogy szükség van-e a 8086 stílusú címátalakításra vagy sem. 2. Egy utasítás dekódolásakor, annak meghatározása érdekében, hogy mely utasítások érzékenyek az IOPL-re és hogy mely utasításokat nem támogat (a valós üzemmódhoz hasonlóan). 3.1111 Regiszterek és utasítások A 8086-os virtuális üzemmódban rendelkezésre álló regiszterkészlet magába foglalja a 8086 processzor összes regiszterét, valamint a 8086 processzor után bevezetett új regisztereket (FS és GS). Olyan utasítások állnak rendelkezésre, melyek közvetlenül a szegmensregiszterekkel dolgoznak. Az 10FFEFH feletti lineáris címek a V86 felügyelőprogram, az operációs rendszer, valamint a többi rendszersoftware rendelkezésére állnak. A felügyelőprogramnak is szüksége lehet adatszegmensdeszkriptorokra, mivel elemeznie kell a 8086 programnak a címtartomány első MByte-jában található
megszakításvektor-táblázatát és más részeit. A 8086 operációs rendszer implementálására általában két választási lehetőség van: 1. A 8086 operációs rendszer a 8086 program részeként fut Ez a megközelítés a következő esetekben előnyös: A 8086 alkalmazás kódja megváltoztatja az operációs rendszert. Nincs elég idő a a 8086 operációs rendszernek egy Pentium CPU operációs rendszerként történő újraimplementálására. 280 8086-os virtuális üzemmód 2. A 8086 operációs rendszer a V86 felügyelőprogramban van implementálva vagy emulálva. Ez a megközelítés a következő esetekben előnyös: Az operációs rendszer funkciói több 8086-os virtuális taszk között könnyebben koordinálhatók. A 8086 operációs rendszer funkciói Pentium CPU rendszerhívásokkal könnyen emulálhatók. Megjegyzendő, hogy a 8086 processzor operációs rendszerének implementálására választott módnak különböző 8086
operációs rendszerek felhasználása esetén különböző 8086-os virtuális taszkjai lesznek. 3.1121 Lapozás a 8086-os virtuális taszkok esetében Egyetlen 8086-os virtuális taszknak sincs szüksége lapozásra, a lapozás azonban hasznos vagy szükséges lehet a következő esetekben: Több 8086-os virtuális taszk képzése. Minden egyes taszk a lineáris címek alsó MByte-ját más és más fizikai címtartományra kell leképezze. Az 1 MByte-nál jelentkező címcsonkítás emulálása. A 8086 család tagjai 1 MByte-nál nagyobb címet is megadhatnak. Például egy 0FFFFH értékű szelektor és egy 0FFFFH értékű ofszet által meghatározott tényleges cím értéke 10FFEFH (1 MByte plusz 65519 Byte). A 8086 processzor, mivel csak 20 bites címeket tud képezni, levágja a legmagasabb bitet, tehát 0FFFEH-ra csonkítja ezt a címet. A Pentium processzor az ilyen címeket nem csonkítja. Ha a 8086 programok valamelyike függ a címcsonkítástól, egy 8086-os
virtuális taszkban ugyanez a hatás érhető el az 100000H és 110000H illetve a 0 és 100000H közti lineáris címeknek ugyanarra a fizikai címre történő leképezésével. 281 Általános CPU programozási információk A fizikai címtartománynál nagyobb lineáris címtartomány képzése. Multitaszkingban futó több 8086 program számára közös 8086 operációs rendszer vagy ROM kód megosztása. Csapda állítás a memóriába leképezett I/O eszközöknek, illetve ezek átirányítása. 3.1122 Védelem egy 8086-os virtuális taszkon belül Egy 8086 program szegmensei közt nem kötelező a védelem. A 8086-os virtuális taszkban futó rendszersoftware-nek a 8086 alkalmazói programmal szemben való védelmére a software-tervezők a következőket kell figyelembe vegyék: Minden egyes taszk lineáris címtartományának első MByte-ját (plusz 64 kByte-ot) a 8086 processzorra írt program számára kell lefoglalni. Egy 8086 processzortaszk nem
generálhat e tartományon kívül eső címeket. A virtuális gép felügyelőprogramjának és a minden egyes 8086-os virtuális taszk címtartományában levő rendszersoftware védelmére az U/S bitet kell használni. Ha a processzor 8086-os virtuális üzemmódban van, akkor a CPL értéke 3 (legkevésbé privilegizált); ezért egy 8086 processzorra írt programnak csak felhasználói privilégiumai vannak. Ha a virtuális gép felügyelőprogramja lapjainak felügyelői privilégiumai vannak, akkor ezekhez a 8086 program nem férhet hozzá. 3.113 Belépés a 8086-os virtuális üzemmódba és az abból való kilépés A 3.83 ábra összefoglalja egy 8086 programba való belépés és az abból való kilépés módozatait. A 8086-os virtuális üzemmódba való belépés a VM flag 1-re állítása által történik. Ez kétféleképpen valósítható meg: 282 8086-os virtuális üzemmód 1. Egy taszkra való átkapcsolás az új TSS-ből betölti az EFLAGS regiszter
képét. Az új taszk TSS-e nem 16, hanem 32 bites kell legyen, mivel a 16 bites TSS nem tölti fel az EFLAGS felső, a VM flaget tartalmazó szavát. Az EFLAGS regiszter új tartalmában 1-re állított VM flag azt jelenti, hogy az új taszk 8086 utasításokat hajt végre, ezért a szegmensregiszterek TSS-ből való feltöltésekor a processzor 8086 stílusban alakítja ki a báziscímet. 2. Egy taszk procedúrájában található IRET utasítás feltölti az EFLAGS regisztert a veremből. Az 1-re állított VM flag azt jelenti, hogy a procedúra, amelyre a vezérlés visszaadódik, egy 8086 procedúra. Az IRET utasítás végrehajtásakor a CPL értéke 0 kell legyen, ellenkező esetben a processzor nem változtatja meg a VM állapotát. Taszkváltás vagy IRET Belépés az inicializálásba Megszakítás, kivétel 8086 program (V86 mód) IRET Taszkváltás V86 monitor (védett mód) Taszkváltás Egyéb CPU taszk (védett mód) Taszkváltás Taszkváltás 3.83 ábra:
Belépés a 8086-os virtuális üzemmódba és az abból való kilépés A 8086-os virtuális üzemmódba taszkátkapcsolással való belépés esetén a szegmensregiszterek a TSS-ből töltődnek fel, a VM flag beállítására egy IRET utasítást használva fel, a szegmensregiszterek a PL0 verem szegmensregisztereiből töltődnek fel (lásd a 3.84 ábrát) 283 Általános CPU programozási információk Megszakítás vagy kivétel fellépte esetén a processzor kilép a 8086-os virtuális üzemmódból. Ilyenkor két eset lehetséges: 1. A megszakítás vagy kivétel egy taszkátkapcsolást okoz Egy 8086-os virtuális taszkról bármilyen más taszkra való átkapcsolás esetén az EFLAGS regiszter feltöltődik az új taszk TSS-éből. Ha az új TSS 32 bites és az EFLAGS új tartalmának VM flagje törölve van, vagy ha az új TSS 16 bites, akkor a processzor törli az EFLAGS regiszter VM flagjét, a védett módú címalakot felhasználva az új TSS-ből feltölti a
szegmensregisztereket, és védett módban megkezdi az új taszk utasításának végrehajtását. 2. A megszakítás vagy kivétel egy 0 privilégiumszintű (legprivilegizáltabb) procedúrát hív meg. A processzor tárolja az EFLAGS regiszter aktuális tartalmát, majd törli a VM flaget. A megszakítás- vagy kivételkezelő emiatt "natív" 32 bites védett-módú kódként fut. Ha a megszakítás vagy kivétel egy hasonló szegmensben vagy 0-tól különböző privilégiumszintű szegmensben levő procedúrát hív meg, akkor a processzor általános védelmi hibát generál, a hibakód annak a kódszegmensnek a szelektora, melyre a hívás vonatkozott. Hibakód nélkül Nem használt Hibakóddal ESP a TSS-ből Nem használt Régi GS Régi GS Régi FS Régi FS Régi DS Régi DS Régi ES Régi ES Régi SS Régi SS Régi ESP Régi ESP Régi EFLAG Régi EFLAG Régi CS Régi EIP Régi CS Új ESP Régi EIP Hibakód 284 ESP a TSS-ből Új ESP 8086-os
virtuális üzemmód 3.84 ábra: A 0 privilégiumszintű verem állapota 8086-os virtuális módban, a megszakítást követően A rendszersoftware- nem változtatja meg közvetlenül a VM flag állapotát, ehelyett megváltoztatja a vermen vagy a TSS-ben tárolt EFLAGS képének egyes bitjeinek állapotát. Amikor az első 8086-os virtuális taszkot felépíti, a 8086-os virtuális felügyelőprogram az EFLAGS-nek a vermen vagy a TSS-ben levő képének VM bitjét 1-re állítja. A megszakítás- és kivételkezelők elemezhetik a vermen levő VM flag állapotát. Ha a megszakított procedúra 8086-os virtuális módban futott, akkor a kezelőnek esetleg szüksége lehet a 8086-os virtuális felügyelőprogram maghívására. 3.1131 Taszkátkapcsolások általi tranzíciók Egy 8086-os virtuális taszkba illetve abból való átkapcsolásnak az oka a következő három közül az egyik: 1. Egy taszkkaput meghívó megszakítás 2. A 32 bites operációs rendszer ütemezőjének egy
akciója 3. IRET utasítás végrehajtása 1-re állított NT flag esetén Az előbbi esetek bármelyikében a processzor az új TSS-ben levő képnek megfelelően megváltoztatja az EFLAGS regiszter VM flagjének állapotát. Ha az új TSS 16 bites, akkor az EFLAGS regiszter felső szava nincs a TSS-ben, ebben az esetben a processzor törli a VM flaget. A processzor a VM flaget még azelőtt módosítja, hogy a szegmensregisztereket az új TSS-ből feltöltené. A VM flag új beállítása meghatározza azt, hogy a processzor az új szegmensregiszter-képeket 8086, 80286 vagy 32 bites szelektorokként értelmezi. 3.1132 Átmenet trap- és megszakításkapukon keresztül A trap- és megszakításkapukat meghívó kivételek és megszakítások nyomán a processzor kiléphet a 8086-os virtuális 285 Általános CPU programozási információk üzemmódból. A kivétel vagy megszakítás végrehajtásával tér vissza a 8086 programba. egy IRET utasítás A kivételek és
megszakítások háromféleképpen kezelhetők: 1. A 8086-os virtuális felügyelőprogram által 2. A 8086-os virtuális felügyelőprogram átadhatja a vezérlést a 8086 program saját megszakításkezelőjére. 3. Egy védett módú megszakításkiszolgáló rutin által Ha a megszakítást vagy kivételt a felügyelőprogram kell kezelje és ha az EFLAGS vermen tárolt képében a VM flag 1-re van állítva, akkor a megszakításkezelő átadja a vezérlést a felügyelőprogramnak. A felügyelőprogram az első két módszer egyikét használja. Ha nincs szükség arra, hogy a megszakítást vagy kivételt a felügyelőprogram kezelje, akkor a 3-ra állítható IOPL lehetővé teszi, hogy minden virtuális módú megszakítást a védett módú megszakításrutin kezeljen. Mivel egy 8086 program a 8086 processzoron való futtatásra volt tervezve, ezért ennek egy 8086-os virtuális taszkban 8086 stílusú megszakításvektor-táblázata van, mely a 0 lineáris címen kezdődik.
Ezért a felügyelőprogram közbelépését és a védett módba való átkapcsolást igénylő kivételek és megszakítások esetén a processzor ezt a táblázatot nem használja közvetlenül, ehelyett a kezelőket az IDT-n keresztül hívja meg. 8086-os virtuális módban egy megszakítás vagy kivétel számára az IDT bejegyzése vagy-vagy alapon a következőket kell tartalmazza: Egy taszkkaput. Egy 32 bites trapkaput (14-es deszkriptortípus) vagy egy 32 bites megszakításkaput (15-es deszkriptortípus), mely egy nem megegyező, 0. privilégiumszintű (legprivilegizáltabb) kódszegmensre kell mutasson. A 32 bites trap- vagy megszakításkapukat használó megszakítások és kivételek a 0. privilégiumszintet használják A szegmensregiszterek 286 8086-os virtuális üzemmód tartalma e privilégiumszint vermén lesznek tárolva. Egy 8086 programot futtató 8086-os virtuális taszk esetén a futás során bekövetkező kivétel vagy megszakítás után a
verem állapotát a 3.84 ábra szemlélteti Miután a processzor a 8086-os szegmensregisztereket elmenti a 0. privilégiumszint vermére, a kezelő procedúra futtatása előtt törli a szegmensregisztereket. Ez lehetővé teszi a megszakításkezelő számára, hogy az biztonságosan elmentse és visszaállítsa a DS, ES, FS és GS regiszterek tartalmát úgy, mintha azok a Pentium CPU szelektorai lennének. A rendes taszkok vagy 8086-os virtuális taszkok által meghívott megszakításkezelők a regiszterek elmentésére és visszaállítására bármely taszk esetén ugyanazt a kódrészt használhatják. E regisztereknek az IRET utasítás végrehajtása előtti törlése nem okoz trapet a kivételkezelőben. A szegmensregiszterekben értékeket váró vagy visszaadni akaró megszakítás-kezelők a regisztereknek a 0. privilégiumszint vermére mentett képét kell használniuk. Az olyan megszakításkezelők, melyeknek tudniuk kell, hogy a megszakítás 8086-os virtuális
módban lépett fel vagy sem, megvizsgálhatják az EFLAGS regiszter eltárolt tartalmának VM flagjét. Egy megszakítás vagy kivétel visszaküldése a 8086 programnak a következő lépésekből áll: 1. A 8086 megszakításvektor felhasználása a megfelelő kezelő procedúra helyének megállapítására. 2. A 8086 program FLAGS, CS és IP értékeinek tárolása a 3 (legkevésbé privilegizált) privilégiumszint vermén. 3. A visszatérési kapcsolat lecserélése a 0 privilégiumszint vermén úgy, hogy az a 3. privilégiumszinten levő kezelő procedúrára mutasson 4. A vezérlésnek a kezelőre való átadása, egy IRET utasítás végrehajtásával. 5. Amikor a 3 privilégiumszinten levő kezelő IRET utasítása újból meghívja a 8086-os virtuális felügyelőprogramot, a visszatérési kapcsolat visszaállítása a 0. privilégiumszint vermén úgy, hogy az az 287 Általános CPU programozási információk eredeti, megszakított, mutasson. 3.
privilégiumszinten levő procedúrára 6. A vezérlésnek a megszakított procedúrának való visszaadása, egy IRET utasítás végrehajtásával. Ha az IOPL 3-ra van állítva és a megszakításkapu DPL-je szintén 3-ra, akkor az INT n utasítások a megadott vektorszámmal egy trap által megszakadnak. Az olyan megszakításvektorok, melyeknek IDT kapuja 3ra van állítva, megvizsgálhatják az EFLAGS veremre mentett képének a VM bitjét annak megállapítása céljából, hogy a megszakítást vissza kell-e téríteni a felügyelőprogramhoz vagy át kell adni a 8086 program megszakításkezelőjének. 3.114 Érzékeny utasítások Amikor a Pentium processzor 8086-os virtuális üzemmódban működik, a CLI, STI, PUSHF, POPF, INT n, és IRET utasítások érzékenyek az IOPL-re. Az IOPL-re védett üzemmódban érzékeny IN, INS, OUT és OUTS utasítások a 8086-os virtuális üzemmódban nem érzékenyek. A 8086-os virtuális módban érzékeny utasítások teljes
felsorolása a következő: CLI STI PUSHF POPF INT n IRET - Megszakítást engedélyező bit törlése - Megszakítást engedélyező bit 1-re állítása - Flagek veremre helyezése - Flagek leemelése a veremről - Software-megszakítás - Visszatérés megszakításból 8086-os virtuális módban való futás alatt a CPL értéke mindig 3. Ha az IOPL értéke kisebb mint 3, a fenti utasítások végrehajtására tett próbálkozás általános védelmi hibát okoz. Ezen utasítások az IOPL-re azért érzékenyek, hogy lehetőséget adhassanak a 8086-os virtuális felügyelőprogramnak arra, hogy az a hatásukat emulálhassa. Ezen utasítások működését akkor, amikor a virtuális mód kiterjesztése működésben van, a függelék tárgyalja. 288 8086-os virtuális üzemmód 3.115 Virtuális megszakítások támogatása Számos, nem multitaszking rendszerekre írt 8086 program a megszakítások vezérlése érdekében az IF flaget állítja. Multitaszking környezetben ez
problémák forrása lehet. Emiatt a 386 és 486 processzorokon futó felügyelőprogramok a software-ből egy virtuális megszakításflaget állítnak. Az IF flaget állító minden utasítás a felügyelőprogramra adja át a vezérlést, az ezeken a processzorokon való emuláció céljából. A Pentium processzornak a virtuális megszakításflagtámogatásáról több információ a függelékben található 3.116 A 8086 operációs rendszerhívások emulációja Számos 8086 operációs rendszerhívás a paramétereknek a veremre való helyezése, majd egy INT n utasítás végrehajtása által történik. Az INT n utasítás érzékeny az IOPL-re amiatt, hogy lehetővé tegye az, hogy a 8086-os virtuális felügyelőprogram emulálni tudja a 8086 operációs rendszer funkcióit, vagy a megszakítást visszaküldhesse a 8086 operációs rendszerhez. Ha az IOPL<3, az INT n utasításokat a felügyelőprogram fogja el. Ha IOPL=3, akkor a megszakításokat a védett módú
megszakításkezelő rutin szolgálja ki, a 486 processzorral kompatibilis módon. A 386 és 486 processzorokon a 8086-os virtuális üzemmódban végrehajtott minden INT n utasítást a felügyelőprogram kell elfogjon, amikor az IOPL<3. A Pentium proceszszornak a megszakításkezelést támogató virtuális módú kiterjesztéséről információk a függelékben találhatók. A 3.85 ábra meghatározza, hogy a 8086-os virtuális módban az IOPL értékére alapozva a processzor milyen műveleteket fog végezni. 289 Általános CPU programozási információk IOPL =3 <3 Processzor művelet Megszakítása a V86 módból a védett módba Törli a VM és a TF flaget Ha a szolgáltatás megszakítás kapun keresztül történik, törli az IF flaget PL0 értékei lecserélődnek a TSS értékeire Elmenti a GS, FS, DS és ES regisztereket a PL0 veremre Nullára állítja a GS, FS, DS és ES regisztereket Elmenti megszakított taszk SS, EIP, EFLAG, CS és EIP regisztereit a
PL0 veremre Beállítja CS és EIP értékeit a megszakíitás kapu alapján Általános védelmi kivétel 3. 85 ábra: A software-megszakítás műveletei 3.117 Virtuális I/O Számos, nem multitaszking rendszerekre írt 8086 program az I/O portokhoz közvetlen módon fér hozzá. Multitaszking környezetben ez problémák forrása lehet. Ha ugyanahhoz a porthoz több mint egy program fér hozzá, ezek megzavarhatják egymást. Legtöbb multitaszking rendszer megköveteli azt, hogy az alkalmazói programok a portokat az operációs rendszeren keresztül érjék el. Ez egyszerűbb, központosított vezérlést eredményez. Az I/O védelmet a processzor olyan I/O-k létrehozásával valósítja meg, melyek kompatibilisek a környezettel és átlátszóak a 8086 programok számára. Az I/O portok védelmét a tervezők a következőkben felsorolt, különböző szempontok figyelembevételével valósíthatják meg: Az I/O közvetlen végrehajtására tett minden egyes kísérlet
esetén meg kell védeni az I/O címtartományt és kivételeket kell generálni. A 8086 programot hagyni kell, hogy az I/O-t közvetlenül végezze el. 290 8086-os virtuális üzemmód Bizonyos I/O portok elérésére tett kísérletek esetén kivételeket kell generálni. Bizonyos, a memóriába leképezett I/O portok elérésére tett kísérletek esetén kivételeket kell generálni. Az I/O portokhoz való hozzáférést vezérlő módszer attól függ, hogy a hozzáférések I/O-ra vagy a memóriába vannak leképezve. 3.1171 I/O-ra leképezett I/O A bizonyos I/O címek elérésére tett kísérletek esetén kivételek generálására az I/O engedélyező bittérkép használható. Minden egyes 8086-os virtuális taszk I/O engedélyező bittérképe meghatározza, hogy az adott taszk esetében mely I/O címek generálnak kivételeket. Mivel minden taszknak más és más I/O engedélyező bittérképe lehet, különböző taszkok esetében a kivételeket
generáló I/O címek különbözhetnek. A védett módtól ez abban különbözik, hogy az IOPL-t senki nem vizsgálja meg. 3.1172 Memóriába leképezett I/O A memóriába leképezett I/O-t használó rendszerekben a processzor lapozási lehetőségei felhasználhatók az I/O portokhoz való hozzáférési kísérletek esetén kivételek generálására. A 8086-os virtuális felügyelőprogram a memóriába leképezett I/O vezérlésére a lapozást a következőképpen használhatja: Az I/O műveletek végrehajtását igénylő taszkok lineáris címtartományának egy részét az I/O portok által használt fizikai címtartományra képezi le. Az I/O portokat (különböző lapokon) különböző címekre téve, a lapozó mechanizmus megvalósíthatja a taszkok egymástól való elszigetelését. A lineáris címtartomány egy részét olyan lapokra képezi le, melyek nincsenek jelen. Így ahányszor a taszk megkísérli egy I/O művelet 291 Általános CPU
programozási információk végrehajtását ezeken a lapokon, egy kivétel generálódik. A rendszersoftware- ezután majd értelmezheti a megpróbált I/O műveletet. Az I/O tartomány software-emulációja bizonyos körülmények közt az operációs rendszer részéről túl sok közbelépést igényel. Ilyenkor lehetséges az, hogy csak az első I/O hozzáférés megkísérlése okozzon kivételt. A rendszersoftware- ezután eldöntheti, hogy az I/O vezérlésének kizárólagos joga igeiglenesen átadható-e egy programnak vagy sem. Ha igen, akkor az I/O védelmét megszünteti és a program számára lehetővé teszi, hogy az teljes sebességgel fusson. 3.1173 Különleges I/O pufferek Az intelligens kontrollerek pufferei (például egy bittérképes keretpuffer) a lapok leképezésével szintén emulálhatók. A puffer lineáris tartománya minden egyes 8086-os virtuális taszk esetében más és más fizikai tartományra képezhető le. A 8086-os virtuális felügyelőprogram
azt vezérli, hogy melyik virtuális puffert kell a fizikai címtartományban levő valós pufferbe másolni. 3.118 Különbségek a 8086 CPU-hoz képest 8086-os virtuális üzemmódban általában a 8086 és 8088 processzorokra írt programok futnak. A következő felsorolás bemutatja a 8086 processzor és a Pentium processzor valamint más 32 bites processzorok 8086-os virtuális üzemmódja közti kisebb eltéréseket. 1. Az utasítások végrehajtásához szükséges órajelek száma A 32 bites processzorokon legtöbb utasítás kevesebb órajel alatt hajtódik végre, mint a 8086 processzoron. A leginkább befolyásolt területek a következők: 292 Az I/O műveletek alkalmával az I/O eszközök által igényelt késleltetések. 8086-os virtuális üzemmód A 8087 koprocesszorral párhuzamosan működő 8086 processzor esetében feltételezett késleltetések. 2. Az osztáskivételek a DIV utasításra mutatnak A Pentium processzor esetében az osztáskivételek
mindig a hibát okozó utasításra mutató CS:IP értéket mentik el. A 8086 processzornál a CS:IP a következő utasításra mutat. 3. Meghatározatlan 8086 processzor-opkódok A 8086 processzor esetében nem definiált opkódok a Pentium processzoron vagy érvénytelen-opkód kivételt generálnak, vagy a Pentium számára definiált új utasításként hajtódnak végre. 4. A PUSH SP által a veremre helyezett érték A PUSH SP utasítás végrehajtásakor a Pentium processzor más adatot helyez a veremre, mint a 8086. A Pentium processzor az SP-nek a csökkentés előtti értékét helyezi a veremre, míg a 8086 a csökkentés utáni értékét. Ha a veremre helyezett adatra szükség van, akkor a PUSH SP utasítást a következő három utasítással kell helyettesíteni: PUSH BP MOV BP, SP XCHG BP, [BP] Ez a kód a Pentiumon úgy működik, mint a PUSH SP a 8086 processzoron. 5. Léptetés vagy forgatás több mint 31 bittel A Pentium processzor a léptetés és forgatás
számlálóinak csak az alsó 5 bitjét veszi figyelembe. Ez a számláló értékét legtöbb 31-re korlátozza 6. Redundáns prefixek A Pentium processzor az utasítások hosszát 15 Byte-ra korlátozza. E határ megsértésére az egyetlen lehetőség az utasítás előtti redundáns prefixek használata. Az utasításhossz-határ megsértése esetén általános védelmi kivétel generálódik. A 8086 processzor nem korlátozza az utasítások hosszát. 293 Általános CPU programozási információk 7. A 0 vagy 65535 értékű ofszetet átlépő operandus A 8086 processzoron egy, a 65535 ofszetet (például a 65535 ofszetre egy szót másoló MOV) vagy 0 ofszetet (például egy szó kiemelése a veremból egy PUSH által, amikor az SP regiszter értéke 1) átlépő operandushoz való hozzáférés esetén az ofszet modulo 65535 alapon megcsonkul. A Pentium processzor ebben az esetben egy kivételt generál, általános védelmi kivételt, ha a szegmens egy adatszegmens (azaz
a szegmenset a CS, DS, ES, FS, vagy GS regiszterek címzik), vagy veremkivételt, ha a szegmens egy veremszegmens (melyet az SS regiszter címez). 8. A 65535 ofszetet átlépő sorozatos végrehajtás A 8086 processzor esetében, ha az utasítások sorozatos végre hajtása a 65535 ofszet átlépése után is folytatódik, akkor a processzor a következő utasítást ugyanazon szegmens 0 ofszetjéről tölti be. A Pentium processzor ebben az esetben általános védelmi kivételt generál. 9. A LOCK használata csak bizonyos utasításokra van korlátozva A LOCK prefix és az általa vezérelt jel kizárólag annak megelőzésére használható, hogy más buszvezérlők az adatátviteli műveletet megszakítsák. A LOCK prefix csak a memóriát módosító, következő Pentium utasításokkal használható. A LOCK bármilyen más utasítással (vagy az alábbiakban felsoroltakkal abban az esetben, ha azok nem a memóriát módosítják) való használata érvénytelen-opkód kivételt
eredményez. Bitteszt és -változtatás: a BTS, BTR és BTC utasítások. Csere: az XCHG, XADD, CMPXCHG és CMPXCHG8B utasítások (az XCHG esetében nincs szükség a LOCK prefixre). Egyoperandusú aritmetikai és logikai: INC, DEC, NOT és NEG utasítások. Kétoperandusú aritmetikai és logikai: ADD, ADC, SUB, SBB, AND, OR és XOR utasítások. 10. Lépésenkénti végrehajtás külső megszakításkezelők A Pentium processzor lépésenkénti végrehajtás kivételeinek prioritása 294 8086-os virtuális üzemmód különbözik a 8086 processzorétól. Ez a változtatás megelőzi hogy a külső megszakításkezelő is léptetve legyen akkor, amikor a program megszakított. A Pentium processzor lépésenkénti végrehajtás kivételének minden más külső megszakításnál nagyobb prioritása van. Az NT utasítás vagy egy kivétel által meghívott megszakításkezelőt a Pentium azonban még mindig lépésenként hajt végre. 11. IDIV kivételek a
80H és 8000H hányadosok esetében Az IDIV utasítás hányadosaként a Pentium képes a legkisebb negatív szám generálására. A 8086 processzor ehelyett azonban osztáshiba kivételt generál. 12. Flagek a veremben Az EFLAGS regiszter PUSH utasítás, megszakítások, vagy kivételek által tárolt tartalma a 8086 processzoron tárolttól a 12.-től 15-ig terjedő bitekben különbözik A 8086 processzoron ezek a bitek úgy tárolódnak, mintha 1-re lettek volna állítva, a Pentiumon azonban 8086-os virtuális módban a 15. bit értéke mindig 0 és a 12.-től 14-ig terjedő bitekben mindig az utoljára beléjük töltött érték van. 13. Az NMI kezelőt megszakító NMI Miután a Pentium processzor egy NMI kivételt elfogad, a következő IRET utasítás végrehajtásáig maszkolja az NMI megszakítást. 14. A lebegőpontos-hiba kivételt hívó lebegőpontos hibák A lebegőpontos-hiba kivételek a Pentium processzoron meghívják a lebegőpontos-hiba kivétel kezelőjét. Ha
a 8086 processzor a 8087 megszakítás számára más kivételt használ, akkor mindkét kivételvektor a lebegőpontos-hiba kivétel kezelőjére kell mutasson. A Pentium processzornak olyan jelei vannak, melyek külső logika hozzáadásával támogatják a számos személyi számítógépen használt megszakítás-kezelő mechanizmus emulációjának a felhasználó által definiált hibajelentéseit. 15. A numerikus kivételek meg kell engedjék a prefixek használatát A Pentium processzoron a lebegőpontos kivételek számára lementett CS és IP regiszterek az ESC utasítás előtt esetleg jelenlevő prefixekre 295 Általános CPU programozási információk mutatnak. A 8086 processzoron az elmentett CS:IP az ESC utasításra mutat. 16. A Lebegőpontos Egység (FPU) nem használja a megszakításkontrollert A Pentium processzornak küldött lebegőpontos hibajel nem halad át a megszakításkontrolleren (A 8087 koprocesszor INT jele viszont áthalad). A koprocesszor-hiba
kivétel kezelőjéből egyes utasításokat törölni kell, amennyiben azok a megszakításkezelőt használják. A Pentium processzornak olyan jelei vannak, melyek külső logika hozzáadásával támogatják a számos személyi számítógépen használt megszakításkezelő mechanizmus emulációjának a felhasználó által definiált hibajelentéseit. 17. A busz tartására adott válasz A 8086 és Intel286 processzoroktól eltérően a Pentium processzor válaszol a buszvezérlés átvevésére irányuló, más lehetséges buszvezérlőktől (például DMA kontrollertől) érkező kérésekre egy olyan nem illeszkedő operandus részeinek átvitele esetén, mint például egy dupla szót képező két szó. 18. A 8086-os virtuális üzemmódban a CPL értéke 3 A 8086 processzor nem támogatja a védelmet, így CPL-je sincs. A 8086-os virtuális mód egy 3 értékű CPL-t használ, mely megakadályozza a privilegizált utasítások végrehajtását. Ezek a következők:
296 LIDT utasítás LGDT utasítás LMSW utasítás A MOV utasításnak a vezérlőregiszterek elmentésére szolgáló speciális alakjai. CLTS utasítás HLT utasítás INVD utasítás WBINVD utasítás INVLPG utasítás RDMSR utasítás WRMSR utasítás RSM utasítás feltöltésére és 8086-os virtuális üzemmód A fenti utasítások a processzornak az inicializálását követő valós üzemmódjában hajthatók végre. Lehetővé teszik a rendszeradatstruktúrák (például a deszkriptortáblázatok) inicializálását a védett módba való belépés előtt. Mivel a 8086-os virtuális üzemmódba csak védett módból lehet belépni, ezek a struktúrák a belépéskor már inicializálva vannak. 19. A denormált kivétel kezelése különbözik A különbségeinek részletei a 23. fejezetben találhatók kivételkezelés 3.119 Különbségek a 286 CPU-hoz képest A 8086-os virtuális üzemmód és az Intel286 valós üzemmódja
közti különbségek az alkalmazások és az operációs rendszer közti interfészre vannak hatással. Az alkalmazás a 3 privilégiumszinten (felhszanálói módban) fut, így a védett privilégiumú utasítások és architekturális lehetőségek használatára tett minden kísérlet a 8086-os virtuális felügyelőprogramot fogja meghívni. A felügyelőprogram elemzi ezeket a hívásokat és emulálja őket. 3.1191 Privilégiumszint A 8086-os virtuális módban futó programok privilégiumszintje 3 (felhasználói mód), mely megakadályozza a privilegizált utasítások végrehajtását. A privilegizált utasítások a következők: LIDT utasítás LGDT utasítás LMSW utasítás A MOV utasításnak a vezérlő- és debugregiszterek feltöltésére és elmentésére szolgáló speciális alakjai. CLTS utasítás HLT utasítás INVD utasítás WBINVD utasítás INVLPG utasítás 297 Általános CPU programozási információk
RDMSR utasítás WRMSR utasítás RSM utasítás A 8086-os virtuális módba csak védett módból lehet belépni, így ennek nincs szüksége ezeknek az utasításoknak a végrehajtására. Míg a 8086-os virtuális üzemmódban nem, addig valós üzemmódban ezek az utasítások végrehajthatók. 3.1192 A busz lezárása A 286 processzor a buszlezáró funkciót a 386, 486 és Pentium processzoroktól eltérő módon implementálja. Ez a tény a 8086 programok számára attól függően lehet észrevehető vagy sem, hogy a 8086-os virtuális felügyelőprogram a LOCK prefixet hogyan kezeli. Az LOCK prefix-szel ellátott utasítások érzékenyek az IOPL-re, a software-tervezők tetszés szerint emulálhatják őket. Ezért ha a 8086 programoknak a LOCK közvetlen végrehajtása engedélyezve van, a memória lezárásának a 8086 processzorra jellemző módját használó programok a Pentium és más 32 bites processzorokon lehet, hogy nem fognak megfelelően futni. A LOCK
prefix és az általa vezérelt buszjel kizárólag annak megelőzésére használható, hogy más buszvezérlők az adatátviteli műveletet megszakítsák. A LOCK prefix csak a memóriát módosító, következő Pentium utasításokkal használható. A LOCK bármilyen más utasítással (vagy az alábbiakban felsoroltakkal abban az esetben, ha azok nem a memóriát módosítják, például ha a céloperandus egy regiszter) való használata érvénytelen-opkód kivételt eredményez. Bitteszt és -változtatás: a BTS, BTR és BTC utasítások. Csere: az XCHG, XADD, CMPXCHG és CMPXCHG8B utasítások (az XCHG esetében nincs szükség a LOCK prefixre). Egyoperandusú aritmetikai és logikai: INC, DEC, NOT és NEG utasítások. 298 8086-os virtuális üzemmód Kétoperandusú aritmetikai és logikai: ADD, ADC, SUB, SBB, AND, OR és XOR utasítások. A lezárt utasítások garantáltan csak a céloperandus által megadott memóriarészt zárják le, egyes
esetekben azonban nagyobb részeket is lezárhatnak. A 8086 és 286 processzoroktól eltérően a Pentium processzor válaszol a buszvezérlés átvevésére irányuló, más lehetséges buszvezérlőktől (például DMA kontrollertől) érkező kérésekre egy olyan nem illeszkedő operandus részeinek átvitele esetén, mint például egy dupla szót képező két szó. 3.1110 Különbségek a 386 és 486 CPU-hoz képest A valós üzemmód az Intel386, Intel486 és Pentium processzorokon ugyanúgy viselkedik. Amikor a virtuális módú kiterjesztés le van tiltva (a CR4 VME bitjének értéke 0), akkor a Pentium processzor 8086-os virtuális üzemmódjának viselkedése a 386 és 486 processzorokével megegyező. A virtuális módú kiterjesztés engedélyezésével (a CR4 VME bitjének értéke 1) a Pentium processzor 8086-os virtuális üzemmódjának teljesítménye jelentős mértékben megnő. E kiterjesztésekkel kapcsolatos információk a függelékben találhatók. A
maximális teljesítmény elérése érdekében a Pentium processzorra portált programok engedélyezett cache-el kell fussanak. 299 Általános CPU programozási információk Ábra- és példajegyzék 1.1 ábra: A Pentium processzor blokkvázlata 12 1.2 ábra: Az INTEGER egység 13 1.3 ábra: A PIPELINE-ok belső felépítésének blokkvázlata 14 1.4 ábra: Cache-vonal állapotai a MESI protokoll szerint 16 1.5 ábra: Az FPU pipeline-ja 19 1.6 ábra: Cache kezelési modellek 20 1.7 ábra: DRAM idődiagramok 21 1.8 ábra: Az M1- es és a Pentium processzorok pipelinejainak összehasonlítása . 24 1.9 ábra: Az M1-es definiálatlan CACHE-e bármilyen arányban tartalmazhat adatot és utasítást. Az utasításvonal CACHE pedig az INTEGER egység által leginkább használt utasításokat tárolja. 27 1.10 ábra: Az M1-es processzor szuperpipeline-okból felépített INTEGER egysége. 29 1.11 ábra: Kiugrás a végrehajtási sorrendből Az M1-es processzorban az egyik
pipeline végrehajtási sorában lévő utasításnak nem kell megvárnia a másik pipeline lassúbb utasítását. Kiugorva a végrehajtási sorból, időt lehet megtakarítani a vérehajtás sor. 30 1.12 ábra: Nx586 alapú IBM PC kompatibilis számítógép felépítése NxVL vagy NxPCI rendszerinterface chip felhasználásával. A matematikai processzor külön tokban helyezkedik el, míg a másodszintű cache vezérlője a processzorlapkán kapott helyet. 32 1.13 ábra: A NexGen szabadalmaztatott RISC86-os architektúrája dinamikusan fordítja az összetett X86-os (CISC) utasításokatRISC86-os utasításokká, így tehát kihasználhatja a RISC utasítások sebességi előnyeit. 34 3.1 ábra: Szegmentált címzés 64 3.2 ábra: Alkalmazások számára elérhető regiszterkészlet 66 3.3 ábra: Szegmentált memória 68 3.4 ábra: A verem működése 71 3.5 ábra: Az EFLAGS regiszter 72 300 Ábra- és példajegyzék 3.6 ábra: Állapotbitek 73 3.7 ábra: A vezérlő
regiszterek felépítése 78 3.8 ábra: Nyomkövető regiszterek 83 3.9 ábra: Az EDX regiszter tartalma reszetelés után 87 3.10 ábra: A CR0 regiszter tartalma reszetelés után 88 3.11 ábra: A processzor állapota a reszetelést követően 90 3.12 ábra: A processzor állapota a reszetet követően 100 3.13 ábra: Az algoritmus és a forrásszöveg ezzel kapcsolatos sorainak száma . 101 3.14 ábra: A BLD és az ASM forrásállomány közti összefüggés . 104 3-1 példa: STARTUP.ASM 104 3-2 példa: MAIN.ASM 113 3.15 ábra: A TEMP GDT létrehozása és a védett módba való átkapcsolás (a forrásszöveg 162-172 sorai) . 115 3.16 ábra: A GDT, IDT és TSS ROM-ból RAM-ba másolása (a forrásszöveg 196-261 sorai). 115 3.17 ábra: Átkapcsolás a taszkra (a forrásszöveg 282 296 sorai). 116 3-3 példa: Az alkalmazás lefordítására és felépítésére szolgáló parancsköteg-állomány . 117 3-4 példa: Build-állomány. 117 3.18 ábra: Címek lefordítása 120
3.19 ábra: Kivételek és megszakítások 123 3.20 ábra: Memória kezelő regiszterek 125 3.21 ábra: Sík modell 132 3.22 ábra: Védett sík modell 134 3.23 ábra: Multiszegmens modell 135 3.24 ábra: TI BIT - A deszkriptor tábla kiválasztása 137 3.25 ábra: Szegmens fordítás 138 3.26 ábra: Szegmens regiszterek 139 3.27 ábra: Szegmens szelektor 140 3.28 ábra: Szegmens deszkriptorok 142 3.29 ábra: Alkalmazási szegmens típusok 145 3.30 ábra: Szegmens deszkriptor (a szegmens nincs jelen) 148 3.31 ábra: Deszkriptor táblázatok 149 3.32 ábra: Pszeudó deszkriptor formátum 150 3.33 ábra: A lineáris cím formátuma 152 301 Általános CPU programozási információk 3.34 ábra: Lapfordítás 153 3.35 ábra: A lapcímtár formátuma és a laptáblázatok elemei a 4K-s lapokhoz. 154 3.36 ábra: Laptáblázat bejegyzés formátuma nem jelenlévő lapoknál . 155 3.37 ábra: Kombinált szegmens- és lapcím fordítás 160 3.38 ábra: minden egyes
szegmensnek biztosítani kell saját laptáblázatot . 161 3.40 ábra: Rendszer szegmens- és kapu típusok 164 3.39 ábra: Védett módban használt deszkriptor mezők 166 3.41 ábra: Védelmi gyűrűk 171 3.42 ábra: Privilégium ellenőrzés adathozzáféréseknél 172 3.43 ábra: Privilégium ellenőrzés taszkkapu nélküli vezérlésátadásoknál. 175 3.44 ábra: Call kapu 177 3.45 ábra: A call kapu mechanizmusa 178 3.46 ábra: Privilégium ellenörzés call kapuval történő vezérlésátadásnál. 180 3.47 ábra: Kezdeti stack pointerek egy TSS-ben 182 3.48 ábra: Stack keret szintek közötti hívás alatt 184 3.49 ábra: Szintek közötti visszatérés ellenőrzés 187 3.50 ábra: Érvényes deszzkriptor típusok LSL műveletekhez 191 3.51 ábra: Egy laptáblázat bejegyzés védelmi mezői 195 3.52 ábra: Kombinált lapcímtár és laptáblázat védelem 198 3.53 ábra: 32 bites taszk állapot szegmens 203 3.54 ábra: TSS Deszkriptor 204 3.55 ábra: Taszk
regiszter 207 3.56 ábra: Taszk kapudeszkriptor 208 3.57 ábra: Taszkokra jellemző taszk kapuk 209 3.58 ábra: Taszkváltás alatti ellenörzés 213 3.59 ábra: Beágyazott taszkok 215 3.60 ábra: A taszkváltások hatása a Busy, NT és LINK mezőkre . 216 3.61 ábra: Lineáris átfedés a fizikai memóriában 221 3.62 ábra: Kivételek és megszakításvektorok 224 3.63 ábra: Kivételek és megszakítások egymás közötti prioritása. 229 302 Ábra- és példajegyzék 3.64 ábra: IDT lokalizálása a memóriában az IDTR segítségével . 230 3.65 ábra: IDT kapudeszkriptor 232 3.66 ábra: Megszakítás procedura hívás 234 3.67 ábra: Verem keret egy megszakítás vagy kivétel után 235 3.68 ábra: Megszakítás taszkkapcsolás 238 3.69 ábra: Hibakód 240 3.70 ábra: Megszakítás és kivétel osztályok 244 3.71 ábra: Dupla hiba viszonyok 245 3.72 ábra: Érvénytelen TSS állapotok 247 3.73 ábra: Laphiba hibakódok 253 3.74 ábra: Adattípusok által
igényelt illeszkedési feltételek 260 3.75 ábra: Kivételek összefoglalása 262 3.75 ábra: Hibakódok összefoglalása 263 3.76 ábra: Az üzemmód-állapotok közti átmenetek 266 3.77 ábra: Az SMM kezdeti állapota 267 3.78 ábra: Az állapottároló formátuma 270 3.79 ábra: Állapot-beosztás 271 3.80 ábra: SMM revízió-azonosító 271 3.81 ábra: SMM revízió-azonosító táblázat 272 3.82 ábra: Felfüggesztett állapotból való automatikus újraindítás. 273 3.83 ábra: Belépés a 8086-os virtuális üzemmódba és az abból való kilépés. 280 3.84 ábra: A 0 privilégiumszintű verem állapota 8086-os virtuális módban, a megszakítást követően. 281 3. 85 ábra: A software-megszakítás műveletei 287 303 Általános CPU programozási információk Előzetes a második kötet tartalmából Címzésmódok - amit, és amivel címezhetünk FPU - felépítés, szerkezet - veremkezelés - működés, kivételek - adatformátumok, pontosság -
párhuzamos kezelés Optimalizáció - hogy a programjaink jobbak legyenek I/O kezelés - portkezelési lehetőségek Trace, debug - a hibák felderítése Lehetőségek - az ötödik generációs processzorok által nyújtott további lehetőségek Utasításkészlet - A Pentium processzor teljes utasításkészlete Függelékek - A P54 Pentium processzor részletesebb blokkvázlata és egyéb adatai - A PowerPC 601, 603, 604 processzorok blokkvázlatai, és egyéb adataik Products mentioned in this book are mentioned for identification purposes only. Product names appearing in this book may or may not be registered trade marks or copyrights of their respective companies. 304