Parte de una serie sobre |
Modos de microprocesador para la arquitectura x86 |
---|
|
La primera plataforma compatible se muestra entre paréntesis |
En informática, el modo protegido , también llamado modo de dirección virtual protegida , [1] es un modo operativo de las unidades centrales de procesamiento (CPU) compatibles con x86 . Permite que el software del sistema utilice funciones como segmentación , memoria virtual , paginación y multitarea segura diseñadas para aumentar el control de un sistema operativo sobre el software de aplicación . [2] [3]
Cuando se enciende un procesador que admite el modo protegido x86, comienza a ejecutar instrucciones en modo real , para mantener la compatibilidad con versiones anteriores de procesadores x86. [4] Solo se puede ingresar al modo protegido después de que el software del sistema configure una tabla de descriptores y habilite el bit de habilitación de protección (PE) en el registro de control 0 (CR0). [5]
El modo protegido se agregó por primera vez a la arquitectura x86 en 1982, [6] con el lanzamiento del procesador 80286 (286) de Intel , y luego se amplió con el lanzamiento del 80386 (386) en 1985. [7] Debido a las mejoras agregadas por el modo protegido, se ha adoptado ampliamente y se ha convertido en la base para todas las mejoras posteriores a la arquitectura x86 (IA-32), [8] aunque muchas de esas mejoras, como instrucciones agregadas y nuevos registros, también trajeron beneficios al modo real.
El primer procesador x86, el Intel 8086 , tenía un bus de direcciones de 20 bits para su memoria , al igual que su variante Intel 8088. [9] Esto les permitía acceder a 220 bytes de memoria, equivalentes a 1 megabyte . [9] En ese momento, 1 megabyte se consideraba una cantidad relativamente grande de memoria, [10] por lo que los diseñadores de la IBM Personal Computer reservaron los primeros 640 kilobytes para uso de las aplicaciones y el sistema operativo y los 384 kilobytes restantes para el BIOS (Basic Input/Output System) y la memoria para dispositivos complementarios . [11]
A medida que el costo de la memoria disminuyó y el uso de la misma aumentó, la limitación de 1 MB se convirtió en un problema importante. Intel pretendía resolver esta limitación junto con otras con el lanzamiento del 286. [11]
El modo protegido inicial, lanzado con el 286, no fue ampliamente utilizado; [11] por ejemplo, fue utilizado por Coherent (desde 1982), [12] Microsoft Xenix (alrededor de 1984) [13] y Minix . [14] Varias deficiencias como la incapacidad de hacer llamadas BIOS y DOS debido a la incapacidad de volver al modo real sin reiniciar el procesador impidieron su uso generalizado. [15] La aceptación se vio obstaculizada adicionalmente por el hecho de que el 286 solo permitía el acceso a la memoria en segmentos de 64 kilobytes , direccionados por sus cuatro registros de segmento, lo que significa que solo se podía acceder a 4 × 64 KB , equivalentes a 256 KB, a la vez. [11] Debido a que cambiar un registro de segmento en modo protegido causaba que se cargara un descriptor de segmento de 6 bytes en la CPU desde la memoria, la instrucción de carga del registro de segmento tomaba muchas decenas de ciclos de procesador, lo que la hacía mucho más lenta que en el 8086 y el 8088; Por lo tanto, la estrategia de calcular direcciones de segmento sobre la marcha para acceder a estructuras de datos mayores a 128 kilobytes (el tamaño combinado de los dos segmentos de datos) se volvió poco práctica, incluso para los pocos programadores que la dominaban en el 8086 y el 8088.
El 286 mantuvo la compatibilidad con versiones anteriores del 8086 y el 8088 al entrar inicialmente en modo real al encenderse. [4] El modo real funcionaba de manera prácticamente idéntica al 8086 y al 8088, lo que permitía que la gran mayoría del software existente para esos procesadores se ejecutara sin modificaciones en el 286 más nuevo. El modo real también servía como un modo más básico en el que se podía configurar el modo protegido, resolviendo una especie de problema del huevo y la gallina. Para acceder a la funcionalidad extendida del 286, el sistema operativo configuraba algunas tablas en la memoria que controlaban el acceso a la memoria en modo protegido, establecía las direcciones de esas tablas en algunos registros especiales del procesador y luego configuraba el procesador en modo protegido. Esto habilitaba el direccionamiento de 24 bits, lo que permitía al procesador acceder a 224 bytes de memoria, equivalentes a 16 megabytes . [9]
Con el lanzamiento del 386 en 1985, [7] se abordaron muchos de los problemas que impedían la adopción generalizada del modo protegido anterior. [11] El 386 se lanzó con un tamaño de bus de direcciones de 32 bits, lo que permite acceder a 2 32 bytes de memoria, equivalente a 4 gigabytes . [16] Los tamaños de segmento también se aumentaron a 32 bits, lo que significa que se podía acceder al espacio de direcciones completo de 4 gigabytes sin la necesidad de cambiar entre múltiples segmentos. [16] Además del aumento del tamaño del bus de direcciones y los registros de segmento, se agregaron muchas otras características nuevas con la intención de aumentar la seguridad y la estabilidad operativas. [17] El modo protegido ahora se usa en prácticamente todos los sistemas operativos modernos que se ejecutan en la arquitectura x86, como Microsoft Windows , Linux y muchos otros. [18]
Además, aprendiendo de los fallos del modo protegido 286 para satisfacer las necesidades de DOS multiusuario , Intel añadió un modo virtual 8086 independiente , [19] que permitió emular varios procesadores 8086 virtualizados en el 386. Sin embargo, la virtualización de hardware x86 necesaria para virtualizar el modo protegido en sí tuvo que esperar otros 20 años. [20]
Con el lanzamiento del 386, se agregaron las siguientes características adicionales al modo protegido: [2]
Hasta el lanzamiento del 386, el modo protegido no ofrecía un método directo para volver al modo real una vez que se ingresaba al modo protegido. IBM ideó una solución alternativa (implementada en el IBM AT ) que implicaba reiniciar la CPU a través del controlador del teclado y guardar los registros del sistema, el puntero de pila y, a menudo, la máscara de interrupción en la RAM del chip del reloj de tiempo real. Esto permitió que el BIOS restaurara la CPU a un estado similar y comenzara a ejecutar código antes del reinicio. [ aclaración necesaria ] Más tarde, se utilizó un triple fallo para reiniciar la CPU 286, que era mucho más rápido y limpio que el método del controlador del teclado (y no depende del hardware compatible con IBM AT, pero funcionará en cualquier CPU 80286 en cualquier sistema).
Para entrar en modo protegido, primero se debe crear la Tabla de Descriptores Globales (GDT) con un mínimo de tres entradas: un descriptor nulo, un descriptor de segmento de código y un descriptor de segmento de datos. En una máquina compatible con IBM, la línea A20 (línea de dirección 21) también debe estar habilitada para permitir el uso de todas las líneas de dirección de modo que la CPU pueda acceder a más de 1 megabyte de memoria (solo se permite el uso de las primeras 20 después del encendido, para garantizar la compatibilidad con software más antiguo escrito para los modelos IBM PC y PC/XT basados en Intel 8088 ). [22] Después de realizar esos dos pasos, el bit PE debe estar configurado en el registro CR0 y se debe realizar un salto lejano para borrar la cola de entrada de precarga . [23] [24]
; programa MASM ; ingresar al modo protegido (establecer bit PE) mov EBX , CR0 ; guardar el registro de control 0 (CR0) en EBX o EBX , PE_BIT ; establecer el bit PE mediante ORing, guardar en EBX mov CR0 , EBX ; guardar EBX nuevamente en CR0 ; borrar cola de precarga; (usando instrucción de salto lejano jmp) jmp CLEAR_LABEL CLEAR_LABEL:
Con el lanzamiento del 386, se podía salir del modo protegido cargando los registros de segmento con valores de modo real, deshabilitando la línea A20 y borrando el bit PE en el registro CR0, sin necesidad de realizar los pasos de configuración inicial requeridos con el 286. [25]
El modo protegido tiene una serie de características diseñadas para mejorar el control de un sistema operativo sobre el software de aplicación, con el fin de aumentar la seguridad y la estabilidad del sistema. [3] Estas adiciones permiten que el sistema operativo funcione de una manera que sería significativamente más difícil o incluso imposible sin el soporte de hardware adecuado. [26]
En el modo protegido, hay cuatro niveles de privilegio o anillos , numerados del 0 al 3, siendo el anillo 0 el más privilegiado y el 3 el menos privilegiado. El uso de anillos permite que el software del sistema restrinja el acceso a los datos, las puertas de llamadas o la ejecución de instrucciones privilegiadas por parte de las tareas. [27] En la mayoría de los entornos, el sistema operativo y algunos controladores de dispositivos se ejecutan en el anillo 0 y las aplicaciones se ejecutan en el anillo 3. [27]
Según el Manual de referencia del programador Intel 80286 , [28]
El 80286 sigue siendo compatible con la mayoría de los programas de aplicación 8086 y 80186. La mayoría de los programas de aplicación 8086 se pueden volver a compilar o ensamblar y ejecutar en el 80286 en modo protegido.
En su mayor parte, la compatibilidad binaria con el código en modo real, la capacidad de acceder a hasta 16 MB de memoria física y 1 GB de memoria virtual fueron los cambios más evidentes para los programadores de aplicaciones. [29] Esto no estuvo exento de limitaciones. Si una aplicación utilizaba o dependía de alguna de las técnicas que se indican a continuación, no se ejecutaba: [30]
En realidad, casi todos los programas de aplicación DOS violaban estas reglas. [32] Debido a estas limitaciones, el modo virtual 8086 se introdujo con el 386. A pesar de estos posibles contratiempos, Windows 3.0 y sus sucesores pueden aprovechar la compatibilidad binaria con el modo real para ejecutar muchas aplicaciones de Windows 2.x ( Windows 2.0 y Windows 2.1x ) en modo protegido, que se ejecutaban en modo real en Windows 2.x. [33]
Con el lanzamiento del 386, el modo protegido ofrece lo que los manuales de Intel llaman modo 8086 virtual . El modo 8086 virtual está diseñado para permitir que el código escrito previamente para el 8086 se ejecute sin modificaciones y simultáneamente con otras tareas, sin comprometer la seguridad o la estabilidad del sistema. [34]
Sin embargo, el modo 8086 virtual no es completamente compatible con versiones anteriores de todos los programas. Los programas que requieren manipulación de segmentos, instrucciones privilegiadas, acceso directo al hardware o que utilizan código automodificable generarán una excepción que debe ser atendida por el sistema operativo. [35] Además, las aplicaciones que se ejecutan en modo 8086 virtual generan una trampa con el uso de instrucciones que involucran entrada/salida (E/S), lo que puede afectar negativamente el rendimiento. [36]
Debido a estas limitaciones, algunos programas diseñados originalmente para ejecutarse en el 8086 no pueden ejecutarse en modo 8086 virtual. Como resultado, el software del sistema se ve obligado a comprometer la seguridad del sistema o la compatibilidad con versiones anteriores cuando trabaja con software heredado . Un ejemplo de este tipo de compromiso se puede ver con el lanzamiento de Windows NT , que eliminó la compatibilidad con versiones anteriores para aplicaciones DOS "de mal comportamiento". [37]
En modo real, cada dirección lógica apunta directamente a una ubicación de memoria física, cada dirección lógica consta de dos partes de 16 bits: La parte de segmento de la dirección lógica contiene la dirección base de un segmento con una granularidad de 16 bytes, es decir, un segmento puede comenzar en la dirección física 0, 16, 32, ..., 2 20 − 16. La parte de desplazamiento de la dirección lógica contiene un desplazamiento dentro del segmento, es decir, la dirección física se puede calcular como physical_address = segment_part × 16 + offset, si la línea de dirección A20 está habilitada, o (segment_part × 16 + offset) mod 2 20 , si A20 está desactivado. [ aclaración necesaria ] Cada segmento tiene un tamaño de 2 16 bytes.
En el modo protegido, la parte_segmentada se reemplaza por un selector de 16 bits , en el que los 13 bits superiores (bit 3 a bit 15) contienen el índice de una entrada dentro de una tabla de descriptores . El siguiente bit (bit 2) especifica si la operación se utiliza con la GDT o la LDT. Los dos bits más bajos (bit 1 y bit 0) del selector se combinan para definir el privilegio de la solicitud, donde los valores de 0 y 3 representan el privilegio más alto y más bajo, respectivamente. Esto significa que el desplazamiento de bytes de los descriptores en la tabla de descriptores es el mismo que el del selector de 16 bits, siempre que los tres bits inferiores estén en cero.
La entrada de la tabla de descriptores define la dirección lineal real del segmento, un valor límite para el tamaño del segmento y algunos bits de atributo (banderas).
La dirección del segmento dentro de la entrada de la tabla de descriptores tiene una longitud de 24 bits, por lo que cada byte de la memoria física se puede definir como límite del segmento. El valor límite dentro de la entrada de la tabla de descriptores tiene una longitud de 16 bits, por lo que la longitud del segmento puede estar entre 1 byte y 216 bytes . La dirección lineal calculada es igual a la dirección de la memoria física.
La dirección del segmento dentro de la entrada de la tabla de descriptores se amplía a 32 bits, de modo que cada byte de la memoria física se puede definir como límite del segmento. El valor límite dentro de la entrada de la tabla de descriptores se amplía a 20 bits y se completa con un indicador de granularidad (bit G, para abreviar):
El procesador 386 también utiliza valores de 32 bits para el desplazamiento de dirección.
Para mantener la compatibilidad con el modo protegido 286, se agregó un nuevo indicador predeterminado (bit D, para abreviar). Si el bit D de un segmento de código está desactivado (0), todos los comandos dentro de este segmento se interpretarán como comandos de 16 bits de manera predeterminada; si está activado (1), se interpretarán como comandos de 32 bits.
80286 Descriptor de segmento | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
80386 Descriptor de segmento | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Dónde:
Además de añadir el modo virtual 8086, el 386 también añadió paginación al modo protegido. [39] A través de la paginación, el software del sistema puede restringir y controlar el acceso de una tarea a las páginas, que son secciones de la memoria. En muchos sistemas operativos, la paginación se utiliza para crear un espacio de dirección virtual independiente para cada tarea, impidiendo que una tarea manipule la memoria de otra. La paginación también permite que las páginas se muevan fuera del almacenamiento primario y hacia un almacenamiento secundario más lento y más grande , como una unidad de disco duro . [40] Esto permite que se utilice más memoria de la que está físicamente disponible en el almacenamiento primario. [40]
La arquitectura x86 permite el control de páginas a través de dos matrices : directorios de páginas y tablas de páginas . Originalmente, un directorio de páginas tenía el tamaño de una página, cuatro kilobytes, y contenía 1.024 entradas de directorio de páginas (PDE), aunque las mejoras posteriores a la arquitectura x86 han añadido la capacidad de utilizar tamaños de página más grandes. Cada PDE contenía un puntero a una tabla de páginas. Una tabla de páginas también tenía originalmente un tamaño de cuatro kilobytes y contenía 1.024 entradas de tabla de páginas (PTE). Cada PTE contenía un puntero a la dirección física de la página real y solo se utiliza cuando se utilizan las páginas de cuatro kilobytes. En un momento dado, solo un directorio de páginas puede estar en uso activo. [41]
Mediante el uso de anillos, puertas de llamadas privilegiadas y el Segmento de estado de tarea (TSS), introducido con el 286, se hizo posible la multitarea preventiva en la arquitectura x86. El TSS permite modificar registros de propósito general, campos de selector de segmento y pilas sin afectar a los de otra tarea. El TSS también permite que el nivel de privilegio de una tarea y los permisos del puerto de E/S sean independientes de los de otra tarea.
En muchos sistemas operativos no se utilizan todas las características del TSS. [42] Esto se debe comúnmente a problemas de portabilidad o a problemas de rendimiento creados con los conmutadores de tareas de hardware. [42] Como resultado, muchos sistemas operativos utilizan tanto hardware como software para crear un sistema multitarea. [43]
Los sistemas operativos como OS/2 1.x intentan cambiar el procesador entre los modos protegido y real. Esto es lento e inseguro, ya que un programa en modo real puede hacer que un ordenador se estropee fácilmente . OS/2 1.x define reglas de programación restrictivas que permiten que una API de la familia o un programa vinculado se ejecuten en modo real o protegido. Algunos de los primeros sistemas operativos Unix , OS/2 1.x y Windows utilizaban este modo.
Windows 3.0 podía ejecutar programas en modo real en modo protegido de 16 bits; al cambiar al modo protegido, decidió conservar el modelo de nivel de privilegio único que se usaba en modo real, por lo que las aplicaciones y las DLL de Windows pueden enganchar interrupciones y realizar acceso directo al hardware. Esto se mantuvo así durante la serie Windows 9x . Si un programa de Windows 1.x o 2.x está escrito correctamente y evita la aritmética de segmentos, se ejecutará de la misma manera tanto en modo real como en modo protegido. Los programas de Windows generalmente evitan la aritmética de segmentos porque Windows implementa un esquema de memoria virtual de software, que mueve el código del programa y los datos en la memoria cuando los programas no se están ejecutando, por lo que manipular direcciones absolutas es peligroso; los programas solo deben mantener identificadores de bloques de memoria cuando no se están ejecutando. Iniciar un programa antiguo mientras Windows 3.0 se está ejecutando en modo protegido activa un cuadro de diálogo de advertencia, que sugiere ejecutar Windows en modo real u obtener una versión actualizada de la aplicación. Actualizar programas que se comportan bien mediante la utilidad MARK con el parámetro MEMORY evita este cuadro de diálogo. No es posible ejecutar algunos programas GUI en modo protegido de 16 bits y otros en modo real. En Windows 3.1 , el modo real ya no era compatible y no se podía acceder a él.
En los sistemas operativos de 32 bits modernos, el modo 8086 virtual todavía se utiliza para ejecutar aplicaciones, por ejemplo, programas extensores DOS compatibles con DPMI (a través de máquinas DOS virtuales ) o aplicaciones Windows 3.x (a través del subsistema Windows en Windows ) y ciertas clases de controladores de dispositivos (por ejemplo, para cambiar la resolución de pantalla utilizando la funcionalidad BIOS) en OS/2 2.0 (y posteriores OS/2) y Windows NT de 32 bits , todos bajo el control de un núcleo de 32 bits. Sin embargo, los sistemas operativos de 64 bits (que se ejecutan en modo largo ) ya no lo utilizan, ya que el modo 8086 virtual se ha eliminado del modo largo.
Sistema de control de acceso a memoria según la reivindicación 4, en el que dicho primer modo de dirección es un modo de dirección real y dicho segundo modo de dirección es un modo de dirección virtual protegido.
El objetivo es proteger a todos los demás (incluido el sistema operativo) de su programa.
Intel lanza el procesador Intel386
Lo interesante es que los diseñadores de la época nunca sospecharon que alguien necesitaría más de 1 MB de RAM.
80386SX: versión de bajo costo del 80386. Este procesador tenía un bus de datos externo de 16 bits y un bus de direcciones externo de 24 bits.
ha sido imposible hasta la fecha y ha obligado a los equipos de desarrollo de BIOS a agregar soporte en el BIOS para llamadas de funciones de 32 bits desde aplicaciones de 32 bits.
... en segundo lugar, el modo protegido también era incompatible con la gran cantidad de código de modo real que circulaba en ese momento.
Una desventaja de usar el modo V86 es la velocidad: cada instrucción sensible a IOPL hará que la CPU pase al modo kernel, al igual que la E/S a los puertos que están enmascarados en el TSS.
El proceso de paginación permite al sistema operativo superar los límites reales de la memoria física. Sin embargo, también tiene un impacto directo en el rendimiento debido al tiempo necesario para escribir o recuperar datos del disco.
Solo un directorio de páginas puede estar activo a la vez, indicado por el registro CR3.
La razón por la que la conmutación de tareas por software es tan popular es que puede ser más rápida que la conmutación de tareas por hardware. Intel nunca desarrolló realmente la conmutación de tareas por hardware, la implementaron, vieron que funcionaba y simplemente la dejaron así. Los avances en la multitarea mediante software han hecho que esta forma de conmutación de tareas sea más rápida (algunos dicen que hasta 3 veces más rápida) que el método por hardware. Otra razón es que la forma de Intel de cambiar de tareas no es en absoluto portátil.
... ambos dependen de la capacidad de los procesadores Intel para cambiar de tarea, pero dependen de ella de diferentes maneras.