Thursday, December 30, 2010

Utilización de los anillos de privilegio del x86 en TORO

En la arquitectura x86 existen 4 niveles de privilegio, siendo el anillo 0 el más privilegiado y el anillo 3 el menos. En un sistema operativo tradicional el nivel de mayor privilegio es del kernel y el de menor nivel es el del usuario.

Al usar un SO de uso general, el código y datos del kernel utilizan descriptores de anillo 0, mientras que la aplicación de usuario utiliza el anillo 3. La capacidad de la GDT es de 8192 descriptores pero estos no se utilizan en general, usándose solo 4 descriptores, dos descriptores para datos y código de usuario, y dos más para datos y código del kernel. Estos descriptores se utilizan para el acceso a toda la memoria, es decir, que permiten acceder a los 4 GB (caso del direccionamiento de 32 bits).

El hecho de utilizar diferentes niveles de privilegio agrega latencias debido a que el procesador deberá corroborar que cada acceso de escritura/lectura/ejecución es válido. En un SO de uso general la utilización de diferentes niveles de privilegios es totalmente necesario, permite que se ejecuten varios procesos y que éstos no se solapen; y por otro lado que aplicaciones mal programadas no sobreescriban código del kernel.

Si suponemos que corremos una aplicación dedicada multihilo, que ésta se ejecuta sola en el sistema y que la aplicación fue escrita con suficiente cuidado como para no realizar escrituras sobre zonas prohibidas, será necesaria la protección?, suponiendo una situación así podemos simplificar bastante el SO.

Primero, tanto la aplicación de usuario como el código y datos del kernel estarían en el mismo nivel de privilegio , por lo tanto, cuando debemos realizar una llamada al sistema no habría ningún salto de nivel de privilegio y se podrían implementar simplemente con la instrucción “call”. Recordemos que actualmente para soportar las llamadas al sistema se utiliza una interrupción que permite realizar el salto de nivel de privilegio de anillo 3 a anillo 0 y es muy costosa.

Segundo, cuando los dispositivos de hardware producen interrupciones y nos encontramos ejecutando código de usuario se producirán saltos de niveles de privilegio. Ésto se debe a que dejamos de ejecutar código de anillo 3 para ejecutar una rutina de manejo de interrupción que se encuentra en anillo 0. Si la aplicación de usuario se ejecuta en el mismo nivel del kernel nos ahorramos la latencia que presenta saltar a un mayor nivel de privilegio.

En el caso de TORO, el kernel y la aplicación de usuario se ejecutan en anillo 0, por otro lado, como ambos se compilan juntos, las llamadas al sistema son implementadas como simples instrucciones “call” a funciones del kernel.

Matias E. Vara

Saturday, November 27, 2010

Ese viejo TORO

Desde el 2006, año en el cual se vieron modificados los objetivos de TORO, se discontinuó el proyecto TORO OS correspondiente a las versión 1.x.x. Estas versiones lograron un gran éxito en cuanto funcionalidad. La versión más estable fue la 1.1.3, de vez en cuando me pongo a ver el source de esas versiones y me da mucha lástima haberlo dejado, de todas formas me era imposible llevar a cabo ambos proyectos de forma simultanea. Por eso he decidido hacer un pequeño homenaje a esas versiones. Para eso muestro a continuación como testear toro 1.1.3 a través de BOCHS. He puesto un par de screenshots para que observen la belleza de una shell en PASCAL. Diviértanse!

Par estas simulaciones es necesario BOCHS para x86, recuerden que las versión 1.1.3 son solo para 32 bits. Aquí les incluyo el contenido del archivo torobch.bxrc

megs: 256

romimage: file=BIOS-bochs-latest, address=0xf0000

floppya: 1_44=toro-1.1.3.img, status=inserted

boot: floppy

Es necesario bajar la imagen de toro-1.1.3 desde el link: http://sourceforge.net/projects/toro/files/images/toro-1.1.3/toro-1.1.3.img/download

Si todo anda bien, la primer ventana que verán cuando ejecuten BOCHS será:

Corresponde el bootloader GRUB, allí se elige la opción TORO-1.1.3 y se le da enter.

Comenzará a cargar el SO y luego la Shell:

Estamos listo para ingresar comandos a TORO. El primer comando que veremos es el ls que como todos ya sabrán lista el directorio actual.

Ahora vamos a ir hasta el directorio donde se encuentra el source de TORO utilizando cd.

Y vamos a ejecutar echo printk.pas esto despliega el contenido del archivo en pantalla.

Todos los comandos de la Shell los pueden ver en el directorio /BIN como es de esperar, estos son:

