Tartalomjegyzék
Tartalomjegyzék Tartalomjegyzék...............................................................................3 §2. fejezet: Processzor erőforrások.................................................21 Landmark 2.00 ............................................................................................. 21 CHECKIT 3.0 ............................................................................................. 23 MIPS 1.20: (MIPS) ............................................................................................. 26 CPUTEST 1.1 (MIPS) ............................................................................................. 29 3. Fejezet: Általános CPU programozási információk..................31 3.1. A memória felépítése ............................................................................................. 31 3.1.1. Nemszegmentált vagy "lapos" modell .................................................................................. 32 3.1.2. Szegmentált modell .................................................................................. 33 3.2. Regiszterek ............................................................................................. 34 3.2.1. Általános regiszterek .................................................................................. 34 3.2.2. Szegmensregiszterek
3
Tartalomjegyzék .................................................................................. 35 3.2.3. Utasításmutató .................................................................................. 37 3.2.4. A verem felépítése és használata .................................................................................. 37 3.2.5. Flagregiszter .................................................................................. 39 3.2.5.1. Állapotbitek ............................................................................ 39 3.2.6 Rendszer-regiszterek .................................................................................. 42 3.2.6.1. Rendszer-flagek ............................................................................ 42 3.2.6.2. Vezérlőregiszterek ............................................................................ 45 3.2.6.3. Nyomkövető regiszterek ............................................................................ 51 3.3. CPU üzemmódok ............................................................................................. 53 3.3.1. Valós üzemmód ("valós mód") .................................................................................. 53 3.3.2. Védett üzemmód .................................................................................. 53 3.3.3.Rendszermenedzselő üzemmód
4
Tartalomjegyzék .................................................................................. 53 3.4. Inicializálás és az üzemmódok közötti átkapcsolás ............................................................................................. 55 3.4.1. A processzor inicializálása .................................................................................. 55 3.4.1.1. A processzor állapota reszetelés után ............................................................................ 56 3.4.1.2. Az első végrehajtott utasítás ............................................................................ 60 3.4.1.3. A cache engedélyezése ............................................................................ 61 3.4.2. Software inicializálás valós üzemmódban .................................................................................. 62 3.4.2.1. Rendszertáblázatok ............................................................................ 62 3.4.2.2. Az NMI megszakítás ............................................................................ 63 3.4.3. Software inicializálása védett üzemmódban .................................................................................. 63 3.4.3.1. Rendszertáblázatok ............................................................................ 64 3.4.3.2. Megszakítások ............................................................................ 64 3.4.3.3. Lapozás
5
Tartalomjegyzék ............................................................................ 65 3.4.3.4. Taszkok ............................................................................ 66 3.4.3.5. A TLB, BTB és cache tesztelése ............................................................................ 68 3.4.4. Üzemmódváltás .................................................................................. 68 3.4.4.1. Átkapcsolás védett módba ............................................................................ 68 3.4.4.2. Visszakapcsolás valós üzemmódba ............................................................................ 70 3.4.5. Példa inicializálásra és üzemmód átkapcsolásra .................................................................................. 71 3.4.5.1. A példa célja ............................................................................ 71 2.4.5.2. A memória elrendezése a reset-elést követően ............................................................................ 72 3.4.5.3. Az algoritmus ............................................................................ 72 3.4.5.4. Eszközök használata ............................................................................ 75 3.4.5.5. A STARTUP.ASM listája ............................................................................ 77 3.4.5.6. A MAIN.ASM forráskódja
6
Tartalomjegyzék ............................................................................ 86 3.4.5.7. Állományok támogatása ............................................................................ 87 3.5. A valós üzemmód felépítése, működése ............................................................................................. 90 3.5.1. Címek lefordítása .................................................................................. 90 3.5.2. Regiszterek és utasítások .................................................................................. 91 2.5.3. Megszakítás és kivétel kiszolgálás .................................................................................. 92 3.5.4. Valós üzemmódú kivételek .................................................................................. 93 3.6. A Védett üzemmód felépítése, működése ............................................................................................. 97 3.6.1. Memóriaszervező regiszterek. .................................................................................. 99 3.6.2. Rendszer utasítások .................................................................................. 100 3.6.3. Védett üzemmódú memóriaszervezés .................................................................................. 102 3.6.3.1 A szegmentálási modell kiválasztása ............................................................................ 105 3.6.3.1.1. A sík modell
7
Tartalomjegyzék ...................................................................... 105 3.6.3.1.2. Védett sík modell ...................................................................... 107 3.6.3.1.3. Multiszegmens modell ...................................................................... 108 3.6.3.2. Szegmensfordítás ............................................................................ 110 3.6.3.2.1. Szegmensregiszterek ...................................................................... 112 3.6.3.2.2. Szegmensszelektorok ...................................................................... 113 3.6.3.2.3. Szegmens deszkriptorok ...................................................................... 114 3.6.3.2.4. Szegmensdeszkriptor-táblázatok ...................................................................... 121 3.6.3.2.5. Deszkriptortáblázat bázisregiszterek ...................................................................... 122 3.6.3.3. Lapfordítás ............................................................................ 123 3.6.3.3.1. Lapozási opciók ...................................................................... 124 3.6.3.3.2. Lineáris cím ...................................................................... 126 3.6.3.3.3. Laptáblázatok
8
Tartalomjegyzék ...................................................................... 126 3.6.3.3.4. Laptáblázat bejegyzések ...................................................................... 127 3.6.3.3.5. Lapkeret cím ...................................................................... 127 3.6.3.3.6. A Present (betöltött, jelenlevő) bit ...................................................................... 128 3.6.3.3.7 Hozzáfért (accessed) és "piszkos" (dirty) bitek ...................................................................... 129 3.6.3.3.8. Írás/olvasás illetve felhasználó/felügyelő bitek ...................................................................... 130 3.6.3.3.9. Lapszintű cache-vezérlő bitek ...................................................................... 130 3.6.3.3.10. Fordítási segédpufferek ...................................................................... 130 3.6.3.4. Szegmens- és lapfordítás keverése ............................................................................ 131 3.6.3.4.1. A sík modell ...................................................................... 132 3.6.3.4.2 Több lapot átfogó szegmensek ...................................................................... 133 3.6.3.4.3. Több szegmenst átfogó lapok ...................................................................... 133
9
Tartalomjegyzék 3.6.3.4.4. Nem illeszkedő lap- és szegmenshatárok ...................................................................... 133 3.6.3.4.5. Illeszkedő lap- és szegmenshatárok ...................................................................... 133 3.6.3.4.6. Egy laptáblázat elhelyezése szegmensenként ...................................................................... 134 3.7. Védelemi mechanizmusok ............................................................................................. 135 3.7.1. Szegmens szintű védelem .................................................................................. 135 3.7.2. A szegmens deszkriptorok és a védelem .................................................................................. 136 3.7.2.1. Típusellenőrzés ............................................................................ 137 3.7.2.2. Határ (limit) ellenőrzés ............................................................................ 140 3.7.3. Privilégium szintek .................................................................................. 142 3.7.4. Az adathozzáférések korlátozása .................................................................................. 144 3.7.4.1. Kódszegmensekbeli adatok elérése ............................................................................ 146 3.7.5. Vezérlésátadások korlátozása .................................................................................. 146
10
Tartalomjegyzék 3.7.6. Kapudeszkriptorok .................................................................................. 149 3.7.6.1. Veremváltás ............................................................................ 152 3.7.6.2. Visszatérés egy procedúrából ............................................................................ 155 3.7.7. Az operációs rendszer számára lefoglalt utasítások .................................................................................. 158 3.7.7.1. Privilegizált utasítások ............................................................................ 159 3.7.7.2. Érzékeny utasítások ............................................................................ 160 3.7.8. Mutatók érvényességét ellenőrző utasítások .................................................................................. 160 3.7.8.1. Deszkriptor érvényességének ellenőrzése ............................................................................ 164 3.7.8.2. Mutatók integritása és az RPL ............................................................................ 166 3.7.9. Lapszinti védelem .................................................................................. 167 3.7.9.1. A laptáblázat bemenetek által tartalmazott védelmi paraméterek ............................................................................ 168 3.7.9.1.1. A megcímezhető tartományt érintő megszorítások
11
Tartalomjegyzék ...................................................................... 168 3.7.9.1.2. Típusellenőrzés ...................................................................... 170 3.7.9.1.3. A védelem kombinálása a laptáblázatok mindkét szintjén ...................................................................... 171 3.7.9.1.4. A lapvédelem fölülírói ...................................................................... 171 3.7.9.2. Lap- és szegmensvédelem kombinálása ............................................................................ 173 3.8. Védett üzemmódú multitaszking ............................................................................................. 175 3.8.1. Taszk-állapot-szegmens .................................................................................. 176 3.8.2. A TSS deszkriptor .................................................................................. 178 3.8.3. Taszkregiszter .................................................................................. 179 3.8.4. Taszk kapudeszkriptorok .................................................................................. 181 3.8.5. Taszkkapcsolás .................................................................................. 182 3.8.6. Taszkok visszafelé kapcsolása (LINKING) .................................................................................. 187 3.8.6.1. A Busy (foglalt) bit megelőzi a hurkok
12
Tartalomjegyzék kialakulását ............................................................................ 189 3.8.6.2. A taszk visszakapcsolások módosítása ............................................................................ 190 3.8.7. Taszkok címtartománya .................................................................................. 191 3.8.7.1. Taszkok által lineárisról- fizikai címre végzett leképzés ............................................................................ 191 3.8.7.2. A taszkok logikai címtartománya ............................................................................ 192 3.9. Védett üzemmódú kivételek és megszakítások ............................................................................................. 194 3.9.1. Kivétel- és megszakításvektorok .................................................................................. 195 3.9.2. Utasítások újraindítása .................................................................................. 199 3.9.3. Megszakítások engedélyezése és letiltása .................................................................................. 199 3.9.3.1. További NMI megszakítások maszkolása ............................................................................ 200 3.9.3.2. INTR megszakítások maszkolása ............................................................................ 200 3.9.3.3. Debug hibák maszkolása az RF bit segítségével ............................................................................ 201
13
Tartalomjegyzék 3.9.3.4. Egyes kivételek és megszakítások maszkolása ............................................................................ 202 3.9.4. Szimultán kivételek és megszakítások közötti prioritás .................................................................................. 203 3.9.5. A megszakításdeszkriptor-táblázat .................................................................................. 205 3.9.6. IDT deszkriptorok .................................................................................. 206 3.9.7. Megszakítás taszkok és megszakítás-kezelő procedurák .................................................................................. 207 3.9.7.1. Megszakítás-kezelő procedúrák ............................................................................ 207 3.9.7.1.1. A megszakítás-kezelő eljárás verme ...................................................................... 208 3.9.7.1.2. Visszatérés egy megszakítás-kezelő eljárásból ...................................................................... 208 3.9.7.1.3. A megszakítás-kezelő eljárás flaghasználata ...................................................................... 209 3.9.7.1.4. Védelem a megszakítás-kezelő eljárásokban ...................................................................... 209 3.9.7.2. Megszakítás-kezelő taszkok
14
Tartalomjegyzék ............................................................................ 210 3.9.8. Hibakódok .................................................................................. 211 3.9.9. Kivétel feltételek .................................................................................. 212 3.9.9.1. 0-s számú megszakítás - Osztáshiba (Divide Error) ............................................................................ 213 3.9.9.2. 1-es számú megszakítás - Debug kivétel ............................................................................ 213 3.9.9.3. 3-as számú megszakítás - Töréspont (Breakpoint) ............................................................................ 214 3.9.9.4. 4-es számú megszakítás - Túlcsordulás (Overflow) ............................................................................ 214 3.9.9.5. 5-ös számú megszakítás - Határsértés (Bounds Check) ............................................................................ 215 3.9.9.6. 6-os számú megszakítás - Érvénytelen utasítás (Invalid Opcode) ............................................................................ 215 3.9.9.7. 7-es számú megszakítás - nem elérhető eszköz (Device Not Available) ............................................................................ 216 3.9.9.8. 8-as számú megszakítás - Kettős hiba, dupla hiba (Double Fault)
15
Tartalomjegyzék ............................................................................ 216 3.9.9.9. 9-es számú megszakítás - (az Intel által fenntartott, használata nem ajánlott) ............................................................................ 220 3.9.9.10. 10-es számú megszakítás - Érvénytelen TSS (Invalid TSS) ............................................................................ 220 3.9.9.11. 11-es számú megszakítás - Szegmens nincs jelen, (Segment Not Present) ............................................................................ 222 3.9.9.12. 12-es számú megszakítás - verem kivétel (Stack Exception) ............................................................................ 224 3.9.9.13. 13-as számú megszakítás - Általános védelmi hiba (General Protection) ............................................................................ 225 3.9.9.14. 14-es számú megszakítás - Laphiba (Page Fault) ............................................................................ 227 3.9.9.14.1. Taszkkapcsolás alatti laphiba ...................................................................... 229 3.9.9.14.2. Laphiba összeférhetetlen veremmutatóval ...................................................................... 229 3.9.9.15. 16-os számú megszakítás - Lebegőpontos egység hiba, Floating-Point Error) ............................................................................ 230 3.9.9.15.1. Numerikus kivételek kezelése
16
Tartalomjegyzék ...................................................................... 232 3.9.9.15.2. Szimultán kivételekre adott válaszok ...................................................................... 234 3.9.9.16. 17-es számú megszakítás - Illeszkedés ellenőrzés ellenőrzési hiba (Alignment Check) ............................................................................ 235 3.9.9.17. 18-as számú megszakítás - Processzortípus ellenőrzés (Machine Check) ............................................................................ 238 3.9.10. A kivételek összefoglalása .................................................................................. 238 3.9.11. Hibakódok összefoglalása .................................................................................. 240 3.10. Rendszermenedzselő üzemmód ............................................................................................. 242 3.10.1. Az SMI megszakítás .................................................................................. 244 3.10.2. Az SMM kezdeti állapota .................................................................................. 245 3.10.2.1. Az SMM végrehajtása ............................................................................ 246 3.10.3. Az SMRAM processzor-állapot tároló formátuma .................................................................................. 248 248 3.10.3.1. Az SMM revízió-azonosító (FEFCH ofszet)
17
Tartalomjegyzék ............................................................................ 252 3.10.3.2. I/O trap-újraindítás (FF00H ofszet) ............................................................................ 253 3.10.3.3. Felfüggesztett állapotból való automatikus újraindítás (FF02H ofszet) ............................................................................ 254 3.10.3.4. Az állapottároló bázisa (FEF8H ofszet) ............................................................................ 254 3.10.4. Az SMRAM relokációja .................................................................................. 255 3.10.5. Visszatérés az SMM-ből .................................................................................. 257 3.11. 8086-os virtuális üzemmód ............................................................................................. 258 3.11.1. 8086 CPU kód végrehajtása .................................................................................. 259 3.11.1.1. Regiszterek és utasítások ............................................................................ 259 3.11.2.1. Lapozás a 8086-os virtuális taszkok esetében ............................................................................ 260 3.11.2.2. Védelem egy 8086-os virtuális taszkon belül ............................................................................ 261 3.11.3. Belépés a 8086-os virtuális üzemmódba és az abból való kilépés .................................................................................. 262
18
Tartalomjegyzék 3.11.3.1. Taszkátkapcsolások általi tranzíciók ............................................................................ 264 3.11.3.2. Átmenet trap- és megszakításkapukon keresztül ............................................................................ 264 3.11.4. Érzékeny utasítások .................................................................................. 267 3.11.5. Virtuális megszakítások támogatása .................................................................................. 268 3.11.6. A 8086 operációs rendszerhívások emulációja .................................................................................. 268 3.11.7. Virtuális I/O .................................................................................. 270 3.11.7.1. I/O-ra leképezett I/O ............................................................................ 270 3.11.7.2. Memóriába leképezett I/O ............................................................................ 271 3.11.7.3. Különleges I/O pufferek ............................................................................ 272 3.11.8. Különbségek a 8086 CPU-hoz képest .................................................................................. 272 3.11.9. Különbségek a 286 CPU-hoz képest .................................................................................. 277 3.11.9.1. Privilégiumszint ............................................................................ 277
19
Tartalomjegyzék 3.11.9.2. A busz lezárása ............................................................................ 278 3.11.10. Különbségek a 386 és 486 CPU-hoz képest .................................................................................. 279 Ábra- és példajegyzék.......................................................................280 Előzetes a második kötet tartalmából..............................................301 §
§ µ§
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.
20
Landmark 2.0
§2. fejezet: Processzor erőforrások tektúrájúösszevetettük céljából processzorát.néhány gyártó 32, vagy 64 bites X86-os archiettől eltérő eseteket külön közöljük. A belső cache -méret különböző processzoroknál az eredmények kiértékelése különböző lehet, során akitérünk. különbségekre típusjelzés szerintTIvalamilyen fixen beforrasztott processzor állta akByte sarat akülső tesztek nyúzópróbái cache-sel, ésalaplapba során. esetleg FPU nélkül következménye, hogy a mérések. különböző Az méretű SLC33-as külső processzort cache-t tartalmazott. tartalmazó Az alaplap SLC2-50-es 64történtek kByte, alaplap azmeg SLC2-66 nem rendelkezett 12815ns-os külső cache-foglalattal. használtunk fel. AzEnnek ezektől eltérő esetekben 256 kByte cache-t tartalmazzák afoglalattal. lebegőpontos A -táblázatokban afogadó "+FPU" jelzés külső jelöltük koprocesszort koprocesszor jelent. jelenlétét, Haegységet. azépült aNx 486SX mérési eredmények 486SLC típusoknál lebegőpontos nem egység NxVL rendszervezérlő nélkül értékelendőek. chip-pel Az 586-os fel, és processzort nem rendelkezett alaplap koprocesszor aktuális típusjelzés "követtük el"tuningolt" őket". Ezek alatt, csak jobb azösszehasonlíthatóság előírtnál magasabb órajellel érdekében meghajtott Am486DX4-120 valójában defizikailag kifogástalanul egya AmDX4-100, működő 120MHz-es példányok, órajel pl.: az frekvenciával.
Landmark 2.00 Processor Típus:
CPU (MHz)
FPU (MHz)
PENTIUM 90
519,47
1743,79
PENTIUM 66
385,85
1299,15
PENTIUM 60
346,74
1169,92
NEXGEN Nx586 P90
527.15
--
Am 486DX4-120 *
401,59
1059,28
INTEL 486DX4-100
359,53
882,57
Am 486DX4-100
334,15
856,64
Processzor erőforrások
Am 486DX2-100 *
334,62
882,79
INTEL 486DX2-80 *
267,70
706,05
Am 486DX2-80
267,70
704,11
Cyrix 486DX2-V80
264,45
770,57
INTEL 486DX2-66
222,96
587,49
Am 486DX2-66
222,91
588,02
Cyrix 486DX2-V66
219,94
640,87
TI 486SLC2-66+FPU
152,76
162,07
INTEL 486SX2-50
167,30
14,10
TI 486SLC2-50+FPU
115,15
116,70
Am 486DX-40
133,84
353,06
TI 486SXLC-40
129,81
10,66
Landmark 2.0
TI 486SLC-40
129,90
6,45
INTEL 486DX-33
110,37
291,15
TI 486SLC-33
107,98
7,42
INTEL 486SX-25
83,67
7,04
Am 386 DX-40
62,40
--
Am 386SX-40
52,19
--
µ§ µ§
CHECKIT 3.0 Processor Type:
Dhrystones
Whetstones
PENTIUM 90
70577
25940900
PENTIUM 66
52749
21665700
Processzor erőforrások PENTIUM 60
47474
19360100
NEXGEN Nx586 P90
59343
1015400
Am 486DX4-120 *
55852
20808800
INTEL 486DX4-100
43158
14893800
Am 486DX4-100
39211
12872800
Am 486DX2-100 *
47474
17337700
INTEL 486DX2-80 *
39211
13109500
Am 486DX2-80
39211
13109500
Cyrix 486DX2-V80
39211
13876500
INTEL 486DX2-66
33609
11419900
Am 486DX2-66
33609
11419900
Cyrix 486DX2-V66
33609
11561800
Landmark 2.0 TI 486SLC2-66+FPU
29759
3705600
INTEL 486SX2-50
24348
461000
TI 486SLC2-50+FPU
21427
2605100
Am 486DX-40
19303
6880100
TI 486SXLC-40
16999
334800
TI 486SLC-40
9749
201600
INTEL 486DX-33
15785
5703700
TI 486SLC-33
11236
224000
INTEL 486SX-25
12054
226600
Am 386 DX-40
11631
312200
Am 386SX-40
7206
114600
µ§
Processzor erőforrások MIPS 1.20: (MIPS)
Landmark 2.0 Processzor Típus:
Gener Intege Mem. al Inst. r Inst. -mem.
Reg. -reg.
Reg. átlagos -mem. : (MIPS )
PENTIUM 90
13,34
23,48
17,19
29,59
28,21
22,36
PENTIUM 66
9,84
17,39
13,10
21,91
21,44
16,73
PENTIUM 60
8,88
15,66
11,79
19,74
19,30
15,07
NEXGEN Nx586 P90
7,73
27,54
4,44
31,52
13,86
16,94
Am 486DX4-120 *
11,96
27,99
16,05
34,24
25,55
23,16
INTEL 486DX4-100
10,04
27,17
13,36
34,40
21,27
21,25
Am 486DX4-100
9,9
23,30
13,21
28.50
21,18
19,22
Am 486DX2-100 *
10,01
23,32
13,37
28,53
21,33
19,31
INTEL 486DX2-80 *
8,05
18,66
10,70
22,82
17,06
15,46
Am 486DX2-80
7,97
18,66
10,70
22,82
17,06
15,44
Processzor erőforrások Cyrix 486DX2-V80
9,70
22,90
14,09
29,62
19,80
19,23
INTEL 486DX2-66
6,66
15,54
8,91
19,01
14,21
12,86
Am 486DX2-66
6,68
15,53
8,91
19,00
14,20
12,86
Cyrix 486DX2-V66
8,08
19,05
11,72
24,64
16,47
15,99
TI 486SLC2-66+FPU
7,29
13,59
10,73
15,31
14,81
12,34
INTEL 486SX2-50
5,00
11,66
6,68
14,26
10,68
9,66
TI 486SLC2-50+FPU
5,66
10,24
8,01
11,54
11,08
9,31
Am 486DX-40
4,03
9,32
5,35
11,41
8,55
7,73
TI 486SXLC-40
4,77
11,13
6,95
14,13
9,36
9,33
TI 486SLC-40
4,77
11,13
6,70
14,42
9,36
9,28
INTEL 486DX-33
3,31
7,69
4,41
9,41
7,05
6,37
TI 486SLC-33
3,96
9,27
5,69
12,01
7,77
7,74
Landmark 2.0 INTEL 486SX-25
2,51
5,83
3,34
7,13
5,33
4,83
Am 386 DX-40
3,14
6,08
4,00
8,86
5,65
5,71
Am 386SX-40
2,60
5,82
3,61
8,42
4,76
5,04
µ§
CPUTEST 1.1 (MIPS) 486-os architektúrák mennyiben hasonlítanak, vagy el egymástól, elég matematikai aamérési műveletek -koprocesszorral vizsgálódnunk. és Az anélkül ugrások sebességi (JMP/CALL), különbözik különbségéből az INTEL kitűnik, és hogy az AMD améretétől. Cyrix által processzorok használt struktúráktól. felépítése lényegesen Egy gyorsabb CPU-t takar koprocesszort, tokozás. Az és INTEL kicsivel ésapedig gyorsabb, az AMD az DX2-66 INTEL-től -os processzora esetében processzor belülről kitűnik, teljesen hogy megegyezik! az INTEL Mindegyik alaptalanul tesztprogram perlekedett: aAz a az két teljesen ez azonos Ebben eredményeket aaközött mutatott. Cyrix DX2-80 viszi aés pálmát. -asok esetében A szintén tesztprogramok áruló Texas SCL40 mérő-algoritmus -kategóriában SXLC40 párosa, hosszait ugyanis is érdemes különbség megfigyelni. akülönböző két típus között SXLC40-ben µ §a helyzet. csak aisaA belső-cache 8adatok kByte. A mért méretében adatokból van. kiderült, Az SLC40-ben Landmark 1függ kByte CPU (!), sebesség belsőcache mérése mérettől, nem, egyébként FPU mérése azonos teljesítményű nagymértékben processzorok a esetében esetén. szeretnénk!) (Sokszor Dhrystone-ok sajnos nem csak Whetstone-ok azt a nem paramétert esetében mérjük az eredmény amelyiket nagymértékben azonban aaz helyzet függ sokkal cache jobb. A MIPS a-térnek CPUTEST Pentiumok, és az Nx586 isnincsenek. meglehetősen alacsony értékeket mérünk. belsőcache-ek Csodák feltöltésével, ebben a-aesetében műfajban és -ugrás azegyszer utasítás előrejelzéssel A processzorok foglalják a külső, el és magukat, CALL utasítás pipeline-ok esetében pedig helyzet az még után rosszabb: lehetnek az előbbiekben tele utasítással. (A ismertetett utasítás eredményeként procedúrák kétszer hajtódnak végre.) a nem CALL, /lásd: és CPUTEST egyszer a1.1 RET JMP-CALL utasítások vérehajtásáról készült táblázat/ műveleteinek Pentiuméval: aegy sebességét kizárólag vetjük regiszterek között az végrehajtott súlycsoportba műveletekben tartozó mindig fejezetben aztúl Nx586 már tárgyalt vezetett. -(pl.: 32 Ennek regiszter, magyarázata és aazonos regiszter -12ns-os az Nx586-ról átnevezési szóló technológia. szerepelt fényesen, Sajnos az(A ezt Nx586 az alaplapra a össze memória integrált műveletek méréseinél CACHE-RAM nem -oknak es processzorához.) tulajdonítjuk. A másik Nexgen összetevő, 10ns-os hogy cache-RAM PCI-buszra -okat épülő a P90rendszervezérlő processzorral chippel nyúlfarknyival NxPCI nagyobb rendszer sebesség vezérlő) érhető ugyanazon el.ír elő (90MHz-nél kb.: 2,5-3%) processzorok INTEGER műveleti a Pentiumokhoz sebessége. viszonyított Most nézzük meglehetősen milyen különbségek magas vannak az generációs utasítások processzorban. végrehajtásának Kiemeltünk ütemezésében néhány néhány matematikai konkurens utasítást ötödik teljesség végrehajtáshoz igénye szükséges nélkül. A órajel táblázat ciklusok az utasítások utasítás számával végrehajtásának meg. Aidejét aa matematikai pontosságú alakok processzorra használatát vonatkozó feltételezik. (FP)adja a kétszeres UTASÍTÁS késés: FP ADD 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 2 2 2 2 40 40 8 39
Pentium 3 1 3 2 39 39 10 41
IBM 601 4 1 4 2 31 29 9 36
UNIX rendszer alattAlpha) mért INTEGER, és Floating teljesítményeit. mások (pl.: PowerPC, Egyesek R4400, RISC processzorként software-ből hardware-sen emulálvaPoint (pl.: valósítják Nx586), meg azoperációs x86-os architektúrát.
UNIX SPECint SPECfp tesztek
típus 60 Pentium Pentium 66 Pentium 75 Pentium 90 Pentium 100 SPARC+ PowerPC601 PowerPC603 PowerPC604 HP7100 Alpha21064 MIPS R4400SC Cyrix M1 Gyártók: µ §
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 -NEXGEN -DEC µ§
Belső-cache 16méret kByte 16 kByte 16 kByte 16 kByte 16 kByte 36 kByte 32 kByte 16 kByte 32 kByte -16 kByte 16 kByte 16 kByte
A memória felépítése
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
Általános CPU programozási információk 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. 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.1.1. 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
A memória felépítése 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 nemlétező címet (melyhez nem tartozik memória) jelöl, akkor egy kivétel keletkezik (kivételeket lásd később).
3.1.2. 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
Általános CPU programozási információk 3.2. Regiszterek A processzornak tizenhat, a programozók által használható regisztere van. Amint azt a 3.2. á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.2.1. Á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 3.2. á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,
A memória felépítése CH és DH (felső Byte-ok) illetve AL, BL, CL és DL (alsó Byte-ok). µ§
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ó 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.2.2. 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
Általános CPU programozási információk 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 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. µ§ 3.3. ábra: Szegmentált memória 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
A memória felépítése 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 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 szegmensregiszter használandó akkor, amikor csak egy ofszet van megadva, egyszerű szabályok határozzák meg.
3.2.3. 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.2.4. 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
Általános CPU programozási információk 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 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
A memória felépítése LEAVE, a változókhoz való könnyebb hozzáférés érdekében az EBP regisztert automatikusan beállítják.
3.2.5. 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 3.5. á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. µ§
3.4. ábra: A verem működése
3.2.5.1. Á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. µ§
Általános CPU programozási információk
3.5. ábra: Az EFLAGS regiszter
Regiszterek
Név
Szándék
Kialakulási feltétel
OF
Túlcsordulás
Az eredmény meghaladta a pozitív vagy negatív határt
SF
Előjel
Az eredmény negatív
ZF
Zero
Az eredmény nulla
AF
Félátvitel
Átvitel történt a 3. biten (BCD-nél használatos)
PF
Paritás
Az eredmény alsó Byte-jában páros számú 1 bitek vannak
CF
Átvitel
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.
Regiszterek 3.2.6 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 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.2.6.1. 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 3.5. á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
Regiszterek 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. 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.
Regiszterek 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 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.
Regiszterek
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 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.2.6.2. 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
Regiszterek 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.
Regiszterek µ§
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 á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)
Regiszterek 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).
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
Regiszterek 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 ténylegesen felhasználásra nem kerül. A CLTS utasítás 0ra á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
Regiszterek 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.
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
Regiszterek 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.2.6.3. Nyomkövető 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 3.8. ábra illusztrálja. µ§
Regiszterek 3.8. ábra: Nyomkövető regiszterek
CPU üzemmódok 3.3. CPU üzemmódok
3.3.1. 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.3.2. 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.3.3.Rendszermenedzselő üzemmód A Pentium mikroprocesszor a rendszermenedzselő üzemmmódot (SMM - System Management Mode) is támogatja. Minden új
CPU üzemmódok 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#) 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.
Inicializálás és az üzemmódok közötti átkapcsolás 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.4.1. 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.
Inicializálás és az üzemmódok közötti átkapcsolás
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 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.4.1.1. 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. µ§
Inicializálás és az üzemmódok közötti átkapcsolás 3.9. ábra: Az EDX regiszter tartalma reszetelés után
µ§
3.10. ábra: A CR0 regiszter tartalma reszetelés után
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
RESET - BIST nélkül
INIT
EFLAG
00000002h
00000002h
EIP
0000FFF0h
0000FFF0h
CR0
60000010h
A CD és NW biteket nem cseréli, a 4. bitet 1-be állítja, az összes többit törli.
CR2, CR3, CR4
00000000h
00000000h
CS
szelektor=0F000h bázis=0FFF0000h határ=0FFFFh elérési jogok vannak, írható, olvasható, hozzáférhrtő
szelektor=0F000h bázis=0FFF0000h határ=0FFFFh elérési jogok vannak, írható, olvasható, hozzáférhető
SS, DS, ES, FS, GS
szelektor=0000h bázis=0000h határ=0FFFFh
szelektor=0000h bázis=0000h határ=0FFFFh
Inicializálás és az üzemmódok közötti átkapcsolás elérési jogok vannak, írható, olvasható, hozzáférhető
elérési jogok vannak, írható, olvasható, hozzáférhető
EDX
000005xxh
000005xxh
EAX
hibátlan önteszt esetén nulla
0
EBX, ECX, ESI, EDI, EBP, ESP
00000000h
00000000h
LDTR
szelektor=0000h bázis=00000000h határ=0FFFFh elérési jogok vannak, írható, olvasható
szelektor=0000h bázis=00000000h határ=0FFFFh elérési jogok vannak, írható, olvasható
GDTR, IDTR
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ó
DR0, DR1, DR2, DR3
00000000h
DR6
FFFF0FF0h
FFFF0FF0h
DR7
00000400h
00000400h
Inicializálás és az üzemmódok közötti átkapcsolás Time Stamp számláló
0
Nem cseréli
Vezérlő és esemény kiválasztó
0
Nem cseréli
TR12
0
Nem cseréli
Minden más modell specifikus regiszter
Nem definiált
Nem cseréli
Adat és kód Cache, TLB-k
Érvénytelen
Érvénytelen
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.4.1.2. 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 beolvasásához a CS regiszter bázis része hozzáadódik az EIP tartalmához
Inicializálás és az üzemmódok közötti átkapcsolás é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.4.1.3. 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
Inicializálás és az üzemmódok közötti átkapcsolás felhasználásával, egy későbbi tartalmazza. 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.4.2. 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.4.2.1. 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.
Inicializálás és az üzemmódok közötti átkapcsolás 3.4.2.2. 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 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.4.3. 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.
Inicializálás és az üzemmódok közötti átkapcsolás 3.4.3.1. 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 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.4.3.2. 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
Inicializálás és az üzemmódok közötti átkapcsolás 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.4.3.3. 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. 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
Inicializálás és az üzemmódok közötti átkapcsolás 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 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.4.3.4. 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
Inicializálás és az üzemmódok közötti átkapcsolás 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.
Inicializálás és az üzemmódok közötti átkapcsolás 3.4.3.5. 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.4.4. Ü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.4.4.1. Á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.
Inicializálás és az üzemmódok közötti átkapcsolás
Inicializálás és az üzemmódok közötti átkapcsolás 3.4.4.2. 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.
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
Inicializálás és az üzemmódok közötti átkapcsolás segítségével tilthatók le. 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.4.5. 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.4.5.1. 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.
Inicializálás és az üzemmódok közötti átkapcsolás 2.4.5.2. 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 3.12. ábra a memória elrendezését mutatja a processzor reszetelését követően és e példa kezdeti pontján. µ§
3.12. ábra: A processzor állapota a reszetet követően
3.4.5.3. Az algoritmus A példa főbb lépéseit a 3.13. ábra mutatja, a STARTUP.ASM forrásszöveg sorainak számozásával együtt. ASM sorok 157
Meghatározás 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
171-172
A GDT pointerét a GDTR regiszterbe tőlti.
174-177
A CR0 regiszter védet üzemmód bitjének beállítása.
Inicializálás és az üzemmódok közötti átkapcsolás 179-181
Közeli ugrás a valód módot törlő sorra.
184-186
DS és ES regiszterek feltöltése a GDT[1] deszkriptorral, most mindkettő a teljes fizikai memória területre mutat.
188-195
Végrehajt egy specifikus tábla inicializálást amire az új védett mód miatt van szükség.
196-218
Az alkalmazás GDT-jét a ROM-ból a RAM-ba másolja
220-238
Az alkalmazás IDT-jét a ROM-ból a RAM-ba másolja
241-243
Az alkalmazás GDTR regiszterének feltöltése
244-245
Az alkalmazás IDTR regiszterének feltöltése
247-261
Az alkalmazás TSS-ét a ROM-ból a RAM-ba másolja
263-267
A TSS deszkriptor felfrissítése.
277
TR regiszter feltöltése (taszkválltás nélkül)
282-286
SS és ESP feltöltése az alkalmazásban talált TSS értékekkel.
287
Az alkalmazás TSS-ében talált EFLAG elmentése
288
Az alkalmazás TSS-ében talált CS elmentése
Inicializálás és az üzemmódok közötti átkapcsolás
289 290-293 296
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). 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.
Inicializálás és az üzemmódok közötti átkapcsolás
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.4.5.4. 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 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
ASM386 és Startup.A58
BLD386 vezérlő és BLD file
Hatás
Inicializálás és az üzemmódok közötti átkapcsolás
Bootstrap
public startup startup:
bootstrap start(startup)
Közeli ugrás a 0FFFFFFF0h-nál a startra
GDT elhelyezkedés
public GDT_EPROM GDT_EPROM TABLE_REG <>
TABLE GDT(location = GDT_EPROM )
A GDT elhelyezkedése a DGT_EPROM pozícióra lesz programozva.
IDT elhelyezkedés
public TABLE IDT_EPROM IDT(location= IDT_EPROM IDT_EPROM) TABLE_REG <>
Az IDT elhelyezkedése az IDT_EPROM pozícióra lesz programozva.
RAM kezdet
RAM_START equ 400h
A RAM_START a 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.
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ó
memory(reser v= 0...3FFFh)
SEGMENT
Az alkalmazás TSS deszkriptorát a GDT 10. pontjára teszi. Az inicializált
Inicializálás és az üzemmódok közötti átkapcsolás elhelyezkedés
kód mérete és elhelyezhedése.
startup.code (base=0FFFF0 000h) memory (RANGE( RO M_AREA= ROM(x..y))
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.4.5.5. A STARTUP.ASM 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 startup.a58 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
Inicializálás és az üzemmódok közötti átkapcsolás 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
; használhatja azt átmeneti területek létrehozásánál. ; ;2. A rendszernek van elegendő szabadon ; szabadon használható RAM-ja amibe bemásolható ; a GDT, IDT, TSS kezdeti értékei ; ; ;Konfigurációs adat, meg kell hogy egyezzen a build nyelv ;file-al. CS_BASE EQU 0FFFF0000h ; ;A CS_BASE a STARTUP_CODE lineáris címe, ami a build ;nyelv file-ban van megadva. ; RAM_START EQU 400h ; ;A RAM_START a szabadon használható RAM kezdete a ;lineáris memória területen. A GDT, IDT és a kezdeti TSS ;ezen hely fölé másolódnak és egy kis adatszegmenst is ;kihagy ezen a lineáris címen. A RAM_START-nál lévő 32 ;bites szó tartalmazza a lemásolt táblázatok fölötti első ;szabad Byte lineáris címét. Ez akkor hasznos, ha memória ;managert használunk. ; TSS_INDEX EQU 10 ; ;A TSS index az indítás után elsőként futó taszk TSS-ének ;indexe. ; ; ; ; ; ;Szerkezet a rendszer adat számára ; ;TSS szerkezet TASK_STATE STRUC
Inicializálás és az üzemmódok közötti átkapcsolás 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 79 80 81
link link_h ESP0 SS0 SS0_h ESP1 SS1 SS1_h ESP2 SS2 SS2_h CR3_reg EIP_reg EFLAGS_REG EAX_reg ECX_reg EDX_reg EBX_reg ESP_reg EBP_reg ESI_reg EDI_reg ES_reg ES_h CS_reg CS_h SS_reg SS_h DS_reg DS_h FS_reg FS_h GS_reg GS_h LDT_reg LDT_h TRAP_reg
DW DW DD DW DW DD DW DW DD DW DW DD DD
? ? ? ? ? ? ? ? ? ? ? ? ? DD
DD DD DD DD DD DD DD DD DW DW DW DW DW DW
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
DW DW DW DW
? ? ? ?
DW DW DW DW DW
? ? ? ? ?
Inicializálás és az üzemmódok közötti átkapcsolás 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
IO_map_base DW ? TASK_STATE ENDS ; ;A deszkriptor elemi szerkezete DESC STRUC lim_0_15 DW ? bas_0_15 DW ? bas_16_23 DW ? acces DB ? gran DB ? bas_24_31 DB ? DESC ENDS ; ;Szerkezet az LGDT és LIDT utasítások részére ;TABLE_REG STRUC table_lim DW ? tabla_linear DD ? TABLE_REG ENDS ;A GDT és IDT deszkriptorok ofszetje a builder által generált 101 ;GDT-ben. ;GDT_DESC_OFF EQU 1*SIZE (DESC) ;IDT_DESC_OFF EQU 2*SIZE (DESC) ; ;Értékadások az átmeneti GTD felépítéséhez. LINEAR_SEL EQU 2*SIZE (DESC) LINEAR_PROTO_LO EQU 00000FFFFh LINEAR_PROTO_HI EQU 000CF9200h ; ;Védett mód engedélyező bit a CR0-ban PE_BIT EQU 1 ; ;------------------------------------------------------------------; ;----------------------ADAT SZEGMENS----------------------; ;Kezdetben ez az adatszegmens a lineáris 0 címen ;kezdődik a CPU bekapcsolási állapota miatt.
Inicializálás és az üzemmódok közötti átkapcsolás 119 120 121 122
; STARTUP_DATA SEGMENT RW ; 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 ; 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
Inicializálás és az üzemmódok közötti átkapcsolás 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: 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 ;
Inicializálás és az üzemmódok közötti átkapcsolás 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
;Elvégzi a tábla specifikus beállításokat. ; ; ; ...... ; ; ; ;Lásd a 3.16 ábrát. ;Az EPROM GDT-t a RAM-ba másolja a ;RAM_START+size(STARTUP_DATA) címre. MOV EAX,RAM_START ADD EAX,OFFSET (end_data) MOV EBX,RAM_START MOV ECX,CS_BASE ADD ECX,OFFSET (GDT_EPROM) MOV SI,[ECX].table_linear MOV EDI,EAX MOVZX ECX,[ECX].table_lim MOV APP_GDT_RAM[EBX].table_lim,CX INC EXC MOV EDX,EAX MOV APP_GDT_ram[EBX].table_linear,EAX ADD EAX,ECX REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] ; ;A GDT bázicímének rögzítése a deszkriptorban. MOV ECX,EDX MOV [EDX[.bas_0_15+GDT_DESC_OFF,CX ROR ECX,16 MOV [EDX[.bas_16_23+GDT_DESC_OFF,CL MOV [EDX[.bas_24_31+GDT_DESC_OFF,CH ; ;Az EPROM IDT RAM-ba másolása a ;RAM_START+size(STARTUP_DATA)+SIZE címre. MOV ECX,CS_BASE ADD ECX,OFFSET (IDT_EPROM) MOV SI,[ECX].table_linear
Inicializálás és az üzemmódok közötti átkapcsolás 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
MOV EDI,EAX MOVZX ECX,[ECX].table_lim MOV APP_IDT_RAM[EBX].table_lim,CX INC EXC MOV APP_IDT_ram[EBX].table_linear,EAX MOV EBX,EAX ADD EAX,EXC REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] ; ;Az IDT mutató rögzítése a GDT-ben. MOV [EDX[.bas_0_15+IDT_DESC_OFF,BX ROR EBX,16 MOV [EDX[.bas_16_23+IDT_DESC_OFF,BL MOV [EDX[.bas_24_31+IDT_DESC_OFF,BH ; ;GDTR és IDTR regiszterek feltöltése MOV EBX,RAM_START DB 66h LGDT APP_GDT_ram[EBX] DB 66h LIDT APP_IDT_ram[EBX] ; ;A TSS mozgatása MOV EDI,EAX MOV EBX,TSS_INDEX*SIZE(DESC) MOV ECX,GDT_DESC_OFF MOV GS,CX MOV DH,GS:[EBX].bas_24_31 MOV DL,GS:[EBX].bas_16_23 ROL EDX,16 MOV DX,GS:[EBX].bas_0_15 MOV ESI,EDX LSL ECX,EBX INC ECX MOV EDX,EAX ADD EAX,ECX REP MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]
Inicializálás és az üzemmódok közötti átkapcsolás 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 294 ; 295 ;Egy távoli ugrás szimulálása a taszk inicializálásához. 296 IRETD
Inicializálás és az üzemmódok közötti átkapcsolás 297 298 299 300
; STARTUP_CODE ENDS ; END STARTUP, DS:STARTUP_DATA, SS:STARTUP_DATA
3.4.5.6. A MAIN.ASM 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
Inicializálás és az üzemmódok közötti átkapcsolás µ§
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) µ§
3.16. ábra: A GDT, IDT és TSS ROM-ból RAM-ba másolása (a forrásszöveg 196-261 sorai) µ§
3.17. ábra: Átkapcsolás a taszkra (a forrásszöveg 282 296 sorai)
3.4.5.7. Állományok támogatása A STARTUP.ASM és MAIN.ASM 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. ASM386 ASM386 BLD386 bootstrap
STARTUP.ASM MAIN.ASM STARTUP.OBJ, MAIN.OBJ buildfile (EPROM.BLD) (STARTUP) Bootload
Inicializálás és az üzemmódok közötti átkapcsolás 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
(OBJECT=startup,
INITIAL,
DPL=0, NOT INTENABLED) , ; TABLE
PROTECTED_MODE_TASK (OBJECT=main_module, DPL=0, NOT INTENABLED)
Inicializálás és az üzemmódok közötti átkapcsolás 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
A valós üzemmód felépítése, működése 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.5.1. 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
A valós üzemmód felépítése, működése 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. µ§
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.5.2. 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. É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ó
A valós üzemmód felépítése, működése 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.5.3. 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. Á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
A valós üzemmód felépítése, működése ü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.5.4. 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 3.19. ábra a valós üzemmódú kizárásokat részletezi. Meghatározás
Vektor
A kivétel forrása
Hibamutató pointer visszatérés után
Osztási hiba
0
DIV és IDIV utasítások
van
Nyomkövetés
1
Akármi
NMI
2
Nem maszkolható megszakítás
Töréspont
3
INT utasítás
nincs
Túlcsordulás
4
INTO utasítás
nincs
(1.megj) van
A valós üzemmód felépítése, működése Határ ellenörzés
5
BOUND utasítás
van
Hibás műveleti kód
6
Fenntartott műveletkódok és helytelen LOCK prefix használat
van
Eszköz nem elérhető
7
ESC vagy WAIT utasítások
van
Dupla hiba
8
Interrupt tábla túl kicsi, hiba előfordulása egy másik hiba kezelése közben
van
Fenntartva
9
Érvénytelen TSS (3.megjegyzés)
10
JMP, CALL, IRET utasítások, megszakításik és kivételek
van
Szegmens nincs jelen (3.megjegyzés)
11
Akármilyen művelet, amelyik cseréli a szegmenseket
van
Stack kivétel
12
Stack ofszet túl nagy
van
CS, DS, ES, FG, GS szegmens túlfutás
13
Ofszet túlnyúlik a 64K-s határon, kód végrehajtási kísérlet a CS határán túl
van
Laphiba (3.megjegyzés)
14
Akármilyen művelet, amelyik hivatkozik a memóriára
van
Fenntartva
15
van
A valós üzemmód felépítése, működése
Lebegőpontos hiba
16
ESC vagy WAIT utasítások
van (2.megj)
Illeszkedés ellenörzés (3.megjegyzés)
17
Akármilyen adat hivatkozás
nincs
Fenntartva
18-31
Software megszakítás
0-255 INT n utasítások
Maszkolható megszakítás
32-255
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.
A valós üzemmód felépítése, működése
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.
A védett üzemmód felépítése, működése
A védett üzemmód felépítése, működése 3.6.1. 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. µ§
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. LDTR Local Descriptor Table Register - helyi deszkriptortáblázat regiszter Ez a regiszter tartalmazza a helyi deszriptortáblázat (LDT) 32
A védett üzemmód felépítése, működése 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.6.2. Rendszer utasítások A redszer utasítások a következő funkciókat látják el: 1. 2. 3. 4. 5. 6. 7.
mutatók paraméterellenőrzése deszkriptortáblázatok címzése multitaszking lebegőpontos műveletek ki- és beviteli műveletek megszakítás-vezérlés nyomkövetés, hibakeresés
A védett üzemmód felépítése, működése 8. cache-szervezés 9. 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.
A védett üzemmód felépítése, működése 3.6.3. 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)
A védett üzemmód felépítése, működése 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 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 védett üzemmód felépítése, működése 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 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
A védett üzemmód felépítése, működése 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 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.6.3.1 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.6.3.1.1. A sík modell A legegyszerűbb modell a sík modell. Ebben a modellben minden
A védett üzemmód felépítése, működése 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. 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 3.21 á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. µ§
3.21. ábra: Sík modell
A védett üzemmód felépítése, működése 3.6.3.1.2. 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. µ§
A védett üzemmód felépítése, működése
3.22. ábra: Védett sík modell
3.6.3.1.3. 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 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
A védett üzemmód felépítése, működése 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. µ§
3.23. ábra: Multiszegmens modell
A védett üzemmód felépítése, működése 3.6.3.2. 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
A védett üzemmód felépítése, működése 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 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. µ§
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. µ§
3.25. ábra: Szegmens fordítás
A védett üzemmód felépítése, működése 3.6.3.2.1. 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 3.26 á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. µ§ 3.26. ábra: Szegmens regiszterek 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, LGS és LFS utasítások. Ezek az utasítások expliciten a szegmensregiszterekre vonatkoznak. 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.
A védett üzemmód felépítése, működése 3.6.3.2.2. 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. 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 3.27. ábra egy szelektor formátumát mutatja be. µ§ 3.27. ábra: Szegmens szelektor 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). 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á.
A védett üzemmód felépítése, működése
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 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.6.3.2.3. 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 3.28. ábra mutatja be. Bármely típusú deszkriptor ennek az alapformátumnak a változatait használja. µ§
A védett üzemmód felépítése, működése
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. 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
A védett üzemmód felépítése, működése 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: 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
A védett üzemmód felépítése, működése é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 méretü szegmenst foglalunk le, ez a szegmens nem kell feltétlenül lefele növekvő legyen.
A védett üzemmód felépítése, működése
Típus 11 10 9 8 Deszkriptor E W A típus
Meghatározás
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
8 Deszkriptor A típus
Meghatározás
0
1
0
0
0
Kód
Csak végrehajtható
1
1
0
0
1
Kód
Csak végrehajtható, hozzáférhető
A védett üzemmód felépítése, működése 2
1
0
1
0
Kód
végrehajtható, olvasható
3
1
0
1
1
Kód
végrehajtható, olvasható, hozzáférhető
4
1
1
0
0
Kód
Csak végrehajtható, illeszkedő
5
1
1
0
1
Kód
Csak végrehajtható, hozzáférhető, illeszkedő
6
1
1
1
0
Kód
végrehajtható, olvasható, illeszkedő
7
1
1
1
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 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
A védett üzemmód felépítése, működése 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 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
A védett üzemmód felépítése, működése 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 mem.szervezé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. µ§
3.30. ábra: Szegmens deszkriptor (a szegmens nincs jelen)
3.6.3.2.4. Szegmensdeszkriptor-táblázatok Két fajta deszkriptortáblázat létezik:
A védett üzemmód felépítése, működése • •
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ő. µ§
3.31. ábra: Deszkriptor táblázatok
3.6.3.2.5. 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
A védett üzemmód felépítése, működése 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. µ§ 3.32. ábra: Pszeudó deszkriptor formátum A cache vonal feltöltés teljesítményének maximalizálása érdekében célszerű a GDT és IDT báziscímeit egy nyolc Byte-os kerethez illeszteni. A GDT, illetve 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. 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.6.3.3. 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
A védett üzemmód felépítése, működése 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. 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.6.3.3.1. 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.
A védett üzemmód felépítése, működése
A védett üzemmód felépítése, működése 3.6.3.3.2. Lineáris cím A 3.33 ábrán egy 4 kByte-os lap lineáris címének formátumát láthatjuk. µ§
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.6.3.3.3. 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
A védett üzemmód felépítése, működése 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. µ§
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.6.3.3.4. 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. µ§
3.35. ábra: A lapcímtár formátuma és a laptáblázatok elemei a 4K-s lapokhoz.
3.6.3.3.5. Lapkeret cím A lapkeret cím a lap fizikai kezdőcímét határozza meg. A
A védett üzemmód felépítése, működése 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.6.3.3.6. 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 szóló információt. A 3.36 ábrán látható a laptáblázat bejegyzés formátuma abban az esetben, ha a Present bit értéke 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 védett üzemmód felépítése, működése 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.
3.6.3.3.7 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.
A védett üzemmód felépítése, működése 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.6.3.3.8. Í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ó.
3.6.3.3.9. 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.6.3.3.10. 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
A védett üzemmód felépítése, működése 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 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.6.3.4. Szegmens- és lapfordítás keverése A 3.37. ábra egyesíti a 3.36 és 3.34 ábrákat, és összefoglalja a logikai címek fizikai címekre való fordításának mindkét stádiumát, a lapozás
A védett üzemmód felépítése, működése 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.6.3.4.1. 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ó.
A védett üzemmód felépítése, működése 3.6.3.4.2 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.6.3.4.3. 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.6.3.4.4. 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.6.3.4.5. 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
A védett üzemmód felépítése, működése 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. µ§
3.37. ábra: Kombinált szegmens- és lapcím fordítás 3.6.3.4.6. 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. µ§
3.38. ábra: minden egyes szegmensnek biztosítani kell saját laptáblázatot
Védelmi mechanizmusok 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.7.1. Szegmens szintű védelem
Védelmi mechanizmusok 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 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.7.2. 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
Védelmi mechanizmusok 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, 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.7.2.1. 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 3.40. á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
Meghatározás
Decimális
Bináris
0
0000
Fenntartva
1
0001
Hozzáférhető 16 bites TSS
2
0010
LDT
Védelmi mechanizmusok
3
0011
Foglalt 16 bites TSS
4
0100
16 bites Call kapu
5
0101
Taszk kapu
6
0110
16 bites megszakítás kapu
7
0111
16 bites csapda kapu
8
1000
Fenntartva
9
1001
Hozzáférhető 32 bites TSS
10
1010
Fenntartva
11
1011
Foglalt 32 bites TSS
12
1100
32 bites Call kapu
13
1101
Fenntartva
14
1110
32 bites megszakítás kapu
Védelmi mechanizmusok
15
1111
32 bites csapda kapu
3.40. ábra: Rendszer szegmens- és kapu típusok 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.
Védelmi mechanizmusok
•
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. µ§
3.39. ábra: Védett módban használt deszkriptor mezők
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.7.2.2. 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.
Védelmi mechanizmusok
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 2 12 skálatényezővel. Ebben az esetben a határ a 0FFFH-tól (212- 1 vagy 4 kByte) egészen FFFF_FFFFHig (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 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 2 32-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
Védelmi mechanizmusok 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 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.7.3. 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
Védelmi mechanizmusok 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 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
Védelmi mechanizmusok 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ória-hozzáférés a kevésbé privilegizált szinten menjen végbe.
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. µ§
3.41. ábra: Védelmi gyűrűk
3.7.4. 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 szegmens-
Védelmi mechanizmusok szelektor betöltésének pillanatában történik. Amint azt a 3.42. ábra mutatja, három különböző privilegizálási szint kerül ilyen típusú ellenőrzés alá. 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. µ
§
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ű 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.
Védelmi mechanizmusok 3.7.4.1. 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.7.5. Vezérlésátadások korlátozása 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
Védelmi mechanizmusok 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.
µ
§
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
Védelmi mechanizmusok é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. 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.
Védelmi mechanizmusok
3.7.6. 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: - 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 3.44. ábra egy callkapu formátumát illusztrálja. µ
§
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
Védelmi mechanizmusok foglalhat helyet, de a megszakításdeszkriptor-táblázatban (IDT-ben) nem. 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 3.45. ábra bemutatja a címzésnek ezen formáját. µ
§
3.45. ábra: A call kapu mechanizmusa 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ő
Védelmi mechanizmusok 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. µ
§
3.46. ábra: Privilégium ellenörzés call kapuval történő vezérlésátadásnál
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
Védelmi mechanizmusok 3.7.6.1. 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. 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
Védelmi mechanizmusok kezdeti veremmutató segítségével új verem lesz létrehozva. µ
§
3.47. ábra: Kezdeti stack pointerek egy TSS-ben 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.
Védelmi mechanizmusok
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.
Ellenőrzi, hogy a meghívott procedúra veremének mérete elég nagy legyen ahhoz, hogy befogadja a paramétereket és a regiszterek elmentett tartalmát; ha ez nincs teljesítve, veremkivételt generál.
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. µ
§
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 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
Védelmi mechanizmusok é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.7.6.2. 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.
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.
2.
Az SS és ESP regiszterek régi tartalmát (az aktuális verem tetején)
Védelmi mechanizmusok 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
Hibakód
Stack
0
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 verem teteje + 7 a veremszegmens határán belül kell legyen
Védelmi mechanizmusok
A visszatérő kód szegmensdeszkriptorának a deszkroptor-táblázat határán belül kell lennie
Védelmi
CS
A visszatérést végző szegmensdeszkriptor kódszegmensre kell vonatkozzon
Védelmi
CS
Szegmens nincs jelen
CS
Védelmi
CS
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.
ESP + N + 15 * a veremszegmens határán belül Stack hiba kell legyen
Az ESP + N + 12 * helyen található szegmensszelektor nem lehet nullás szelektor
Védelmi
0
SS
Védelmi mechanizmusok
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)
* 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.7.7. Az operációs rendszer számára lefoglalt utasítások
Védelmi mechanizmusok 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.7.7.1. 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 Clear Task-Switched Flag - taszkváltásjelző bit törlése HLT Halt Processor - leállás INVD Invalidate Cache - belső cache érvénytelenítése INVLPG Invalidate TLB Entry - TLB bejegyzés érvénytelenítése LGDT Load GDT Register - a globális deszkriptortáblázat-regiszter betöltése LIDT Load IDT Register - a megszakítás deszkriptortáblázatregiszter betöltése LLDT Load LDT Register - a lokális deszkriptortáblázat-regiszter betöltése LMSWLoad Machine Status Word - a gépi állapotszó betöltése LTR Load Task Register - taszkregiszter betöltése 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
Védelmi mechanizmusok érvénytelenítés
3.7.7.2. É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.7.8. 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 A LAR utasítás annak ellenőrzésére használatos, hogy a mutató
Védelmi mechanizmusok 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 3.50. á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
Deszkriptor típus
Érvényes?
0
fenntartva
nem
Védelmi mechanizmusok
1
fenntartva
nem
2
LDT
igen
3
fenntartva
nem
4
fenntartva
nem
5
Taszk kapu
nem
6
fenntartva
nem
7
fenntartva
nem
8
fenntartva
nem
9
Lehetséges 32 bites TSS
igen
A
fenntartva
nem
B
Foglalt 32 bites TSS
igen
C
32 bites call kapu
nem
Védelmi mechanizmusok D
fenntartva
nem
E
32 bites megszakítás kapu
nem
F
32 bites trap kapu
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.
Védelmi mechanizmusok 3.7.8.1. 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.
Védelmi mechanizmusok
Védelmi mechanizmusok 3.7.8.2. 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.
Védelmi mechanizmusok ARPL (Adjust Requested Privilege Level) - a szelektor RPL mezőjének beállítása 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.7.9. 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.
Védelmi mechanizmusok 3.7.9.1. 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. µ
§
3.51. ábra: Egy laptáblázat bejegyzés védelmi mezői
3.7.9.1.1. 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.
Védelmi mechanizmusok
Védelmi mechanizmusok 3.7.9.1.2. 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-
Védelmi mechanizmusok szintű lapra való írási kísérletet, és ugyanakkor átmásolhatja is a lapot.
3.7.9.1.3. 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 3.52. á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.7.9.1.4. 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égium
User
hozzáférhetőség
Csak
Laptáblázat bejegyzés Privilégium
User
hozzáférhetőség
Csak
Kombinált effektus Privilégium
User
hozzáférhetőség
Csak
Védelmi mechanizmusok olvasható
olvasható
olvasható
User
Csak olvasható
User
Írható/ olvasható
User
Csak olvasható
User
Írható/ olvasható
User
Csak olvasható
User
Csak olvasható
User
Írható/ olvasható
User
Írható/ olvasható
User
Írható/ olvasható
User
Csak Supervisor Csak Supervisor Írható/ olvasható olvasható olvasható
User
Csak Supervisor Írható/ Supervisor Írható/ olvasható olvasható olvasható
User
Írható/ Supervisor Csak Supervisor Írható/ olvasható olvasható olvasható
User
Írható/ Supervisor Írható/ Supervisor Írható/ olvasható olvasható olvasható
Supervisor
Csak olvasható
User
Csak Supervisor Írható/ olvasható olvasható
Supervisor
Csak olvasható
User
Írható/ Supervisor Írható/ olvasható olvasható
Supervisor
Írható/ olvasható
User
Csak Supervisor Írható/ olvasható olvasható
Supervisor
Írható/ olvasható
User
Írható/ Supervisor Írható/ olvasható olvasható
Supervisor
Csak Supervisor Csak Supervisor Írható/ olvasható olvasható olvasható
Védelmi mechanizmusok
Supervisor
Csak Supervisor Írható/ Supervisor Írható/ olvasható olvasható olvasható
Supervisor
Írható/ Supervisor Csak Supervisor Írható/ olvasható olvasható olvasható
Supervisor
Írható/ Supervisor Írható/ Supervisor Írható/ olvasható olvasható olvasható
3.52. ábra: Kombinált lapcímtár és laptáblázat védelem
3.7.9.2. 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 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,
Védelmi mechanizmusok virtuális címterületre leképezett állományokat, illetve a felügyelőprogram területeit.
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
Védett üzemmódú multitaszking képes a megszakítás-taszkok alatt megjelenő megszakítások kezelésére. 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.8.1. 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 3.53. á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
Védett üzemmódú multitaszking tárolják:
2.
•
Az általános regisztereket (EAX, ECX, EDX, EBX, ESP, EBP, ESI, és EDI).
•
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).
Védett üzemmódú multitaszking
µ
§
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é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.8.2. A TSS deszkriptor Mint minden más szegmenst, a taszk-állapot-szegmenst is egy deszkriptor határoz meg. A 3.54. ábra bemutatja a TSS deszkriptor formátumát. µ
§
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. A Bázis, Limit, és DPL mezőknek, illetve a Felbontás
Védett üzemmódú multitaszking (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.8.3. 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
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 3.56. á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.
Védett üzemmódú multitaszking
µ
§
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 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.8.4. Taszk kapudeszkriptorok µ
§
3.56. ábra: Taszk kapudeszkriptor
Védett üzemmódú multitaszking
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. 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. µ
§
3.57. ábra: Taszkokra jellemző taszk kapuk
3.8.5. Taszkkapcsolás A processzor átadja a vezérlést egy másik taszknak a következő négy eset bármelyikében: 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
Védett üzemmódú multitaszking é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: 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édett üzemmódú multitaszking 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 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.
Védett üzemmódú multitaszking 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
Állapot ellenörzés
Kivétel1
Hibakód hivatkozás
1
A TSS deszkriptor jelen van a memóriában
NP
Az új taszk TSS-e
2
A TSS deszkriptor nem foglalt
TS, GP
A taszk visszakapcsolt TSS-e
3
A TSS szegmens határ nagyobb vagy egyenlő mint 108
TS
Az új taszk TSS-e
4
A regiszterek feltöltve a TSS értékeivel
5
Az új érvényes taszk LDT szelektora2
TS
Az új taszk LDT-je
6
A kódszegmens DPL értéke
TS
Új kódszegmens
Védett üzemmódú multitaszking megegyezik a szelektor RPL értékével 7
Az SS szelektor érvényes2
TS
Új veremszegmens
8
A veremszegmens jelen van a memóriában
SF
Új veremszegmens
9
A veremszegmens DPL értéke megegyezik a CPL értékkel
TS
Új veremszegmens
10
Az új taszk LDT-je jelen van a memóriában
TS
Az új taszk LDT-je
11
A CS szelektor érvényes2
TS
Új kódszegmens
12
A kódszegmens jelen van a memóriában
NP
Új kódszegmens
13
A veremszegmens DPL értéke megegyezik a szelektor RPL értékével
TS
Új veremszegmens
14
A DS, ES, FS és GS szelektorok érvényesek2
TS
Új adatszegmens
15
A DS, ES, FS és GS szegmensek olvashatók
TS
Új adatszegmens
16
A DS, ES, FS és GS szegmensek jelen vannak a memóriában
NP
Új adatszegmens
17
A DS, ES, FS és GS
TS
Új adatszegmens
Védett üzemmódú multitaszking szegmensek DPL értéke nagyobb vagy egyenlő a CPL értékével
3.58. ábra: Taszkváltás alatti ellenörzés 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.8.6. 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 3.59. ábrát). µ
§
Védett üzemmódú multitaszking 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 3.60. á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 utasítás vagy 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 Busy bitje
A bit törölt
Nem változik
A bit törölt
Az új taszk NT flagje
Nem változik
A flag beállítódik
Nem változik
A régi taszk NT flagje
Nem változik
Nem változik
A flag törölt
Az új taszk Link mezője
Nem változik
A szelektorral betöltve
Nem változik
Védett üzemmódú multitaszking A régi taszk Link mezője
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.8.6.1. 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
Védett üzemmódú multitaszking
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.8.6.2. 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.
Védett üzemmódú multitaszking 3.8.7. 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.8.7.1. 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
Védett üzemmódú multitaszking 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 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 3.61. á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.8.7.2. 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
Védett üzemmódú multitaszking 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.
A GDT szegmensdeszkriptorain keresztül. Minden taszk hozzá tud férni a GDT-ben levő deszkriptorokhoz. Ha ezek a deszkriptorok 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.
µ
§
3.61 ábra: Lineáris átfedés a fizikai memóriában
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.
2.
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.
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
Védett üzemmódú kivételek és megszakítások utasításokat gyakran nevezik "softwaremegszakí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.9.1. 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 3.62. ábra a kivétel- és megszakítás-vektorok kirendelését mutatja. Vektorszám
Meghatározás
0
Osztási hiba
1
Debug kivétel
2
Nem maszkolható megszakítás
Védett üzemmódú kivételek és megszakítások
3
Töréspont
4
INTO túlcsordulást talált
5
BOUND határ túllépés
6
Nem megengedett op. kód
7
Eszköz nem elérhető
8
Dupla hiba
9
Koprocesszor szegmens túlfutás
10
Érvénytelen taszk státusz szegmens
11
Szegmens nincs jelen
12
Verem hiba
13
Általános védelmi hiba
14
Laphiba
Védett üzemmódú kivételek és megszakítások
15
Intel által fenntartva
16
Lebegőpontos hiba
17
Illeszkedés ellenőrzés
18
Géptípus ellenőrzés
19-31
Intel által fenntartva
32-255
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.
Védett üzemmódú kivételek és megszakítások 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.
Védett üzemmódú kivételek és megszakítások 3.9.2. 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.9.3. Megszakítások engedélyezése és letiltása Bizonyos feltételek és jelzőbit-beállítások arra késztetik a
Védett üzemmódú kivételek és megszakítások processzort, hogy egyes megszakítás- és kivételtípusokat letiltson.
3.9.3.1. 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.9.3.2. 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
Védett üzemmódú kivételek és megszakítások vizsgálhatók, illetve módosíthatók. A POPF utasítással lehet a megváltoztatott formát az EFLAGS regiszterbe visszatölteni. •
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.9.3.3. 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.
Védett üzemmódú kivételek és megszakítások
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 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.9.3.4. 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.
Védett üzemmódú kivételek és megszakítások 3.9.4. 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, á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 Magas
Osztály
Meghatározás
1. osztály
Trap az előző műveleten -Töréspont -Debug trap kivétel
2. osztály
Külső megszakítás -NMI megszakítás -Maszkolható megszakítás
3. osztály
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
4. osztály
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
Védett üzemmódú kivételek és megszakítások Alacsony 5. osztály
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
Védett üzemmódú kivételek és megszakítások 3.9.5. 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. µ
§
3.64. ábra: IDT lokalizálása a memóriában az IDTR segítségével 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
Védett üzemmódú kivételek és megszakítások 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.9.6. 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. µ
§
3.65. ábra: IDT kapudeszkriptor
Védett üzemmódú kivételek és megszakítások 3.9.7. 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.9.7.1. 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. µ
§
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.
Védett üzemmódú kivételek és megszakítások 3.9.7.1.1. 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 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. µ
§
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.9.7.1.2. 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 állítja vissza, ha a CPL=0. Az IF bit csak akkor módosul, ha CPL<= IOPL.
Védett üzemmódú kivételek és megszakítások 3.9.7.1.3. 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.9.7.1.4. 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: •
A
kivételt-,
vagy
megszakítás-kezelő
rutinokat
illeszkedő
Védett üzemmódú kivételek és megszakítások (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.9.7.2. 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. µ
§
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
•
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
Védett üzemmódú kivételek és megszakítások 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.9.8. 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 3.69. á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 µ
§
3.69. ábra: Hibakód Ha az IDT bit nincs beállítva (set), a TI bit mutatja meg, hogy a
Védett üzemmódú kivételek és megszakítások 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.9.9. 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 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.
Védett üzemmódú kivételek és megszakítások 3.9.9.1. 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.9.9.2. 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
hiba
Adat cím töréspont
trap
Általános detektálás
hiba
Lépésenkénti végrehajtás
trap
Taszkkapcsolás töréspont
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.
Védett üzemmódú kivételek és megszakítások 3.9.9.3. 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 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.9.9.4. 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ó.
Védett üzemmódú kivételek és megszakítások 3.9.9.5. 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.
3.9.9.6. 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.
Védett üzemmódú kivételek és megszakítások 3.9.9.7. 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 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.9.9.8. 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.
Védett üzemmódú kivételek és megszakítások Osztály
Vektorszám
Meghatározás
1
Debug kivétel
2
NMI megszakítás
Jóindulatú
3
Tőréspont
kivételek
4
Túlcsordulás
és megszakítások
5
Határellenörzés
6
Érvénytelen op. kód
7
Eszköz nem elérhető
16
FPU hiba
0
Osztási hiba
Járulékos
10
Érvénytelen TSS
kivételek
11
Szegmens nincs jelen
Védett üzemmódú kivételek és megszakítások
Laphibák
12
Verem hiba
13
Ált. védelmi hiba
14
Laphiba
3.70. ábra: Megszakítás és kivétel osztályok
Első
Második kivétel
kivétel
Jóindulatú
Járulékos
Laphiba
Jóindulatú
ok
ok
ok
Járulékos
ok
Dupla hiba
ok
Laphiba
ok
Dupla hiba
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)
Védett üzemmódú kivételek és megszakítások kivételek, illetve laphiba kivételek. Ezt a felosztást a 3.70. á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.
Védett üzemmódú kivételek és megszakítások 3.9.9.9. 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.9.9.10. 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
Meghatározás
TSS szegmens
A TSS szegmenshatár kisebb mint 67h
LDT szegmens
Érvénytelen LDT, vagy LDT nincs jelen
Verem szegmens
A veremszegmens szelektor túllépi a deszkriptor tábla határt
Védett üzemmódú kivételek és megszakítások
Verem szegmens
A verem szegmens nem írható
Verem szegmens
A veremszegmens DPL-je nem kompatibilis a CPL-el
Verem szegmens
A veremszegmens szelektor RPL-je nem kompatibilis a CPL-el
Kódszegmens
A kódszegmens szelektor túllépi a deszkriptor tábla határt
Kódszegmens
A kódszegmens nem végrehajtható
Kódszegmens
A nem illeszkedő kódszegmens DPL-je nem egyenlő a CPL-el
Kódszegmens
Az illeszkedő kódszegmens DPL-je nagyobb a CLP-nél
Adatszegmens
Az adatszegmens szelektor túllépi a deszkriptor tábla határt
Adatszegmens
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
Védett üzemmódú kivételek és megszakítások ú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.9.9.11. 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.
•
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ória-
Védett üzemmódú kivételek és megszakítások hozzá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 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.
Védett üzemmódú kivételek és megszakítások 3.9.9.12. 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. 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.
Védett üzemmódú kivételek és megszakítások 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.9.9.13. 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
•
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,
Védett üzemmódú kivételek és megszakítások 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 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.
Védett üzemmódú kivételek és megszakítások
•
Egy taszkkapcsolásban résztvevő TSS-beli szelektor
3.9.9.14. 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: 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.
Védett üzemmódú kivételek és megszakítások
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). µ
P
0
A hiba oka egy nem jelenlévő lap volt
1
A hiba oka egy lapszint védelem megszegés volt
W/R 0
U/S
§
A hibát okozó memória hozzáférés egy olvasás volt
1
A hibát okozó memória hozzáférés egy írás volt
0
A hiba keletkezésekor a végrehajtás supervisor módban történt.
1
A hiba keletkezésekor a végrehajtás user módban történt.
RSV 0 1
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
Védett üzemmódú kivételek és megszakítások 3.73. ábra: Laphiba hibakódok
3.9.9.14.1. Taszkkapcsolás alatti laphiba Egy taszkkapcsolás alatt a következő műveletek idéznek elő memória hozzáférést: •
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.9.9.14.2. 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:
Védett üzemmódú kivételek és megszakítások
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) 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.9.9.15. 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.
Védett üzemmódú kivételek és megszakítások
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, 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.
Védett üzemmódú kivételek és megszakítások •
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.
3.9.9.15.1. 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).
Védett üzemmódú kivételek és megszakítások
•
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 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
Védett üzemmódú kivételek és megszakítások kivételként van kezelve, a memória nem lesz felfrissítve, és a veremből semmi sem lesz kiemelve.
3.9.9.15.2. 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ő: 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.
Védett üzemmódú kivételek és megszakítások
3.9.9.16. 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 3.74. á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)
Védett üzemmódú kivételek és megszakítások Adat típus
A címnek oszthatónak kell lennie:
WORD
2
DWORD
4
rövid REAL
4
hosszú REAL
8
TEMPREAL
8
Szelektor
2
48 bites szegmentált mutató
4
32 bites lap mutató
4
32 bites szegmentált mutató
2
48 bites pszeudo deszkriptor
4
FSTENV/FLDENV mentési terület
2 vagy 4, az operandusmérettől függően.
Védett üzemmódú kivételek és megszakítások FSAVE/FSTOR mentési terület Bit sztring
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 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
Védett üzemmódú kivételek és megszakítások programoknak ritkán van szükségük.
3.9.9.17. 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.9.10. A kivételek összefoglalása A 3.75.ábra összefoglalja a Pentium processzor által felismert kivételeket. Meghatározás
Vektor Visszatérési szám cím a hibára mutat?
Kivétel típus
A kivétel forrása
Osztás nullával
0
Igen
Hiba
DIV és IDIV művelet
Debug kivétel
1
*1
*1
Akármilyen kód vagy adat hivatkozás
Töréspont
3
Nem
Trap
INT 3 művelet
Túlcsordulás
4
Nem
Trap
INTO művelet
Határsértés
5
Igen
Hiba
BOUND művelet
Védett üzemmódú kivételek és megszakítások
Érvénytelen op. kód
6
Igen
Hiba
Fenntartott műveleti kódok
Eszköz nem elérhető
7
Igen
Hiba
ESC és WAIT művelet
Dupla hiba
8
Igen
Abort
Bármi
Érvénytelen TSS
10
Igen2
Hiba
JMP, CALL, IRET művelet, megszakítások és kivételek
Szegmens nincs jelen
11
Igen2
Hiba
Akármilyen művelet ami szegmenst vált
Verem hiba
12
Igen
Hiba
Verem művelet
Általános védelmi hiba
13
Igen
Hiba/ trap3
Akármilyen kód vagy adat hivatkozás
Laphiba
14
Igen
Hiba
Akármilyen kód vagy adat hivatkozás
FPU hiba
16
Igen
Hiba4
ESC és WAIT művelet
Illeszkedés ellenőrzés
17
Igen
Hiba
Akármilyen adat hivatkozás
Védett üzemmódú kivételek és megszakítások
Géptípus ellenőrzés
18
Software megszakítás
0-255
-
Nem
Modellfüggő
Trap
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. 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.9.11. Hibakódok összefoglalása A 3.75. ábra összesíti minden egyes kivételt követő hiba információt.
Védett üzemmódú kivételek és megszakítások Meghatározás
Vektor szám
Hibakód van ?
Osztási hiba
0
Nincs
Debug kivétel
1
Nincs
Töréspont
3
Nincs
Túlcsordulás
4
Nincs
Határellenörzés
5
Nincs
Érvénytelen op. kód
6
Nincs
Eszköz nem elérhető
7
Nincs
Dupla hiba
8
Van, mindíg nulla
Érvénytelen TSS
10
Van
Szegmens nincs jelen
11
Van
Verem hiba
12
Van
Ált. védelmi hiba
13
Van
Védett üzemmódú kivételek és megszakítások
Laphiba
14
Van, spec. formátum
FPU hiba
16
Nincs
Illeszkedés ellenőrzés
17
Van, mindíg nulla
Modell ellenőrzés
18
Modellfüggő
Software megszakítás
0-255
Nincs
3.75. ábra: Hibakódok összefoglalása
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
Védett üzemmódú kivételek és megszakítások nem, csak a firmware tudja használni. A 3.76. á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.
•
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.
Védett üzemmódú kivételek és megszakítások 3.10.1. 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. µ
§
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.
Védett üzemmódú kivételek és megszakítások 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.10.2. 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
Tartalom
EFLAG
2
EIP
8000h
CS szelektor
3000h, ez az érték a 30000h báziscím inicializáló utasítását adja
DS, ES, FS, GS, SS szelektorok
0
DS, ES, FS, GS, SS határ
0FFFFFFFFh
DS, ES, FS, GS, SS jellemzők
16 bites, felfelé növekvő
Védett üzemmódú kivételek és megszakítások
CR0
0, 2, 3 és 31. bitek törölve (PE, EM, TS, PG)
CR4
0
CR6
Nem definiált
CR7
400h
GDTR, LDTR, IDTR, TSSR
Nem definiált
Modell specifikus regiszter
Nincs módosítva
3.77 ábra: Az SMM kezdeti állapota 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.10.2.1. 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
Védett üzemmódú kivételek és megszakítások 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 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
Védett üzemmódú kivételek és megszakítások 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.10.3. 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
Regiszter
0FFFC
CR0
0FFF8
CR3
0FFF4
EFLAG
0FFF0
EIP
0FFEC
EDI
0FFE8
ESI
Védett üzemmódú kivételek és megszakítások
0FFE4
EBP
0FFE0
ESP
0FFDC
EBX
0FFD8
EDX
0FFD4
ECX
0FFD0
EAX
0FFCC
DR6
0FFC8
DR7
0FFC4
TR*
0FFC0
LDTR*
0FFBC
GS*
0FFB8
FS*
Védett üzemmódú kivételek és megszakítások
0FFB4
DS*
0FFB0
SS*
0FFAC
CS*
0FFA8
ES
0FFA7-0FF04
Fenntartva
0FF02
Leállás automatikus újraindítása
0FF00
I/O trap újraindítása
0FEFC
SMM reviziószám
0FEF8
Állapot tároló bázisa
0FEF7-0FE00
Fenntartva
3.78. ábra: Az állapottároló formátuma Megjegyzések:
Védett üzemmódú kivételek és megszakítások •
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 3.79. á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 á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 3.79. á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, EAX, EFLAG, EIP
Igen
Igen
Igen
CR0, CR3, DR6, DR7, TR, LDTR, GS, FS, DS, SS, CS, ES
Igen
Igen
Nem
CR1, CR2, CR4, A GDT láthatatlan deskriptor regiszterei, LDT, IDT, CS, DS, ES, FS, GS
Igen
Nem
Nem
Védett üzemmódú kivételek és megszakítások DR0-DR7, FP regiszterek STn, FCS, FSW, címző szó, FP utasítás mutató, FP op. kód és operandus mutató
Nem
Nem
Nem
3.79. ábra: Állapot-beosztás
3.10.3.1. Az SMM revízió-azonosító (FEFCH ofszet) A 32 bites SMM revízió-azonosító megadja az SMM verziószámát és a processzor által nyújtott lehetőségeket. µ
§
3.80. ábra: SMM revízió-azonosító 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
Megjegyzés Alap SMM verzió azonosító
16
A processzor támogatja az I/O trap újraindítást
17
A processzor támogatja az SRAM áthelyezését
Védett üzemmódú kivételek és megszakítások
3.81. ábra: SMM revízió-azonosító táblázat Megjegyzés: Minden más bit fenntartott.
3.10.3.2. 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.
Rendszermenedzselő üzemmód 3.10.3.3. 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 3.82. ábra mutatja. Érték a belépésnél Érték a kilépésanél
CPU működés a kilépésnél
0
0
Visszatér a megszakított program következő utasítására
0
1
Kiszámíthatatlan
1
0
Visszatér a HLT utáni utasításra
1
1
Visszatés a megszakított HLT utasításra
3.82. ábra: Felfüggesztett állapotból való automatikus újraindítás
3.10.3.4. 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ő
Rendszermenedzselő üzemmód 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. 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.10.4. 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.
Rendszermenedzselő üzemmód
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.
Rendszermenedzselő üzemmód 3.10.5. 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.
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ó.
8086-os virtuális üzemmód
3.11.1. 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.11.1.1. 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:
8086-os virtuális üzemmód
•
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.
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.11.2.1. 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,
8086-os virtuális üzemmód 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. •
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.11.2.2. 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á.
8086-os virtuális üzemmód
3.11.3. 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: 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. µ
§
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).
8086-os virtuális üzemmód 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. µ
§
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.
8086-os virtuális üzemmód
3.11.3.1. 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.11.3.2. Á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 üzemmódból. A kivétel vagy megszakítás egy IRET utasítás végrehajtásával tér vissza a 8086 programba. 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.
8086-os virtuális üzemmód 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 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
8086-os virtuális üzemmód 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 trap-et 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 eredeti, megszakított, 3. privilégiumszinten levő procedúrára mutasson. 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
8086-os virtuális üzemmód 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.11.4. É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.
8086-os virtuális üzemmód 3.11.5. 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.11.6. 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.
8086-os virtuális üzemmód
IOPL =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
<3
Általános védelmi kivétel
3. 85. ábra: A software-megszakítás műveletei
8086-os virtuális üzemmód 3.11.7. 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.
•
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.11.7.1. 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
8086-os virtuális üzemmód 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.11.7.2. 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 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.
8086-os virtuális üzemmód 3.11.7.3. 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.11.8. 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: •
Az I/O műveletek alkalmával az I/O eszközök által igényelt késleltetések.
•
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
8086-os virtuális üzemmód é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. 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).
8086-os virtuális üzemmód 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 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
8086-os virtuális üzemmód 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 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
8086-os virtuális üzemmód 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: • • • • • • • • • • • •
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
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
kivételkezelés
8086-os virtuális üzemmód különbségeinek részletei a 23. fejezetben találhatók.
3.11.9. 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.11.9.1. 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 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
8086-os virtuális üzemmód 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.11.9.2. 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.
•
Kétoperandusú aritmetikai és logikai: ADD, ADC, SUB, SBB, AND, OR és XOR utasítások.
8086-os virtuális üzemmód 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.11.10. 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.
Általános CPU programozási információk
Ábra- és példajegyzék Tartalomjegyzék...............................................................................3 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. ..........................20 §2. fejezet: Processzor erőforrások.................................................21 Landmark 2.00 ............................................................................................. 21 CHECKIT 3.0 ............................................................................................. 23 MIPS 1.20: (MIPS) ............................................................................................. 26 CPUTEST 1.1 (MIPS) ............................................................................................. 29 3. Fejezet: Általános CPU programozási információk..................31 3.1. A memória felépítése ............................................................................................. 31 3.1.1. Nemszegmentált vagy "lapos" modell .................................................................................. 32 3.1.2. Szegmentált modell .................................................................................. 33
Ábra- és példajegyzék 3.1. ábra: Szegmentált címzés.............................33 3.2. Regiszterek ............................................................................................. 34 3.2.1. Általános regiszterek .................................................................................. 34 3.2. ábra: Alkalmazások számára elérhető regiszterkészlet....................................................35 3.2.2. Szegmensregiszterek .................................................................................. 35 3.2.3. Utasításmutató .................................................................................. 37 3.2.4. A verem felépítése és használata .................................................................................. 37 3.2.5. Flagregiszter .................................................................................. 39 3.4. ábra: A verem működése..............................39 3.2.5.1. Állapotbitek ............................................................................ 39 3.5. ábra: Az EFLAGS regiszter..........................40 3.6. ábra: Állapotbitek.........................................41 3.2.6 Rendszer-regiszterek .................................................................................. 42 3.2.6.1. Rendszer-flagek ............................................................................ 42 3.2.6.2. Vezérlőregiszterek ............................................................................ 45 3.7. ábra: A vezérlő regiszterek felépítése..........47
Általános CPU programozási információk 3.2.6.3. Nyomkövető regiszterek ............................................................................ 51 3.8. ábra: Nyomkövető regiszterek......................52 3.3. CPU üzemmódok ............................................................................................. 53 3.3.1. Valós üzemmód ("valós mód") .................................................................................. 53 3.3.2. Védett üzemmód .................................................................................. 53 3.3.3.Rendszermenedzselő üzemmód .................................................................................. 53 3.4. Inicializálás és az üzemmódok közötti átkapcsolás ............................................................................................. 55 3.4.1. A processzor inicializálása .................................................................................. 55 3.4.1.1. A processzor állapota reszetelés után ............................................................................ 56 3.9. ábra: Az EDX regiszter tartalma reszetelés után......................................................................57 3.10. ábra: A CR0 regiszter tartalma reszetelés után......................................................................57 3.11. ábra: A processzor állapota a reszetelést követően..............................................................60 3.4.1.2. Az első végrehajtott utasítás ............................................................................ 60 3.4.1.3. A cache engedélyezése ............................................................................ 61
Ábra- és példajegyzék 3.4.2. Software inicializálás valós üzemmódban .................................................................................. 62 3.4.2.1. Rendszertáblázatok ............................................................................ 62 3.4.2.2. Az NMI megszakítás ............................................................................ 63 3.4.3. Software inicializálása védett üzemmódban .................................................................................. 63 3.4.3.1. Rendszertáblázatok ............................................................................ 64 3.4.3.2. Megszakítások ............................................................................ 64 3.4.3.3. Lapozás ............................................................................ 65 3.4.3.4. Taszkok ............................................................................ 66 3.4.3.5. A TLB, BTB és cache tesztelése ............................................................................ 68 3.4.4. Üzemmódváltás .................................................................................. 68 3.4.4.1. Átkapcsolás védett módba ............................................................................ 68 3.4.4.2. Visszakapcsolás valós üzemmódba ............................................................................ 70 3.4.5. Példa inicializálásra és üzemmód átkapcsolásra
Általános CPU programozási információk .................................................................................. 71 3.4.5.1. A példa célja ............................................................................ 71 2.4.5.2. A memória elrendezése a reset-elést követően ............................................................................ 72 3.12. ábra: A processzor állapota a reszetet követően..............................................................72 3.4.5.3. Az algoritmus ............................................................................ 72 3.13. ábra: Az algoritmus és a forrásszöveg ezzel kapcsolatos sorainak száma.................................74 3.4.5.4. Eszközök használata ............................................................................ 75 3.14. ábra: A BLD és az ASM forrásállomány közti összefüggés.................................................77 3.4.5.5. A STARTUP.ASM listája ............................................................................ 77 3-1 példa: STARTUP.ASM.................................77 3.4.5.6. A MAIN.ASM forráskódja ............................................................................ 86 3-2 példa: MAIN.ASM........................................86 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)....................................................................87 3.16. ábra: A GDT, IDT és TSS ROM-ból RAMba másolása (a forrásszöveg 196-261 sorai)........87 3.17. ábra: Átkapcsolás a taszkra (a forrásszöveg 282 296 sorai)......................................................87 3.4.5.7. Állományok támogatása
Ábra- és példajegyzék ............................................................................ 87 3-3 példa: Az alkalmazás lefordítására és felépítésére szolgáló parancsköteg-állomány......88 3-4 példa: Build-állomány...................................88 3.5. A valós üzemmód felépítése, működése ............................................................................................. 90 3.5.1. Címek lefordítása .................................................................................. 90 3.18. ábra: Címek lefordítása..............................91 3.5.2. Regiszterek és utasítások .................................................................................. 91 2.5.3. Megszakítás és kivétel kiszolgálás .................................................................................. 92 3.5.4. Valós üzemmódú kivételek .................................................................................. 93 3.19. ábra: Kivételek és megszakítások...............95 3.6. A Védett üzemmód felépítése, működése ............................................................................................. 97 3.6.1. Memóriaszervező regiszterek. .................................................................................. 99 3.20. ábra: Memória kezelő regiszterek..............99 3.6.2. Rendszer utasítások .................................................................................. 100 3.6.3. Védett üzemmódú memóriaszervezés .................................................................................. 102 3.6.3.1 A szegmentálási modell kiválasztása
Általános CPU programozási információk ............................................................................ 105 3.6.3.1.1. A sík modell ...................................................................... 105 3.21. ábra: Sík modell.......................................106 3.6.3.1.2. Védett sík modell ...................................................................... 107 3.22. ábra: Védett sík modell............................108 3.6.3.1.3. Multiszegmens modell ...................................................................... 108 3.23. ábra: Multiszegmens modell....................109 3.6.3.2. Szegmensfordítás ............................................................................ 110 3.24. ábra: TI BIT - A deszkriptor tábla kiválasztása........................................................111 3.25. ábra: Szegmens fordítás............................111 3.6.3.2.1. Szegmensregiszterek ...................................................................... 112 3.6.3.2.2. Szegmensszelektorok ...................................................................... 113 3.6.3.2.3. Szegmens deszkriptorok ...................................................................... 114 3.28. ábra: Szegmens deszkriptorok..................115 3.29. ábra: Alkalmazási szegmens típusok........119 3.30. ábra: Szegmens deszkriptor (a szegmens nincs jelen)........................................................121 3.6.3.2.4. Szegmensdeszkriptor-táblázatok ...................................................................... 121 3.31. ábra: Deszkriptor táblázatok.....................122
Ábra- és példajegyzék 3.6.3.2.5. Deszkriptortáblázat bázisregiszterek ...................................................................... 122 3.6.3.3. Lapfordítás ............................................................................ 123 3.6.3.3.1. Lapozási opciók ...................................................................... 124 3.6.3.3.2. Lineáris cím ...................................................................... 126 3.33. ábra: A lineáris cím formátuma................126 3.6.3.3.3. Laptáblázatok ...................................................................... 126 3.34. ábra: Lapfordítás.......................................127 3.6.3.3.4. Laptáblázat bejegyzések ...................................................................... 127 3.35. ábra: A lapcímtár formátuma és a laptáblázatok elemei a 4K-s lapokhoz...............127 3.6.3.3.5. Lapkeret cím ...................................................................... 127 3.6.3.3.6. A Present (betöltött, jelenlevő) bit ...................................................................... 128 3.36. ábra: Laptáblázat bejegyzés formátuma nem jelenlévő lapoknál.............................................128 3.6.3.3.7 Hozzáfért (accessed) és "piszkos" (dirty) bitek ...................................................................... 129 3.6.3.3.8. Írás/olvasás illetve felhasználó/felügyelő bitek
Általános CPU programozási információk ...................................................................... 130 3.6.3.3.9. Lapszintű cache-vezérlő bitek ...................................................................... 130 3.6.3.3.10. Fordítási segédpufferek ...................................................................... 130 3.6.3.4. Szegmens- és lapfordítás keverése ............................................................................ 131 3.6.3.4.1. A sík modell ...................................................................... 132 3.6.3.4.2 Több lapot átfogó szegmensek ...................................................................... 133 3.6.3.4.3. Több szegmenst átfogó lapok ...................................................................... 133 3.6.3.4.4. Nem illeszkedő lap- és szegmenshatárok ...................................................................... 133 3.6.3.4.5. Illeszkedő lap- és szegmenshatárok ...................................................................... 133 3.37. ábra: Kombinált szegmens- és lapcím fordítás...............................................................134 3.6.3.4.6. Egy laptáblázat elhelyezése szegmensenként ...................................................................... 134 3.38. ábra: minden egyes szegmensnek biztosítani kell saját laptáblázatot.......................................134 3.7. Védelemi mechanizmusok ............................................................................................. 135
Ábra- és példajegyzék 3.7.1. Szegmens szintű védelem .................................................................................. 135 3.7.2. A szegmens deszkriptorok és a védelem .................................................................................. 136 3.7.2.1. Típusellenőrzés ............................................................................ 137 3.40. ábra: Rendszer szegmens- és kapu típusok ...........................................................................139 3.39. ábra: Védett módban használt deszkriptor mezők................................................................140 3.7.2.2. Határ (limit) ellenőrzés ............................................................................ 140 3.7.3. Privilégium szintek .................................................................................. 142 3.41. ábra: Védelmi gyűrűk...............................144 3.7.4. Az adathozzáférések korlátozása .................................................................................. 144 3.42. ábra: Privilégium ellenőrzés adathozzáféréseknél..........................................145 3.7.4.1. Kódszegmensekbeli adatok elérése ............................................................................ 146 3.7.5. Vezérlésátadások korlátozása .................................................................................. 146 3.43. ábra: Privilégium ellenőrzés taszkkapu nélküli vezérlésátadásoknál...............................147 3.7.6. Kapudeszkriptorok .................................................................................. 149 3.44. ábra: Call kapu.........................................149
Általános CPU programozási információk 3.45. ábra: A call kapu mechanizmusa..............150 3.46. ábra: Privilégium ellenörzés call kapuval történő vezérlésátadásnál..................................151 3.7.6.1. Veremváltás ............................................................................ 152 3.47. ábra: Kezdeti stack pointerek egy TSS-ben ...........................................................................153 3.48. ábra: Stack keret szintek közötti hívás alatt ...........................................................................154 3.7.6.2. Visszatérés egy procedúrából ............................................................................ 155 3.49. ábra: Szintek közötti visszatérés ellenőrzés ...........................................................................158 3.7.7. Az operációs rendszer számára lefoglalt utasítások .................................................................................. 158 3.7.7.1. Privilegizált utasítások ............................................................................ 159 3.7.7.2. Érzékeny utasítások ............................................................................ 160 3.7.8. Mutatók érvényességét ellenőrző utasítások .................................................................................. 160 3.50. ábra: Érvényes deszzkriptor típusok LSL műveletekhez.....................................................163 3.7.8.1. Deszkriptor érvényességének ellenőrzése ............................................................................ 164 3.7.8.2. Mutatók integritása és az RPL ............................................................................ 166 3.7.9. Lapszinti védelem
Ábra- és példajegyzék .................................................................................. 167 3.7.9.1. A laptáblázat bemenetek által tartalmazott védelmi paraméterek ............................................................................ 168 3.51. ábra: Egy laptáblázat bejegyzés védelmi mezői.................................................................168 3.7.9.1.1. A megcímezhető tartományt érintő megszorítások ...................................................................... 168 3.7.9.1.2. Típusellenőrzés ...................................................................... 170 3.7.9.1.3. A védelem kombinálása a laptáblázatok mindkét szintjén ...................................................................... 171 3.7.9.1.4. A lapvédelem fölülírói ...................................................................... 171 3.52. ábra: Kombinált lapcímtár és laptáblázat védelem.............................................................173 3.7.9.2. Lap- és szegmensvédelem kombinálása ............................................................................ 173 3.8. Védett üzemmódú multitaszking ............................................................................................. 175 3.8.1. Taszk-állapot-szegmens .................................................................................. 176 3.53. ábra: 32 bites taszk állapot szegmens.......178 3.8.2. A TSS deszkriptor .................................................................................. 178
Általános CPU programozási információk 3.54. ábra: TSS Deszkriptor..............................178 3.8.3. Taszkregiszter .................................................................................. 179 3.55. ábra: Taszk regiszter.................................181 3.8.4. Taszk kapudeszkriptorok .................................................................................. 181 3.56. ábra: Taszk kapudeszkriptor.....................181 3.57. ábra: Taszkokra jellemző taszk kapuk.....182 3.8.5. Taszkkapcsolás .................................................................................. 182 3.58. ábra: Taszkváltás alatti ellenörzés............187 3.8.6. Taszkok visszafelé kapcsolása (LINKING) .................................................................................. 187 3.59. ábra: Beágyazott taszkok..........................188 3.60. ábra: A taszkváltások hatása a Busy, NT és LINK mezőkre...................................................189 3.8.6.1. A Busy (foglalt) bit megelőzi a hurkok kialakulását ............................................................................ 189 3.8.6.2. A taszk visszakapcsolások módosítása ............................................................................ 190 3.8.7. Taszkok címtartománya .................................................................................. 191 3.8.7.1. Taszkok által lineárisról- fizikai címre végzett leképzés ............................................................................ 191 3.8.7.2. A taszkok logikai címtartománya ............................................................................ 192
Ábra- és példajegyzék 3.61 ábra: Lineáris átfedés a fizikai memóriában ...........................................................................193 3.9. Védett üzemmódú kivételek és megszakítások ............................................................................................. 194 3.9.1. Kivétel- és megszakításvektorok .................................................................................. 195 3.62. ábra: Kivételek és megszakításvektorok. .197 3.9.2. Utasítások újraindítása .................................................................................. 199 3.9.3. Megszakítások engedélyezése és letiltása .................................................................................. 199 3.9.3.1. További NMI megszakítások maszkolása ............................................................................ 200 3.9.3.2. INTR megszakítások maszkolása ............................................................................ 200 3.9.3.3. Debug hibák maszkolása az RF bit segítségével ............................................................................ 201 3.9.3.4. Egyes kivételek és megszakítások maszkolása ............................................................................ 202 3.9.4. Szimultán kivételek és megszakítások közötti prioritás .................................................................................. 203 3.63. ábra: Kivételek és megszakítások egymás közötti prioritása................................................204 3.9.5. A megszakításdeszkriptor-táblázat .................................................................................. 205 3.64. ábra: IDT lokalizálása a memóriában az
Általános CPU programozási információk IDTR segítségével.............................................205 3.9.6. IDT deszkriptorok .................................................................................. 206 3.65. ábra: IDT kapudeszkriptor........................206 3.9.7. Megszakítás taszkok és megszakítás-kezelő procedurák .................................................................................. 207 3.9.7.1. Megszakítás-kezelő procedúrák ............................................................................ 207 3.66. ábra: Megszakítás procedura hívás...........207 3.9.7.1.1. A megszakítás-kezelő eljárás verme ...................................................................... 208 3.67. ábra: Verem keret egy megszakítás vagy kivétel után........................................................208 3.9.7.1.2. Visszatérés egy megszakítás-kezelő eljárásból ...................................................................... 208 3.9.7.1.3. A megszakítás-kezelő eljárás flaghasználata ...................................................................... 209 3.9.7.1.4. Védelem a megszakítás-kezelő eljárásokban ...................................................................... 209 3.9.7.2. Megszakítás-kezelő taszkok ............................................................................ 210 3.68. ábra: Megszakítás taszkkapcsolás............210 3.9.8. Hibakódok .................................................................................. 211
Ábra- és példajegyzék 3.69. ábra: Hibakód...........................................211 3.9.9. Kivétel feltételek .................................................................................. 212 3.9.9.1. 0-s számú megszakítás - Osztáshiba (Divide Error) ............................................................................ 213 3.9.9.2. 1-es számú megszakítás - Debug kivétel ............................................................................ 213 3.9.9.3. 3-as számú megszakítás - Töréspont (Breakpoint) ............................................................................ 214 3.9.9.4. 4-es számú megszakítás - Túlcsordulás (Overflow) ............................................................................ 214 3.9.9.5. 5-ös számú megszakítás - Határsértés (Bounds Check) ............................................................................ 215 3.9.9.6. 6-os számú megszakítás - Érvénytelen utasítás (Invalid Opcode) ............................................................................ 215 3.9.9.7. 7-es számú megszakítás - nem elérhető eszköz (Device Not Available) ............................................................................ 216 3.9.9.8. 8-as számú megszakítás - Kettős hiba, dupla hiba (Double Fault) ............................................................................ 216 3.70. ábra: Megszakítás és kivétel osztályok.....218 3.71. ábra: Dupla hiba viszonyok......................218
Általános CPU programozási információk 3.9.9.9. 9-es számú megszakítás - (az Intel által fenntartott, használata nem ajánlott) ............................................................................ 220 3.9.9.10. 10-es számú megszakítás - Érvénytelen TSS (Invalid TSS) ............................................................................ 220 3.72. ábra: Érvénytelen TSS állapotok..............221 3.9.9.11. 11-es számú megszakítás - Szegmens nincs jelen, (Segment Not Present) ............................................................................ 222 3.9.9.12. 12-es számú megszakítás - verem kivétel (Stack Exception) ............................................................................ 224 3.9.9.13. 13-as számú megszakítás - Általános védelmi hiba (General Protection) ............................................................................ 225 3.9.9.14. 14-es számú megszakítás - Laphiba (Page Fault) ............................................................................ 227 3.73. ábra: Laphiba hibakódok..........................229 3.9.9.14.1. Taszkkapcsolás alatti laphiba ...................................................................... 229 3.9.9.14.2. Laphiba összeférhetetlen veremmutatóval ...................................................................... 229 3.9.9.15. 16-os számú megszakítás - Lebegőpontos egység hiba, Floating-Point Error) ............................................................................ 230 3.9.9.15.1. Numerikus kivételek kezelése
Ábra- és példajegyzék ...................................................................... 232 3.9.9.15.2. Szimultán kivételekre adott válaszok ...................................................................... 234 3.9.9.16. 17-es számú megszakítás - Illeszkedés ellenőrzés ellenőrzési hiba (Alignment Check) ............................................................................ 235 3.74. ábra: Adattípusok által igényelt illeszkedési feltételek............................................................237 3.9.9.17. 18-as számú megszakítás - Processzortípus ellenőrzés (Machine Check) ............................................................................ 238 3.9.10. A kivételek összefoglalása .................................................................................. 238 3.75. ábra: Kivételek összefoglalása.................240 3.9.11. Hibakódok összefoglalása .................................................................................. 240 3.75. ábra: Hibakódok összefoglalása...............242 3.10. Rendszermenedzselő üzemmód ............................................................................................. 242 3.10.1. Az SMI megszakítás .................................................................................. 244 3.76. ábra: Az üzemmód-állapotok közti átmenetek..........................................................244 3.10.2. Az SMM kezdeti állapota .................................................................................. 245 3.77 ábra: Az SMM kezdeti állapota.................246 3.10.2.1. Az SMM végrehajtása
Általános CPU programozási információk ............................................................................ 246 3.10.3. Az SMRAM processzor-állapot tároló formátuma .................................................................................. 248 248 3.78. ábra: Az állapottároló formátuma............250 3.79. ábra: Állapot-beosztás..............................252 3.10.3.1. Az SMM revízió-azonosító (FEFCH ofszet) ............................................................................ 252 3.80. ábra: SMM revízió-azonosító...................252 3.81. ábra: SMM revízió-azonosító táblázat......253 3.10.3.2. I/O trap-újraindítás (FF00H ofszet) ............................................................................ 253 3.10.3.3. Felfüggesztett állapotból való automatikus újraindítás (FF02H ofszet) ............................................................................ 254 3.82. ábra: Felfüggesztett állapotból való automatikus újraindítás.....................................254 3.10.3.4. Az állapottároló bázisa (FEF8H ofszet) ............................................................................ 254 3.10.4. Az SMRAM relokációja .................................................................................. 255 3.10.5. Visszatérés az SMM-ből .................................................................................. 257 3.11. 8086-os virtuális üzemmód ............................................................................................. 258 3.11.1. 8086 CPU kód végrehajtása .................................................................................. 259
Ábra- és példajegyzék 3.11.1.1. Regiszterek és utasítások ............................................................................ 259 3.11.2.1. Lapozás a 8086-os virtuális taszkok esetében ............................................................................ 260 3.11.2.2. Védelem egy 8086-os virtuális taszkon belül ............................................................................ 261 3.11.3. Belépés a 8086-os virtuális üzemmódba és az abból való kilépés .................................................................................. 262 3.83. ábra: Belépés a 8086-os virtuális üzemmódba és az abból való kilépés................262 3.84. ábra: A 0. privilégiumszintű verem állapota 8086-os virtuális módban, a megszakítást követően............................................................263 3.11.3.1. Taszkátkapcsolások általi tranzíciók ............................................................................ 264 3.11.3.2. Átmenet trap- és megszakításkapukon keresztül ............................................................................ 264 3.11.4. Érzékeny utasítások .................................................................................. 267 3.11.5. Virtuális megszakítások támogatása .................................................................................. 268 3.11.6. A 8086 operációs rendszerhívások emulációja .................................................................................. 268 3. 85. ábra: A software-megszakítás műveletei.269 3.11.7. Virtuális I/O
Általános CPU programozási információk .................................................................................. 270 3.11.7.1. I/O-ra leképezett I/O ............................................................................ 270 3.11.7.2. Memóriába leképezett I/O ............................................................................ 271 3.11.7.3. Különleges I/O pufferek ............................................................................ 272 3.11.8. Különbségek a 8086 CPU-hoz képest .................................................................................. 272 3.11.9. Különbségek a 286 CPU-hoz képest .................................................................................. 277 3.11.9.1. Privilégiumszint ............................................................................ 277 3.11.9.2. A busz lezárása ............................................................................ 278 3.11.10. Különbségek a 386 és 486 CPU-hoz képest .................................................................................. 279 Ábra- és példajegyzék.......................................................................280 Előzetes a második kötet tartalmából..............................................301
Előzetes a második kötet tartalmából
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
Általános CPU programozási információk not be registered trade marks or copyrights of their respective companies.