¿Tengo que meter el código de error empujada a la pila de ciertas excepciones, antes de regresar desde el controlador de interrupción?

StackOverflow https://stackoverflow.com/questions/491613

Pregunta

He cargado una idt de la tabla con 256 entradas, todo apunta a similar controladores:

  • para las excepciones de 8 y de 10 a 14, presione el número de excepción (estas excepciones empujar a un código de error automáticamente)
  • para los otros, de impulsar un "dummy" código de error y el número de excepción;
  • a continuación, saltar a un controlador común

Así que cuando el trabajador entra, la pila está correctamente alineado y contiene la excepción/número de interrupción, código de error (que puede ser simplemente un maniquí), eflags, cs y eip.

Mi pregunta se refiere a devolver desde el controlador de interrupción.Yo uso iret para volver después de tomar el número de excepción y el código de error de la pila, pero esto no funciona con la excepción n ° 8;si dejo el código de error en la pila, entonces se devuelve bien!

Preguntas:

  • ¿tengo que dejar el código de error en la pila de excepciones que poner el código de error?Si es así, ¿cómo iret determinar si se ha pop un código de error o no?
  • tan pronto como me habilitar las interrupciones siempre me excepción 8 (doble falta), pero luego todo corre bien (estoy desarrollando un hobby OS).Es este un comportamiento normal o tengo un error en alguna parte?
¿Fue útil?

Solución

Si la CPU introdujo un código de error automáticamente, el controlador debe abrirlo antes del iret. La instrucción <=> no sabe de dónde viene, si es una falla, una trampa o una interrupción externa. Siempre hace lo mismo y supone que no hay código de error en la pila.

Cita del SDM (Software Developer's Manual), Volumen 3, Capítulo 5, sección 5.13 titulada Código de error:

  

El código de error se inserta en la pila   como palabra doble o palabra (dependiendo de   la interrupción, trampa o tarea predeterminada   tamaño de la puerta). Para mantener la pila alineada   para empujes de doble palabra, la mitad superior   del código de error está reservado. Nota   que el código de error no aparece cuando   la instrucción IRET se ejecuta para   volver de un manejador de excepciones, entonces   el controlador debe eliminar el código de error   antes de ejecutar una devolución.

Puede encontrar el Manual del desarrollador de software IA-32 aquí : http://www.intel.com/products/processor/manuals/

Volumen 3 parte 1, capítulo 5, describe el manejo de excepciones e interrupciones. El Volumen 2 parte 1 tiene la especificación para la instrucción <=>.

Otros consejos

Escribí un pequeño x86 OS hace un tiempo. Eche un vistazo al archivo isr. asm en el repositorio de cvs.

Observe cómo configuramos los controladores, la mayoría inserta una palabra ficticia en la pila para dar cuenta de los pocos controladores que obtienen automáticamente un código de error. Luego, cuando regresemos a través de una iret, siempre podemos asumir 2 palabras d en la pila, independientemente de la interrupción, y realizar un add esp, 8 antes de la iret para limpiar las cosas muy bien.

Eso debería responder a su primera pregunta.

En cuanto a su segunda pregunta: una doble falla cuando habilita las interrupciones, ... hmmm podría ser un problema con la paginación si no la configuró correctamente. Podría ser un millón de otras cosas también :)

Tuve un problema similar con " fallas dobles " tan pronto como habilité las interrupciones. Bueno, parecían como fallas dobles, ¡pero realmente eran interrupciones de temporizador!

Las fallas dobles son el número de interrupción 8.

Desafortunadamente, una configuración PIC predeterminada señala las interrupciones del temporizador como número de interrupción (DEFAULT_PIC_BASE + TIMER_OFFSET) = (8 + 0) = <=>.

Enmascarando todas mis interrupciones de PIC (hasta que estuve listo para configurar correctamente el PIC) silenció estas interrupciones de temporizador de doble falla.

(Los PIC requieren que la CPU reconozca las interrupciones antes de producir la siguiente. Dado que su código no reconocía la interrupción inicial del temporizador, ¡el PIC nunca le dio más! Es por eso que solo obtuvo una, en lugar de la trillón podría haber esperado.)

¿Tengo que dejar el código de error en la pila de excepciones que poner el código de error?

Como han mencionado otros, usted tiene que hacer bien:

pop %eax
/* Do something with %eax */
iret

O si desea ignorar el código de error:

add $4, %esp
iret

Si no, iret va a interpretar el código de error como el nuevo CS, y que es probable que obtener un error de protección general como se mencionó en: ¿Por qué iret de un manejador de fallos de página de generar la interrupción 13 (error de protección general) y el código de error 0x18?

Mínima de Trabajo de esta página controlador que he creado para ilustrar esto.Intente comentar el pop y verla volar.

Compare lo anterior con un La división de error de excepción que no pop de la pila.

Tenga en cuenta que si usted simplemente int $14, sin más byte que se envía:esto sólo sucede en el real de la excepción.

Intel Manual de Volumen 3 Guía de Programación de sistemas - 325384-056US de septiembre de 2015 La tabla 6-1."De Modo protegido de Excepciones e Interrupciones" en la columna "Código de Error" contiene la lista de interrupciones que empujar el código de error o no.

38.9.2.2 "error de Página de Códigos de Error", explica cuál es el error medio.

Una buena manera de lidiar con esto es empujar un maniquí código de error 0 en la pila para las interrupciones que no hacen esto para hacer las cosas uniforme.James Molloy tutorial hace exactamente eso.

El kernel de Linux 4.2 parece hacer algo similar.Bajo arch/x86/entrada/entry64.S que los modelos de las interrupciones con has_error_code:

trace_idtentry page_fault do_page_fault has_error_code=1

y luego la usa en el mismo archivo como:

.ifeq \has_error_code
pushq $-1 /* ORIG_RAX: no syscall to restart */
.endif

que hace el push cuando has_error_code=0.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top