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

Monday, November 08, 2010

Cambios en el SVN

Estaré realizando algunos cambios en la estructura de directorios del SVN asi que tal vez esté fuera de servicio algunas horas. Recomiendo hacer un update de las carpetas.

Saludos
Matias E. Vara
www.torokernel.org

Thursday, October 28, 2010

Presentacion de BugCON 2010

Aquí les dejo el link a la presentacion que hice para BugCon 2010. Espero se diviertan, saludos.

Matias E. Vara
www.torokernel.org

Sunday, September 19, 2010

Migracion de Hilos sobre TORO

En ambientes multicore es preciso contar con la capacidad de crear hilos no sólo en el procesador local sino en procesadores remotos. TORO brinda la posibilidad de crear hilos en cualquier procesador, desde cualquier procesador, a través de la llamada al sistema BeginThread().
Podemos diferenciar dos procedimientos en el kernel:

- La emigración de hilos: cuando los hilos se dirigen hacia otro procesador diferente a donde se está ejecutando el hilo que los creo.
- La inmigración de hilos: cuando el procesador huésped encola en el planificador local a los hilos que provienen de otros procesadores.

Este es el único punto del núcleo en el cual se requiere de algún tipo de mecanismo de sincronización entre los procesadores para poder enviar y recibir los procesos que deben migrar. El mecanismo es denominado “Exchange Slot”, y permite la comunicación entre procesadores sin utilizar operaciones atómicas. En este caso particular, se utiliza para el envío de nuevos hilos, pero puede ser utilizada para el envío de cualquier tipo de datos.
Por cada procesador existe una estructura denominada TSchedulerExchangeSlot:

TSchedulerExchangeSlot = record
DispatcherArray: array[0..MAX_CPU-1] of PThread;

EmigrateArray: array[0..MAX_CPU-1] of PThread;

end;


Siendo MAX_CPU el número de procesadores y PThread un puntero a una estructura TThread. De la definición de la estructura, se observa que cada procesador posee dos arreglos (DispatcherArray y EmigrateArray), y cada uno puntea a un grupo de hilos.
El procedimiento de envío de hilos hacia otros procesadores puede ser descripto en tres niveles:
1 – El usuario invoca al procedimiento BeginThread()para crear un nuevo hilo, si el parámetro CPUID es diferente al identificador de la CPU local, el kernel sabe que este nuevo hilo deberá ser migrado, y entonces lo agrega a la lista ligada DispatcherArray[CPUID].
2 – Cuando se ejecuta el planificador del procesador local (se invoca la llamada al sistema SysThreadSwitch), el procedimiento Emigrating() chequea si alguna de las entradas del arreglo EmigrateArray[] es nula. De ser así, desplaza todos los hilos desde la entrada correspondiente a DispatcherArray[] hasta EmigrateArray[].
3 – Durante la planificación de un procesador remoto el procedimiento Inmigrating() chequea la entrada del arreglo EmigrateArray[] correspondiente a su CPUID de la estructura TSchedulerExchangeSlot de cada procesador. Si no es nula, esta contiene un puntero al primer elemento de una cola ligada de procesos que están intentando migrar hacia su procesador. El procedimiento toma la cola de hilos y los coloca en la lista de hilos listos para ser ejecutados, luego vuelve a la entrada en el arreglo EmigrateArray[] nula.
Es claro que el arreglo DispatcherArray[] es de lectura/escritura solo para el procesador local. Mientras el arreglo EmigrateArray[] es de escritura/lectura para el procesador local y remoto, pero que la escritura sobre éste es sincronizada a través de la utilización del puntero nulo.
El “Exchange Slot” no requiere de ningún procedimiento que involucre un “pooling” de una variable del tipo “Lock”, evitando la utilización de operaciones atómicas y todo lo que ellas conllevan.


La inmigración y emigración de hilos entre procesadores se realiza únicamente cuando se invoca al planificador -es decir- cuando el hilo cede el procesador al kernel. En ese momento el Sistema realiza tareas de mantenimiento. Como se observa en la figura, cuando se llama al planificador, éste primero realiza la inmigración de hilos, luego realiza la emigración de hilos, y finalmente realiza la planificación de un nuevo hilo para el procesador local.

Matias E. Vara
www.torokernel.org

Thursday, July 22, 2010

Toro en BugCon 2010!

