Segment d'état de la tâche - Task state segment
Le segment d'état de tâche ( TSS ) est une structure sur les ordinateurs x86 qui contient des informations sur une tâche . Il est utilisé par le noyau du système d' exploitation pour la gestion des tâches. Plus précisément, les informations suivantes sont stockées dans le TSS:
- État du registre du processeur
- Autorisations de port d'E / S
- Pointeurs de pile de niveau interne
- Lien TSS précédent
Toutes ces informations doivent être stockées à des endroits spécifiques du TSS, comme spécifié dans les manuels IA-32 .
Emplacement du TSS
Le TSS peut résider n'importe où dans la mémoire . Un registre de segment appelé registre de tâches (TR) contient un sélecteur de segment qui pointe vers un descripteur de segment TSS valide qui réside dans le GDT (un descripteur TSS peut ne pas résider dans le LDT ). Par conséquent, pour utiliser un TSS, les opérations suivantes doivent être effectuées par le noyau du système d'exploitation:
- Créer une entrée de descripteur TSS dans le GDT
- Chargez le TR avec le sélecteur de segment pour ce segment
- Ajouter des informations au TSS en mémoire si nécessaire
Pour des raisons de sécurité, le TSS doit être placé dans une mémoire accessible uniquement au noyau .
Registre des tâches
Le registre TR est un registre de 16 bits qui contient un sélecteur de segment pour le TSS. Il peut être chargé via l' instruction LTR . LTR est une instruction privilégiée et agit d'une manière similaire aux autres charges de registre de segment. Le registre des tâches comporte deux parties: une partie visible et accessible par le programmeur et une partie invisible qui est automatiquement chargée à partir du descripteur TSS.
Enregistrer les états
Le TSS peut contenir les valeurs enregistrées de tous les registres x86 . Ceci est utilisé pour la commutation de tâches . Le système d'exploitation peut charger le TSS avec les valeurs des registres dont la nouvelle tâche a besoin et après avoir exécuté un commutateur de tâche matérielle (comme avec une instruction IRET ), le CPU x86 chargera les valeurs sauvegardées du TSS dans les registres appropriés. Notez que certains systèmes d'exploitation modernes tels que Windows et Linux n'utilisent pas ces champs dans le TSS car ils implémentent la commutation de tâches logicielles.
Notez que lors d'un changement de tâche matérielle, certains champs de l' ancien TSS sont mis à jour avec le contenu actuel du registre du CPU avant que les valeurs du nouveau TSS ne soient lues. Ainsi, certains champs TSS sont en lecture / écriture, tandis que d'autres sont en lecture seule:
-
Champs de lecture / écriture : lus et écrits lors d'un changement de tâche matérielle.
- Tous les registres à usage général (
EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP); - Tous les registres de segments (
CS,DS,ES,FS,GS,SS); - État d'exécution actuel (
EIP,EFlags); - Le
Linkchamp dans le nouveau TSS, si le changement de tâche était dû à unCALLouINTplutôt qu'à unJMP.
- Tous les registres à usage général (
-
Champs en lecture seule: en lecture seule si nécessaire, comme indiqué.
- Registre de contrôle 3 (
CR3), également connu sous le nom de registre de base du répertoire de pages (PDBR).- Lire pendant un changement de tâche matérielle.
- Le registre de la table de descripteurs locaux (
LDTR);- Lire pendant un changement de tâche matérielle.
- Les paires d'empilement à trois niveaux de privilège (
SS0:ESP0,SS1:ESP1,SS2:ESP2);- Lire lors d'un inter-niveau
CALLouINTpour établir une nouvelle pile.
- Lire lors d'un inter-niveau
- Le pointeur Bitmap du port IO (
IOPB) et le Bitmap du port I / O lui-même;- Lire au cours d' une
IN,OUT,INSouOUTSinstruction siCPL > IOPLpour confirmer l'instruction est légal (voir les autorisations de port d' E / S ci - dessous).
- Lire au cours d' une
- Registre de contrôle 3 (
Le PDBRchamp est en fait le tout premier extrait du nouveau TSS: puisqu'un commutateur de tâche matériel peut également basculer vers un mappage de table de page complètement différent, tous les autres champs (en particulier le LDTR) sont relatifs au nouveau mappage.
Autorisations de port d'E / S
Le TSS contient un pointeur 16 bits vers le bitmap des autorisations de port d'E / S pour la tâche en cours . Ce bitmap, généralement mis en place par le système d'exploitation lors du démarrage d'une tâche, spécifie les ports individuels auxquels le programme doit avoir accès. Le bitmap d'E / S est un tableau de bits d'autorisations d'accès aux ports; si le programme a l'autorisation d'accéder à un port, un "0" est stocké à l'index de bit correspondant, et si le programme n'a pas l'autorisation, un "1" y est stocké. Si la limite de segment du TSS est inférieure au bitmap complet, tous les bits manquants sont supposés être "1".
La fonctionnalité fonctionne comme suit: lorsqu'un programme émet une instruction de port d'E / S x86 telle que IN ou OUT (voir les listes d'instructions x86 - et notez qu'il existe des versions de longueur d'octet, de mot et de dword), le matériel effectuera un Le niveau de privilège d'E / S (IOPL) vérifie si le programme a accès à tous les ports d'E / S. Si le niveau de privilège actuel (CPL) du programme est numériquement supérieur au niveau de privilège d'E / S (IOPL) (le programme est moins privilégié que ce que spécifie l'IOPL), le programme n'a pas accès au port d'E / S à tous les ports. Le matériel vérifiera ensuite le bitmap des autorisations d'E / S dans le TSS pour voir si ce programme peut accéder au (x) port (s) spécifique (s) dans l'instruction IN ou OUT. Si (tous les) bit (s) pertinent (s) dans le bitmap des autorisations de port d'E / S est / sont clair, le programme est autorisé à accéder au (x) port (s) et l'instruction est autorisée à s'exécuter. Si (l'un des) bit (s) pertinent (s) est / sont mis (s) - ou si (l'un des) bit (s) est / sont au-delà de la limite de segment du TSS - le programme n'a pas accès et le processeur génère une protection générale faute . Cette fonction permet aux systèmes d'exploitation d'accorder un accès sélectif aux ports aux programmes utilisateur.
Pointeurs de pile de niveau interne
Le TSS contient 6 champs pour spécifier le nouveau pointeur de pile lorsqu'un changement de niveau de privilège se produit. Le champ SS0 contient le sélecteur de segment de pile pour CPL = 0 et le champ ESP0 / RSP0 contient la nouvelle valeur ESP / RSP pour CPL = 0. Lorsqu'une interruption se produit en mode protégé (32 bits), le processeur x86 recherchera dans le TSS SS0 et ESP0 et chargera leurs valeurs dans SS et ESP respectivement. Cela permet au noyau d'utiliser une pile différente de celle du programme utilisateur, et d'avoir cette pile unique pour chaque programme utilisateur.
Une nouvelle fonctionnalité introduite dans les extensions AMD64 est appelée la table de pile d'interruptions (IST), qui réside également dans le TSS et contient des pointeurs de pile logiques (segment + décalage). Si une table de descripteur d'interruption spécifie une entrée IST à utiliser (il y en a 8), le processeur chargera la nouvelle pile à partir de l'IST à la place. Cela permet d'utiliser des piles en bon état en cas d'erreurs graves ( NMI ou Double défaut par exemple). Auparavant, l'entrée pour l'exception ou l'interruption dans l'IDT pointait vers une porte de tâche, provoquant le basculement du processeur vers la tâche pointée par la porte de tâche. Les valeurs de registre d'origine ont été enregistrées dans le courant TSS au moment de l'interruption ou de l'exception. Le processeur a ensuite mis les registres, y compris SS: ESP, à une valeur connue spécifiée dans le TSS et a sauvegardé le sélecteur dans le TSS précédent. Le problème ici est que la commutation de tâches matérielles n'est pas prise en charge sur AMD64.
Lien TSS précédent
Il s'agit d'un sélecteur 16 bits qui permet de relier ce TSS au précédent. Ceci n'est utilisé que pour la commutation de tâches matérielles. Voir les manuels IA-32 pour plus de détails.
Utilisation de TSS sous Linux
Bien qu'un TSS puisse être créé pour chaque tâche exécutée sur l'ordinateur, le noyau Linux ne crée qu'un seul TSS pour chaque CPU et les utilise pour toutes les tâches. Cette approche a été choisie car elle offre une portabilité plus facile vers d'autres architectures (par exemple, l' architecture AMD64 ne prend pas en charge les commutateurs de tâches matérielles), ainsi que des performances et une flexibilité améliorées. Linux utilise uniquement le bitmap d'autorisation de port d'E / S et les fonctionnalités de pile interne du TSS; les autres fonctionnalités ne sont nécessaires que pour les commutateurs de tâches matérielles, que le noyau Linux n'utilise pas.
Le vecteur d' exception x86 10 est appelé l'exception TSS non valide (#TS). Il est émis par le processeur chaque fois que quelque chose ne va pas avec l'accès TSS. Par exemple, si une interruption se produit dans CPL = 3 et transfère le contrôle à CPL = 0, le TSS est utilisé pour extraire SS0 et ESP0 / RSP0 pour le commutateur de pile. Si le registre de tâches contient un mauvais sélecteur TSS, une erreur #TS sera générée. L'exception TSS non valide ne devrait jamais se produire pendant le fonctionnement normal du système d'exploitation et est toujours liée à des bogues du noyau ou à une défaillance matérielle.
Pour plus de détails sur les exceptions TSS, voir Volume 3a, Chapitre 6 du manuel IA-32 .
TSS en mode x86-64
L' architecture x86-64 ne prend pas en charge les commutateurs de tâches matérielles. Cependant, le TSS peut toujours être utilisé sur une machine fonctionnant dans les modes étendus 64 bits. Dans ces modes, le TSS est toujours utile car il stocke:
- Les adresses du pointeur de pile pour chaque niveau de privilège.
- Adresses de pointeur pour la table de pile d'interruptions (la section pointeur de pile de niveau interne ci-dessus, traite de la nécessité de cela).
- Adresse de décalage du bitmap d'autorisation IO.
En outre, le registre de tâches est étendu dans ces modes pour pouvoir contenir une adresse de base de 64 bits.