Bueno ejecutando reboot el sistema es cerrado y podemos apagar tranquilos la maquina virtual.

Espero que les haya gustado, hagan sus propias experiencias ejecutando comandos. También pueden quemar la imagen en un disket de 3 ½ y probarlo en una maquina real.

ATENCION: Las versiones 1.x.x no tienen nada que ver con las versión 0.XX son cosas diferentes.


Matias E. Vara

www.torokernel.org

Saturday, November 20, 2010

Toro Builder subido!

Se encuentra disponible la interfaz de desarrollo de Toro, esta permite la compilacion y debug del núcleo muy fácilmente a través de ECLIPSE y QEMU, para bajarlo hacer click aqui pero antes visitar el nuevo WIKI de TORO para mayor información. Si hay alguien interesado en ser EDITOR del WIKI por favor contáctese conmigo a torokernel@gmail.com, saludos.

Matias E. Vara
www.torokernel.org

Wednesday, November 10, 2010

Cambio de Contexto

En este artículo intentaré dar una breve descripción de qué es un cambio de contexto y en particular como lo implementa TORO en las versiones a partir de la 0.01. No hablaré acerca de cómo lo implementa TORO OS en las versiones 1.x.x, solo diré que utiliza cambio de contexto por hardware. En futuros artículos mostraré la implementación en pascal de todas estas ideas. Cualquier duda a las referencias! Diviértanse!.

Como sabemos el encargado de distribuir los hilos en un kernel es el planificador. A parte de implementar el algoritmo de planificación éste realiza el procedimiento de “cambio de contexto”. Al seleccionar un nuevo hilo, el planificador llena los registros del procesador con los valores que tenían justo antes de que el hilo invoque al núcleo (OJO este comentario está ligado al algoritmo de planificación de TORO que es el de hilo cooperativo).


Imagen 1. Procedimiento de carga de un Nuevo proceso.


En la arquitectura x86-64 algunos de los registros de uso general son RAX, RBX, RCX, etc. Además de éstos registros también deben ser actualizados algunos registros de sistema como son el CR3. Éstos guardan información acerca del directorio de páginas del hilo que va ser cargado. El procedimiento se denomina “Cambio de contexto” y es una operación crítica debido a que se ejecuta de forma continua por lo que debe ser muy rápida.

El procedimiento de cambio de contexto puede ser implementado tanto por software como por hardware.

Cuando se implementa por hardware, se hace uso de los mecanismos que brinda una arquitectura en particular para realizar el cambio de contexto. Por ejemplo, para la arquitectura x86, se utilizan las estructuras denominadas descriptores de tareas, estas se encuentran en la GDT (Global Descriptor Table) y cuando se debe cargar una nueva tarea simplemente se utiliza la instrucción “call” al descriptor de tarea (denominado en la literatura como TSS)[1].

Por otro lado, en la implementación por software, el cambio de contexto se realiza “a mano” y es una rutina escrita por el programador la encargada de salvar el valor de los registros.

A primera vista el cambio de contexto por hardware parece la opción más óptima debido a que no interviene el programador y se realiza de forma “automática”. Pero en general ocurre que en los cambios de contexto por hardware se guardan los valores de todos los registros, pero resulta que a veces no se están utilizando todos los registros. De esta forma la implementación por hardware puede no ser la más óptima.

Por este motivo el cambio de contexto implementado en TORO es por software, se utilizan técnicas de programación para no utilizar los mecanismos de cambio de contexto que brinda un hardware en particular. El planificador al seleccionar un nuevo hilo, carga en los registros del procesador los valores que corresponde al nuevo hilo, y luego comienza su ejecución; el hilo comienza su ejecución justo después del momento en que se llamó al procedimiento SysThreadSwitch.

Como el cambio de contexto se realiza siempre luego de haberse invocado a la función SysThreadSwitch, el planificador supone que en ese instante los registros del procesador no están siendo utilizados por la aplicación de usuario. De esta forma se limita únicamente a salvar el estado de la pila del hilo que debe ser removido. Para la implementación sobre la arquitectura x86-64, esto se logra salvando en la estructura TThread el valor del registro RSP, el cual guarda la posición dentro de la pila.

El cambio de contexto implementado en TORO es más rápido que el de hardware y que el implementado en un SO de uso general. La elección del método de cambio de contexto se encuentra directamente relacionado con el modelo de hilo cooperativo.

Así la utilización de cambio de contexto por software suma portabilidad y velocidad [2].


[1]. Intel. IA-32 Intel® Architecture Software Developer’s Manual. Vol3. 2004.

[2]. Osdev Wiki, Context Switching, http://wiki.osdev.org/Context_Switching.


Matias E. Vara

www.torokernel.org