El segmento de estado de tarea ( TSS ) es una estructura en los ordenadores basados en x86 que contiene información sobre una tarea . El núcleo del sistema operativo lo utiliza para la gestión de tareas. En concreto, en el TSS se almacena la siguiente información:
Toda esta información debe almacenarse en ubicaciones específicas dentro del TSS según se especifica en los manuales IA-32 .
El TSS puede residir en cualquier parte de la memoria . Un registro de segmento llamado registro de tareas (TR) contiene un selector de segmento que apunta a un descriptor de segmento TSS válido que reside en la GDT (un descriptor TSS no puede residir en la LDT ). Por lo tanto, para utilizar un TSS, el núcleo del sistema operativo debe realizar lo siguiente:
Por motivos de seguridad, el TSS debe colocarse en una memoria a la que sólo pueda acceder el kernel .
El registro TR es un registro de 16 bits que contiene un selector de segmento para el TSS. Se puede cargar mediante la instrucción LTR . LTR es una instrucción privilegiada y actúa de manera similar a otras cargas de registros de segmento. El registro de tareas tiene dos partes: una parte visible y accesible para el programador y una parte invisible que se carga automáticamente desde el descriptor del TSS.
El TSS puede contener valores guardados de todos los registros x86 . Esto se utiliza para la conmutación de tareas . El sistema operativo puede cargar el TSS con los valores de los registros que necesita la nueva tarea y, después de ejecutar un cambio de tarea de hardware (como con una instrucción IRET), la CPU x86 cargará los valores guardados del TSS en los registros apropiados. Tenga en cuenta que algunos sistemas operativos modernos, como Windows y Linux [1], no utilizan estos campos en el TSS, ya que implementan la conmutación de tareas de software.
Tenga en cuenta que durante un cambio de tarea de hardware, ciertos campos del TSS antiguo se actualizan con el contenido de los registros actuales de la CPU antes de que se lean los valores del nuevo TSS. Por lo tanto, algunos campos del TSS son de lectura y escritura, mientras que otros son de solo lectura:
EAX
, EBX
, ECX
, EDX
, ESI
, EDI
, EBP
, ESP
);CS
, DS
, ES
, FS
, GS
, SS
);EIP
, EFlags
);Link
campo en el nuevo TSS, si el cambio de tarea se debió a un CALL
o INT
en lugar de un JMP
.CR3
), también conocido como Registro base del directorio de páginas ( PDBR
).LDTR
);SS0:ESP0
, SS1:ESP1
, SS2:ESP2
);CALL
o INT
para establecer una nueva pila.IOPB
) y el propio mapa de bits del puerto de E/S;IN
se OUT
desea confirmar INS
que la instrucción es legal (ver los permisos del puerto de E/S a continuación).OUTS
CPL > IOPL
De hecho, el PDBR
campo es el primero que se lee del nuevo TSS: dado que un cambio de tarea de hardware también puede cambiar a una asignación de tabla de páginas completamente diferente, todos los demás campos (especialmente el LDTR
) son relativos a la nueva asignación.
El TSS contiene un puntero de 16 bits al mapa de bits de permisos de puerto de E/S para la tarea actual . Este mapa de bits, que normalmente configura el sistema operativo cuando se inicia una tarea, especifica los puertos individuales a los que el programa debe tener acceso. El mapa de bits de E/S es una matriz de bits de permisos de acceso a puertos; si el programa tiene permiso para acceder a un puerto, se almacena un "0" en el índice de bit correspondiente y, si el programa no tiene permiso, se almacena un "1". Si el límite de segmento del TSS es menor que el mapa de bits completo, se supone que todos los bits faltantes son "1".
La función funciona de la siguiente manera: cuando un programa emite una instrucción de puerto de E/S x86 como IN o OUT (consulte los listados de instrucciones x86 y observe que existen versiones de longitud de byte, palabra y dword), el hardware realizará una verificación de nivel de privilegio de E/S (IOPL) para ver si el programa tiene acceso a todos los puertos de E/S. Si el nivel de privilegio actual (CPL) del programa es numéricamente mayor que el nivel de privilegio de E/S (IOPL) (el programa tiene menos privilegios que los que especifica el IOPL), el programa no tiene acceso a todos los puertos de E/S. Luego, el hardware verificará el mapa de bits de permisos de E/S en el TSS para ver si ese programa puede acceder al puerto o puertos específicos en la instrucción IN o OUT. Si (todos los) bits relevantes en el mapa de bits de permisos de puerto de E/S están limpios, se permite el acceso al programa al puerto o puertos y se permite la ejecución de la instrucción. Si (alguno de) los bits relevantes están configurados, o si (alguno de) los bits superan el límite de segmento del TSS, el programa no tiene acceso y el procesador genera una falla de protección general . Esta característica permite que los sistemas operativos otorguen acceso selectivo a los puertos a los programas de usuario.
El TSS contiene 6 campos para especificar el nuevo puntero de pila cuando se produce un cambio de nivel de privilegio. El campo SS0 contiene el selector de segmento de pila para CPL=0, y el campo ESP0/RSP0 contiene el nuevo valor ESP/RSP para CPL=0. Cuando se produce una interrupción en el modo protegido (32 bits), la CPU x86 buscará SS0 y ESP0 en el TSS y cargará sus valores en SS y ESP respectivamente. Esto permite que el núcleo utilice una pila diferente a la del programa de usuario y que esta pila sea única para cada programa de usuario.
Una nueva característica introducida en las extensiones AMD64 se llama Tabla de pila de interrupciones (IST), que también reside en la TSS y contiene punteros de pila lógicos (segmento + desplazamiento). Si una tabla de descriptores de interrupciones especifica una entrada IST para usar (hay 7), el procesador cargará la nueva pila desde la IST en su lugar. Esto permite que se usen pilas que se sabe que están en buen estado en caso de errores graves ( NMI o Double fault , por ejemplo). Anteriormente, la entrada para la excepción o interrupción en la IDT apuntaba a una puerta de tarea, lo que hacía que el procesador cambiara a la tarea que apuntaba la puerta de tarea. Los valores de registro originales se guardaban en la TSS actual en el momento en que se producía la interrupción o excepción. Luego, el procesador configuraba los registros, incluido SS:ESP, en un valor conocido especificado en la TSS y guardaba el selector en la TSS anterior. El problema aquí es que el cambio de tareas de hardware no es compatible con AMD64.
Se trata de un selector de 16 bits que permite vincular este TSS con el anterior. Solo se utiliza para la conmutación de tareas de hardware. Consulte los manuales de IA-32 para obtener más detalles.
Aunque se podría crear un TSS para cada tarea que se ejecuta en la computadora, el núcleo de Linux solo crea un TSS para cada CPU y los usa para todas las tareas. Se seleccionó este enfoque porque proporciona una portabilidad más fácil a otras arquitecturas (por ejemplo, la arquitectura AMD64 no admite conmutadores de tareas de hardware) y un rendimiento y una flexibilidad mejorados. Linux solo usa el mapa de bits de permisos de puerto de E/S y las características de pila interna del TSS; las otras características solo son necesarias para los conmutadores de tareas de hardware, que el núcleo de Linux no usa. [2]
El vector de excepción x86 10 se denomina excepción TSS no válida (#TS). El procesador la emite siempre que algo sale mal con el acceso a TSS. Por ejemplo, si se produce una interrupción en CPL=3 y se transfiere el control a CPL=0, se utiliza la TSS para extraer SS0 y ESP0/RSP0 para el cambio de pila. Si el registro de tareas contiene un selector TSS incorrecto, se generará un error #TS. La excepción TSS no válida nunca debería producirse durante el funcionamiento normal del sistema operativo y siempre está relacionada con errores del núcleo o fallos de hardware.
Para obtener más detalles sobre las excepciones de TSS, consulte el Volumen 3a, Capítulo 6 del manual IA-32 . [3]
La arquitectura x86-64 no admite cambios de tareas de hardware. Sin embargo, el TSS puede seguir utilizándose en una máquina que funcione en los modos extendidos de 64 bits. En estos modos, el TSS sigue siendo útil, ya que almacena:
Además, el registro de tareas se amplía en estos modos para poder contener una dirección base de 64 bits.