Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anterior Revisión previa
Próxima revisión
Revisión previa
td3:de0a3en64 [2012/07/06 13:20]
mdoallo
— (actual)
Línea 1: Línea 1:
-====== Cambiar de nivel cero a tres en IA-32e  ====== 
  
-===== Objeto del documento ===== 
- 
-Brindar recomendaciones para el pasaje de nivel de privilegio cero a tres en IA-32e. A partir del ejemplo de programa en IA-32e aportado por el Ing. Dario Alpern. 
- 
-===== Punto de partida ===== 
- 
-El programa long.asm (disponible haciendo click [[http://www.electron.frba.utn.edu.ar/~mdoallo/descargas/ej3.3-pag_ia32e.tar.gz|aquí]]) propone lo siguiente: \\ 
- 
-  ; Hacer un programa que muestre la cantidad de decimas de segundo que estuvo  
-  ; corriendo en modo largo (64 bits) y la cantidad de teclas presionadas. 
-  ; Utilizar para ello las interrupciones en modo protegido 8 (reloj) y 9 (teclado). 
-  ; El cuerpo principal de ejecución se detiene con hlt 
-  ;  
-  ; Hecho por Dario Alejandro Alpern el 11 de marzo de 2008.  
-  ;  
- 
-==== Que dice "info gdt" ==== 
- 
-  * Entrada nula 
-  * Segmento de código de 64 bits con DPL=0 (cs_sel_64) 
-  * Segmento de código de 32 bits con DPL=0 (cs_sel_32) 
-  * Segmento de datos de 32 bits (ds_sel) 
- 
-==== Que dice "info idt" ==== 
- 
-  * Puerta de interrupción en 8 con DPL=0 (cs_sel_64:int8han)  
-  * Puerta de interrupción en 9 con DPL=0 (cs_sel_64:int9han) 
- 
-Con esto podemos deducir que el PIC no está siendo reubicado. 
- 
-==== Que dice "info tab" ==== 
- 
-  <bochs:4> info tab 
-  cr3: 0x00090000 
-  0x00000000-0x001fffff -> 0x00000000-0x001fffff 
-  <bochs:5>  
- 
- 
-Esto nos dice que tenemos una página de dos MB con **identity mapping** 
- 
-===== ¿Cual es la idea? ===== 
- 
-Utilizar "int 30h" para bajar el código de nivel cero a tres.\\ 
-La paginación permanece invariable.\\ 
-El timer tick se usa para actualizar pantalla ejecutando código de nivel 0 como antes.\\ 
-Lo mismo para el manejo del teclado.\\ 
-Probar "int 80h" para acceder a nivel cero desde el tres.\\ 
-El programa para detenerse debe utilizar "jmp $" en vez de "halt" (Está claro que esto consume CPU, es sólo porque está en nivel tres).\\ 
- 
-===== Manos a la obra ===== 
- 
-  * En la GDT declaramos tres segmentos nuevos. Uno para código de 64 bits con DPL=0, otro de datos de 32 bits también con DPL=3 y otro para TSS (Task State Segment) también de 64 bits. 
-  * En la IDT agregamos una puerta de interrupción en 30h con DPL=0, que será para hacer el cambio de privilegio (de cero a tres). También agregamos otra puerta de interrupción en 80h, esta será para acceso a servicios del kernel por código que corre en nivel tres. 
-  * Dado que describimos una TSS en la GDT debemos reservar espacio en memoria a tal efecto. 
- 
-Esto se logra con:  
-  TSS: times tss64_struc_size               db  0 
- 
-La estructura de TSS de 64 bits está disponible mas abajo. 
- 
-  * Asegurarse que la página esté accesible a nivel USER. 
-  * Definir pila de nivel cero (porque no me gusta como está en long.asm) 
- 
-  mov rsp,pila_0  
-  mov ax,ds_sel 
-  mov ss,ax 
- 
-Donde pila_0 de define como:\\ 
- 
-  align 256  
-  times 256 db 0 
-  pila_0: 
- 
-  * Definir pila de nivel tres. 
-  * Inicializar la base del descriptor de TSS en la GDT 
- 
-  mov     eax,TSS 
-  mov     [TSS_sel+gdt+2],ax 
- 
-  * Guardar rsp de nivel 0 en la TSS 
- 
-  mov     [TSS+4],rsp 
- 
-  * Cargar TSS en TR 
- 
-  mov eax,TSS_sel 
-  ltr ax 
- 
-  * Invocar INT 30h para pasar de nivel cero a tres 
-  * Luego de esto se debe verificar que estamos en nivel 3. 
-  * Hacer pruebas de manejo de pila de nivel 3 y uso de int 80h. 
-  * Finalmente "colgar" la ejecución con un jmp $. 
- 
-==== La magia está en int 30h ==== 
- 
-Al ejecutar la interrupción se guarda en la pila de nivel 0 lo siguiente: RIP, CS, RFLAGS, RSP y SS. \\ 
-La idea es alterar CS, RSP y SS de la pila. Para que luego al hacer IRETQ se cambie de nivel.\\ 
-  push rbp 
-  mov rbp,rsp 
-  push rax               ; para trabajar 
-  mov rax,cs_sel3_64 
-  mov [rbp+16],rax 
-  mov rax,pila_3 
-  mov [rbp+32],rax 
-  mov rax,ds_sel3 
-  mov [rbp+40],rax 
-  pop rax 
-  pop rbp 
-  iretq 
- 
-==== Estructura de TS de 64 bits ==== 
- 
-  struc tss64_struc 
-                       resd 1      ; Reservada 
-        .reg_RSP0      resq 1 
-        .reg_RSP1      resq 1 
-        .reg_RSP2      resq 1 
-       resq 1      ; Reservada 
-        .reg_IST1      resq 1 
-        .reg_IST2      resq 1 
-        .reg_IST3      resq 1 
-        .reg_IST4      resq 1 
-        .reg_IST5      resq 1 
-        .reg_IST6      resq 1 
-        .reg_IST7      resq 1 
-                       resd 1      ; Reservada 
-                       resd 1      ; Reservada 
-                       resw 1      ; Reservada 
-        .reg_IOMAP     resw 1 
-  endstruc 
- 
-==== Si todo sale bien ... ==== 
- 
-El programa debe lucir igual que el original (long.asm), sólo que al hacer break el código debe estar en el "jmp $" de nivel 3, a menos que tengamos la suerte de detenerlo justo en alguno de los handler de interrupción (8 o 9) donde estaría corriendo en anillo 0. 
- 
-===== Agradecimientos ===== 
- 
-A Dario Alpern por el aporte de long.asm. A Alejandro Furfaro por meternos en este baile. A Mariano Gonzalez y Juan Carlos Cuttitta que colaboran con ideas todo el tiempo. Al cuerpo docente de la cátedra de TDIII.\\ 
-Se aceptan críticas y comentarios.\\ 
- 
- --- //[[mdoallo@electron.frba.utn.edu.ar|Marcelo Doallo]] 2012/07/05 21:03//