Caricare documenti e articoli online 
INFtub.com è un sito progettato per cercare i documenti in vari tipi di file e il caricamento di articoli online.


 
Non ricordi la password?  ››  Iscriviti gratis
 

IL PROCESSORE 80386

tecnica



APPUNTI DI SISTEMI DI ELABORAZIONE 1

PARTE TRE


CAPITOLO SEI: il processore 80386.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .........

6.1. Introduzione.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .............

6.2 Architettura.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .............

I livelli di bus



6.2.2 I segnali principali.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ......

6.2.3 Endianess.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .................

6.2.4 Cicli pipelined e non pipelined.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ..........

6.2.5 Cicli di interrupt.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ....

6.3 I registri.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .........................

6.3.1 Registri di controllo.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .............................

6.3.2 Registri di debug.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ....

6.3.3 Registro dei flags.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ....

I modi operativi del 386

6.5 Organizzazione della memoria.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .

6.5.1 Introduzione.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ..........

6.5.2 Memoria di sistema e memoria utente.......... ..... ...... .......... ..... ...... .......... ..... ...... ............................

6.5.3 Generazione degli indirizzi.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ...............

6.6 Descrittori.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ................

6.6.1 Descrittori di segmento.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ......................

6.6.2 Impiego del bit D.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ..

6.6.3 Descrittori di controllo.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ......................

6.7 Task State Segment.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ............................

6.6.4 Struttura del TSS.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ..

6.8 La paginazione.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ........

6.8.1 Introduzione.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ..........

6.8.2 Due livelli di paginazione.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .................

6.8.3 Paging cache.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ........

6.8.4 Struttura delle Page entry.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .................

6.8.5 Page fault.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ..............

6.9 Memoria lineare.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ....

6.10 L'emulazione 8086.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .

6.10.1 Modalità reale.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ...

6.10.2 Virtual Mode 8086.......... ..... ...... .......... ..... ...... .......... ..... ...... .......... ..... ...... ...........................







CAPITOLO SEI: il processore 80386



6.1. Introduzione


Elenchiamo di seguito le principali caratteristiche del processore 80386, sottolineando le novità rispetto al precedente 80286.


architettura a 32 bit: i registri interni, la ALU, l'Address Bus e il Data Bus sono a 32 bit (nella versione 386SX l'Address Bus ha 24 fili e il Data Bus 16, come nel 286)

4 GB di indirizzo fisico: infatti abbiamo 32 fili di indirizzo, quindi 2 = 4 GB di memoria indirizzabile (16 MB per il 386SX)

64 TB di indirizzo logico: infatti l'indirizzo logico, come vedremo, è formato da 32+14=46 bit, e quindi 2 = 64 TB di memoria logica indirizzabile (anche il 386SX)

Instruction pipelining: l'architettura sfrutta maggiormente la tecnica di pipelining (tra l'altro un ciclo di bus dura 2 colpi di clock, come nel 286, mentre nell'8086 durava 4 colpi di clock)

Coda di prefetch da 16 byte, mentre il 286 l'aveva da 6 byte

Paginazione: la Memory Management Unit del 386 è simile a quella del 286, ma mentre questa prevedeva solo la segmentazione, la MMU del 386 offre anche la paginazione. Vedremo come è possibile configurare la memoria in modo da essere solo segmentata, solo paginata o entrambi

Cache controller 82385: il 386 è predisposto per funzionare 545b16f con un cache controller esterno progettato apposta

Compatibilità 286: è possibile configurare un segmento di memoria in modalità 286; su quel segmento le operazioni e gli operandi sono a 16 bit

Compatibilità 8086:da una parte si ha il modo reale, già presente nel 286, che è la modalità di avvio del processore, in cui il 386 si comporta sostanzialmente come un 8086; dall'altra si ha l'8086 Virtual Mode, cioè l'emulazione di una o più macchine 8086 in ambiente protetto, dove, all'interno di ciascuna macchina virtuale, le istruzioni che il task vengono interpretate come istruzioni dell'8086

Sia in modalità reale che protetta sono disponibili comunque 2 nuovi registri di segmento: FS e GS; si hanno quindi in totale 6 registri di segmento contro i 4 del 286

Aggiunta di registri orientati al debugging e ai test


6.2 Architettura


I livelli di bus


L'architettura dell'80386 mostra tre livelli di bus: un bus di sistema a 32 bit al quale possono essere agganciati anche altri microprocessori (multibus), un bus locale a 16 bit al quale si affacciano interfacce verso i dispositivi classici (seriale 8251, timer 8254, PIC 8259, PROM...) e infine un bus di CPU a 32 bit sul quale si appoggiano il coprocessore matematico 80387, la RAM e la cache.


Con riferimento alla figura 2 della slide 589 (sez.9), concentriamo l'attenzione su tre parti dell'architettura: la Paging Unit, la Code Queue e la Bus Interface Unit. Mentre nel 286 è presente la sola unità di segmentazione, nel 386 compare anche l'unità di paginazione; è importante notare che l'unità di paginazione si trova a valle dell'unità di segmentazione, e questo significa che la paginazione viene applicata su indirizzi già segmentati.

La coda di prefetch è di 16 byte, più lunga se confrontata con i 6 byte del 286; avendo un Bus Dati con parallelismo più elevato, è corretto mantenere un equilibrio allungando la coda di prefetch.

L'ultimo componente su cui ci soffermiamo è la Bus Interface Unit, composta dall'Address driver, dal Pipeline/bus size control e dal MUX/transceiver. Questa interfaccia gestisce in modo differente i segnali di indirizzamento e di dato, a seconda che si tratti di un 386DX o di un 386SX. Come vediamo subito dopo, in particolare i segnale BEx devono essere generati in un modo particolare.

6.2.2 I segnali principali


Analizziamo in questo paragrafo i principali segnali che escono/entrano dal 386 (ved i anche slide 590-591).


Segnali di indirizzo


