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.
El programa long.asm (disponible haciendo click 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. ;
Con esto podemos deducir que el PIC no está siendo reubicado.
<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
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).
Esto se logra con:
TSS: times tss64_struc_size db 0
La estructura de TSS de 64 bits está disponible mas abajo.
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:
mov eax,TSS mov [TSS_sel+gdt+2],ax
mov [TSS+4],rsp
mov eax,TSS_sel ltr ax
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
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
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.
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.
— Marcelo Doallo 2012/07/05 21:03