Autor Thema: [gelöst] Interrupt-Handling schlägt fehl  (Gelesen 6478 mal)

dietzi

  • Beiträge: 6
    • Profil anzeigen
Gespeichert
« am: 19. February 2017, 21:30 »
Hallo,

ich habe ein Problem mit dem Interrupt-Handling. Ich habe bis jetzt größten teils mit dem Tutorial gearbeitet. Wenn ich meinen Code in Bochs ausführe bekomme ich als Debug-Info "check_cs(0x0010): not a valid code segment !"

Hier mein Code (die betreffenden Zeilen)

Interrupts.S
.macro irq num, map
.global irq\num
irq\num:
    cli
    push $0
    push $\map
jmp irq_stub
.endm


irq 0, 20
irq 1, 21
irq 2, 22
irq 3, 23
irq 4, 24
irq 5, 25
irq 6, 26
irq 7, 27
irq 8, 28
irq 9, 29
irq 10, 30
irq 11, 31
irq 12, 32
irq 13, 33
irq 14, 34
irq 15, 35

.extern handle_interrupt
irq_stub:
    // CPU-Zustand sichern

    push %ebp
    push %edi
    push %esi
    push %edx
    push %ecx
    push %ebx
    push %eax

    // Kernel-Datensegmente laden
    mov $0x10, %ax
    mov %ax, %ds
    mov %ax, %es

    // Handler aufrufen
    push %esp
    call handle_interrupt
    mov %eax, %esp

    // User-Datensegmente laden
    mov $0x23, %ax
    mov %ax, %ds
    mov %ax, %es

    // CPU-Zustand wiederherstellen
    pop %eax
    pop %ebx
    pop %ecx
    pop %edx
    pop %esi
    pop %edi
    pop %ebp

     // Fehlercode und Interruptnummer vom Stack nehmen
    add $8, %esp
 
// Ruecksprung zum unterbrochenen Code
// xchg %bx, %bx
    iret

isr.c
struct cpu_state {
    // Von Hand gesicherte Register
    uint32_t   eax;
    uint32_t   ebx;
    uint32_t   ecx;
    uint32_t   edx;
    uint32_t   esi;
    uint32_t   edi;
    uint32_t   ebp;
 
    uint32_t   intr;
    uint32_t   error;
 
    // Von der CPU gesichert
    uint32_t   eip;
    uint32_t   cs;
    uint32_t   eflags;
    uint32_t   esp;
    uint32_t   ss;
};

struct cpu_state* handle_interrupt(struct cpu_state* cpu)
{
    struct cpu_state* new_cpu = cpu;

if(cpu->intr == 0x21) {
keyboard_handler();
}

if (cpu->intr >= 0x20 && cpu->intr <= 0x2f) {
terminal_writestring("Resetting Master");
if (cpu->intr >= 0x28) {
terminal_writestring("Resetting Slave");
outb(SLAVE_COMMAND, PIC_RESET);
terminal_writestring("Slave resetted");
}
outb(MASTER_COMMAND, PIC_RESET);
terminal_writestring("Master resetted");
}
terminal_writestring("Returning CPU-State");
return new_cpu;
}

handle_interrupt() läuft genau 1 mal durch und wird danach nicht mehr aufgerufen....
Kann mir vielleicht jemand sagen wo der Fehler liegt?

LG Dietzi
« Letzte Änderung: 20. February 2017, 20:16 von dietzi »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 19. February 2017, 22:31 »
Du solltest erst einmal versuchen, genauer einzugrenzen, wann der Fehler genau kommt. Aus der Fehlermeldung wird erst einmal nur klar, dass irgendwo versuchst wird, cs=0x10 zu setzen. Wenn du dich ans Tutorial gehalten hast, ist 0x10 ein Datensegment und deswegen tut das nicht; das Codesegment wäre 0x08.

Weil du sagst, dass handle_interrupt() einmal ausgeführt wird, tippe ich auf das iret als fehlschlagende Instruktion. bochs müsste in der Fehlermeldung auch die Adresse ausgeben, die du aber nicht mitkopiert hast. Die kannst du mal mit deiner Kernelbinary vergleichen, um rauszufinden, wo es genau passiert. Wenn es tatsächlich das iret ist, dann liegt ein falscher Wert auf dem Kernelstack und du musst rausfinden, wo er herkommt.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

dietzi

  • Beiträge: 6
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 20. February 2017, 18:33 »
Hallo,

danke für die schnelle Antwort. Bochs zeigt mir keine Adresse an:
00086139136e[CPU0  ] check_cs(0x0010): not a valid code segment !
00086148001e[CPU0  ] check_cs(0x0010): not a valid code segment !
00086156866e[CPU0  ] check_cs(0x0010): not a valid code segment !
00086381397e[CPU0  ] check_cs(0x0010): not a valid code segment !

Ich verstehe auch nicht so ganz wie es hier zu diesem Fehler kommen kann, da ich genau den Status zurück gebe welchen ich bei Aufruf von handle_interrupt() erhalte. Was ich noch vergessen hatte zu erwähnen: es wird ein GP ausgelöst - evtl. hilft das der Lösungsfindung.....

LG Dietzi

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 20. February 2017, 18:49 »
Naja, wenn bochs es nicht anzeigt, musst du eben andere Möglichkeiten nehmen, um das zu debuggen. Zum Beispiel einen Breakpoint vor dem iret setzen und dort dann den Stack anschauen, ob der aussieht wie erwartet.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