A2 - A31 (30 fili) e BE0 - BE3 (4 fili) per il 386 DX

A1 - A (23 fili) e BHE, BLE (2 fili) per il 386 SX


Con i 30 fili di indirizzo si possono indirizzare 4Gb con una granularità di una DoubleWord (4 byte); tramite i fili BE0 - BE3 è possibile indicare esattamente quale BYTE dei quattro si vuole, oppure quale WORD delle quattro, oppure quale DOUBLEWORD delle quattro.

BYTE

 

WORD

 











Figura 1: i possibili indirizzamenti (386DX)


Le configurazioni con il pallino indicano indirizzamenti non allineati.

Per il 386 SX il discorso è analogo ma più semplice. In questo caso con i 23 fili di indirizzo si possono indirizzare 16 Mb con granularità di una WORD (2 byte); tramite i fili BHE e BLE è possibile indicare esattamente quale BYTE dei due si vuole, oppure quale WORD delle due (vedi fig. 2).

E' importante notare che, nel caso del 386DX, dal processore escono in totale 30+4 fili contro i 32 dell'Address Bus. Questo significa che in qualche modo i fili di indirizzo A0 e A1 dell'Address Bus devono essere "costruiti" a partire dal valore dei segnali BE0-BE3. La logica che genera questi due fili di indirizzo è rappresentata in fig.3.








Figura 2: i possibili indirizzamenti (386SX)










Figura 3: costruzione dei segnali A0 e A1

Segnali di dato


D0-D31 (32 fili) per il 386 DX

D0-D15 (16 fili) per il 386 SX



Segnali di controllo


W/R: fili di Write e Read, come nel 286

D/C: fili di Data e Control

M/IO: Trasferimento in memoria o trasferimento I/O


Questi 3 segnali definiscono il tipo di ciclo sul bus eseguito dalla CPU secondo la seguente tabella.


M/IO

D/C

W/R

tipo di ciclo




INTA




I/O READ




I/O WRITE




MEM CODE READ (FETCH)




HALT o SHUTDOWN




MEM DATA READ




MEM DATA WRITE


CLK2: come nel 286, il clock ha frequenza doppia rispetto alla frequenza del processore

LOCK: permette di rendere indivisibile l'istruzione corrente

NA:  definisce la modalità del ciclo (pipeline o non pipeline) che vediamo tra poco

BS16: quando è attivo, indica che il bus è a 16 bit (permette la compatibilità con  memorie progettate per bus a 16 bit; vedi slide 593 in basso)


ADS: Address Strobe


READY: indica la conclusione di un trasferimento sul bus (se non torna attivo, la CPU inserisce cicli di WAIT)

HOLD: richiesta per il controllo del bus da parte di un altro bus master (DMA controller, CPU...)

HLDA: acknowledge per il controllo del bus


PEREQ, BUSY, ERROR: segnali relativi al coprocessore


6.2.3 Endianess



La memorizzazione delle informazioni avviene con il criterio "little endian" : nei byte di indirizzo basso vengono memorizzati i bit meno significativi.



 


6.2.4 Cicli pipelined e non pipelined


Il 386 può eseguire due tipi di cicli, ognuno composto da 2 colpi di clock:


ciclo pipelined

ciclo non pipelined


Se il segnale di controllo NA è attivo (attivo basso), allora il processore esegue dei cicli pipelined. Nella slide 594 sono presenti due diagrammi temporali a confronto, in alto quello relativo a cicli pipelined, in basso quello relativo a cicli normali.

Come si può notare dalle figure, nel ciclo pipelined i segnali di controllo e gli indirizzi per il ciclo i sono validi già a partire dalla metà del ciclo i-1. L'effetto che si ottiene è quello di allungare l'intervallo di tempo che intercorre tra la validità degli indirizzi e quella dei dati, in modo da dare più tempo alla memoria/dispositivo di presentare i dati.


6.2.5 Cicli di interrupt


Il ciclo di interrupt è composto da cicli di 3 colpi di clock ciascuno, tra i quali è interposto un ciclo di IDLE lungo 4 colpi di clock. Per tutta la durata (10 colpi di clock), i principali segnali di controllo sono LOW, eccetto i segnali BE1-BE3 e il segnale A2, che vale 1 nella prima parte e vale 0 nella seconda parte.

