Modalità protetta
# Modalità protetta

In informatica, la modalità protetta, chiamata anche modalità di indirizzamento virtuale protetto, è una modalità operativa delle unità centrali di elaborazione (CPU) compatibili con l'architettura x86. Essa consente al software di sistema di utilizzare funzionalità come la segmentazione, la memoria virtuale, la paginazione e il multitasking sicuro, progettate per aumentare il controllo di un sistema operativo sul software delle applicazioni.

Quando una CPU che supporta la modalità protetta x86 viene accesa, inizia a eseguire istruzioni in modalità reale per garantire la compatibilità retrospettiva con le CPU x86 precedenti. La modalità protetta può essere attivata solo dopo che il software di sistema ha configurato una tabella dei descrittori e abilitato il bit di abilitazione della protezione (PE) nel registro di controllo 0 (CR0).

La modalità protetta è stata introdotta per la prima volta nell'architettura x86 nel 1982 con il rilascio del processore Intel 80286 (286) e successivamente estesa con il rilascio dell'80386 (386) nel 1985. Grazie alle migliorie apportate dalla modalità protetta, essa è stata ampiamente adottata ed è diventata la base per tutti i successivi miglioramenti all'architettura x86, anche se molte di queste migliorie, come le istruzioni aggiunte e i nuovi registri, hanno apportato benefici anche alla modalità reale.

## Storia

L'Intel 8086, il predecessore del 286, era originariamente progettato con un bus indirizzi a 20 bit. Ciò consentiva al processore di accedere a $2^{20}$ byte di memoria, equivalenti a 1 megabyte. All'epoca, 1 megabyte era considerato una quantità relativamente grande di memoria, quindi i progettisti dell'IBM riservavano i primi 640 kilobyte per l'uso da parte delle applicazioni e del sistema operativo e i restanti 384 kilobyte per il BIOS (Basic Input / Output System) e memoria per le periferiche.

Con la diminuzione del costo della memoria e l'aumento dell'uso della stessa, la limitazione di 1 MB divenne un problema significativo. Intel intese risolvere questa limitazione, insieme ad altre, con il rilascio del 286.

## Il 286

Secondo il Manuale del Programmatore Intel 80286:

   "l'80286 rimane compatibile verso l'alto con la maggior parte dei programmi applicativi 8086 e 80186. La maggior parte dei programmi applicativi 8086 può essere ricompilata o riassemblata ed eseguita sull'80286 in modalità protetta".

La modalità protetta iniziale, rilasciata con il 286, non fu ampiamente utilizzata. Ad esempio, fu utilizzata da sistemi come Coherent (dal 1982), Microsoft Xenix (intorno al 1984) e Minix. Diverse limitazioni, come l'incapacità di accedere al BIOS o alle chiamate DOS a causa dell'incapacità di tornare alla modalità reale senza ripristinare il processore, ne impedirono un utilizzo diffuso. Inoltre, l'accettazione fu ostacolata dal fatto che il 286 consentiva l'accesso alla memoria solo in segmenti a 16 bit tramite ciascuno dei quattro registri di segmento, il che significa che potevano essere accessibili solo 4*216 byte, equivalenti a 256 kilobyte, alla volta. Poiché il cambio di un registro di segmento in modalità protetta causava il caricamento di un descrittore di segmento da 6 byte nella CPU dalla memoria, l'istruzione di caricamento del registro di segmento richiedeva molti cicli di processore, rendendola molto più lenta rispetto all'8086. Pertanto, la strategia di calcolare gli indirizzi di segmento al volo per accedere a strutture di dati più grandi di 128 kilobyte (la dimensione combinata dei due segmenti di dati) divenne impraticabile, anche per quei pochi programmatori che l'avevano padroneggiata sull'8086/8088.

