OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Jan 19, 2018 7:33 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: [SOLVED] QEMU Rebooting after enabling interrupts (IDT OK)
PostPosted: Sun Jan 07, 2018 3:54 pm 
Offline
Member
Member
User avatar

Joined: Fri Apr 08, 2016 5:03 am
Posts: 120
Location: keyboard.cpp - line 420
Hi :)

I'm trying to enable interrupts in my OS but QEMU keeps crashing.

What I know:
- My IDT is filled in properly:
Image
- My ISRs are getting called.

Here is my code:
idt.cpp (Adapted from a few example from the wiki :D )
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 !

_________________
My github page: https://github.com/AlexandreRouma
Meme-deving since 420 Bc (before cocain) !
YouTube: https://www.youtube.com/channel/UCyJnOD ... C8Y7pccc6A
Twitter: https://twitter.com/WhatsTheGeekYT


Last edited by DeezRamChips on Wed Jan 10, 2018 8:52 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: QEMU Rebooting after enabling interrupts (IDT is correct
PostPosted: Sun Jan 07, 2018 6:54 pm 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 124
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;
    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.


Top
 Profile  
 
 Post subject: Re: QEMU Rebooting after enabling interrupts (IDT is correct
PostPosted: Sun Jan 07, 2018 8:04 pm 
Offline
Member
Member
User avatar

Joined: Fri Apr 08, 2016 5:03 am
Posts: 120
Location: keyboard.cpp - line 420
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 #-o
And guess what ? IT SLOVED IT !!!!!!! Thank you soo much :D :D :D

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...

_________________
My github page: https://github.com/AlexandreRouma
Meme-deving since 420 Bc (before cocain) !
YouTube: https://www.youtube.com/channel/UCyJnOD ... C8Y7pccc6A
Twitter: https://twitter.com/WhatsTheGeekYT


Top
 Profile  
 
 Post subject: Re: QEMU Rebooting after enabling interrupts (IDT is correct
PostPosted: Wed Jan 10, 2018 4:45 am 
Offline
Member
Member
User avatar

Joined: Mon Feb 22, 2016 4:40 am
Posts: 56
Location: United Kingdom
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.

_________________
Current developing Tupai, a monolithic x86 operating system
http://zesterer.homenet.org/projects.shtml


Top
 Profile  
 
 Post subject: Re: QEMU Rebooting after enabling interrupts (IDT is correct
PostPosted: Wed Jan 10, 2018 7:49 am 
Offline
Member
Member
User avatar

Joined: Fri Apr 08, 2016 5:03 am
Posts: 120
Location: keyboard.cpp - line 420
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 :D

_________________
My github page: https://github.com/AlexandreRouma
Meme-deving since 420 Bc (before cocain) !
YouTube: https://www.youtube.com/channel/UCyJnOD ... C8Y7pccc6A
Twitter: https://twitter.com/WhatsTheGeekYT


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], z0rr0 and 11 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group