Nel primo ciclo avviene l'acknowledge dell'interrupt (il processore informa il dispositivo mittente di aver ricevuto l'interrupt), nel ciclo di IDLE l'interrupt controller gesti­sce l'arbitraggio e risponde all'interrupt, nel terzo ciclo avviene la lettura, sul Data Bus, dell'indice nel vettore delle interruzioni.


6.3 I registri


Con le eccezioni che vediamo tra poco, i registri presenti sono gli stessi del 286, ma vengono estesi a 32 bit.















Figura 4: i registri dell'80386

I classici registri del 286, cioè AX,BX,CX... sono estesi a 32 bit e cambiano nome in EAX, EBX, ECX....

I registri, o meglio selettori, di segmento CS, DS, ES... rimangono a 16 bit.

I registri per la gestione del modo protetto GDTR e IDTR sono estesi a 32+16 bit, mentre i registri LDTR e TR rimangono a 16 bit.


Come abbiamo già accennato, le novità sono rappresentate da 2 nuovi registri di segmento, FS e GS, e da una serie di registri di supporto, utili per certe funzioni particolari come il controllo, il debug e i test (vedi fig. 5).


CRi = Registri di controllo

CR0: coincide con la Machine Status Word del 286; contiene la configurazione della macchina

CR1: non visibile al set delle istruzioni

CR2 e CR3: riguardano i meccanismi di paginazione


DRi = Registri di debug

DR0-7 : registri utilizzati per memorizzare informazioni riguardanti il debugging (DR4 e DR5 non sono visibili al set di istruzioni)



















Figura 5: i nuovi registri di controllo, debug e test


TRi = Registri di test

T6 e T7: sono gli unici gestibili dall'utente e servono nel self test sul meccanismo di paginazione; gli altri registri sono usati come LFSR (Linear Feedback Shift Register) per l'autodiagnostica del processore in fase di collaudo e controllo (in questo caso occorre attivare il RESET; il risultato del test viene riportato nel registro EAX).


6.3.1 Registri di controllo


Vediamo quali sono le funzioni di registri di controllo (vedi anche slide 599 retro).


CR0


Questo registro è compatibile con la Machine Status Word (MSW) del 286. I bit importanti hanno il significato riportato in tabella.


PE=0/1

386 in Real Mode/386 in Protected Mode

MP=0/1

Coprocessore matematico non presente/presente

EM=1

Il 386 genera un'eccezione ogni qualvolta trova un'istruzione floating point. E' possibile utilizzare questo meccanismo per emulare le istruzioni floating-point

TS

Come nel 286, viene settato ogni volta che avviene un task switch

ET=0/1

E' presente un coprocessore 287/387. Il 386 è in grado di gestire entrambi i coprocessori, ma il protocollo di comunicazione è diverso (nuovo!).

PG=0/1

La paginazione è disabilitata /abilitata (nuovo!)


CR2

In questo registro l'80386 deposita il valore dell'ultimo indirizzo lineare a 32 bit che ha causato un page fault (eccezione 14). Questo indirizzo può essere utile nel caso in cui si voglia risalire alla causa del page fault (vedremo più avanti che cos'è un indirizzo lineare).


CR3

Questo registro è chiamato anche Page Directory Base Register (PDBR) perché contiene l'indirizzo fisico (su 20 bit) della Page Directory delle pagine (vedremo più avanti l'organizzazione delle pagine).


6.3.2 Registri di debug


Vediamo quali sono le funzioni di registri di debug.


DR0 - DR3

Questi 4 registri contengono gli indirizzi lineari su 32 bit dei breakpoint settati.



 

Figura 6: i registri di debug

DR6 (Debug status register)



Contiene l'informazione relativa a quale evento ha scatenato l'interrupt 1 (Single Step trap); i possibili eventi sono i seguenti:


L'indirizzo dell'istruzione attuale coincide con uno degli indirizzi contenuti in DR0-DR3; il bit Bi relativo è settato

L'esecuzione avviene in modalità Single Step (modalità settata dall'eventuale debugger); il bit BS è settato

E' avvenuto un tentativo di modifica dei registri DRi; il bit BD è settato

E' avvenuta una Task Switch trap; il bit BT è settato



DR7 (Debug control register)



All'interno di DR7, per ogni indirizzo (e quindi registro) di breakpoint, ci sono i seguenti campi:


RWi : indica il tipo di accesso che determina il breakpoint


RW

tipo di accesso




code fetch (breapoint sulla lettura del codice)



Data write (breakpoint sulla scrittura dei dati)






Data R/W (breakpoint sulla lettura o scrittura dei dati)



LENi : specifica il tipo di allineamento con cui interpretare gli indirizzi scritti nei registri DR0-DR3


LEN

tipo di allineamento




allineamento al byte (32 bit di indirizzo)



allineamento a word (bit meno significativo forzato a 0)






allineamento a double word (primi 2 bit meno significativi forzati a 0)



Li : abilitazione locale; il breakpoint è valido solo nel task attuale (questo bit è resettato nel momento in cui avviene un task switch)


Gi : abilitazione globale; il breakpoint è valido per ogni task


E' presente anche un campo GD il quale, se posto a 1, blocca i registri di debug in modo tale che non sia possibile modificarli.


6.3.3 Registro dei flags


Vediamo quali sono i bit più importanti del registro dei flags EFLAGS (vedi anche slide 601 retro)


Figura 7: il registro EFLAGS


Ogni task del sistema ha il suo registro dei flags.


Gli unici bit nuovi rispetto al 286 sono i seguenti due:


RF (Resume flag): questo flag è legato ai registri di debug; tramite RF è possibile mascherare selettivamente alcune eccezioni durante la fase di debugging.


VM (Virtual 8086 Mode): quando questo flag è azzerato, il processore opera nei modi  80386 Protected Mode, 80286 Emulation Mode e Real Mode. Quando VM è settato, il processore esegue il task secondo le modalità Virtual Mode 8086, pur conservando i meccanismi di protezione al di fuori del task.


I modi operativi del 386


Per chiarire meglio l'ultimo punto, presentiamo qui i modi operativi offerti dal 386.


REAL MODE: emulazione 8086/8088, 1Mb di memoria gestibile, 20 bit di indirizzo, 16 di dato, mondo MS-DOS


PROTECTED MODE: abilitate tutte le protezioni e le priorità del 386; da questo ambiente possono essere selezionati due modalità operative:

80286 PROTECTED MODE (286 EMULATION): emula il 286 con 24 bit di indirizzo e 16 bit di dato

VIRTUAL MODE 8086: uno o più task possono essere eseguiti in questa modalità; ogni task utilizza una macchina 8086 virtuale in cui può operare il DOS (modalità usata da alcuni sistemi operativi per attivare finestre DOS). Nota: le istruzioni eseguite dal task vengono interpretate secondo lo stile 8086, quindi senza protezioni all'interno del task, ma al di fuori di questo ci sono tutte le protezioni del 386.


6.5 Organizzazione della memoria

6.5.1 Introduzione


L'organizzazione della memoria è molto simile a quella già incontrata nel 286, eccetto naturalmente per le dimensioni, che qui sono maggiori.

Distinguiamo tra memoria logica e memoria fisica. La prima è quella indirizzabile tramite l'indirizzo logico su 46 bit, la seconda è quella indirizzabile dal bus di 32 bit (quella presente effettivamente nel sistema può essere di meno).

