diff --git a/include/asm.h b/include/asm.h index aabe01e..111727a 100755 --- a/include/asm.h +++ b/include/asm.h @@ -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) \ diff --git a/include/cpu.h b/include/cpu.h index 1cf59f8..1de28c7 100755 --- a/include/cpu.h +++ b/include/cpu.h @@ -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); diff --git a/include/gdt.h b/include/gdt.h index fff1490..75a9032 100755 --- a/include/gdt.h +++ b/include/gdt.h @@ -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); diff --git a/include/interrupts.h b/include/interrupts.h index 63277ff..3cfeb7d 100755 --- a/include/interrupts.h +++ b/include/interrupts.h @@ -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 diff --git a/include/shell.h b/include/shell.h index 3b5fee8..421b0ca 100644 --- a/include/shell.h +++ b/include/shell.h @@ -17,4 +17,6 @@ int mode(); int clear(); int regs(); int info(); -int pagefault(); +int pgfaultr(); +int pgfaultw(); +int divzerr(); diff --git a/lib/cpu.c b/lib/cpu.c index 9349540..f26422d 100755 --- a/lib/cpu.c +++ b/lib/cpu.c @@ -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(); } /*******************************************************************************/ diff --git a/lib/gdt.c b/lib/gdt.c index 77c12b7..95a668f 100755 --- a/lib/gdt.c +++ b/lib/gdt.c @@ -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 */ diff --git a/lib/interrupts.c b/lib/interrupts.c index d94e8db..423a571 100755 --- a/lib/interrupts.c +++ b/lib/interrupts.c @@ -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("\r\n"); + show_cpu(stack); + print("\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); } /******************************************************************************/ diff --git a/lib/keyboard.c b/lib/keyboard.c index c81af97..7e86c4c 100755 --- a/lib/keyboard.c +++ b/lib/keyboard.c @@ -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) { diff --git a/lib/shell.c b/lib/shell.c index 6cb8f62..3292cfa 100644 --- a/lib/shell.c +++ b/lib/shell.c @@ -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; } diff --git a/lib/video.c b/lib/video.c index 3fd6c5b..a43aec2 100755 --- a/lib/video.c +++ b/lib/video.c @@ -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;