Triple falla en el núcleo de cosecha propia
assembly operating-system (3)
Puede vincular qemu a una sesión de depuración de gdb a través de las herramientas de depuración remota en gdb. Esto se puede hacer emitiendo los siguientes comandos:
qemu -s [optional arguments]
Luego, dentro de su sesión de gdb, abra su ejecutable de kernel y luego de establecer un punto de interrupción en su función switch_page_directory()
, escriba el siguiente comando en el indicador de gdb:
target remote localhost:1234
A continuación, puede pasar por un solo paso a través de su kernel en el punto de interrupción y ver dónde se está produciendo la falla triple.
Otro paso a considerar es instalar realmente algunos manejadores de excepciones predeterminados en su IDT ... la razón por la cual tiene fallas triples es porque la CPU está lanzando una excepción, pero no hay un manejador de excepciones adecuado para manejarlo. Por lo tanto, con algunos controladores predeterminados instalados, especialmente el controlador de fallas dobles, puede detener efectivamente el kernel sin entrar en una falla triple que restablece automáticamente la PC.
Finalmente, asegúrese de haber reprogramado el PIC antes de pasar al modo protegido ... de lo contrario, las interrupciones de hardware predeterminadas programadas para dispararse desde el BIOS en modo real ahora activarán las interrupciones de excepción en modo protegido.
Intento escribir un kernel, principalmente con fines de entretenimiento, y me encuentro con un problema si creo que es triple fallamiento. Todo funcionó antes de intentar habilitar la búsqueda. El código que se está rompiendo es este:
void switch_page_directory(page_directory_t *dir){
current_directory = dir;
asm volatile("mov %0, %%cr3":: "r"(&dir->tablesPhysical));
u32int cr0;
asm volatile("mov %%cr0, %0": "=r"(cr0));
cr0 |= 0x80000000;//enable paging
asm volatile("mov %0, %%cr0":: "r"(cr0)); //this line breaks
}//switch page directory
He estado siguiendo una variedad de tutoriales / documentos para esto, pero el que estoy usando para buscar es http://www.jamesmolloy.co.uk/tutorial_html/6.-Paging.html . No estoy seguro de qué otro código será útil para resolver esto, pero si hay más que debería proporcionar, estaré más que feliz de hacerlo.
Editar =====
Creo que CS, DS y SS están seleccionando las entradas correctas, aquí está el código utilizado para configurarlas
global gdt_flush
extern gp
gdt_flush:
lgdt [gp] ; Load the GDT with our ''gp'' which is a special pointer
mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:flush2 ; 0x08 is the offset to our code segment: Far jump!
flush2:
ret ; Returns back to the C code!
y aquí está la estructura de gdt en sí misma
struct gdt_entry{
unsigned short limit_low;
unsigned short base_low;
unsigned char base_middle;
unsigned char access;
unsigned char granularity;
unsigned char base_high;
} __attribute__((packed));
struct gdt_ptr{
unsigned short limit;
unsigned int base;
} __attribute__((packed));
struct gdt_entry gdt[5];
struct gdt_ptr gp;
El IDT es muy similar a esto.
También estaba enfrentando el mismo problema con el tutorial de paginación.Pero después de algunas búsquedas encontré la solución que estaba sucediendo porque tan pronto como la paginación está habilitada, todas las direcciones se vuelven virtuales y para resolverlo debemos mapear las direcciones virtuales a las mismas direcciones físicas para se refieren a lo mismo y esto se llama mapeo de identidad.
puede seguir este enlace para obtener ayuda adicional en la implementación de Identity Maping.
y una cosa más que tiene es poner a cero el espacio recién asignado porque puede contener valores basura y memset no se hizo en el tutorial, funcionará en bochs porque establece el espacio en cero para usted, pero el otro emulador (qemu) y el hardware real son tan amable.
GDT: no dices cuál es el contenido de las entradas de GDT, pero las cosas que has mostrado son bastante similares a la parte anterior del tutorial al que te vinculaste y si has configurado las entradas de la misma manera, entonces todo debería estar bien (es decir, asignación de segmentos planos con un segmento de código de anillo 0 para CS, segmento de datos de anillo 0 para todo lo demás, ambos con una base de 0 y un límite de 4 GB).
IDT: probablemente no importe de todos modos si las interrupciones están deshabilitadas y no (todavía) espera causar fallas en la página.
Tablas de página: las tablas de página incorrectas parecen el sospechoso más probable. Asegúrese de que su mapeo de identidad cubra todo el código, los datos y la memoria de pila que está usando (al menos).
El código fuente vinculado a la parte inferior de http://www.jamesmolloy.co.uk/tutorial_html/6.-Paging.html definitivamente crea algo que funciona correctamente tanto con QEMU como con Bochs, así que con suerte puedes comparar lo que haces. Rehaciendo con lo que está haciendo, y descubriendo qué está mal.
QEMU es bueno en general, pero recomendaría Bochs para el desarrollo de cosas de muy bajo nivel: incluye (o puede configurarse para incluir) un depurador interno muy útil. por ejemplo, establecer reset_on_triple_fault=0
en la cpu:
línea del archivo de configuración, establecer un punto de interrupción en el código switch_page_directory()
, ejecutar en el punto de interrupción, luego instrucciones de un solo paso y ver qué pasa ...