OSDev.org https://forum.osdev.org/ |
|
[SOLVED] QEMU Rebooting after enabling interrupts (IDT OK) https://forum.osdev.org/viewtopic.php?f=1&t=32669 |
Page 1 of 1 |
Author: | DeezRamChips [ Sun Jan 07, 2018 3:54 pm ] |
Post subject: | [SOLVED] QEMU Rebooting after enabling interrupts (IDT OK) |
Hi I'm trying to enable interrupts in my OS but QEMU keeps crashing. What I know: - My IDT is filled in properly: - My ISRs are getting called. Here is my code: idt.cpp (Adapted from a few example from the wiki ) Code: #include <stddef.h> #include <stdint.h> #include "idt.h" #include "terminal.h" #define IDT_ENTRY_COUNT 0xFF IDT_Class IDT; uint8_t _IDT[IDT_ENTRY_COUNT * 8]; void lidt(void* base, uint16_t size) { // This function works in 32 and 64bit mode struct { uint16_t length; void* base; } __attribute__((packed)) IDTR = { size, base }; asm ( "lidt %0" : : "m"(IDTR) ); // let the compiler choose an addressing mode } void encodeIdtEntry(uint8_t *target, uint32_t offset, uint16_t selector, uint8_t type) { // Encode the offset target[0] = offset & 0xFF; target[1] = (offset >> 8) & 0xFF; target[6] |= (offset >> 16) & 0xFF; target[7] |= (offset >> 24) & 0xFF; // Encode the selector target[2] = selector & 0xFF; target[3] = (selector >> 8) & 0xFF; // Encode the Zero target[4] = 0x00; // And... Type target[5] = type; } void IDT_Class::load() { for (int i = 0; i < 0xFF; i++) { encodeIdtEntry(&_IDT[i * 8], (uint32_t)&ASM_ISR_0, 8, 0x8E); } encodeIdtEntry(&_IDT[33 * 8], (uint32_t)&ASM_ISR_KBD, 8, 0x8E); lidt(&_IDT, 0xFF); } uint8_t IDT_Class::DEBUG(int index) { return _IDT[index]; } isr.asm (Also from wiki example) Code: .align 4 .global ASM_ISR_0 .global ASM_ISR_KBD ASM_ISR_0: pushal; cld /* C code following the sysV ABI requires DF to be clear on function entry */ call ISR_0 popal; iret ASM_ISR_KBD: pushal; cld /* C code following the sysV ABI requires DF to be clear on function entry */ call ISR_KBD popal; iret isr.cpp (Entirely my own) Code: #include "io.h" #include "terminal.h" extern "C" { void ISR_0(void) { outb(0x20,0x20); //Terminal.println("DEFAULT !"); } void ISR_KBD(void) { outb(0x20,0x20); char b = inb(0x60); Terminal.println("KEYBOARD !"); } } kernel.cpp (kernl_main() is my own and PIC_remap is from the wiki) Code: #include <stddef.h> #include <stdint.h> #include "terminal.h" #include "io.h" #include "gdt.h" #include "idt.h" #include "string.h" /* reinitialize the PIC controllers, giving them specified vector offsets rather than 8h and 70h, as configured by default */ #define ICW1_ICW4 0x01 /* ICW4 (not) needed */ #define ICW1_SINGLE 0x02 /* Single (cascade) mode */ #define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */ #define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */ #define ICW1_INIT 0x10 /* Initialization - required! */ #define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */ #define ICW4_AUTO 0x02 /* Auto (normal) EOI */ #define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */ #define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */ #define ICW4_SFNM 0x10 /* Special fully nested (not) */ #define PIC1 0x20 /* IO base address for master PIC */ #define PIC2 0xA0 /* IO base address for slave PIC */ #define PIC1_COMMAND PIC1 #define PIC1_DATA (PIC1+1) #define PIC2_COMMAND PIC2 #define PIC2_DATA (PIC2+1) /* arguments: offset1 - vector offset for master PIC vectors on the master become offset1..offset1+7 offset2 - same for slave PIC: offset2..offset2+7 */ void PIC_remap(int offset1, int offset2) { unsigned char a1, a2; a1 = inb(PIC1_DATA); // save masks a2 = inb(PIC2_DATA); outb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4); // starts the initialization sequence (in cascade mode) io_wait(); outb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4); io_wait(); outb(PIC1_DATA, offset1); // ICW2: Master PIC vector offset io_wait(); outb(PIC2_DATA, offset2); // ICW2: Slave PIC vector offset io_wait(); outb(PIC1_DATA, 4); // ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100) io_wait(); outb(PIC2_DATA, 2); // ICW3: tell Slave PIC its cascade identity (0000 0010) io_wait(); outb(PIC1_DATA, ICW4_8086); io_wait(); outb(PIC2_DATA, ICW4_8086); io_wait(); outb(PIC1_DATA, a1); // restore saved masks. outb(PIC2_DATA, a2); } extern "C" // Use C link for kernel_main void kernel_main(void) { Terminal.Init(80, 25); Terminal.setColor(0x0E); Terminal.clear(); Terminal.hideCursor(); Terminal.println("Welcome to MemeOS !"); Terminal.setColor(0x07); Terminal.print("Loading GDT... "); GDT.load(); Terminal.OK(); Terminal.print("Remapping PIC... "); PIC_remap(0x20, 0x28); Terminal.OK(); Terminal.print("Loading IDT... "); IDT.load(); Terminal.OK(); for (long i = 0; i < 8; i++) { Terminal.print("IDT[33] at index 0x"); Terminal.print(dumpHexByte(i)); Terminal.print(" = 0x"); Terminal.println(dumpHexByte(IDT.DEBUG((8 * 33) + i))); } Terminal.println("Allowing interrupts..."); asm("sti"); Terminal.println("<- DONE ->"); for(;;) { asm("hlt"); } } I'm booting my OS with GRUB2 and compiling it using g++/as on Bash For Windows Symtoms: - QEMU reboots - BOCHS says: Code: 00456186320e[CPU0 ] check_cs(0x0014): conforming code seg descriptor dpl > cpl, dpl=3, cpl=0 <- ^^^ A LOT of times this line, not gonna copy them all ^^^ -> 00456186416e[CPU0 ] check_cs(0x0014): conforming code seg descriptor dpl > cpl, dpl=3, cpl=0 00456186416e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d) 00456186424e[CPU0 ] check_cs(0x0014): conforming code seg descriptor dpl > cpl, dpl=3, cpl=0 00456186424e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d) 00456186432e[CPU0 ] check_cs(0x0014): conforming code seg descriptor dpl > cpl, dpl=3, cpl=0 00456186432e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d) 00456186440e[CPU0 ] check_cs(0x0014): conforming code seg descriptor dpl > cpl, dpl=3, cpl=0 00456186440e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d) 00456186440e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08) 00456186440i[CPU0 ] CPU is in protected mode (active) 00456186440i[CPU0 ] CS.mode = 32 bit 00456186440i[CPU0 ] SS.mode = 32 bit 00456186440i[CPU0 ] EFER = 0x00000000 00456186440i[CPU0 ] | EAX=0000000e EBX=00000008 ECX=0000041a EDX=000003d5 00456186440i[CPU0 ] | ESP=00103080 EBP=00000000 ESI=00000000 EDI=00000000 00456186440i[CPU0 ] | IOPL=0 ID vip vif ac vm RF nt of df if tf sf zf af pf cf 00456186440i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D 00456186440i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 ffffffff 1 1 00456186440i[CPU0 ] | DS:0018( 0003| 0| 0) 00000000 ffffffff 1 1 00456186440i[CPU0 ] | SS:0018( 0003| 0| 0) 00000000 ffffffff 1 1 00456186440i[CPU0 ] | ES:0018( 0003| 0| 0) 00000000 ffffffff 1 1 00456186440i[CPU0 ] | FS:0018( 0003| 0| 0) 00000000 ffffffff 1 1 00456186440i[CPU0 ] | GS:0018( 0003| 0| 0) 00000000 ffffffff 1 1 00456186440i[CPU0 ] | EIP=00100014 (00100014) 00456186440i[CPU0 ] | CR0=0x60000011 CR2=0x00000000 00456186440i[CPU0 ] | CR3=0x00000000 CR4=0x00000000 00456186440i[CPU0 ] 0x0000000000100014>> iret : CF 00456186440e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting 00456186440i[SYS ] bx_pc_system_c::Reset(HARDWARE) called 00456186440i[CPU0 ] cpu hardware reset 00456186440i[APIC0 ] allocate APIC id=0 (MMIO enabled) to 0x0000fee00000 Hope someone can help, thanks a lot ! |
Author: | MichaelPetch [ Sun Jan 07, 2018 6:54 pm ] |
Post subject: | Re: QEMU Rebooting after enabling interrupts (IDT is correct |
Often these problems are related to a variety of issues. Compiling /linking/ linker scripts / startup code being wrong etc. You don't show everything here. Since you have Github can you make your current project available. I didn't see MemeOS listed in your repositories. Saw PeanutOS but it hasn't been updated in 2 years. Since you are using Bochs you should step through it with the debugger. the <b>info idt</b> command is useful. The EIP=0x100014 should give you a hint as to to what function that is crashing in. You can use OBJDUMP to dump an ELF executable to text and find out what function is associated with that address and the line of code. Since Bochs doesn't do symbolic debugging OBJDUMP is a valuable tool. As well on Windows are you using a cross compiler or a native Windows G++? On Windows I really recommend a cross compiler. Microsoft packing isn't the same as G++ which has been known to cause grief. Since you are using G++ have you created a linker script that deals with CTOR static initialization and called the required functions before calling into your code? The Bochs output you do show suggests there are some kind of issue with your IDT (or maybe your IDTR). I also find this suspicious: Code: target[6] |= (offset >> 16) & 0xFF; Why are you using |= instead of = ?target[7] |= (offset >> 24) & 0xFF; This looks wrong: Code: lidt(&_IDT, 0xFF); 0xFF seems to be the number of entries, not the size.
|
Author: | DeezRamChips [ Sun Jan 07, 2018 8:04 pm ] |
Post subject: | Re: QEMU Rebooting after enabling interrupts (IDT is correct |
Quote: As well on Windows are you using a cross compiler or a native Windows G++? On Windows I really recommend a cross compiler. Microsoft packing isn't the same as G++ which has been known to cause grief. Since you are using G++ have you created a linker script that deals with CTOR static initialization and called the required functions before calling into your code? Yes, I'm using a cross compiler (GCC compiled for i686-elf on LSW) My linker script is the one given in the "Bear Bones" tutorial. Quote: The Bochs output you do show suggests there are some kind of issue with your IDT (or maybe your IDTR). I also find this suspicious: Code: target[6] |= (offset >> 16) & 0xFF; target[7] |= (offset >> 24) & 0xFF; Why are you using |= instead of = ? This looks wrong: Code: lidt(&_IDT, 0xFF); 0xFF seems to be the number of entries, not the size. Yeah, I'm realy dumb, I guess I wasn't quite awake when I wrote this And guess what ? IT SLOVED IT !!!!!!! Thank you soo much I feel soo dumb right now... I just uploaded it on github. I corrected the mistakes and added handling for every single exception, might be usefull... |
Author: | zesterer [ Wed Jan 10, 2018 4:45 am ] |
Post subject: | Re: QEMU Rebooting after enabling interrupts (IDT is correct |
DeezRamChips wrote: I feel soo dumb right now... OS development is literally the process of feeling dumb until you wake up one day and realise that you're more informed than almost all other software developers. But you still feel dumb, because you spent years building an OS that nobody will use. |
Author: | DeezRamChips [ Wed Jan 10, 2018 7:49 am ] |
Post subject: | Re: QEMU Rebooting after enabling interrupts (IDT is correct |
zesterer wrote: DeezRamChips wrote: I feel soo dumb right now... OS development is literally the process of feeling dumb until you wake up one day and realise that you're more informed than almost all other software developers. But you still feel dumb, because you spent years building an OS that nobody will use. Couldn't have said it better |
Page 1 of 1 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |