Memória kezelő regiszterek

A processzor négy memória kezelő regisztert (GDTR, LDTR, IDTR, és TR) alkalmaz, hogy megadja azoknak az adat struktúráknak (leíró táblázatoknak) a címét és méretét melyek a szegmentált memóriakezelésért felelősek. Speciális rendszer utasítások felelősek ezen regiszterekbe való írás illetve olvasásért.
 

2.5. ábra: A memória menedzselő regiszterek felépítése

Globális leíró tábla regiszter

A GDTR (GDTR - Global Descriptor Table Register; Globális leíró tábla regiszter) tartalmazza a GDT (globális leíró tábla) 32 bites lineáris kezdő címét, és egy 16 bites tábla limitet, avagy a GDT bájtban mért hosszát. A kezdő cím a lineáris 0-tól számított bájtban mért cím, míg a hossz bájtban mért hosszt adja meg. A kezdőcímet érdemes néggyel osztható címre helyezni (sőt lehet 4096-tal osztható címre is). A LGDT utasítás betölti az operandusban megadott 6 bájtot a GDTR regiszterbe. A fenti ábrán látható, hogy hogyan kell felépíteni a betöltendő 6 bájtot: a felső 32 bitre a lineáris cím, míg az alsó 16-ra pedig a limitnek kell kerülnie. A SGDT hasonló logika alapján a megadott címre menti el ezt a bizonyos 6 bájtot. Bekapcsolás vagy reszet után a GDTR 32 bites címe 0-ra illetve a limit 0FFFFh-ra van állítva. Ezt nekünk kell beállítani, ha védett módba akarunk lépni.
 

Lokális leíró tábla regiszter

Amint az ábrából is láthatjuk más a felépítése a LDTR regiszternek (LDTR - Local Descriptor Table Register; Lokális leíró tábla regiszter). Két részből áll ezen regiszter. Az egyik a rendszer regiszter, amit mi magunk is beállíthatunk a másik, amihez nem férhetünk hozzá egy rejtett rész (angol terminológia szerint a hidden-part).

A látható rész egy 16 bites szegmens kiválasztó, míg a rejtett rész tartalmaz egy 32 bites kezdő címet, 16 bites limitet, majd leíró attribútumokat az LDT számára. A rejtett résszel nem kell törődnünk, hisz úgy sem férünk hozzá. Az LLDT és az SLDT utasításokkal tölthetjük be, illetve kérdezhetjük le az LDT-t leíró kiválasztó értékét. Tehát ezen utasítások használatakor csak a látható rész, a 16 bites szegmens kiválasztót kell megadnunk, illetve az SLDT-nél csak ezt kapjuk vissza. Hogy miért van a láthatatlan rész? A lényege az, hogy az LLDT utasítás után, ahogy betöltöttük az új szegmens kiválasztót a LDTR látható részébe, a processzor automatikusan feltölti az LDTR rejtett részét a GDT-ből. Részletezve: tegyük fel, hogy elkészítettük a rendszer szegmens leírót (system-segment descriptor) az LDT számára, a szükséges megfontolások szerint. (Megadtunk mindent, amit egy ilyen leírónál kell, így az ott helyezkedik el minden információval a GDT-ben, s annak már egy eleme, leírója.) Most már csak hivatkozni kell rá, s betöltjük az LDTR-be. Ekkor mi csak a 16 bites kiválasztót adjuk meg, s a processzor a rejtett részt a kiválasztó ismerete által feltölti, avagy bemásolja a rejtett részbe a leírót egy az egybe. Erre azért van szükség, hogy minél gyorsabban meglegyen az LDT lineáris címe, ugyanis amikor az LDT egyik leírójára hivatkozunk gyorsan, kell elő állítani, hogy hol is kezdődik az LDT. Így nem kell mindig a GDT-hez nyúlni, hogy hol kezdődik az LDT, és csak azután az LDT egyik leíróját kiolvasni, s csak a végén a kívánt leíró által prezentált memória területet, szegmenst elérni. Ehelyett gyorsabban elérhetjük. De ne higgyük, hogy csak ez a regiszter áll két részből, hasonlóan működik az összes szegmens regiszter. (CS, DS, stb.)

