Clase pre-parcial
Organización del Computador 2
Segundo cuatrimestre 2023
Ejercicio 1 - 2c 2023 recu
En un sistema como el desarrollado en los talleres se desea modificar la forma en que las tareas se muestran en la pantalla. En lugar de realizar la syscall draw (previamente implementada como int 88) se quiere que las tareas tengan acceso directo a la memoria de video:
Ejercicio 1 - 2c 2023 recu
Con el diseño propuesto hay una única tarea actualmente en pantalla (con acceso a la memoria física de video). Las tareas que no se encuentren en pantalla podrán escribir a las direcciones virtuales de video pero verán sus escrituras reflejadas en la pantalla virtual compartida (dummy).
Soltar la tecla TAB cambiará la tarea actualmente en pantalla. Los cambios de tarea en pantalla se realizarán de manera cíclica (T1-T2-T3-T4-T1-T2-. . . ).
Se solicita describir los cambios requeridos para implementar esta nueva característica.
Ejercicio 1 - 2c 2023 recu - Preguntas
Ejercicio 1 - 2c 2023 recu - Resolución conceptual
Nos piden un montón de cosas, busquemos qué hay que resolver sí o sí:
Ejercicio 1 - 2c 2023 recu - Esquema de memoria
Agregar un mapping al esquema de memoria de las tareas
Ejercicio 1 - 2c 2023 recu - Esquema de memoria
Agregar un mapping al esquema de memoria de las tareas
1a
1a
Ejercicio 1 - 2c 2023 recu - Esquema de memoria
mmu.c
paddr_t mmu_init_task_dir(paddr_t phy_start) {
/* … */
// Mappeo código, stack y shared
mmu_map_page(cr3, TASK_CODE_VIRTUAL + PAGE_SIZE * 0, phy_start,� MMU_P | MMU_U);
mmu_map_page(cr3, TASK_CODE_VIRTUAL + PAGE_SIZE * 1, phy_start + PAGE_SIZE,� MMU_P | MMU_U);
mmu_map_page(cr3, TASK_CODE_VIRTUAL + PAGE_SIZE * 2, stack,� MMU_P | MMU_U | MMU_W);
mmu_map_page(cr3, TASK_CODE_VIRTUAL + PAGE_SIZE * 3, SHARED,� MMU_P | MMU_U);
// Mappeo video dummy (2 páginas)
mmu_map_page(cr3, 0x08004000, 0x1E000, MMU_P | MMU_U | MMU_W);
mmu_map_page(cr3, 0x08005000, 0x1F000, MMU_P | MMU_U | MMU_W);
}
Ejercicio 1 - 2c 2023 recu - Intercambio de pantallas
Poder intercambiar la pantalla entre una tarea y la que le sigue:
Idea | Scheduling de tareas | Scheduling de pantallas |
Tarea actual | int8_t current_task; | int8_t current_video_task; |
Inicializar tareas | void sched_init(); | void video_init(); |
Cambiar de tarea | int de clock (_isr32)�+ sched_next_task(); | int de teclado (_isr33)�+ swap_video_page(); |
Ejercicio 1 - 2c 2023 recu - Intercambio de pantallas
Poder intercambiar la pantalla entre una tarea y la que le sigue:
Cambiar de tarea son tres cosas:
Ejercicio 1 - 2c 2023 recu - Intercambio de pantallas
video.c
int8_t current_video_task; // Variable global
void swap_video_page() {
int next_video_task = (current_video_task + 1) % MAX_TASKS;
paddr_t cr3_current = tss_tasks[current_video_task].cr3;
paddr_t cr3_next = tss_tasks[next_video_task].cr3;
// La tarea actual pasa a la dummy
mmu_map_page(cr3_current, 0x08004000, 0x1E000, MMU_P | MMU_U | MMU_W);
mmu_map_page(cr3_current, 0x08005000, 0x1F000, MMU_P | MMU_U | MMU_W);
// La siguiente tarea pasa a la posta
mmu_map_page(cr3_next, 0x08004000, 0xB8000, MMU_P | MMU_U | MMU_W);
mmu_map_page(cr3_next, 0x08005000, 0xB9000, MMU_P | MMU_U | MMU_W);
// Y ahora la tarea nueva es la actual :)
current_video_task = next_video_task;
}
Ejercicio 1 - 2c 2023 recu - Primer pantalla
Al arrancar el sistema: determinar quién tiene la primer pantalla
Alguien tiene que ser la primera en tener la pantalla. Dos opciones:
Ejercicio 1 - 2c 2023 recu - Primer pantalla
video.c
int8_t current_video_task; // Variable global
�// NOTA: En algún lugar de kernel.asm vamos a tener que llamar a video_init!
paddr_t video_init() {
int first_task = 0;
paddr_t cr3 = tss_tasks[first_task].cr3;
current_video_task = first_task;
// Mappeo video posta (2 páginas)
mmu_map_page(cr3, 0x08004000, 0xB8000, MMU_P | MMU_U | MMU_W);
mmu_map_page(cr3, 0x08005000, 0xB9000, MMU_P | MMU_U | MMU_W);
}
Ejercicio 1 - 2c 2023 recu - Responder al teclado
Ejercicio 1 - 2c 2023 recu - Responder al teclado
isr.asm
global _isr33
_isr33: ;rutina de atención del teclado
pushad
; 1. Le decimos al PIC que vamos a atender la interrupción
call pic_finish1
; 2. Leemos la tecla desde el teclado y la procesamos
in al, 0x60
push eax
cmp al, 0x8F
jne .no_es_soltar_tab
call swap_video_page
.no_es_soltar_tab:
call tasks_input_process
add esp, 4
popad
iret
Ejercicio 1 - 2c 2023 recu - current_video_task
Agregar un mecanismo para que una tarea pueda responder: ¿Quién tiene la pantalla?
Ejercicio 1 - 2c 2023 recu - Múltiples dummy
Agregar una forma de que las tareas no se choquen en la dummy
Ejercicio 1 - 2c 2023 recu - Múltiples dummy
video.c
void swap_video_page() {
/* ... */
// La tarea actual pasa a la dummy
copy_page(dummy_video_page_de(current_video_task), 0xB8000);
copy_page(dummy_video_page_de(current_video_task) + PAGE_SIZE, 0xB9000);
mmu_map_page(cr3_current, 0x08004000, 0x1E000, MMU_P | MMU_U | MMU_W);
mmu_map_page(cr3_current, 0x08005000, 0x1F000, MMU_P | MMU_U | MMU_W);
// La siguiente tarea pasa a la posta
copy_page(0xB8000, dummy_video_page_de(next_video_task));
copy_page(0xB9000, dummy_video_page_de(next_video_task) + PAGE_SIZE);
mmu_map_page(cr3_next, 0x08004000, 0xB8000, MMU_P | MMU_U | MMU_W);
mmu_map_page(cr3_next, 0x08005000, 0xB9000, MMU_P | MMU_U | MMU_W);
/* ... */
}
Preguntas?
Ahora pasamos al Ej. 2
Ejercicio 2 - 1c 2023 recu
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
Tenemos un montón de software escrito para el ENTEL575 pero lamentablemente no poseemos hardware que lo pueda correr. ¿Podrías desarrollar un sistema que nos permita hacerlo?
Ejercicio 2 - 1c 2023 recu
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
Tenemos un montón de software escrito para el ENTEL575 pero lamentablemente no poseemos hardware que lo pueda correr. ¿Podrías desarrollar un sistema que nos permita hacerlo? Para ello, respondé los siguientes puntos:
Ejercicio 2 - 1c 2023 recu
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
Tenemos un montón de software escrito para el ENTEL575 pero lamentablemente no poseemos hardware que lo pueda correr. ¿Podrías desarrollar un sistema que nos permita hacerlo? Para ello, respondé los siguientes puntos:
Ejercicio 2 - 1c 2023 recu
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
Tenemos un montón de software escrito para el ENTEL575 pero lamentablemente no poseemos hardware que lo pueda correr. ¿Podrías desarrollar un sistema que nos permita hacerlo? Para ello, respondé los siguientes puntos:
Ejercicio 2
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
Tenemos un montón de software escrito para el ENTEL575 pero lamentablemente no poseemos hardware que lo pueda correr. ¿Podrías desarrollar un sistema que nos permita hacerlo? Para ello, respondé los siguientes puntos:
Recomendaciones:
Ejercicio 2
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
Ejercicio 2
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
Ejercicio 2
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
Ejercicio 2
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
B. Realice un diagrama de pila que muestre el estado de la pila del kernel luego de que una aplicación de usuario intentó ejecutar RSTLOOP.
¿Qué ocurre cuando una tarea intenta ejecutar RSTLOOP?
Ejercicio 2
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
B. Realice un diagrama de pila que muestre el estado de la pila del kernel luego de que una aplicación de usuario intentó ejecutar RSTLOOP.
+
-
+
-
+
-
¿Qué ocurre cuando una tarea intenta ejecutar RSTLOOP?
Ejercicio 2
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
B. Realice un diagrama de pila que muestre el estado de la pila del kernel luego de que una aplicación de usuario intentó ejecutar RSTLOOP.
+
-
+
-
+
-
SS |
ESP |
EFLAGS |
CS |
EIP |
+
-
<- esp al comienzo de RAI opcode inválido
¿Qué ocurre cuando una tarea intenta ejecutar RSTLOOP?
Ejercicio 2
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
B. Realice un diagrama de pila que muestre el estado de la pila del kernel luego de que una aplicación de usuario intentó ejecutar RSTLOOP.
+
-
+
-
+
-
C. ¿Qué dirección de retorno se encuentra en la pila al atender la excepción?
Ejercicio 2
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
B. Realice un diagrama de pila que muestre el estado de la pila del kernel luego de que una aplicación de usuario intentó ejecutar RSTLOOP.
+
-
+
-
+
-
C. ¿Qué dirección de retorno se encuentra en la pila al atender la excepción?
Ejercicio 2
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
D. Describa una posible implementación de RSTLOOP utilizando el mecanismo descrito en (a) y (b).
Ejercicio 2
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
D. Describa una posible implementación de RSTLOOP utilizando el mecanismo descrito en (a) y (b).
Ejercicio 2
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
D. Describa una posible implementación de RSTLOOP utilizando el mecanismo descrito en (a) y (b).
Modificamos la rutina de atención de la interrupción 6.
Dados:
- EIP: Puntero a la instrucción no reconocida
- CS, EFLAGS, ESP, SS: Estado de la tarea
Hacer:
Ejercicio 2
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
D. Describa una posible implementación de RSTLOOP utilizando el mecanismo descrito en (a) y (b).
Modificamos la rutina de atención de la interrupción 6.
Dados:
- EIP: Puntero a la instrucción no reconocida
- CS, EFLAGS, ESP, SS: Estado de la tarea
Hacer:
E. ¿Qué pasa si no hacemos este paso?
Ejercicio 2
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
F. Detalle los cambios a las estructuras del sistema visto en el taller que haría para realizar la implementación descrita en (d).
G. Muestre código para la rutina de atención de interrupciones descrita en (d) y todo otro cambio de comportamiento que haya visto necesario.
Ejercicio 2
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
F. Detalle los cambios a las estructuras del sistema visto en el taller que haría para realizar la implementación descrita en (d). -> modificamos sólo la RAI de opcode invalido (isr6)
G. Muestre código para la rutina de atención de interrupciones descrita en (d) y todo otro cambio de comportamiento que haya visto necesario.
SS |
ESP |
EFLAGS |
CS |
EIP |
+
-
<- esp al comienzo de RAI opcode inválido
=> [ESP] = EIP
Si en EIP se encuentra la secuencia de bytes 0x0F, 0x0B: (Leemos los bytes en [EIP], [EIP+1])
Sino:
Ejercicio 2
El ENTEL575 fue un microprocesador compatible con los Intel i686. Este procesador incluía varias funcionalidades extra que nunca fueron replicadas por Intel. Una de ellas es la operación RSTLOOP, la cual escribe un cero en ECX 'reiniciando' el contador de vueltas. RSTLOOP se codifica con la secuencia de bytes 0x0F 0x0B.
G. Muestre código para la rutina de atención de interrupciones descrita en (d) y todo otro cambio de comportamiento que haya visto necesario.
isr.asm
extern current_task
extern sched_disable_task
_isr6:
; cargamos el EIP de la tarea
mov ecx, [esp]
; cargamos la instrucción
mov cx, [ecx]
; es rstloop?
cmp cx, 0x0B0F
je .emulate_rstloop
; no es, deshabilitamos
push DWORD [current_task]
call sched_disable_task
...
...
; salto a IDLE
add esp, 4
jmp (12 << 3):0
.emulate_rstloop:
mov ecx, 0
add DWORD [esp], 2
iret
Si en EIP se encuentra la secuencia de bytes 0x0F, 0x0B: (Leemos los bytes en [EIP], [EIP+1])
Sino:
Nota: [ESP] = EIP
sched.c
typedef enum {
TASK_SLOT_FREE,
TASK_RUNNABLE,
TASK_PAUSED
} task_state_t;
typedef struct {
int16_t selector;
task_state_t state;
} sched_entry_t;
static sched_entry_t sched_tasks[MAX_TASKS] = {0};
int8_t current_task = 0;
// ...
void sched_disable_task(int8_t task_id) {
kassert(task_id >= 0 && task_id < MAX_TASKS, "Invalid task_id");
sched_tasks[task_id].state = TASK_PAUSED;
}
// ...
Preguntas?