Diferencias
Muestra las diferencias entre dos versiones de la página.
| 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:// | ||
| - | |||
| - | ; 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: | ||
| - | * Puerta de interrupción en 9 con DPL=0 (cs_sel_64: | ||
| - | |||
| - | Con esto podemos deducir que el PIC no está siendo reubicado. | ||
| - | |||
| - | ==== Que dice "info tab" ==== | ||
| - | |||
| - | < | ||
| - | cr3: 0x00090000 | ||
| - | 0x00000000-0x001fffff -> 0x00000000-0x001fffff | ||
| - | < | ||
| - | |||
| - | |||
| - | 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 " | ||
| - | |||
| - | ===== 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 | ||
| - | |||
| - | 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, | ||
| - | 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 | ||
| - | mov | ||
| - | |||
| - | * Guardar rsp de nivel 0 en la TSS | ||
| - | |||
| - | mov | ||
| - | |||
| - | * Cargar TSS en TR | ||
| - | |||
| - | mov eax, | ||
| - | 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 " | ||
| - | |||
| - | ==== 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, | ||
| - | mov [rbp+16], | ||
| - | mov rax,pila_3 | ||
| - | mov [rbp+32], | ||
| - | mov rax,ds_sel3 | ||
| - | mov [rbp+40], | ||
| - | pop rax | ||
| - | pop rbp | ||
| - | iretq | ||
| - | |||
| - | ==== Estructura de TS de 64 bits ==== | ||
| - | |||
| - | struc tss64_struc | ||
| - | resd 1 ; Reservada | ||
| - | .reg_RSP0 | ||
| - | .reg_RSP1 | ||
| - | .reg_RSP2 | ||
| - | resq 1 ; Reservada | ||
| - | .reg_IST1 | ||
| - | .reg_IST2 | ||
| - | .reg_IST3 | ||
| - | .reg_IST4 | ||
| - | .reg_IST5 | ||
| - | .reg_IST6 | ||
| - | .reg_IST7 | ||
| - | resd 1 ; Reservada | ||
| - | resd 1 ; Reservada | ||
| - | resw 1 ; Reservada | ||
| - | .reg_IOMAP | ||
| - | 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.\\ | ||
| - | |||
| - | --- // | ||