Amikor taszk váltás történik, az új taszk LDT kiválasztója automatikusan betöltődik a TSS-ből. (Hasonlóan a régi is elmentődik a régi TSS-ébe.) Ezáltal minden taszknak saját LDT-je lehet. (Persze ne felejtsük el, ha LLDT utasítással írunk az LDTR-be akkor a régi elveszik.)

Bekapcsoláskor vagy reszet után a processzor az LDTR szegmens kiválasztóját és 32 bites lineáris címét 0-ra állítja, míg a limitet 0FFFFh-ra a GDT-hez hasonlóan.
 

Megszakítás leíró tábla regiszter

Az ábráról is láthatjuk, hogy az IDTR (IDTR - Interrupt Descriptor Table Register; Megszakítás leíró tábla regiszter) az GDTR-hez hasonlítható. (Az előbb tárgyaltak szerint az IDT-re is elmondhatjuk, hogy nem szegmens, ugyanis nincs leíró, pontosabban kiválasztó mellyel hivatkozhatnánk rá.) Az IDTR a GDTR-hez hasonlóan egy 32 bites lineáris tábla kezdő címből illetve ezen tábla 16 biten tárolt méretét tartalmazó részből áll. (Minden a GDTR hasonlatára.) Az LIDT illetve SIDT utasításokkal írhatunk bele, illetve olvashatjuk ki értékét. Itt is 6 bájtos tábla cím-limit adatot vár az LIDT illetve ad vissza az SIDT. Bekapcsoláskor illetve reszet után a lineáris kezdő cím 0, a limit - a tábla mérete bájtban - pedig 0FFFFh. (Megjegyezném, hogy valós módban - azért hogy a processzor megőrizze a kompatibilitást, s rugalmasabb legyen a felépítés - az IDTR regiszter használt méghozzá 32 bites lineáris címe 0, limitje a kiszámolható 256 * 4 bájt = 1024 bájt. (256 elem, 4 bájt egy megszakítás vektor, mely a megszakítást végző 20 (+1) bites rutin fizikai címe) 1024 bájt, az-az 3FFh.)
 

Taszk regiszter

Az ábra alapján a TR (TR - Task Register; Taszk regiszter) pedig az LDTR-rel hozható rokonságba. Hasonlóan egy 16 bites szegmens kiválasztóból áll a látható rész, míg a rejtett a 32 bites lineáris kezdő címből, 16 bit bájtbeli tábla méretből, illetve a szegmens leíró által tárolt attribútumokból. A TR mindig az éppen aktuális taszk TSS kiválasztóját tartalmazza. Ez a kiválasztó a GDT-ben egy rendszer szegmens leíróra mutat, (ahogy ezt az előzőekben láttuk) amit az LDTR-ben az elmondottak szerint, csak létre kell hozni, s ezek után hivatkozhatunk is rá.

A jól megszokott logika alapján az LTR utasítással írhatunk a TR-be, illetve onnan az STR-rel olvashatjuk ki az ott tárolt kiválasztót. (Mivel csak kiválasztó van a látható részben, ezért csak azt kell lementeni, illetve a TR-be tölteni.) Az LTR után a GDT-ből a kiválasztott leíró adatai a TR rejtett részébe töltődik automatikusan.

Bekapcsolás után a szegmens kiválasztó a TR látható részében 0, illetve a rejtett részben a lineáris kezdő cím 0, és a limit 0FFFFh.

Amikor taszk váltás történik a TR-be kerül az új taszk TSS kiválasztója, míg a régi taszk TSS kiválasztója az új taszk TSS-ének előző taszk mutató (previous task link) mezőjébe kerül. (Fent láttuk, hogy a taszkok egymásba-ágyazásakor ennek feltétele az EFLAGS regiszter NT flagjének 1 értéke.) A TR-be történt kiválasztó írás után a fent elmondottak szerint megtörténik a rejtett rész feltöltése.
 

Vezérlő regiszterek

A vezérlő regiszterek (CR - Control Registers; Vezérlő regiszterek) CR0, CR1, CR2, CR3, és CR4 meghatározzák a processzor működését, működésének módját, illetve az éppen futó taszk viselkedését illetve a taszk lehetőségeit.
 

