Segmento stato attività - Task state segment
Il segmento di stato dell'attività ( TSS ) è una struttura su computer basati su x86 che contiene informazioni su un'attività . Viene utilizzato dal kernel del sistema operativo per la gestione delle attività. Nello specifico, le seguenti informazioni sono memorizzate nel TSS:
- Stato del registro del processore
- Autorizzazioni della porta I / O
- Puntatori allo stack di livello interno
- Collegamento TSS precedente
Tutte queste informazioni devono essere archiviate in posizioni specifiche all'interno del TSS come specificato nei manuali IA-32 .
Posizione del TSS
Il TSS può risiedere ovunque nella memoria . Un registro di segmento chiamato registro attività (TR) contiene un selettore di segmento che punta a un descrittore di segmento TSS valido che risiede nel GDT (un descrittore TSS potrebbe non risiedere nell'LDT ). Pertanto, per utilizzare un TSS, il kernel del sistema operativo deve eseguire quanto segue:
- Crea una voce descrittore TSS nel GDT
- Carica il TR con il selettore di segmento per quel segmento
- Aggiungere le informazioni al TSS in memoria secondo necessità
Per motivi di sicurezza, il TSS dovrebbe essere posizionato in una memoria accessibile solo al kernel .
Registro delle attività
Il registro TR è un registro a 16 bit che contiene un selettore di segmento per il TSS. Può essere caricato tramite l' istruzione LTR . LTR è un'istruzione privilegiata e agisce in modo simile ai caricamenti di altri registri di segmento. Il registro delle attività ha due parti: una parte visibile e accessibile dal programmatore e una invisibile che viene caricata automaticamente dal descrittore TSS.
Registra gli stati
Il TSS può contenere valori salvati di tutti i registri x86 . Viene utilizzato per il cambio di attività . Il sistema operativo può caricare il TSS con i valori dei registri necessari per il nuovo task e dopo aver eseguito un task switch hardware (come con un'istruzione IRET ) la CPU x86 caricherà i valori salvati dal TSS nei registri appropriati. Si noti che alcuni sistemi operativi moderni come Windows e Linux non utilizzano questi campi in TSS poiché implementano la commutazione delle attività software.
Si noti che durante un cambio di task hardware, alcuni campi del vecchio TSS vengono aggiornati con il contenuto del registro corrente della CPU prima che i valori del nuovo TSS vengano letti. Pertanto alcuni campi TSS sono di lettura / scrittura, mentre altri sono di sola lettura:
-
Campi di lettura / scrittura : letti e scritti durante un cambio di attività hardware.
- Tutti i registri generici (
EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP); - Tutti i registri di segmento (
CS,DS,ES,FS,GS,SS); - Stato di esecuzione corrente (
EIP,EFlags); - Il
Linkcampo nel nuovo TSS, se il cambio di attività era dovuto aCALLoINTpiuttosto che aJMP.
- Tutti i registri generici (
-
Campi di sola lettura: letti solo quando richiesto, come indicato.
- Registro di controllo 3 (
CR3), noto anche come registro di base della directory delle pagine (PDBR).- Leggere durante un cambio di attività hardware.
- La tabella dei descrittori locali register (
LDTR);- Leggere durante un cambio di attività hardware.
- Le coppie pila tre livello di privilegio (
SS0:ESP0,SS1:ESP1,SS2:ESP2);- Leggere durante un livello intermedio
CALLoINTper stabilire un nuovo stack.
- Leggere durante un livello intermedio
- Il puntatore bitmap della porta di
IOPBI / O ( ) e la bitmap della porta di I / O stessa;- Leggi nel corso di una
IN,OUT,INSoOUTSistruzioni seCPL > IOPLper confermare l'istruzione è legale (vedi I permessi di porta I / O di seguito).
- Leggi nel corso di una
- Registro di controllo 3 (
Il PDBRcampo è infatti il primo in assoluto letto dal nuovo TSS: poiché un task switch hardware può anche passare a una mappatura della tabella di pagina completamente diversa, tutti gli altri campi (specialmente il LDTR) sono relativi alla nuova mappatura.
Autorizzazioni della porta I / O
Il TSS contiene un puntatore a 16 bit alla bitmap delle autorizzazioni della porta I / O per l' attività corrente . Questa bitmap, di solito impostata dal sistema operativo all'avvio di un'attività, specifica le singole porte a cui il programma deve avere accesso. La bitmap di I / O è un array di bit di autorizzazioni di accesso alla porta; se il programma dispone dell'autorizzazione per accedere a una porta, viene memorizzato uno "0" nell'indice di bit corrispondente e se il programma non dispone dell'autorizzazione, viene memorizzato uno "1". Se il limite di segmento del TSS è inferiore alla bitmap completa, si presume che tutti i bit mancanti siano "1".
La funzione opera come segue: quando un programma emette un'istruzione della porta I / O x86 come IN o OUT (vedere gli elenchi di istruzioni x86 - e notare che ci sono versioni a lunghezza byte, parola e dword), l'hardware eseguirà un Controllare il livello di privilegio I / O (IOPL) per vedere se il programma ha accesso a tutte le porte I / O. Se il livello di privilegio corrente (CPL) del programma è numericamente maggiore del livello di privilegio di I / O (IOPL) (il programma è meno privilegiato di quanto specificato dall'IOPL), il programma non ha accesso alla porta I / O per tutti porti. L'hardware controllerà quindi la bitmap dei permessi di I / O nel TSS per vedere se quel programma può accedere alle porte specifiche nell'istruzione IN o OUT. Se (tutti) i bit rilevanti nella bitmap dei permessi della porta I / O sono chiari, al programma è consentito l'accesso alle porte e l'esecuzione dell'istruzione è consentita. Se (uno qualsiasi dei) bit rilevanti è / sono impostati - o se (uno qualsiasi dei) bit è / sono oltre il limite del segmento TSS - il programma non ha accesso e il processore genera una protezione generale colpa . Questa funzione consente ai sistemi operativi di concedere l'accesso selettivo alla porta ai programmi utente.
Puntatori allo stack di livello interno
Il TSS contiene 6 campi per specificare il nuovo puntatore allo stack quando si verifica una modifica del livello di privilegio. Il campo SS0 contiene il selettore di segmento dello stack per CPL = 0 e il campo ESP0 / RSP0 contiene il nuovo valore ESP / RSP per CPL = 0. Quando si verifica un interrupt in modalità protetta (32 bit), la CPU x86 cercherà nel TSS SS0 ed ESP0 e caricherà i loro valori rispettivamente in SS ed ESP. Ciò consente al kernel di utilizzare uno stack diverso rispetto al programma utente e anche di avere questo stack univoco per ogni programma utente.
Una nuova funzionalità introdotta nelle estensioni AMD64 è chiamata Interrupt Stack Table (IST), che risiede anche nel TSS e contiene puntatori allo stack logici (segmento + offset). Se una tabella descrittore di interrupt specifica una voce IST da utilizzare (ce ne sono 8), il processore caricherà invece il nuovo stack dall'IST. Ciò consente di utilizzare stack noti in caso di errori gravi ( ad esempio NMI o Double fault ). In precedenza, la voce per l'eccezione o l'interruzione nell'IDT puntava a un gate di attività, facendo sì che il processore passasse all'attività puntata dal gate di attività. I valori di registro originali sono stati salvati nel TSS corrente al momento in cui si è verificata l'interruzione o l'eccezione. Il processore quindi imposta i registri, incluso SS: ESP, su un valore noto specificato nel TSS e salva il selettore nel TSS precedente. Il problema qui è che il cambio di attività hardware non è supportato su AMD64.
Collegamento TSS precedente
Questo è un selettore a 16 bit che permette di collegare questo TSS con quello precedente. Viene utilizzato solo per la commutazione dei task hardware. Vedere i manuali dell'IA-32 per i dettagli.
Uso di TSS in Linux
Sebbene sia possibile creare un TSS per ogni attività in esecuzione sul computer, il kernel Linux crea solo un TSS per ciascuna CPU e li utilizza per tutte le attività. Questo approccio è stato scelto in quanto fornisce una portabilità più semplice ad altre architetture (ad esempio, l' architettura AMD64 non supporta i task switch hardware) e prestazioni e flessibilità migliorate. Linux utilizza solo la bitmap di autorizzazione della porta di I / O e le funzionalità dello stack interno di TSS; le altre funzionalità sono necessarie solo per gli interruttori di attività hardware, che il kernel Linux non utilizza.
Il vettore di eccezione x86 10 è chiamato eccezione TSS non valida (#TS). Viene emesso dal processore ogni volta che qualcosa va storto con l'accesso TSS. Ad esempio, se si verifica un interrupt in CPL = 3 e trasferisce il controllo a CPL = 0, il TSS viene utilizzato per estrarre SS0 e ESP0 / RSP0 per lo stack switch. Se il registro dell'attività contiene un selettore TSS non valido, verrà generato un errore #TS. L'eccezione TSS non valida non dovrebbe mai verificarsi durante il normale funzionamento del sistema operativo ed è sempre correlata a bug del kernel o guasti hardware.
Per maggiori dettagli sulle eccezioni TSS, vedere il volume 3a, capitolo 6 del manuale IA-32 .
TSS in modalità x86-64
L' architettura x86-64 non supporta le opzioni di attività hardware. Tuttavia, il TSS può ancora essere utilizzato in una macchina in esecuzione nelle modalità estese a 64 bit. In queste modalità il TSS è ancora utile in quanto memorizza:
- Lo stack pointer indirizzi per ogni livello di privilegio.
- Indirizzi dei puntatori per la tabella dello stack degli interrupt (la sezione del puntatore dello stack a livello interno sopra, discute la necessità di questo).
- Indirizzo offset della bitmap di autorizzazione IO.
Inoltre, il registro delle attività viene espanso in queste modalità per poter contenere un indirizzo di base a 64 bit.