Generalità
In modo protetto dobbiamo gestire un indirizzamento di tipo logico/virtuale. La memoria dell'x86 è di tipo segmentato, nel senso che è presente un registro di segmento che coincide con il registro di segmento del modo reale. Varia soltanto la dimensione, che passa da 16b a 14b. Come nelle memorie segmentate è presente un offset da 16/32b. L'indirizzo logico è dato dalla somma del registro di segmento e di quello di offset, e si esprime quindi su 46bit.
Il registro di segmento è detto selettore, in quanto seleziona il segmento, mentre quello di offset indica lo sfasamento rispetto all'indirizzo di partenza del segmento. Se il registro di offset è a 32bit ogni segmento è di 4GB. La memoria logica, cioè quella che è visibile al programmatore, è divisa in 2^16 segmenti ognuno di profondità massima 4GB. La memoria logica deve essere portata nella memoria fisica e questo procedimento avviene attraverso la memoria lineare, in cui si mappano gli indirizzi in un unico corpo su 32 bit. Infatti si mette in memoria lineare solo la parte della memoria logica che si sta effettivamente utilizzando. In più la memoria lineare è divisa in due blocchi: una destinata ai processi utenti (local memory) e una dedicata all'OS (Global memory). La memoria lineare non è più segmentata.
Il trasferimento da memoria lineare a memoria fisica avviene attraverso la paginazione. La memoria lineare viene frammentata in pagine, che vengono istanziate (solo quelle occupate) in memoria fisica. La dimensione delle pagine è settabile via hardware e varia da alcuni KB a qualche MB.
Tabelle
Questo discorso vale per le macchine da 16b e da 32b, mentre non funziona sulle architetture a 64b, in quanto i bit di offset sarebbero troppi. In un'architettura di questo genere non si usano più i 14bit di segmento.
I registri di indirizzi coinvolti da un'operazione di trasferimento da/verso [BX] sono, come detto, DS ed EBX. DS:EBX determina l'indirizzo logico su 46bit. A questo punto la paginazione può essere attivata o disabilitata mediante un bit in CR0. La traduzione dell'indirizzo avviene mediante la consultazione di tabelle contenute in cache in modo da effettuarla in breve tempo (per non bloccare la pipeline).
Queste tabelle descrivono le caratteristiche di ogni segmento. Esistono due tabelle:
-Global description table (GDT), per i processi di sistema
-Local description table (LDT), per i processi utente
All'interno del processore sono presenti due puntatori a queste tabelle. Il descrittore associato ad ogni linea della tabella contiene diverse informazioni tra cui l'indirizzo di partenza di ciascun segmento nella memoria lineare, il numero di byte significativi, gli attributi (lettura, lettura/scrittura, codice, dati,…), privilegi (4 livelli). Ogni descrittore è su 8B.
Nel momento in cui si riceve una richiesta di istruzione bisogna effettuare diversi controlli.
-controllo del limite. In DS è contenuto l'indice della riga della tabella corrispondente e bisogna verificare che l'indirizzo assegnato sia minore del limite indicato dal descrittore.
-presenza. Non tutti i segmenti della memoria logica sono presenti in memoria lineare. Il bit di presenza indica se un segmento è disponibile in memoria lineare. Nel caso in cui il segmento non sia già istanziato si genera una trap, in modo da allocare tale spazio in memoria lineare.
-livello di privilegio (DPL)
-R/W, indica se il segmento è scrivibile o no
-Accessed, indica se un segmento non è stato modificato, in modo da renderlo cancellabile in caso di necessità di spazio (swapping).
All'interno di un file eseguibile non sono presenti tutte le informazioni necessarie per l'esecuzione, in quanto non tutte le istruzioni hanno gli operandi pronti nel momento della compilazione. Il file EXE contiene però informazioni su quanti sono i segmenti da utilizzare, le posizioni che bisogna utilizzare all'interno di questi e le istruzioni da eseguire.
Privilegi
Ad ogni risorsa (e quindi segmento) viene attribuito un grado di nobiltà. Ogni volta che si va a manipolare i dati contenuti all'interno di un segmento si deve avere una nobiltà compatibile a quella del segmento stesso. I gradi sono 4, con indicatori da 3 a 0, nel senso che 0 è il livello massimo di nobiltà. Grazie ai privilegi è possibile garantire l'affidabilità del codice e la qualità dei dati.
In fase di decodifica di ogni istruzione, l'hardware confronta il livello di privilegio dell'istruzione con quello del dato che deve gestire. Per essere eseguita, ogni istruzione deve avere un livello DPL maggiore rispetto al DPL del dato che manipola. Nel momento in cui un programma con un certo DPL, chiama qualcosa con un livello DPL inferiore, il processo scende di DPL. In questo modo è impossibile effettuare delle chiamate a procedure con livello più basso, in quanto una trap gestirà questa anomalia.
Paginazione
Per passare da memoria lineare a memoria fisica si effettua la paginazione. La memoria lineare e fisica sono frammentate in pagine con pagine, che normalmente hanno dimensione 4KB. Per effettuare questa conversione l'indirizzo lineare da 32b viene suddiviso in 3 parti:
-I livello (10b), indice ad una cella in una tabella che contiene l'indirizzo alla tabella di livello II. All'interno di questa prima tabella sono presenti 1024 entry.
-II livello (10b), offset rispetto all'indirizzo puntato dall'indirizzo contenuto nella tabella di livello I. La cella corrispondente contiene un indirizzo ad una locazione della memoria fisica, che indica l'inizio di una pagina.
-offset (12b), offset rispetto all'interno della pagina.
Siccome queste tabelle sono grandi, non possono essere in cache. Per questo motivo solo alcune parti (quelle più utilizzate) sono riportate in cache.
Passaggio da modo reale a modo protetto
Il modo reale è attivo principalmente in fase di inizializzazione. Tutti i PC hanno una serie di istruzioni che permettono il passaggio in modo protetto. Affinchè tutto funzioni è necessario inizializzare il kernel del SO, inizializzando la GDT. All'interno della GDT, in fase di accensione vengono inseriti quattro descrittori (zero, dati, stack e codice). L'indirizzo della GDT è messo nel GDT register.
In modo protetto, nel vettore delle interruzioni, ad ogni indice è associato il descrittore del segmento di codice che bisogna eseguire. Nel passaggio da modo reale a modo protetto è necessario che il vettore contenga 256 entry da 8B e non più da 4B.
Per attivare la paginazione è necessario settare un bit in CR0, ma prima bisogna riempire le due tabelle di indirizzi, definire l'indirizzo di testa della tabella di paginazione (CR3), riempire la cache.
Organizzazione della memoria complessiva
Il global space si trova nella parte alta della memoria, mentre la local space nella bassa. La GDT contiene tutti quei selettori che hanno il primo bit a 1. Nei sistemi più semplici è presente una sola description table ed è quindi possibile un solo user process space. Nei sistemi operativi più complessi è possibile attivare più processi contemporaneamente con associato una LDT di 2GB.
Nelle architetture X86 è presente un modello opportuno per effettuare in modo automatico un task switching. Questa operazione avviene mediante il registro TSSR, che permette il salvataggio dei registri, dello stack, dei flag e delle pagine (CR3, tabelle associate, I/O…). In questo modo un task può venire interrotto e riabilitato in tempo breve.
Phisical address extension
All'interno del progetto di Pentium III si è pensato di gestire un ABUS da 36bit, in modo da indirizzare fino a 64GB di memoria fisica. Esso viene gestito a livello di paginazione, facendo in modo che le tabelle abbiano entry da 24 bit. In questo modo è anche possibile diminuire il numero di entry di circa la metà. I restanti 12b sono di offset. Si ottiene un numero di pagine maggiore di pari dimensione.
E' possibile con questo metodo portare le pagine da 4KB a 2MB, aumentando il numero di bit dell'offset (21b).
Estensione a 64bit
Grazie all'X86-64 si è passati a processori a 64bit. In questo modo si hanno due risvolti:
-su dati, in quanto prevedono registri da 64bit, che consentono un maggiore parallelismo dei dati.
-sull'indirizzamento, in quanto l'offset è su 64bit, consentendo di fatto l'eliminazione del registro di segmento. Per ragioni di compatibilità è però necessario, e quindi si usano solo 48bit di offset.
| < Prec. |
|---|