2.6. árba: Vezérlő regiszterek

  • CR0 - rendszer vezérlő flageket tartalmaz melyek vezérlik a processzor állapotát illetve működési módját.
  • CR1 - fenntartott illetve nem létezik
  • CR2 - laphiba (page-fault) kivétel bekövetkezése után azt a pontos lineáris címet tartalmazza, mely a laphibát kiváltotta.
  • CR3 - tartalmazza az lapcímtár (page directory) fizikai kezdőcímét illetve két flag bitet (PCD és PWT). Ezt a kontrol regisztert gyakran emlegetjük PDBR-nek (Page Directory Base Register) is. A felső 20 bit tartalmazza az lapcímtár fizikai kezdőcímét. A kezdőcím 20, és nem 32 bites, ugyanis a lapcímtár kezdőcímét 4 KB-ra (4096 bájtra, lapkeret méretre) kell igazítani. Így 0 bájttól kezdődik a címzés, illetve ami a 20 bites címben 1 az a fizikai memóriában a 4096. bájtot jelenti. A PCD és PWT flagek befolyásolják a lapcímtár illetve a processzor belső adat cache-elését. (A nem tárgyalt bitek, ahogy az ábrán látható 0 értéket tartalmaznak.)
  • CR4 -számos flaget tartalmaz melyek a processzor architektúrai bővítéseit írják le. (Pl. ha adott bit be van kapcsolva akkor az a processzor támogatja azt a fejlesztést.)
Védett módban, hogy vezérlő regiszterből olvassunk vagy ebbe írjunk a MOV utasítás szolgál. A védelem értelmében ezen regiszterek kiolvasása bármely privilégium szinten megengedett (privilégium szint 0-3), az írása pedig csak a 0-s privilégium szinten. Tehát az applikációk - taszkok olvashatják ezen regisztereket, de írni nem tudják. Pl. ugyanis ki akarhatja olvasni az applikáció a CR0 regiszter adott bitjéből, hogy van -e FPU. A fenntartott biteket nem lehet átírni, mindig az előbb kiolvasott értékekkel rendelkeznek.