Il 386, come il 286, attua la segmentazione della memoria: ogni segmento è lungo 2^32 byte = 4 Gbyte e possono esserci fino a 2^14 = 16K segmenti, per un totale di 2^46 = 64 Terabyte. I segmenti sono tra di loro adiacenti e ciascuno di essi possiede una serie di attributi.


8 byte

 

4 Gbyte

 
Mem.logica  tabella descrittori

A ciascun segmento di memoria è associato un oggetto di tipo descrittore (di 8 byte), che raccoglie le caratteristiche e gli attributi del segmento. Quindi abbiamo 2^14 descrittori di segmento che sono organizzati in tabelle (le vedremo tra poco).

Esistono anche descrittori che non sono relativi a segmenti di memoria, ma ad "oggetti" di sistema, cioè descrivono certe strutture importanti del sistema, per esempio la tabella dei descrittori di segmento.

Esiste un terzo tipo di oggetto descrittore, chiamato GATE e riguarda i meccanismi di controllo per il passaggio tra procedure all'interno di un processo utente (intratask) o tra processi utente (intertask).

Approfondiremo nei paragrafi successivi il ruolo di questi descrittori nella gestione della memoria.


Distinguiamo tre tipi di indirizzo presenti nel 386: l'indirizzo logico, l'indirizzo lineare e l'indirizzo fisico.








Figura 8: i tipi di indirizzo del 386




Il primo è quello scritto nella coppia selettore-offset, il secondo si ottiene dopo la segmentazione, il terzo dopo la paginazione.

6.5.2 Memoria di sistema e memoria utente


Abbiamo accennato nel paragrafo precedente a certe tabelle che contengono i descrittori di segmento. L'organizzazione di queste tabelle è esattamente come nel 286.

Per gestire più processi utente in multitasking, la memoria logica è divisa in memoria di sistema e memoria utente: la prima è riservata ai processi di sistema, la seconda ai processi utente. La memoria di sistema ha una dimensione (logica) di 32 Terabyte ed è suddivisa in 2 =8192 segmenti. Ogni processo utente ha a disposizione una memoria logica di 32 Terabyte, anch'essa divisa in 8192 segmenti.

Sia nella memoria di sistema che nella memoria utente, per ogni segmento esiste un descrittore, e questi descrittori sono raccolti in tabelle. La tabella che raccoglie gli 8192 descrittori della memoria di sistema si chiama Global Descriptor Table (GDT). Le tabelle che raccolgono gli 8192 descrittori di ogni processo utente si chiamano Local Descriptor Table. A sua volta, ciascuna delle LDT ha un descrittore memorizzato nella GDT (vedi fig.9).


Il processo di sistema si trova sempre nella memoria fisica, essendo sempre attivo, mentre i processi utente si trovano in parte nella memoria fisica e in parte su disco. Analogamente la GDT si trova sempre in memoria fisica, mentre le varie LDT possono trovarsi anche su disco e quindi necessitano di un descrittore che si trova nella GDT.
















Figura 9: il modello di memoria logica


Il registro GDTR (Global Descriptor Table Register) è lungo 32+16 bit perché contiene l'indirizzo fisico di base della GDT e la sua dimensione.


GDTR

 




Il registro LDTR (Local Descriptor Table Register) è lungo invece 16 bit e contiene l'indirizzo logico del descrittore della LDT corrente.

Il registro GDTR contiene l'indirizzo fisico su 32 bit appunto perché la GDT si trova sempre in memoria fisica. Invece il registro LDTR contiene un indirizzo logico di 16 bit, il quale è un indice che punta a un descrittore presente nella GDT. Questo descrittore descrive la LDT attiva in quel momento. Per rendere più rapidi gli accessi, tale descrittore è sempre caricato nella cache associata al registro LTDR.


6.5.3 Generazione degli indirizzi


La generazione degli indirizzi nel 386 è del tutto analoga a quella vista per il 286. Come sappiamo, un indirizzo è formato da un selettore di segmento su 16 bit, per esempio DS, e da un offset su 32 bit. I primi 13 bit del selettore formano un indice che punta ad un descrittore di segmento (2^13=8192 descrittori), mentre il 14° bit (bit 13 nella figura 10), indica se bisogna cercare il descrittore nella GDT o nella LDT del processo attivo.



TI=0 accede alla GDT

TI=1 accede alla LDT attiva


Esaminiamo il caso in cui TI = 0.

Con i 13 bit prelevati dal selettore si forma un indice che seleziona uno degli 8192 descrittori della GDT. Per ottenere l'indirizzo fisico del descrittore, il numero D va moltiplicato per 8 e sommato all'indirizzo fisico di base della tabella, contenuto nel registro GDTR :


Una volta ottenuto il descrittore di segmento, abbiamo tutte le informazioni per ottenere l'indirizzo fisico desiderato. Vedremo i passi successivi più avanti, dopo aver analizzato la struttura dei descrittori di segmento.

Esaminiamo il caso in cui TI = 1; in questo caso occorre fare un passaggio in più.

 












Noi vogliamo ottenere un certo descrittore di segmento; questo descrittore si trova nella LDT del processo attivo; quindi dobbiamo conoscere l'indirizzo di base della LDT attiva e l'indice, all'interno di questa, del descrittore desiderato. L'indice è scritto nei 13 bit del selettore, mentre l'indirizzo di base della LDT attiva si trova nel descrittore della LDT attiva (ogni LDT ha un descrittore) e questo, infine, si trova dentro la GDT (vedi  fig.10).










Figura 10: trovare la LDT attiva


Per raggiungere il descrittore della LDT attiva, ci occorre l'indirizzo di base della GDT e l'indice, all'interno di questa, per accedere al descrittore della LDT attiva. L'indirizzo fisico della GDT si trova nel registro GDTR, mentre l'indice si trova nel registro LDTR (vedi fig 11). Utilizzando queste due informazioni otteniamo il descrittore della LDT attiva. Tramite questo descrittore otteniamo l'indirizzo di base della LDT attiva. Avendo questo possiamo raggiungere il descrittore di segmento desiderato.