dietzi

  • Beiträge: 6
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 20. February 2017, 19:20 »
Nun folgende Ausgabe (Breakpoint zu start in irq_stub und direkt vor iret)

<bochs:3> sreg
es:0x0018, dh=0x00cf9300, dl=0x0000ffff, valid=1
        Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
cs:0x0008, dh=0x00cf9b00, dl=0x0000ffff, valid=1
        Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-Conforming, Accessed, 32-bit
ss:0x0018, dh=0x00cf9300, dl=0x0000ffff, valid=31
        Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
ds:0x0018, dh=0x00cf9300, dl=0x0000ffff, valid=31
        Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
fs:0x0018, dh=0x00cf9300, dl=0x0000ffff, valid=1
        Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
gs:0x0018, dh=0x00cf9300, dl=0x0000ffff, valid=1
        Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
ldtr:0x0000, dh=0x00008200, dl=0x0000ffff, valid=1
tr:0x0028, dh=0x0000eb10, dl=0x32000080, valid=1
gdtr:base=0x000000000010b840, limit=0x2f
idtr:base=0x000000000010b8e0, limit=0x7ff
<bochs:4> c
00086139138i[CPU0  ] [86139138] Stopped on MAGIC BREAKPOINT
(0) Magic breakpoint
Next at t=86139138
(0) [0x00000010049b] 0008:000000000010049b (unk. ctxt): iret                      ; cf
<bochs:5> sreg
es:0x0023, dh=0x00cff300, dl=0x0000ffff, valid=1
        Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
cs:0x0008, dh=0x00cf9b00, dl=0x0000ffff, valid=1
        Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-Conforming, Accessed, 32-bit
ss:0x0018, dh=0x00cf9300, dl=0x0000ffff, valid=31
        Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
ds:0x0023, dh=0x00cff300, dl=0x0000ffff, valid=1
        Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
fs:0x0018, dh=0x00cf9300, dl=0x0000ffff, valid=1
        Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
gs:0x0018, dh=0x00cf9300, dl=0x0000ffff, valid=1
        Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
ldtr:0x0000, dh=0x00008200, dl=0x0000ffff, valid=1
tr:0x0028, dh=0x0000eb10, dl=0x32000080, valid=1
gdtr:base=0x000000000010b840, limit=0x2f
idtr:base=0x000000000010b8e0, limit=0x7ff
<bochs:6> c
00086139138e[CPU0  ] check_cs(0x0010): not a valid code segment !
00086148003e[CPU0  ] check_cs(0x0010): not a valid code segment !
00086156868e[CPU0  ] check_cs(0x0010): not a valid code segment !
00086381399e[CPU0  ] check_cs(0x0010): not a valid code segment !
00086929429e[CPU0  ] check_cs(0x0010): not a valid code segment !
00087477459e[CPU0  ] check_cs(0x0010): not a valid code segment !
00088025489e[CPU0  ] check_cs(0x0010): not a valid code segment !
00088573519e[CPU0  ] check_cs(0x0010): not a valid code segment !
00089121549e[CPU0  ] check_cs(0x0010): not a valid code segment !
00089536436i[      ] Ctrl-C detected in signal handler.
Next at t=89536436
(0) [0x000000100f70] 0008:0000000000100f70 (unk. ctxt): add ebx, ebx              ; 01db
<bochs:7> sreg
es:0x0010, dh=0x00cf9300, dl=0x0000ffff, valid=1
        Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
cs:0x0008, dh=0x00cf9b00, dl=0x0000ffff, valid=1
        Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-Conforming, Accessed, 32-bit
ss:0x0018, dh=0x00cf9300, dl=0x0000ffff, valid=31
        Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
ds:0x0010, dh=0x00cf9300, dl=0x0000ffff, valid=31
        Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
fs:0x0010, dh=0x00cf9300, dl=0x0000ffff, valid=1
        Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
gs:0x0010, dh=0x00cf9300, dl=0x0000ffff, valid=1
        Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
ldtr:0x0000, dh=0x00008200, dl=0x0000ffff, valid=1
tr:0x0028, dh=0x0000eb10, dl=0x32000080, valid=1
gdtr:base=0x000000000010b840, limit=0x2f
idtr:base=0x000000000010b8e0, limit=0x7ff

Nachtrag:
<bochs:8> info gdt
Global Descriptor Table (base=0x000000000010b840, limit=47):
GDT[0x00]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x01]=Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-Conforming, Accessed, 32-bit
GDT[0x02]=Data segment, base=0x00000000, limit=0xffffffff, Read/Write
GDT[0x03]=Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-Conforming, 32-bit
GDT[0x04]=Data segment, base=0x00000000, limit=0xffffffff, Read/Write
GDT[0x05]=32-Bit TSS (Busy) at 0x00103200, length 0x00080
« Letzte Änderung: 20. February 2017, 19:37 von dietzi »

dietzi

  • Beiträge: 6
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 20. February 2017, 20:16 »
Fehler gefunden...... tss war im header als static deklariert. Habe tss jetzt in der isr.c als "nicht-static" deklariert und in der gdt.h habe ich einen Verweis mittels extern auf tss gesetzt. Und schon geht alles wieder. Danke für deine Hilfe

 

Einloggen