Por lo tanto, los sistemas x86 basados en Linux o Windows solo usan el anillo 0 para el modo kernel y el anillo 3 para el modo de usuario. ¿Por qué los procesadores incluso distinguen cuatro anillos diferentes si todos terminan usando solo dos de todos modos? ¿Y esto ha cambiado en la arquitectura AMD64?
cpu
operating-systems
privileges
AdHominem
fuente
fuente
Respuestas:
Hay dos razones principales.
La primera razón es que, aunque las CPU x86 ofrecen cuatro anillos de protección de memoria, la granularidad de protección ofrecida por lo tanto es solo a nivel de segmento. Es decir, cada segmento se puede establecer en un anillo específico ("nivel de privilegio") de 0 a 3, junto con otras protecciones como escritura deshabilitada. Pero no hay tantos descriptores de segmento disponibles. A la mayoría de los sistemas operativos les gustaría tener una granularidad mucho más fina de protección de memoria. Me gusta ... para páginas individuales.
Entonces, ingrese la protección basada en las entradas de la tabla de páginas (PTE). La mayoría, si no todos los sistemas operativos x86 modernos, más o menos ignoran el mecanismo de segmentación (tanto como pueden, de todos modos) y confían en la protección basada en PTE. Esto se especifica mediante bits de marca, que son los 12 bits inferiores en cada PTE, más el bit 63 en las CPU que admiten la no ejecución. Hay un PTE para cada página, que normalmente es 4K.
Uno de esos bits de bandera se llama bit "privilegiado". Este bit controla si el procesador tiene que estar o no en uno de los niveles "privilegiados" para acceder a la página. Los niveles "privilegiados" son PL 0, 1 y 2. Pero es solo un bit, por lo que en el nivel de protección página por página, el número de "modos" disponibles en lo que respecta a la protección de memoria es solo dos: una página Se puede acceder desde el modo no privilegiado, o no. De ahí solo dos anillos.
Para tener cuatro anillos posibles para cada página, tendrían que tener dos bits de protección en cada entrada de la tabla de páginas, para codificar uno de los cuatro números de anillo posibles (al igual que los descriptores de segmento). Ellos no.
La segunda razón es el objetivo de la portabilidad del sistema operativo. No se trata solo de x86; Unix nos enseñó que un sistema operativo podría ser relativamente portátil para arquitecturas de múltiples procesadores, y que eso era algo bueno. Y algunos procesadores solo admiten dos anillos. Al no depender de múltiples anillos en la arquitectura, los implementadores del sistema operativo hicieron que los sistemas operativos fueran más portátiles.
Hay una tercera razón que es específica para el desarrollo de Windows NT. Los diseñadores de NT (David Cutler y su equipo, a quienes Microsoft contrató de DEC Western Region Labs) habían tenido una amplia experiencia previa en VMS; de hecho, Cutler y algunos de los otros se encontraban entre los diseñadores originales de VMS. Y el procesador VAX para el que se diseñó VMS (y viceversa) tiene cuatro anillos. VMS usa cuatro anillos. (De hecho, el VAX tiene cuatro bits de protección en el PTE, lo que permite combinaciones como "solo lectura desde el modo de usuario, pero grabable desde el anillo 2 y el interior". Pero estoy divagando).
Pero los componentes que se ejecutaron en los anillos 1 y 2 de VMS (Servicios de administración de registros y CLI, resp.) Quedaron fuera del diseño de NT. Ring 2 en VMS realmente no se trataba de la seguridad del sistema operativo, sino más bien de preservar el entorno CLI del usuario de un programa a otro, y Windows NT simplemente no tenía ese concepto; La CLI se ejecuta como un proceso ordinario. En cuanto al anillo 1 de VMS, el código RMS en el anillo 1 tuvo que llamar al anillo 0 con bastante frecuencia, y las transiciones de anillo son caras. Resultó ser mucho más eficiente simplemente ir al anillo 0 y terminar con él en lugar de tener muchas transiciones de anillo 0 dentro del código de anillo 1. (Nuevamente, no es que NT tenga nada como RMS de todos modos).
¿Pero por qué están allí, entonces? En cuanto a por qué x86 implementó cuatro anillos mientras que los sistemas operativos no los usaron, está hablando de sistemas operativos de diseño mucho más reciente que x86. Muchas de las características de "programación del sistema" de x86 se diseñaron mucho antes de que NT o los verdaderos núcleos Unix-ish se implementaran en él, y realmente no sabían qué utilizarían los sistemas operativos. (No fue hasta que obtuvimos la paginación en x86, que no apareció hasta el 80386) que pudimos implementar verdaderos núcleos Unix-ish o VMS sin repensar la administración de memoria desde cero.
Los sistemas operativos x86 modernos no solo ignoran en gran medida la segmentación (simplemente configuran los segmentos C, D y S con la dirección base 0 y el tamaño de 4 GB; los segmentos F y G a veces se utilizan para señalar estructuras de datos clave del sistema operativo), sino que también ignore en gran medida cosas como "segmentos de estado de tarea". El mecanismo TSS se diseñó claramente para el cambio de contexto de subproceso, pero resulta que tiene demasiados efectos secundarios, por lo que los sistemas operativos x86 modernos lo hacen "a mano". La única vez que x86 NT cambia las tareas de hardware, por ejemplo, es para algunas condiciones verdaderamente excepcionales, como una excepción de doble falla.
Re x64, muchas de estas características en desuso quedaron fuera. (Para su crédito, AMD en realidad habló con los equipos del núcleo del sistema operativo y les preguntó qué necesitaban de x86, qué no necesitaban o qué no querían, y qué les gustaría agregar). Los segmentos en x64 solo existen en lo que podría ser llamado forma vestigial, el cambio de estado de la tarea no existe, etc. Y los sistemas operativos continúan usando solo dos anillos.
fuente