Come abbiamo visto, il descrittore della LDT attiva si trova nella cache associata al registro LDTR, il cui contenuto è aggiornato ogni volta che si cambia processo attivo: questo significa che occorre accedere alla GDT solo quando avviene un cambio di processo attivo.









Figura 11: schema dell'indirizzamento in LDT


6.6 Descrittori


6.6.1 Descrittori di segmento


I descrittori di segmento sono identici a quelli del 286, ma qui viene usato tutto lo spazio disponibile nel segmento, quindi 4 word (viene usata anche la word che nel 286 era forzata a 0).

Alcuni campi sono stati ampliati e altri sono totalmente nuovi.


Figura 12: struttura del descrittore di segmento


Limit (20 bit): contiene l'indirizzo lineare del limite superiore del segmento; per motivi di spazio, il limite è espresso in 20 bit anziché in 32; tramite il bit G è possibile comunque estenderlo a 32 bit (vediamo tra poco come).

Base (32 bit): contiene l'indirizzo lineare di base del segmento.

G (1 bit): definisce il modo in cui interpretare il limite; quando G=0 il processore assume che l'indirizzo contenuto nei 20 bit del limite sia misurato in unità di 1 byte; questo significa che il segmento può avere una dimensione massima di 1 Mbyte, dimensione compatibile con i processi Virtual Mode 8086. Se invece G=1, assume che il limite sia espresso in unità di 4096 byte (2 byte), e ciò implica che un segmento può avere una dimensione discreta di n 4096 byte, dove n è un numero intero compreso tra 0 e 220.

D (1 bit): definisce l'ampiezza degli operandi (D=0: 16 bit; D=1: 32 bit) e di conseguenza indica se il segmento opera in modalità 286 o 386.

U (1 bit): bit indefinito utilizzabile dall'utente

X (1 bit): bit riservato


I bit che seguono hanno la stessa funzione che avevano nel 286.

A (1 bit): è settato quando avviene un accesso al segmento di memoria a cui il descrittore si riferisce.

TYPE (3 bit): indicano il tipo di descrittore di segmento e alcuni suoi attributi (codice, dato, stack., leggibile, scrivibile...).

S (1 bit): indica se si tratta di un descrittore di segmento (S=1) o di controllo (S=0).

DPL (2 bit): Descriptor Privileg Level.

P (1 bit): se è azzerato, il segmento descritto non è presente in memoria.


6.6.2 Impiego del bit D


Come abbiamo visto, il bit D definisce la lunghezza degli operandi. La codifica assembler delle istruzioni di trasferimento tra registro e memoria prevede solo due formati:


byte size

full size


Nel primo caso gli operandi sono di 8 bit, nel secondo caso possono essere di 16 o 32 bit; il bit D specifica appunto una di queste due misure. Si hanno quindi queste possibilità:




80386 D=0

80386 D=1

byte size

8 bit

8 bit

8 bit

full size

16 bit

16 bit

32 bit


Es:

(1) MOV [BX],AH (2) MOV WORD PTR[BX], AX


Nel primo caso la semantica dell'istruzione è chiara: abbiamo un trasferimento byte-size; nel secondo caso la semantica è ambigua: vogliamo copiare una word o una dword? (ricorda che AX è a 32 bit). Per eliminare l'ambiguità occorre utilizzare il flag D: se D=0 abbiamo una copia word-size, se D=1 abbiamo una copia dword-size.


Ecco un altro esempio in cui vediamo la codifica di un'istruzione MOV Immediate full-size.



OPC: codice di MOV Immediate full-size

001: registro destinatario: CX

Se D=1 questa istruzione corrisponde a


MOV CX, 66253778  (trasferimento di 4 byte; il prossimo OPCODE è 11)


Se D=0 l'istruzione corrisponde a


MOV CX, 3778  (trasferimento di 2 byte; il prossimo OPCODE è 25)


Nota che il bit D è relativo a un intero segmento. In altre parole, tutte le istruzioni presenti in quel segmento sono interpretate secondo il valore di D. E' però possibile utilizzare un operando di dimensione differente da quella specificata per il segmento in cui è contenuto, anteponendo un operand-size override prefix.


Per esempio, in un segmento a 32 bit (quindi con D=1) l'istruzione:


MOV AX, DS:[offset]


è interpretata dall'assemblatore come un'istruzione con operandi a 16 bit, perché abbiamo scritto AX invece di EAX.

L'istruzione è codificata così:


OPC REG offset a 32 bit

prefix  opcode AX offset


Il prefisso 66, inserito dall'assemblatore, indica che quell'istruzione è da intendersi con operandi a 16 bit nonostante si trovi in un segmento a 32 bit.


Un simile meccanismo lo troviamo anche per gli indirizzi. L'address-size override prefix modifica il valore di default del segmento fissato dal bit D.


In un segmento a 32 bit (D=1), con l'istruzione:


MOV EAX, DWORD PTR DS:[SI]


indichiamo che l'indirizzamento in memoria è su 16 bit perché abbiamo scritto SI invece di ESI.

L'istruzione è codificata così:


OPC    REG offset a 16 bit

prefix  opcode EAX offset


Il prefisso 67, inserito dall'assemblatore, indica che l'indirizzamento va fatto a 16 bit.

Combinando i due prefissi di override visti, si hanno 4 possibilità:



8B 06

MOV EAX, DWORD PTR DS:[ESI]

indirizzo e registro a 32 bit


8B 06

MOV AX, WORD PTR DS:[ESI]

registro a 16, indirizzo a 32


8B 06

MOV EAX, DWORD PTR DS:[SI]

registro a 32, indirizzo a 16


8B 06

MOV AX, WORD PTR DS:[SI]

indirizzo e registro a 16

6.6.3 Descrittori di controllo


Come nel 286, i descrittori di controllo si dividono in due categorie:


Descrittori di flusso o Gate Descriptor

