feat: gestion d'exception avancé avec dump des registres

This commit is contained in:
Nicolas Hordé 2018-10-03 22:50:54 +02:00
parent baf52f0594
commit 72abe00043
11 changed files with 314 additions and 127 deletions

View File

@ -41,6 +41,10 @@
#define ltr(tss) asm volatile ("ltr %%ax":: "a" (tss))
#define str(tss) asm volatile ("str %%ax;\
mov %%ax,%0":: "m" (tss))
/******************************************************************************/
#define outb(port,value) \

View File

@ -43,5 +43,6 @@ bool cansetflag (u32 flag);
void cpuid(u32 op, u32 *eax, u32 *ebx,u32 *ecx, u32 *edx);
u8 getcpuinfos(cpuinfo *inf);
u32 getESP(void);
void dump_regs(exception_stack *stack);
u32 setESP(u32 stack);
void dump_cpu(save_stack *stack);
void show_cpu(save_stack *stack);

View File

@ -77,3 +77,11 @@ typedef struct tss {
void inittr(void);
void initgdt(u32 offset);
void makegdtdes(u32 base, u32 limite, u8 acces, u8 flags, gdtdes *desc);
u32 getdesbase(u16 sel);
u8 getdestype(u16 sel);
u32 getdessize(u16 sel);
u32 getdeslimit(u16 sel);
bool isdesvalid(u16 sel);
u8 getdesbit3(u16 sel);
u32 getdesdpl(u16 sel);
u16 getdesalign(u16 sel);

View File

@ -37,6 +37,29 @@
#define TIMER_FREQ 1193180 /* fréquence pour timer dans un PC ou AT */
#define HZ 100 /* Fréquence d'horloge (ajutste logiciellement sur IBM-PC) */
/* save pile */
typedef struct save_stack {
u32 cr4;
u32 cr3;
u32 cr2;
u32 cr0;
u32 eflags;
u32 ss;
u32 gs;
u32 fs;
u32 es;
u32 ds;
u32 eip;
u32 cs;
u32 esp;
u32 ebp;
u32 edi;
u32 esi;
u32 edx;
u32 ecx;
u32 ebx;
u32 eax;
} save_stack __attribute__ ((packed));
/* exception pile */
typedef struct exception_stack {
u32 error_code;
@ -72,7 +95,7 @@ struct idtr {
void initpic(void);
void enableirq(u8 irq);
void disableirq(u8 irq);
void cpuerror(const u8 * src, const exception_stack *stack);
void cpuerror(const u8 * src, const save_stack *stack);
#endif

View File

@ -17,4 +17,6 @@ int mode();
int clear();
int regs();
int info();
int pagefault();
int pgfaultr();
int pgfaultw();
int divzerr();

177
lib/cpu.c
View File

@ -6,6 +6,7 @@
#include "memory.h"
#include "string.h"
#include "asm.h"
#include "gdt.h"
/* Technologies supportées */
@ -135,103 +136,99 @@ u32 getESP(void)
return stack;
}
/******************************************************************************/
/* Fixe la tête de pile */
u32 setESP(u32 stack)
{
asm("movl %[param],%%esp;": [param] "=r"(stack));
}
/******************************************************************************/
/* Sauvegarde les registres CPU */
void dump_cpu(save_stack *stack)
{
save_stack new;
asm(" addl $0x50,%%esp \n \
pushl %%eax \n \
pushl %%ebx \n \
pushl %%ecx \n \
pushl %%edx \n \
pushl %%esi \n \
pushl %%edi \n \
pushl %%ebp \n \
pushl %%esp \n \
pushl %%cs \n \
pushl 0x0 \n \
pushl %%ds \n \
pushl %%es \n \
pushl %%fs \n \
pushl %%gs \n \
pushl %%ss \n \
pushf \n \
mov %%cr0, %%ebx \n \
pushl %%ebx\n \
mov %%cr2, %%ebx \n \
pushl %%ebx\n \
mov %%cr3, %%ebx \n \
pushl %%ebx\n \
mov %%cr4, %%ebx \n \
pushl %%ebx":::);
memcpy(&new, stack, sizeof(save_stack), 1);
}
/******************************************************************************/
/* Affiche les registres CPU */
void dump_regs(exception_stack *stack)
void show_cpu(save_stack *stack)
{
cli();
u32 eax = 0;
u32 ebx = 0;
u32 ecx = 0;
u32 edx = 0;
u32 esi = 0;
u32 edi = 0;
u32 ebp = 0;
u32 esp = 0;
u32 eip = 0;
u16 cs = 0;
u16 ds = 0;
u16 es = 0;
u16 fs = 0;
u16 gs = 0;
u16 ss = 0;
u32 cr0 = 0;
u32 cr1 = 0;
u32 cr2 = 0;
u32 cr3 = 0;
u32 cr4 = 0;
u32 eflags = 0;
asm("movl %%eax, %[a1] ;" "movl %%ebx, %[b1] ;" "movl %%ecx, %[c1] ;" "movl %%edx, %[d1] ;" "movl %%esi, %[e1] ;" "movl %%edi, %[f1] ;" "movl %%esp, %[g1] ;" "movl %%ebp, %[h1] ;" "movw %%cs, %[i1] ;" "movw %%ds, %[j1] ;" "movw %%es, %[k1] ;" "movw %%fs, %[l1] ;" "movw %%gs, %[m1] ;" "movw %%ss, %[n1] ;" "mov %%cr0, %%eax ;" "mov %%eax, %[o1] ;" "mov %%cr2, %%eax ;" "mov %%eax, %[p1] ;" "mov %%cr3, %%eax ;" "mov %%eax, %[q1] ;" "mov %%cr4, %%eax ;" "mov %%eax,%[r1] ;":
[a1] "=m"(eax),[b1] "=m"(ebx),[c1] "=m"(ecx),[d1] "=m"(edx),[e1] "=m"(esi),
[f1] "=m"(edi),[g1] "=m"(esp),[h1] "=m"(ebp),[i1] "=m"(cs),[j1] "=m"(ds),
[k1] "=m"(es),[l1] "=m"(fs),[m1] "=m"(gs),[n1] "=m"(ss),[o1] "=m"(cr0),
[p1] "=m"(cr2),[q1] "=m"(cr3),[r1] "=m"(cr4));
if (stack!=0) {
eip=stack->eip;
eflags=stack->eflags;
cs=stack->cs;
esp=stack;
printf("\033[0m");
}
else
printf("\033[1mATTENTION PAS DE PILE ! REGISTRES INCERTAINS\r\n");
printf("EAX=%X EBX=%X ECX=%X EDX=%X\r\n", eax, ebx, ecx, edx);
printf("ESI=%X EDI=%X ESP=%X EBP=%X\r\n", esi, edi, esp, ebp);
printf("EIP=%X\r\n", eip);
printf
("CS=%hX DS=%hX ES=%hX FS=%hX GS=%hX SS=%hX\r\n",
(u32) cs, (u32) ds, (u32) es, (u32) fs, (u32) gs, (u32) ss);
printf("CR0=%X CR1=N/A CR2=%X CR3=%X CR4=%X\r\n", cr0, cr2, cr3,
cr4);
asm("pushf ;" "pop %[f1] ;":
[f1] "=m"(eflags));
printf("EFLAGS=%X", eflags);
if (eflags & (1 << 0)) // Carry
printf(" (C1");
else
printf(" (C0");
if (eflags & (1 << 2)) // Parity
printf(" P1");
else
printf(" P0");
if (eflags & (1 << 4)) // Adjust
printf(" A1");
else
printf(" A0");
if (eflags & (1 << 6)) // Zero
printf(" Z1");
else
printf(" Z0");
if (eflags & (1 << 7)) // Sign
printf(" S1");
else
printf(" S0");
if (eflags & (1 << 11)) // Overflow
printf(" O1)\r\n");
else
printf(" O0)\r\n");
printf("EAX=%Y EBX=%Y ECX=%Y EDX=%Y\r\n", stack->eax, stack->ebx, stack->ecx, stack->edx);
printf("ESI=%Y EDI=%Y ESP=%Y EBP=%Y\r\n", stack->esi, stack->edi, stack->esp, stack->ebp);
printf("EIP=%Y EFL=%Y [%c%c%c%c%c%c%c%c%c]\r\n", stack->eip, stack->eflags,
(stack->eflags & (1 <<11)) ? 'O':'-',
(stack->eflags & (1 <<10)) ? 'D':'-',
(stack->eflags & (1 << 9)) ? 'I':'-',
(stack->eflags & (1 << 8)) ? 'T':'-',
(stack->eflags & (1 << 7)) ? 'S':'-',
(stack->eflags & (1 << 6)) ? 'Z':'-',
(stack->eflags & (1 << 4)) ? 'A':'-',
(stack->eflags & (1 << 2)) ? 'P':'-',
(stack->eflags & (1 << 0)) ? 'C':'-');
printf("CS =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n",stack->cs,getdesbase(stack->cs),getdeslimit(stack->cs),getdesdpl(stack->cs),getdestype(stack->cs),getdessize(stack->cs),getdesbit3(stack->cs),getdesbit2(stack->cs),getdesbit1(stack->cs),getdesalign(stack->cs));
printf("DS =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n",stack->ds,getdesbase(stack->ds),getdeslimit(stack->ds),getdesdpl(stack->ds),getdestype(stack->ds),getdessize(stack->ds),getdesbit3(stack->ds),getdesbit2(stack->ds),getdesbit1(stack->ds),getdesalign(stack->ds));
printf("SS =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n",stack->ss,getdesbase(stack->ss),getdeslimit(stack->ss),getdesdpl(stack->ss),getdestype(stack->ss),getdessize(stack->ss),getdesbit3(stack->ss),getdesbit2(stack->ss),getdesbit1(stack->ss),getdesalign(stack->ss));
printf("ES =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n",stack->es,getdesbase(stack->es),getdeslimit(stack->es),getdesdpl(stack->es),getdestype(stack->es),getdessize(stack->es),getdesbit3(stack->es),getdesbit2(stack->es),getdesbit1(stack->es),getdesalign(stack->es));
printf("FS =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n",stack->fs,getdesbase(stack->fs),getdeslimit(stack->fs),getdesdpl(stack->fs),getdestype(stack->fs),getdessize(stack->fs),getdesbit3(stack->fs),getdesbit2(stack->fs),getdesbit1(stack->fs),getdesalign(stack->fs));
printf("GS =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n",stack->gs,getdesbase(stack->gs),getdeslimit(stack->gs),getdesdpl(stack->gs),getdestype(stack->gs),getdessize(stack->gs),getdesbit3(stack->gs),getdesbit2(stack->gs),getdesbit1(stack->gs),getdesalign(stack->gs));
u32 tss;
str(tss);
printf("TR =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n",stack->gs,getdesbase(tss),getdeslimit(tss),getdesdpl(tss),getdestype(tss),getdessize(tss),getdesbit3(tss),getdesbit2(tss),getdesbit1(tss),getdesalign(tss));
struct gdtr gdtreg;
sgdt(&gdtreg);
printf("GDT= %Y %Y\r\n",gdtreg.base,gdtreg.limite);
struct idtr idtreg;
sidt(&idtreg);
printf("IDT= %Y %Y\r\n",idtreg.base,idtreg.limite);
printf("STACK\r\n");
u32 i = 0;
for (u32 *pointer = esp; pointer < KERNEL_STACK_ADDR; pointer += 4) {
printf("+%d:%X\t\t%X\r\n", i++, pointer,
(u32)(*pointer));
if (i > 5) {
print("...\r\n");
break;
}
if (abs(KERNEL_STACK_ADDR-stack->esp)>0x10000)
printf("Pile invalide !");
else
{
u32 i=0;
for (u32 *pointer = stack->esp; pointer < KERNEL_STACK_ADDR; pointer ++) {
if (i>0 && i % 10 == 0) print("\033[10A");
if (i>=10)
print("\033[25C");
printf("+%d:%Y - %Y\r\n", i++, pointer, (u32)(*pointer));
if (i > 20) {
print("...\r\n");
break;
}
}
for(u32 j=0;j<10-(i % 10);j++)
print("\033[01B");
}
printf("\033[0m");
sti();
}
/*******************************************************************************/

116
lib/gdt.c
View File

@ -74,6 +74,122 @@ void initselectors(u32 executingoffset)
ret\n"::[data] "i"(SEL_KERNEL_DATA),[code] "i"(SEL_KERNEL_CODE),[stack] "i"(SEL_KERNEL_STACK),[stackoff] "i"(KERNEL_STACK_ADDR),[offset] "m"(executingoffset));
}
/*******************************************************************************/
/* récupère la base d'un descripteur GDT */
u32 getdesbase(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
return (entry[index].base0_15+(entry[index].base16_23<<16)+(entry[index].base24_31<<24));
}
/*******************************************************************************/
/* récupère la limite d'un descripteur GDT */
u32 getdeslimit(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
return (entry[index].lim0_15+(entry[index].lim16_19<<16));
}
/*******************************************************************************/
/* récupère la limite d'un descripteur GDT */
u32 getdesdpl(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
return (entry[index].acces>>5 & 0b11);
}
/*******************************************************************************/
/* récupère le type d'un descripteur GDT */
u8 getdestype(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
if (((entry[index].acces & 0b10100) == 0) && ((entry[index].acces & 0b01000) > 0) && ((entry[index].acces & 0b0001) > 0) && ((entry[index].flags & 0b0110) == 0))
return 'T';
else
return (((entry[index].acces & 0b1000) > 0) ? 'C' : 'D');
}
/*******************************************************************************/
/* récupère l'info 1 d'un descripteur GDT */
u8 getdesbit1(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
if (((entry[index].acces & 0b10100) == 0) && ((entry[index].acces & 0b01000) > 0) && ((entry[index].acces & 0b0001) > 0) && ((entry[index].flags & 0b0110) == 0))
return (((entry[index].acces & 0b10) > 0) ? 'B' : '-');
else
return (((entry[index].acces & 0b1) > 0) ? 'A' : '-');
}
/*******************************************************************************/
/* récupère l'info 2 d'un descripteur GDT */
u8 getdesbit2(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
if (((entry[index].acces & 0b10100) == 0) && ((entry[index].acces & 0b01000) > 0) && ((entry[index].acces & 0b0001) > 0) && ((entry[index].flags & 0b0110) == 0))
return (((entry[index].flags & 0b1) > 0) ? 'U' : '-');
else if ((entry[index].acces & 0b1000) > 0)
return (((entry[index].acces & 0b10) > 0) ? 'R' : '-');
else
return (((entry[index].acces & 0b10) > 0) ? 'W' : 'R');
}
/*******************************************************************************/
/* récupère l'info 3 d'un descripteur GDT */
u8 getdesbit3(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
if ((entry[index].acces & 0b1000) > 0)
return (((entry[index].acces & 0b100) > 0) ? 'C' : '-');
else
return (((entry[index].acces & 0b100) > 0) ? 'D' : 'U');
}
/*******************************************************************************/
/* récupère l'alignement d'un descripteur GDT */
u16 getdesalign(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
return (((entry[index].flags & 0b1000) > 0) ? 4096: 1);
}
/*******************************************************************************/
/* récupère si descripteur GDT est valide */
bool isdesvalid(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
return ((entry[index].acces & 0b10000000) > 0);
}
/*******************************************************************************/
/* récupère la dimension d'un descripteur GDT */
u32 getdessize(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
if (((entry[index].acces & 0b10100) == 0) && ((entry[index].acces & 0b01000) > 0) && ((entry[index].acces & 0b0001) > 0) && ((entry[index].flags & 0b0110) == 0))
return 32;
else
return (((entry[index].flags & 0b1000) > 0) ? 32 : 16);
}
/*******************************************************************************/
/* Créé un descripteur GDT */

View File

@ -136,11 +136,12 @@ void putidt(u32 offset, u16 select, u16 type, u16 index)
/******************************************************************************/
/* Affiche une erreur CPU et fige l'ordinateur */
void cpuerror(const u8 * src, const exception_stack *stack)
void cpuerror(const u8 * src, const save_stack *stack)
{
printf("\033[31m*** ERREUR CPU : %s *** \r\n", src);
dump_regs(stack);
print("<Appuyer une touche pour continuer>\r\n");
show_cpu(stack);
print("<Appuyer une touche pour continuer>\033[0m\r\n");
sti();
waitascii();
initselectors(retry_address);
/*while (true) {
@ -168,79 +169,90 @@ void interruption()
void exception0()
{
cpuerror("divide error",0x0);
save_stack dump;
exception_stack_noerror *current = getESP()+0x80;
dump_cpu(&dump);
dump.eip=current->eip;
dump.cs=current->cs;
dump.esp=(current+1);
cpuerror("divide error",&dump);
}
void exception1()
{
cpuerror("debug exception",0x0);
cpuerror("debug exception",NULL);
}
void exception2()
{
cpuerror("non-maskable hardware interrupt",0x0);
cpuerror("non-maskable hardware interrupt",NULL);
}
void exception3()
{
cpuerror("INT3 instruction",0x0);
cpuerror("INT3 instruction",NULL);
}
void exception4()
{
cpuerror("INTO instruction detected overflow",0x0);
cpuerror("INTO instruction detected overflow",NULL);
}
void exception5()
{
cpuerror("BOUND instruction detected overrange",0x0);
cpuerror("BOUND instruction detected overrange",NULL);
}
void exception6()
{
cpuerror("invalid instruction opcode",0x0);
cpuerror("invalid instruction opcode",NULL);
}
void exception7()
{
cpuerror("no coprocessor",0x0);
cpuerror("no coprocessor",NULL);
}
void exception8()
{
cpuerror("double fault",0x0);
cpuerror("double fault",NULL);
}
void exception9()
{
cpuerror("coprocessor segment overrun",0x0);
cpuerror("coprocessor segment overrun",NULL);
}
void exception10()
{
cpuerror("invalid task state segment (TSS)",0x0);
cpuerror("invalid task state segment (TSS)",NULL);
}
void exception11()
{
cpuerror("segment not present",0x0);
cpuerror("segment not present",NULL);
}
void exception12()
{
cpuerror("stack fault",0x0);
cpuerror("stack fault",NULL);
}
void exception13()
{
cpuerror("general protection fault (GPF)",0x0);
cpuerror("general protection fault (GPF)",NULL);
}
void exception14()
{
exception_stack *stack = getESP()+0x30;
u8 *errorstring;
switch (stack->error_code) {
save_stack dump;
exception_stack *current = getESP()+0x80;
dump_cpu(&dump);
dump.eip=current->eip;
dump.cs=current->cs;
dump.esp=(current+1);
u8 *errorstring="page fault";
switch (current->error_code) {
case 0:
errorstring="page fault - Supervisory process tried to read a non-present page entry";
break;
@ -266,27 +278,27 @@ void exception14()
errorstring="Page fault - User process tried to write a page and caused a protection fault";
break;
}
cpuerror(errorstring,stack);
cpuerror(errorstring,&dump);
}
void exception15()
{
cpuerror("(reserved)",0x0);
cpuerror("(reserved)",NULL);
}
void exception16()
{
cpuerror("coprocessor error",0x0);
cpuerror("coprocessor error",NULL);
}
void exception17()
{
cpuerror("alignment check",0x0);
cpuerror("alignment check",NULL);
}
void exception18()
{
cpuerror("machine check",0x0);
cpuerror("machine check",NULL);
}
/******************************************************************************/

View File

@ -218,7 +218,9 @@ unsigned convert(u32 keypressed)
}
else if (key == SCAN_F9) {
dump_regs();
save_stack dump;
dump_cpu(&dump);
show_cpu(&dump);
}
else if (key == SCAN_F10) {

View File

@ -22,7 +22,10 @@ static command commands[] = {
{"GDT" , "", &readgdt},
{"IDT" , "", &readidt},
{"INFO" , "", &info},
{"PAGEFAULT" , "", &pagefault}
{"PGFAULTW" , "", &pgfaultw},
{"PGFAULTR" , "", &pgfaultr},
{"DIVZERR" , "", &divzerr}
};
/*******************************************************************************/
@ -56,13 +59,28 @@ void shell()
}
}
/*******************************************************************************/
/* Génère une erreur de division par 0 */
int divzerr()
{
print("Creation d'une erreur de division par 0 !\r\n");
asm("movl $0x0,%ecx; divl %ecx");
}
/*******************************************************************************/
/* Génère une erreur de page à l'adresse 0xE0000000 */
int pagefault()
int pgfaultw()
{
print("Creation d'une erreur de page !\r\n");
asm("mov $0x66666666, %eax \n \
mov %eax,0xE0000000");
asm("movl $0x66666666,(0xE0000000)");
}
/*******************************************************************************/
/* Génère une erreur de page à l'adresse 0xD0000000 */
int pgfaultr()
{
print("Creation d'une erreur de page !\r\n");
asm("movl (0xD0000000),%eax");
}
/*******************************************************************************/
@ -78,7 +96,9 @@ int info()
int regs()
{
dump_regs(0x0);
save_stack dump;
dump_cpu(&dump);
show_cpu(&dump);
return 0;
}

View File

@ -463,6 +463,8 @@ u32 printf(const u8 * string, ...)
break;
case 'x':
case 'X':
case 'y':
case 'Y':
if (asize==0)
num = (u64) va_arg(args, u8);
else if (asize==1)
@ -474,9 +476,9 @@ u32 printf(const u8 * string, ...)
if (charadd == 0xFF)
charadd = '0';
itoa(num, &buffer, 16, sizes[asize], charadd);
if (achar == 'X')
if (achar == 'X'||achar == 'Y')
strtoupper(&buffer);
print(&strbase16);
if (achar == 'X') print(&strbase16);
counter += print(&buffer) + 1;
flag = false;
break;