Toro estará presente en BUGCON 2010, Mexico DF. Realizaré una presentacion mostrando las funcionalidades de TORO y que problemas viene a solucionar. Tambien hare una demostracion en vivo de la compilacion del nucleo y el testeo paso a paso utilizando Eclipse y QEMU. Espero verlos alli.
Aqui les dejo el link para ver a los otros expositores.

Saludos.
Matias E. Vara
www.torokernel.org

Sunday, June 13, 2010

Debugueando TORO con ECLIPSE+QEMU en WIN64 , parte 2

Bueno luego de mucho trabajo he logrado construir un entorno para compilar y testear TORO muy rápidamente utilizando ECLIPSE y emulando TORO sobre QEMU. Básicamente lo que hace ECLIPSE es ser la interfaz gráfica entre GDB y QEMU. Para esto estoy utilizando GDB en forma de debug remoto , caracterisca que esta presente en QEMU. Para entusiarmarlos aqui les pongo un pequeño video en Win64, esta medio desprolijo pero prometo hace un buen tutorial hacerca de eso.



Por otro lado estoy creando un paquete(como se en el video) con todas los ejecutables incluidos de forma de que simplemente sea bajar y ejecutar ECLIPSE, sin necesitar ninguna otra herramienta más.
El mismo procedimiento lo he hecho en Linux y funciona bien , como muestran los screenshot del post anterior.

Un saludo .
Matias E. Vara
www.torokernel.org

Monday, April 12, 2010

Debugueando TORO en Eclipse+QEMU sobre Win64

Al intentar hacer lo mismo sobre Windows me encontré con un grave error en la aplicación GDB. Recordemos que para hacer el Debug , la IDE se conecta al gdbserver a traves del gdb cliente (gdb.exe).Al intenter introducir breakpoints , ocurria el siguiente error :
"Remote 'g' packet reply is too long:
> 0000000000000000000000000000000000000000000000002306000 "
Esto pasa cuando la maquina virtual llega al breakpoint y el gdbserver le enviaba información acerca del estado de la maquina al cliente . Luego de buscar este problema en otros foros , no encontré ninguna solución. Con cambiar la arquitectura, debería ser suficiente :

"SET ARCHITECTURE I386:X86-64:INTEL"

.En Linux esto funciono bien , pero no en Windows. Lo que ocurre es que cuando el cliente gdb se conecta a qemu , este le informa que los tamaños de registros corresponden al de una maquina en modo real de 16 bits. Pero cuando uno pone un breakpoint en el código de toro, la maquina virtual se encuentra en Modo Long con registros de 64bits , con lo cual el paquete enviado sobrepasa el tamaño fijado al comienzo de la conexion y gdb tira ese error.
Lo que hice fue recompilar gdb-7.0 en Win64 y aplicar un parche sencillo por el momento, pero que funciona muy bien. Subiré mi versión de GDB en el próximo paquete que estoy construyendo con todas las herramientas para compilar y testear TORO incluidas.

Saludos.
Matias E. Vara

Monday, April 05, 2010

Debugueando TORO en Eclipse+QEMU

Hola, luego de mucho tiempo buscando la herramienta ideal para compilar y testear toro rapidamente creo haberla encontrado. Casi de casualidad me encontre con la IDE Eclipse y la posibilidad de debugear Linux desde la IDE , y por otro lado encontre un plug-in para dar soporte al lenguaje pascal desde Eclipse. Uniendo estas dos herramientas pude compilar y ejecutar toro paso a paso , linea por linea , colocar breakpoints , etc . Resulto ser una muy potente herramienta que permitira encontrar problemas facilmente. Estoy utilizando la ultima version de Eclipse en un Ubuntu de 64 bits.
Aqui subo un par de screen para motivarlos. Todavia no lo tengo funcionando al 100% .
Pantallas de la ejecucion paso a paso :





Esta es la ventana de qemu que estaba utilizando.




Saludos.

Thursday, January 07, 2010

Lazarus + GDB + QEMU

Estoy trabajando duro para obtener una plataforma para compilar y testear TORO de forma rapida y facil . Para esto estoy haciendo modificaciones sobre el codigo de Lazarus . Lazarus es una IDE para el compilador FREEPASCAL. Estas modificaciones haces posible que cuando se ejecuta "RUN" en la IDE , esta realiza :
- Genera toro.exe
- Genera la imagen booteable de toro .
- Corre QEMU
- Permite debuguear TORO directamente desde la IDE utilizando un cliente GDB.

Saludos.
Matias E. Vara.