Descrittori di oggetti di sistema


Descrittori di flusso


Figura 13: struttura del descrittore di flusso

Destination SELECTOR (14 bit): contiene l'indirizzo logico del descrittore del segmento di codice in cui si trova la subroutine chiamata; se type = 5, contiene l'indirizzo logico del TSS Decriptor

Destination Offset (32 bit): punto di ingresso nel codice di segmento della subroutine chiamata (non usato se type=5); nel 286 questo campo era di 16 bit

DWord Count (5 bit): contiene il numero di word o dword da copiare dallo stack del chiamante nello stack del chiamato (usato solo se type = 4)


TYPE:

0: Indefinito

4: 286 Call Gate

5: Task Gate

6: 286 Interrupt Gate

7: 286 Trap Gate

C: 386 Call Gate

E: 386 Interrupt Gate

F: 386 Trap Gate



Descrittore di oggetti di sistema


Figura 14: struttura del descrittore di sistema

Base (32 bit):

Se type = 2: è l'indirizzo lineare di base di una tabella dei descrittori locali (LDT)

Se type = 1,3,9,B: indirizzo lineare di base del Task State Segment

Limit (20 bit)

Se type = 2: limite superiore della tabella dei descrittori locale (LDT)

Se type =1,3,9,B: limite superiore del TSS


TYPE:

1: 286 TSS disponibile

2: LDT

3: 286 TSS non disponibile

9: 386 TSS disponibile

B: 386 TSS non disponibile



Vediamo nel prossimo paragrafo il significato delle diciture 386 TSS e 286 TSS.

6.7 Task State Segment


Il processore 386 è in grado di eseguire due tipi di task, i task 286 e i task 386.

Come nel 286, anche qui ogni task ha un Task State Segment che lo descrive; siccome si hanno due tipi di task, si avranno anche due tipi di TSS differenti: il 286 TSS e il 386 TSS.

Il primo è identico a quello già visto con il 286, mentre il secondo presenta due novità sostanziali:



è organizzato su 32 bit invece che 16

ha una parte detta BITMAP I/O che nel 286 non esiste

 







6.6.4 Struttura del TSS


Vediamo in questo paragrafo la struttura di un Task State Segment per un task 386.

Come si può notare, la struttura è molto simile a quella TSS del 286, con le seguenti eccezioni.

compare un campo in cui è contenuto il valore del registro CR3, cioè l'indirizzo della Page Directory (vedremo più avanti il meccanismo della paginazione)

un campo BITMAP offset che fornisce l'indirizzo della prima cella della BITMAP degli I/O che si trova più sotto


 

















Figura 15: struttura del TSS 386

Vediamo adesso quale è la funzione della Bitmap degli I/O (detta anche I/O Permission Map), incominciando col dire che tutti i meccanismi di protezione visti nel 286 valgono allo stesso modo anche nel 386:

protezione tramite attributi dei segmenti

protezione tramite livello di privilegio


Nel 386 alcuni di questi meccanismi sono stati potenziati, e questo è il caso dei privilegi sulle operazioni di I/O.