A vezérlő regiszterek adott bitjeinek leírása:

  • CR0, bit 31: Lapozás (PG - Paging): ha bekapcsolt a lapozást (paging) engedélyezi, ha kikapcsolt tiltja. Ha kikapcsolt az összes lineáris cím fizikai memória címet jelent! A lapozást csak védett módban használhatjuk (CR0.PE = 1). Ha valós módban akarnánk használni általános védelmi hibát (#GE - general protection error) kapunk.
  • CR0, bit 30: Cache tiltása (CD - Cache Disable): amikor ez a flag (CD) illetve a következő NW flag kikapcsolt - 0 - akkor az egész fizikai memória mind belső és külső cache-elése engedélyezett. Az alábbi táblázat foglalja össze röviden e két bit kombinációi által kialakítható cache-elést.
  • CR0, bit 29: Nem átíró (NW - Not Write-through): Ha a fenti CD illetve ez az NW flag 0, akkor write-back üzemmódban van a processzor (a PentiumŽ, illetve P6 család processzorai), vagy write-through üzemmódban (az Intel486™ processzor).
Cache működési módok:
CD
NW
Cache-elés illetve írás / olvasási mód
L1
L2
0
0
Így ad a cache-elés legnagyobb teljesítményt.
- Az olvasási találatok (read hit) elérhetőek a cache-ben, az eredménytelen keresés (read miss) után pedig a memóriából

- Az írási találat frissíti a cache-t

- (PentiumŽ illetve P6 processzoroknál) az írás elhibázása után frissítődik a memória

- (P6 processzorok) Az írás elhibázása (write miss) cache vonal betöltést (cache line fill) okoz; az írás sikeressége (write hit) több processzor esetén az eddig megosztott cache vonalakat kizárólagossá teszi az MTRR kontrolja alatt.

- (Intel486™) Minden írás frissíti a memóriát is, az írás hiba nem okozza a cache vonalak betöltését (cache line fill)
- Az Invalid (érvénytelen) cache beállítás megengedett az MESI értelmében.

- A külső snoop megengedett.

Igen

Igen

Igen

Igen
 
 
 
 

Igen

Igen

Igen

Igen

Igen

Igen
 
 
 
 
 
 
 
 
 
 
 
 

Igen

Igen

0
1
Hibás beállítás, általános védelmi hibát (general-protection error) ad vissza 0-s hibakóddal
NA
NA
1
0
A memória koherencia fenntartott.

- Az olvasás sikeressége esetén a cache-ből olvasunk, az olvasás elhibázásakor nincs helyettesítés

- Az írás elhibázásakor a cache frissítve van

- (P5 és P6) Csak megosztott cache vonalra történő írás, illetve írás elhibázás frissíti a fizikai memóriát
- (Intel486™) Minden írás egyben frissíti a memóriát WT#
- (P5) Az írás találat (write hit) a megosztott (shared) cache vonalakat kizárólagossá (excusive) teszi az WB/WT# kontrolja által
- Az Invalid (érvénytelen) cache beállítás megengedett az MESI értelmében.

- A külső snoop megengedett.

Igen

Igen
 
 

Igen

Igen
 
 

Igen

Igen

Igen

Igen
 
 
 
 
 
 
 
 
 
 

Igen

Igen

1
1
A memória koherencia nincs fenntartva, ez a bekapcsolás vagy reszet utáni állapot:

- Olvasási találat után a cache-hez fordul, e hiányában nincs helyettesítés
- Írási találat frissíti a cache-t.

- Írási találat hiányában a memóriához fordul

Igen

Igen

Igen

Igen

Igen

Igen

1.1. táblázat: Cache működési módok

Magyarázat: cache-elési terminológa

Az Intel Architektúrájú processzorok a Pentiummal kezdődően a MESI (modified, exclusive, share, invalid) cache protokollt használják, hogy fenntartsák a koherenciát a belső illetve más processzorok cache-eivel. Az alábbi események fordulnak elő a működés során:

  • Cache line fill: amikor a processzor érzékeli, hogy a memóriából olvasunk egy operandust akkor a memória azon részét beolvassa a cache-be (L1, L2, vagy mindkettőbe). Ezt úgy teszi, hogy egy a 32 bájtos (256 bites) cache vonalat felhasználva beolvassa az adott 32 bájtot, 4 órajel ciklussal. (Ugyanis a rendszersín 64 bites). Ezt nevezzük cache line fill-nek.
  • Cache/read hit: Ha abból a memória területből olvasunk, ami már cache-elve van, akkor az olvasáskor a processzor már a cache-ből olvashatja, s nem kell a memóriára várni.
  • Write hit: Amikor a processzor a memória egyik cache-elhető területébe kíván írni akkor először megvizsgálja a cache-t létezik -e a cache-ben az a memória rész. Ha létezik a valós megfelelő cache vonal akkor, ide a cache-be lehet írni ahelyett, hogy a memóriába kellene. (Persze ez a nem write through, WT#-ra is igaz, hisz az csak átír.)
  • Write miss: Ha nincs annak a memória területnek cache vonal foglalva, akkor cache line fill történik, így lefoglalódik az írás számára a cache vonal.
Lássuk a különböző processzorok cache-einek karakterisztikáját:
Cache vagy buffer
Karakterisztika
L1 Utasítás cache - P6 vagy P5 processzorok: 8 vagy 16 KBájtos, 4 utas asszociatív, 32 bájtos cache line (régi Pentiumok 2 utas t. asszociatív)
- Intel486™: 8 vagy 16 KBájt 4 utas asszociatív, 16 Bájt cache line, az utasítás illetve adat cache e 8 v. 16 KBájtban van együtt
L1 Adat cache - a P6 családba tartozó processzorok: 8 vagy 16 KBájt, 2 utas asszociatív, 32 bájtos cache line szélesség.
- Pentium processzor: 8 vagy 16 KBájt, 4 utas asszociatív 32 bájt cache line, régebbi Pentiumnak: 2 utas asszoc.
- Intel486™: lásd L1 utasítás cache
L2 cache - P6 processzorok: 256, 512 KBájt vagy 1 MBájt 4 utas asszociatív, 32 bájtos cache line-nal (1 MB L2 cache = super cache)
- Pentium: rendszer - alaplap függő, ált: 256 - 512 KBájt, 4 utas asszociatív, 32 bájt cache line méret
- Intel486™: rendszer függő (ált. 256 KBájt)

1.2. táblázat: 32 bites, x86-os processzorok cache-einek jellemzői

  • CR0, bit 18: Illesztés vizsgálat (AM - Allignment Mask): erről már beszéltünk az EFLAGS AC flagjánál. Ha AM = 1, akkor automatikus illesztés vizsgálat történik, egyébként nem. Ennek az automatikus illesztés vizsgáltnak a feltétele, hogy a már említett AC flag is egyenlő legyen 1-gyel, a CPL = 3 (felhasználói programok), illetve a védett, vagy virtual8086-os módban legyen.
  • CR0, bit 16: Írásvédelem (WP - Write protect): Letiltja a kernel szintű rutinoknak, hogy írhassanak a felhasználói szintű read-only lapokba, ha WP = 1. Ha WP = 0 akkor a kernel írhat a felhasználói read-only lapokba.
  • CR0, bit 5: Numerikus hiba (NE - Numeric Error): Ha bekapcsolt engedélyezi az belső - natív mechanizmust, mely jelzi az FPU hibákat, ha kikapcsolt akkor a PC-stílusú FPU hibajelzés lesz a használt.
  • CR0, bit 4: Kibővítés flag (ET - Extension Type): A P5 illetve P6 processzorokban ez fenntartott bit - értéke 1. Az Intel386™ illetve Intel486™ processzorokban arra szolgál, hogy jelezze (ha értéke egy), támogatja -e a Intel 387 DX utasításokat.
  • CR0, bit 3: Taszk kapcsolás bit (TS - Task Switched): Ha bekapcsolt, elősegíti elmenteni az FPU állapotát taszk váltáskor, és addig nem enged az FPU-hoz férni amíg el nem mentettük a tartalmát. Ha a mentés ideje alatt akar az új taszk hozzáférni, akkor az eszköz nem hozzáférhető (#NM - device-not-avaible) kivétel generálódik.
    (Az FPU állapotának lementése kicsit összetett három biten alapul: EM, MP, TS. Bővebben a szakirodalomban.)
     
  • CR0, bit 2: Emuláció (EM - Emulation): Ha bekapcsolt jelzi, hogy nincs a processzornak se belső se külső koprocesszorra. Ha ilyenkor (EM=1) FPU utasítást akarunk végrehajtani, akkor az eszköz nem hozzáférhető (#NM) kivételt kapunk. Ha kikapcsolt jelen van az FPU. (Ha nincs FPU jelen, akkor emulációval lehet helyettesíteni, ekkor az összefüggő EM, MP, TS flageket megfelelően kell beállítani.)
  • CR0, bit 1: Koprocesszor felügyeletét szolgáló bit (MP - Monitor Coprocessor): Kontrolálja a WAIT utasítás (vagy FWAIT) hatását az FPU-ra. (TS és EM flagekkel együtt.)
  • CR0, bit 0: Védett mód engedélyezése (PE - Protection Enable): A védett módba kapcsolhatunk, ha PE = 1 (megfelelő előkészületek után). Amennyiben PE = 0 akkor valós címzésű módot (~valós módot) használunk. (Ahhoz, hogy még a lapozást is használjuk, a PE = 1-re állítása után még PG-t is 1-re kell állítani.)
  • CR3, bit 4: Lap szintű cache tiltása (PCD - Page-level Cache Disable): Az adott lapcímtárak cache-elését szabályozza. Ha bekapcsolt, tiltott a cache-elés, ha kikapcsolt engedélyezett. Ez csak a processzoron lévő cache-re van hatással (L1, és ha van L2). Ezen bitnek nyílván csak akkor van jelentősége, ha a lapozás használt (PE = 1 és PG = 1) és a CD (cache disable) flag a CR0-ban nem bekapcsolt.
  • CR3, bit 3: Lap szintű átlátszó átírtás (PWT - Page-level Writes Transparent): Beállítja, hogy write-through vagy write-back cache-elést használjon az adott lapcímtárra. (~A write-through csak a cache-en keresztül ír, olvas, míg a write-back csak akkor nyúl a memóriához, ha szükséges.)
  • CR4, bit 0: Virtuális 8086-os mód engedélyezése (VME - Virtual 8086 Mode Extension): Ha bekapcsolt engedélyezi virtual8086-os módban a megszakítás- és kivétel- kezelésre vonatkozó kiterjesztést. Ez a bővítmény nem használható, ha ezen bit 0. Ez a kiterjesztés meggyorsíthatja a 8086-os program futását, ugyanis nem a virtual8086-os monitort kell a megszakítások kezeléséért meghívni, hanem maga a 8086-os program (inkább környezet) kezeli le megszakításait. Egyszerűen átirányítjuk hozzá a megszakításokat. A VME bittel a már tárgyalt VIF (Virtual Interrupt Flag) bit is összefüggésben van, együttesen a megbízhatóbb működést segítik elő a multitaszkos környezetben.
  • CR4, bit 1: Védett módú virtuális megszakítások (PVI - Protected-Mode Virtual Interrupts): Ha bekapcsolt engedélyezi védett módban a VIF (Virtual Interrupt Flag) működését. Ha kikapcsolt tiltja.
  • CR4, bit 2: Time-stamp számláló olvasás tiltása (TSD - Time Stamp Disable): Ha bekapcsolt az RDTSC utasítás csak kernel privilégium szinten hajtható végre, ha kikapcsolt, akkor bármely privilégium szinten futtatható.
  • CR4, bit 3: Hibakeresés kiterjesztés bit (DE - Debugging Extension): A DR4 és DR5 debug regiszterre hivatkozik egy nem meghatározott utasítás (#UD - undefinied opcode) kivétel esetén, ha ez a bit bekapcsolt. Ha kikapcsolt nem hivatkozik rá a szoftver kompatibilitás megtartása végett.
  • CR4, bit 4: Lapméret kiterjesztésének bitje (PSE - Page Size Extension): Engedélyezi a 4 MB-os lapok használatát, ha bekapcsolt. Ha PSE flag = 0, akkor csak a 4 KBájtos lapokat használhatjuk. (Működésének feltétele, hogy a lapozás működőképes legyen.)
  • CR4, bit 5: Fizikai címkiterjesztés bitje (PAE - Physical Address Extension): Ez a P6 családtól használható csak, előző processzorokban fenntartott. Ha bekapcsolt akkor, engedélyezett a 36 bites fizikai címzés (így 64 GB fizikai memória címezhető), ha kikapcsolt akkor a 32 bites alap címzést használjuk. (4 GB fizikai memória címezhető).
  • CR4, bit 6: Géptípus ellenőrzés engedélyezése (MCE - Machine-Check Enable): Bekapcsolt állapota esetén engedélyezi a gép-vizsgálati kivétel (machine-check exception) lefutását. Ha kikapcsolt, akkor nem.
  • CR4, bit 7: Globális lap engedélyezése (PGE - Page Global Enable): (P6+) Ha ez a bit bekapcsolt engedélyezi a globális lap lehetőséget, mely annyit tesz, hogy a legtöbbet használt illetve megosztott lapokat globálissá, mindenki által elérhetővé tehetjük, a lapcímtár, vagy laptáblázat adott bejegyzésének 8. bitjének, a global bit bekapcsolásával. Amennyiben kikapcsolt a PGE bit ez a lehetőség nem használható. (Megjegyzendő, hogy az így globálisnak deklarált lapok lapbejegyzései (lapcímtár vagy laptár bejegyzései) taszk váltás, illetve a CR3 regiszter felülírásakor nem törlődnek a TLB-kből, határozatlan ideig tárolódnak. Ezek érvénytelenítésére a PGE kikapcsolása után vagy a INVLPG utasítás segítségével lehetséges.)
  • CR4, bit 8: Teljesítmény figyelő számlálók engedélyezése (PCE - Preformance-Monitoring Counter Enable): Ha bekapcsolt ez a bit, akkor engedélyezi az RDPMC utasítás bármely privilégium szinten történő futtatását, ha kikapcsolt, akkor csak a kernel futtathatja.