Il 286 manteneva la compatibilità con il suo predecessore, l'8086, entrando inizialmente in modalità reale all'accensione. La modalità reale funzionava praticamente in modo identico all'8086, consentendo alla stragrande maggioranza del software esistente per l'8086 di funzionare senza modifiche sul nuovo 286. La modalità reale fungeva anche da modalità più basilare in cui poteva essere configurata la modalità protetta, risolvendo una sorta di problema del tipo "è nato prima l'uovo o la gallina" (La modalità reale è necessaria per configurare la modalità protetta, ma per accedere alle funzionalità estese del 286, è necessario passare alla modalità protetta. Quindi, la modalità reale e la modalità protetta dipendono l'una dall'altra, creando un dilemma simile al problema dell'uovo e della gallina). Per accedere alle funzionalità estese del 286, il sistema operativo avrebbe configurato alcune tabelle in memoria che controllavano l'accesso alla memoria in modalità protetta, impostato gli indirizzi di tali tabelle in alcuni registri speciali del processore e quindi impostato il processore in modalità protetta. Questo abilitava un indirizzamento a 24 bit che consentiva al processore di accedere a 224 byte di memoria, equivalenti a 16 megabyte.

## Il 386

Con il rilascio del 386 nel 1985, molte delle problematiche che avevano impedito l'adozione diffusa della modalità protetta precedente furono affrontate e risolte. Il 386 venne rilasciato con una dimensione del bus degli indirizzi di 32 bit, consentendo l'accesso a 232 byte di memoria, equivalenti a 4 gigabyte. Le dimensioni dei segmenti furono anche aumentate a 32 bit, il che significa che l'intero spazio degli indirizzi di 4 gigabyte poteva essere accessibile senza la necessità di passare tra segmenti multipli. Oltre all'aumento delle dimensioni del bus degli indirizzi e dei registri di segmento, furono aggiunte molte altre nuove funzionalità con l'intenzione di migliorare la sicurezza operativa e la stabilità. La modalità protetta è ora utilizzata virtualmente in tutti i moderni sistemi operativi che funzionano sull'architettura x86, come Microsoft Windows, Linux e molti altri.

Inoltre,consapevoli dagli insuccessi della modalità protetta del 286 nel soddisfare le esigenze del multiutente DOS, Intel aggiunse una modalità virtuale separata dell'8086, che consentiva l'emulazione di più processori virtualizzati dell'8086 sul 386. Tuttavia, la virtualizzazione hardware x86 necessaria per la virtualizzazione della modalità protetta stessa dovette aspettare altri 20 anni.

Quindi, in sintesi, con il rilascio del 386, furono aggiunte le seguenti funzionalità aggiuntive alla modalità protetta:

* Paginazione
* Spazio degli indirizzi fisici e virtuali a 32 bit (lo spazio degli indirizzi fisici a 32 bit non è presente sull'80386SX e su altre varianti del processore 80386 che utilizzano il bus più vecchio del 286.)
* Offset del segmento a 32 bit
* Capacità di tornare alla modalità reale senza effettuare un reset
* Modalità virtuale 8086

## Entrare ed uscire dalla modalità protetta

Fino al rilascio del 386, la modalità protetta non offriva un metodo diretto per tornare alla modalità reale una volta che si era entrati in modalità protetta. IBM ideò un sistema di bypass (implementato nell'IBM AT) che comportava il reset della CPU tramite il controller della tastiera e il salvataggio dei registri di sistema, del puntatore dello stack e spesso dell'interrupt mask nella RAM dell'orologio in tempo reale. Questo permetteva al BIOS di ripristinare la CPU in uno stato simile e iniziare l'esecuzione del codice prima del reset. Successivamente, venne utilizzato un "triple fault" per resettare la CPU del 286, il che risultava molto più rapido e pulito rispetto al metodo del controller della tastiera (e non dipendeva dall'hardware IBM AT-compatibile, ma funzionava su qualsiasi CPU 80286 in qualsiasi sistema).

Per entrare in modalità protetta, è necessario creare prima la Global Descriptor Table (GDT) con un minimo di tre voci: un descrittore nullo, un descrittore del segmento del codice e un descrittore del segmento dei dati. In una macchina compatibile IBM, la linea A20 (21° linea di indirizzo) deve anche essere abilitata per consentire l'uso di tutte le linee di indirizzo, in modo che la CPU possa accedere a più di 1 megabyte di memoria. (Dopo l'accensione, solo le prime 20 linee possono essere utilizzate per garantire la compatibilità con software più vecchi scritti per i modelli IBM PC e PC/XT basati sull'Intel 8088). Dopo aver eseguito questi due passaggi, il bit PE deve essere impostato nel registro CR0 e deve essere eseguito un salto lontano ("far jump") per svuotare la coda di prefetching.

## Caratteristiche principali

Con il rilascio del 386, la modalità protetta poteva essere lasciata caricando i registri di segmento con i valori della modalità reale, disabilitando la linea A20 e cancellando il bit PE nel registro CR0, senza la necessità di eseguire i passaggi iniziali di configurazione richiesti con il 286.

La modalità protetta offre una serie di funzionalità progettate per migliorare il controllo del sistema operativo sul software delle applicazioni, al fine di aumentare la sicurezza e la stabilità del sistema. Queste aggiunte consentono al sistema operativo di funzionare in modo significativamente più complesso o persino impossibile senza il supporto hardware adeguato.

* Livelli di privilegioLivelli di privilegio: in modalità protetta ci sono quattro livelli di privilegio o anelli, numerati da 0 a 3, con l'anello 0 che è il più privilegiato e l'anello 3 il meno privilegiato. L'uso di questi anelli permette al software di sistema di limitare l'accesso a dati, chiamate a porte o l'esecuzione di istruzioni privilegiate.
* Compatibilità con applicazioni in modalità reale: la modalità protetta mantiene la compatibilità con la maggior parte dei programmi delle applicazioni scritti per l'8086, consentendo loro di essere eseguiti senza modifiche.
* Modalità virtuale 8086: la modalità protetta offre la cosiddetta "modalità virtuale 8086," che consente al codice scritto precedentemente per l'8086 di essere eseguito senza modifiche e contemporaneamente ad altre attività, senza compromettere la sicurezza o la stabilità del sistema.
* Gestione della segmentazione: La modalità protetta sostituisce la segmentazione in modalità reale con un sistema basato su selettori e descrittori, consentendo un maggior controllo sulla gestione della memoria.
* Paging: La modalità protetta introduce il paging, che consente al software di sistema di controllare l'accesso alle pagine di memoria. Questo permette di creare uno spazio di indirizzamento virtuale indipendente per ciascuna attività e di spostare le pagine dalla memoria principale a una memoria secondaria più grande.
* Multitasking: Grazie all'uso di anelli, call gates privilegiate e al Task State Segment (TSS), la modalità protetta permette il multitasking preemptive, consentendo a più attività di condividere il processore in modo sicuro e indipendente.
* Sistemi operativi: Diversi sistemi operativi, tra cui OS/2, Windows, e sistemi Unix, utilizzano la modalità protetta per garantire una maggiore stabilità e sicurezza, oltre a consentire l'esecuzione di applicazioni legacy in modalità virtuale 8086.

Con il rilascio del 386, la modalità protetta offre dunque ciò che i manuali Intel chiamano "modalità virtuale 8086". La modalità virtuale 8086 è progettata per consentire al codice precedentemente scritto per l'8086 di essere eseguito senza modifiche e contemporaneamente ad altre attività, senza compromettere la sicurezza o la stabilità del sistema.

Tuttavia, la modalità virtuale 8086 non era completamente retrocompatibile con tutti i programmi. I programmi che richiedevano la manipolazione dei segmenti, istruzioni privilegiate, accesso diretto all'hardware o utilizzavano codice auto-modificante avrebbero generato un'eccezione che doveva essere gestita dal sistema operativo. Infatti la retrocompatibilità era subordinata al rispetto di una serie di condizioni. Se un'applicazione utilizzava o dipendeva da una delle tecniche elencate di seguito, non avrebbe funzionato:

* Aritmetica dei segmenti
* Istruzioni privilegiate
* Accesso diretto all'hardware
* Scrittura in un segmento del codice
* Esecuzione di dati
* Segmenti sovrapposti
* Uso delle funzioni del BIOS, a causa delle interruzioni del BIOS riservate da Intel

Inoltre, le applicazioni in esecuzione in modalità virtuale 8086 generano un'interruzione con l'uso di istruzioni che coinvolgono l'input/output (I/O), il che può avere un impatto negativo sulle prestazioni.

A causa di queste limitazioni, alcuni programmi originariamente progettati per l'8086 non potevano e non possono essere eseguiti in modalità virtuale 8086. Di conseguenza, il software di sistema è costretto a compromettere la sicurezza del sistema o la retrocompatibilità quando si tratta di software legacy. Un esempio di tale compromesso può essere osservato con il rilascio di Windows NT, che ha abbandonato la retrocompatibilità per le applicazioni DOS "ill-behaved" .

In realtà, quasi tutti i programmi applicativi DOS violavano queste regole. È a causa di queste limitazioni, che fu introdotta la modalità virtuale 8086 con il 386. Nonostante questi potenziali ostacoli, Windows 3.0 e le sue versioni successive potevano sfruttare la compatibilità binaria con la modalità reale per eseguire molte applicazioni Windows 2.x (Windows 2.0 e Windows 2.1x) in modalità protetta, le quali funzionavano in modalità reale in Windows 2.x.

Infine, nei sistemi operativi moderni a 64 bit, la modalità virtuale 8086 è stata rimossa.

## indirizzamento dei segmenti

### In Modalità Reale

In "Real Mode", ogni indirizzo logico punta direttamente a una posizione di memoria fisica. Ogni indirizzo logico è composto da due parti da 16 bit: la parte del segmento dell'indirizzo logico contiene l'indirizzo di base di un segmento con una granularità di 16 byte, il che significa che un segmento può iniziare all'indirizzo fisico 0, 16, 32, ..., 220-16. La parte dell'offset dell'indirizzo logico contiene un offset all'interno del segmento, quindi l'indirizzo fisico può essere calcolato come physical_address : = segment_part × 16 + offset (se la linea di indirizzo A20 è abilitata) o (segment_part × 16 + offset) mod 220 (se A20 è disabilitata). Ogni segmento ha una dimensione di 216 byte.

### In Modalità protetta

In "protected mode", segment_part viene sostituita da un selettore da 16 bit, in cui i 13 bit superiori (dal bit 3 al bit 15) contengono l'indice di una voce all'interno di una tabella dei descrittori. Il bit successivo (bit 2) specifica se l'operazione viene utilizzata con la GDT (Global Descriptor Table) o la LDT (Local Descriptor Table). I due bit più bassi (bit 1 e bit 0) del selettore vengono combinati per definire il privilegio della richiesta, dove i valori 0 e 3 rappresentano il privilegio più alto e il più basso, rispettivamente. Ciò significa che l'offset in byte dei descrittori nella tabella dei descrittori è lo stesso del selettore da 16 bit, a patto che i tre bit inferiori siano azzerati.

La voce nella tabella dei descrittori definisce l'indirizzo lineare reale del segmento, un valore limite per la dimensione del segmento e alcuni bit di attributo (flags).

286 L'indirizzo del segmento all'interno della voce della tabella dei descrittori ha una lunghezza di 24 bit, quindi ogni byte della memoria fisica può essere definito come limite del segmento. Il valore limite all'interno della voce della tabella dei descrittori ha una lunghezza di 16 bit, quindi la lunghezza del segmento può variare da 1 byte a 216 byte. L'indirizzo lineare calcolato corrisponde all'indirizzo della memoria fisica.

386 L'indirizzo del segmento all'interno della voce della tabella dei descrittori viene ampliato a 32 bit, quindi ogni byte della memoria fisica può essere definito come limite del segmento. Il valore limite all'interno della voce della tabella dei descrittori viene ampliato a 20 bit e completato con un flag di granularità (G-bit):

* Se il G-bit è zero, il limite ha una granularità di 1 byte, il che significa che la dimensione del segmento può essere di 1, 2, ..., 220 byte.
* Se il G-bit è uno, il limite ha una granularità di 212 byte, il che significa che la dimensione del segmento può essere di 1 × 212, 2 × 212, ..., 220 × 212 byte. Se la paginazione è disabilitata, l'indirizzo lineare calcolato corrisponde all'indirizzo della memoria fisica. Se la paginazione è abilitata, l'indirizzo lineare calcolato viene utilizzato come input per la paginazione.

Il processore 386 utilizza anche valori da 32 bit per l'offset dell'indirizzo.

Per mantenere la compatibilità con la modalità protetta del 286, è stato aggiunto un nuovo flag predefinito (D-bit, in breve). Se il D-bit di un segmento del codice è disattivato (0), tutti i comandi all'interno di questo segmento verranno interpretati come comandi da 16 bit per impostazione predefinita; se è attivato (1), verranno interpretati come comandi da 32 bit.

### Paginazione

Oltre all'aggiunta della modalità virtuale 8086, il 386 ha anche introdotto la paginazione nella modalità protetta. Attraverso la paginazione, il software di sistema può limitare e controllare l'accesso di un'attività alle pagine, che sono sezioni di memoria. In molti sistemi operativi, la paginazione viene utilizzata per creare uno spazio di indirizzi virtuale indipendente per ciascuna attività, impedendo a una di esse di manipolare la memoria di un'altra. La paginazione consente anche di spostare le pagine dalla memoria primaria su una memoria secondaria più lenta e più grande, come un disco rigido.[40] Questo consente di utilizzare più memoria di quella fisicamente disponibile nella memoria primaria.

L'architettura x86 consente il controllo delle pagine attraverso due array: le directory delle pagine e le tabelle delle pagine. Originariamente, una directory delle pagine aveva la dimensione di una pagina, quattro kilobyte, e conteneva 1.024 voci di directory delle pagine (PDE), anche se miglioramenti successivi all'architettura x86 hanno aggiunto la possibilità di utilizzare dimensioni di pagina più grandi. Ogni PDE conteneva un puntatore a una tabella delle pagine. Una tabella delle pagine aveva anche originariamente una dimensione di quattro kilobyte e conteneva 1.024 voci di tabella delle pagine (PTE). Ciascuna PTE conteneva un puntatore all'indirizzo fisico effettivo della pagina e viene utilizzata solo quando si utilizzano pagine di quattro kilobyte. In ogni momento, può essere in uso solo una directory delle pagine.