Infatti, nel 286, per verificare la legittimità di un'operazione di I/O, si va a confrontare il CPL dell'istruzione di I/O con l'IOPL scritto nella parola dei flags. Se il CPL è numericamente superiore all'IOPL (e quindi l'istruzione non ha un privilegio abbastanza grande) il 286 genera un trap.

In altre parole il 286 non è in grado di distinguere tra i vari tipi di I/O, li tratta tutti nello stesso modo. Questa politica è molto limitante e rende impossibile lasciare il permesso all'utente di manipolare certi I/O mentre altri rimangono protetti.

La soluzione consiste nell'avere una mappa dei permessi degli I/O, in cui ad ogni indirizzo di I/O è associato univocamente un bit; la mappa è grande al massimo 64 Kbit, cioè 8 Kbyte, ed è situata in fondo al TSS. Al primo bit è associato l'indirizzo dell'I/O numero 0, al secondo bit è associato l'indirizzo dell'I/O numero 1, e così via.

Quando un'istruzione fa riferimento ad un indirizzo di I/O, avviene in confronto tra CPL e IOPL. Se il CPL è numericamente superiore all'IOPL, nel caso di un Task 286 la CPU genera una trap; nel caso di Task 386, si va a guardare nella Permission Map; se il bit corrispondente è resettato, allora l'istruzione può comunque accedere a quell'I/O, altrimenti viene generata una trap.

Questa tabella può essere manipolata solo da processi con livello di privilegio 0.


6.8 La paginazione


6.8.1 Introduzione


Vediamo in questo paragrafo il meccanismo di paginazione introdotto con il 386. Esistono due motivi fondamentali per cui è stato introdotta questa novità.


Nel caso del 286 la memoria virtuale è stata realizzata tramite la segmentazione; l'unità elementare di swapping tra memoria fisica e disco è infatti il segmento di 64Kbyte, una dimensione che è piccola rispetto alla memoria montata normalmente sui PC. Passando al 386, e quindi a segmenti da 4Gbyte ciascuno, diventa chiaramente impossibile utilizzare tali segmenti come unità di swapping. La scelta della paginazione è quindi obbligatoria allo scopo di avere ancora la memoria virtuale. Questo è un discorso generale valido per tutti i sistemi.

La gestione contemporanea di diverse macchine 8086 virtuali pone un problema di indirizzamento. Infatti, all'interno di ciascuna sessione 8086, gli indirizzi si riferiscono sempre ad uno spazio che va da 0 a 1 Mbyte, mentre in realtà il Mega di memoria logica dedicato a ciascuna sessione si trova in una posizione differente all'interno della memoria logica. Allora occorre un meccanismo che trasformi gli indirizzi generati in ogni sessione 8086 in indirizzi logici corretti; tale meccanismo non può essere la segmentazione (e quindi i descrittori) perché all'interno di una sessione 8086 la modalità protetta è disabilitata (questo discorso sarà ripreso più avanti).


6.8.2 Due livelli di paginazione


La paginazione realizzata nel 386 è a due livelli. Nel primo livello si ha una tabella detta Page Directory, la quale contiene 1024 entry a 32 bit; ciascuna di queste contiene l'indirizzo di una tabella detta Page Table (secondo livello), formata da 1024 entry a 32 bit; ciascuna entry contiene l'indirizzo fisico di una pagina di memoria fisica, lunga 4Kb.

La Page Directory ha una dimensione di 4Kb (4 byte 1024), così come ogni Page Table; siccome si possono avere un massimo di 1024 Page Table, queste presentano un'occupazione massima di 4Kb 210 = 222 = 4 Mbyte. Al massimo si possono avere 1024 1024=1 M di pagine, ciascuna da 4 Kb, per un totale di 4Gb di occupazione.

















Figura 16: meccanismo della paginazione

Dopo la segmentazione, che riduce l'indirizzo logico su 46 bit all'indirizzo lineare su 32 bit (quello che troviamo scritto nei descrittori), avviene la paginazione come illustrato in fig.16.

Nel registro CR3 i 20 bit più significativi puntano ad un indirizzo fisico, allineato a 4Kb, corrispondente alla Page Directory. I 10 bit più significativi dell'indirizzo lineare formano l'indice a una certa entry delle 1024 che costituiscono la Page Directory. In questa entry c'è un indirizzo i cui 20 bit più significativi puntano ad una certa Page Table. Al suo interno, l'entry è selezionata dai 10 bit centrali dell'indirizzo lineare. Infine, in quest'ultima entry, c'è l'indirizzo fisico su 32 bit della pagina selezionata (in realtà è su 20 bit, indirizzo allineato a 4Kb, perché le pagine sono da 4Kb), alla quale si somma l'offset contenuto nell'indirizzo lineare per ottenere l'indirizzo fisico da mandare sull'Address Bus.


L'indirizzo che si ottiene a valle della paginazione è di 32 bit, ed è l'indirizzo che viene posto sull'Address Bus. E' ovvio che, a meno di non avere 4 Gbyte di memoria installata, tale indirizzo avrà i bit più significativi a zero.


6.8.3 Paging cache


Tutte queste tabelle non stanno in memoria fisica per ovvi problemi di occupazione di spazio; inoltre, a giudicare dallo schema, sembra che occorrano due accessi in memoria ogni volta che occorre codificare un indirizzo. Tutto questo renderebbe estremamente lento e inefficiente il processore.

Esiste in effetti una cache apposta per evitare il più possibile accessi in memoria quando occorre trasformare un indirizzo lineare in uno fisico. Tale cache prende il nome di Table Lookaside Buffer, è composta da 32 entry, divisa in 4 set da 8 entry ciascuno. Ciascuna entry è composta da un TAG di 20 bit e da un campo di 32 bit. Il TAG contiene i 20 bit più significativi di un certo indirizzo lineare, il campo contiene la corrispondente entry nella Page Table.

I primi 20 bit dell'indirizzo lineare vengono confrontati con tutti i TAG. Se si ha una corrispondenza, si legge l'indirizzo fisico della pagina desiderata direttamente nella Page Table entry corrispondente.

 












Se invece quell'indirizzo non è presente nel TLB, occorre seguire lo schema di fig. 16, ma può ancora insorgere una complicazione: la Page Table entry o la pagina fisica coinvolte nella codifica possono non essere in memoria fisica, abbiamo cioè un page fault, e questo implica una trap che scatena il caricamento di quelle informazioni da disco. Vediamo tra poco cosa succede in questo caso.


6.8.4 Struttura delle Page entry


Vediamo più in dettaglio la struttura delle Page entry di cui abbiamo parlato finora.







P: indica la presenza o meno in memoria fisica della Page Table puntata dall'indirizzo Page Table address

R/W: definisce l'accessibilità in lettura  e scrittura e viene considerato solo se CPL=3

U/S: indica il livello di privilegio che deve avere il richiedente per accedere alla Page Table a cui l'entry si riferisce; i 4 livelli di privilegio vengono mappati su due soli livelli: User (livello 3) e System (livello 0,1,2). Questo è utile quando si utilizza un modello di memoria flat senza segmenti di codice, dati e stack divisi, quindi con indirizzi a 32 bit su un unico spazio di 4Gb. In questo caso non si possono più utilizzare le protezioni presenti nei segmenti, e quindi occorre avere un meccanismo di protezione a livello di pagine.

A: è settato se è avvenuto un riferimento alla Page Table a cui l'entry si riferisce

USER: sono 3 bit lasciati disponibili per l'utente









P: indica la presenza o meno in memoria fisica della pagina puntata dall'indirizzo Page Frame  address

R/W: definisce l'accessibilità in lettura  e scrittura e viene considerato solo se il richiedente ha CPL=3

U/S: indica il livello di privilegio che deve avere il richiedente per accedere alla pagina a cui l'entry si riferisce; viene considerato solo se il bit U/S nel Page Directory entry è settato. In altre parole, il livello di privilegio presente nella Page Directory (bit U/S) è prioritario rispetto a quello presente nella Page Table entry.

A: è settato se è avvenuto un riferimento alla pagina a cui l'entry si riferisce

D: indica che è avvenuta un'operazione di scrittura sulla pagina a cui l'entry si riferisce


6.8.5 Page fault


Quando, durante il processo di decodifica schematizzato in  fig.16, una Page Directory entry, una Page Table entry oppure una pagina, non si trova in memoria fisica, abbiamo un page fault, il processore scatena l'interrupt 14. L'informazione relativa a quanto è successo viene memorizzata in due punti:

nel registro CR2 viene posto l'indirizzo lineare che ha scatenato il page fault

sullo stack viene posto l'indirizzo logico che ha scatenato il page fault, insieme ad un codice di errore che può essere di tre tipi:

pagina non presente

violazione di un vincolo di scrittura/lettura (bit R/W)

violazione di privilegio (bit U/S)


6.9 Memoria lineare


Nel paragrafo 6.1 abbiamo detto che il 386 può offire memoria solo  paginata e non segmentata; osservando però l'architettura del processore, si vede che l'unità di segmentazione non si può disabilitare (mentre quella di paginazione si può disabilitare tramite il settaggio del bit PG nel registro CR0). Per ottenere una memoria flat o lineare, allora, occorre fare in modo che i selettori di dato contengano lo stesso valore e così anche i selettori di codice; in questo modo l'indirizzo è dato solo dall'offset su 32 bit, per cui si ottiene uno spazio non segmentato di memoria di 4Gb. Per esempio di può fare in modo che i selettori puntino ad uno stesso descrittore, oppure a descrittori differenti contenenti le stesse informazioni.


6.10 L'emulazione 8086


Come abbiamo detto nel par. 6.4, il 386 offre quattro modi operativi:

Real mode

80286 Protected mode

80386 Protected mode

Virtual mode 8086


6.10.1 Modalità reale


In modalità reale, cioè la modalità di avvio del processore, il 386 si comporta come un 8086, ma presenta le seguenti eccezioni:

i registri sono a 32 bit, non a 16

lo spazio di indirizzamento è pari a 1Mb+64Kb


La prima eccezione è chiara: il fatto di essere in modalità reale non influenza la dimensione dei registri. La seconda eccezione va spiegata più dettagliatamente.

Se ad un indirizzo di poco inferiore a 1Mb, per esempio FFFF0h, si somma un offset pari a 10h, si ottiene un indirizzo il cui 21° bit è pari a 1:



F

F

F

F


h



1M-16








h











h



1M



Nell'8086 lo spazio di indirizzamento va da 0h a FFFFFh, cioè da 0 a 1M-1; quindi il 21° bit, quello che dovrebbe andare sul 21° filo dell'Address Bus, viene scartato, e l'indirizzo che si ottiene è 0. Invece nei processori 80x86 il 21° filo esiste e quindi viene settato ad 1. Questo significa che l'indirizzo che si può ottenere va da 0 a 10FFFFh, cioè da 0 a 1M-1+64K, perché l'offset è su 16 bit e quindi vale al massimo 64K.

In definitiva, nei processori 80x86 lo spazio di indirizzamento è più ampio di 64K rispetto a quello dell'8086; visto che questo comportamento è causa di incompatibilità, il filo A20 dell'Address Bus (corrispondente al 21° bit) è stato collegato ad un FLIP-FLOP controllabile via software, il quale permette di forzare il filo a 0, oppure lasciare che assuma il valore 1. Il settaggio di tale parametro è svolto tramite il comando A20=ON|OFF nel file di configurazione CONFIG.SYS.

Il vantaggio di avere quei 64K in più, consiste nell'avere un certo spazio per caricare parte del DOS fuori dalla memoria convenzionale; questo effetto lo si ottiene con il comando DOS=HIGH nel file di configurazione.


6.10.2 Virtual Mode 8086


L'INTEL, per motivi strettamente commerciali, ha voluto realizzare una piattaforma hardware su cui potessero girare contemporaneamente task protetti a 32 bit (WIN32), task protetti a 16 bit (WIN16) e task 8086.

Come si può ottenere un'emulazione di una macchina 8086?

Il primo modo è quello di commutare in modalità reale ogni volta che si attiva una sessione 8086 (Windows 3.0 funzionava così). Questo comporta parecchi svantaggi:

si può avere una sola sessione 8086 alla volta

lo spazio di indirizzamento coincide con il primo Mega di memoria fisica

non lo si può gestire in una finestra, perché il DOS gestisce direttamente la memoria video

gli switch tra task protetti e task 8086 è molto pesante perché occorre cambiare modalità


Il secondo modo consiste nell'avere un'emulazione software, cioè un interprete che prende il codice scritto per 8086 e lo converte in codice per 386, sistemando opportunamente gli indirizzi. Ovviamente questo sistema diventa inadatto in quei casi in cui le prestazioni hanno un minimo di importanza.


Il terzo modo è quello adottato dall'INTEL. Il processore gira in modo protetto, così è in grado di gestire i task WIN32 e WIN16, e quando occorre lanciare un programma scritto per 8086, si lancia un task virtual mode 8086. All'interno di tale task la generazione degli indirizzi non segue il meccanismo della segmentazione, quindi niente descrittori né protezioni, ma piuttosto il classico trucco di traslare a sinistra di 4 posizioni l'indirizzo di un registro di segmento e si sommarlo ad un offset; quello che si ottiene è un indirizzo, come abbiamo visto, che va da 0 a 1M-1+64K. Infatti, è vero che l'indirizzo che si ottiene è su 32 bit (i registri di segmento sono a 32 bit), ma solo i primi 21 bit vengono considerati, mentre i restanti bit sono forzati a zero.

Ma come si fa ad avere più task 8086 attivi contemporaneamente, se tutti generano indirizzi che che fanno riferimento al primo Mega? Per risolvere questo problema viene in aiuto la paginazione.

L'indirizzo su 21 bit generato da un task 8086 viene rimappato tramite la paginazione in una certa posizione; ogni task 8086 ha un Mega che si trova in una certa posizione della memoria fisica.


Task 8086 #1

 

Task 8086 #2

 

Task 8086 #3

 












La paginazione permette anche di non replicare parti di memoria comuni a tutti i task 8086, per esempio porzioni del DOS, ma di manterne una sola copia a cui tutti puntano.











Privacy




Articolo informazione


Hits: 3826
Apprezzato: scheda appunto

Commentare questo articolo:

Non sei registrato
Devi essere registrato per commentare

ISCRIVITI



Copiare il codice

nella pagina web del tuo sito.


Copyright InfTub.com 2024