Unmapping IRQs causes panic.

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
TheChuckster

Unmapping IRQs causes panic.

Post by TheChuckster »

I finally got an IDT working but I encounter a panic.

I disable interrupts, init pics 0x20, 0x28, mask the IRQs, and addinterrupt 20 to my IDT that calls my ISR int32 in my ASM and a dpl of zero, load the idt, enable interrupts, and unmask the irq. When I unmask the IRQ, it panics.

Am I even following the correct procedure to handle the timer interrupt?
pini

Re:Unmapping IRQs causes panic.

Post by pini »

Could you please post your PIC mapping code, and perhaps the detail of your kernel panic too ? It would easier to find out your problem if we got all of this...
Therx

Re:Unmapping IRQs causes panic.

Post by Therx »

Yeh, its the right procedure. If you've got problems I wouldn't use the timer IRQ as its so quick its hard to debug. Unmask the Kbd and then see at what stage it panics. I suspect that the problem is that you're not saving/restoring all the registers at the beginning/end of your ISR which would cause the problem to be when it returns to the code after the ISR

Pete
TheChuckster

Re:Unmapping IRQs causes panic.

Post by TheChuckster »

My ISR:

[extern _testint]
[global _int20]
_int20:
pusha
push ds
push es
push fs
push gs
mov eax,0x10 ; Data segment
mov ds,eax
mov es,eax
cld
call _testint ; Test Interrupt Handler
pop gs
pop fs
pop es
pop ds
popa
iret
TheChuckster

Re:Unmapping IRQs causes panic.

Post by TheChuckster »

As for the PICs:

#define MASTER 0x20
#define MASTERDATA 0x21
#define SLAVE 0xA0
#define SLAVEDATA 0xA1
#define EOI 0x20

#define ICW1_INIT 0x10 // required for PIC initialisation
#define ICW1_EDGE 0x08 // edge triggered IRQs
#define ICW1_SINGLE 0x02 // only MASTER (not cascaded)
#define   ICW1_ICW4 0x01 // there IS an ICW4 control word

#define ICW4_SFNM 0x10 // Special Fully Nested Mode
#define ICW4_BUFFER 0x08 // Buffered Mode
#define ICW4_MASTER 0x04 // this is the Master PIC
#define ICW4_AEOI 0x02 // Auto EOI
#define ICW4_8086 0x01 // 80/86 Mode

void init_pics(int pic1, int pic2)
{
   byte md,sd;

   md=inportb(MASTERDATA); // save state of MASTER DATA
   sd=inportb(SLAVEDATA); // save state of SLAVE DATA

   outportb(MASTER, EOI); // Send EOI | resets the chip

   outportb(MASTER, ICW1_INIT+ICW1_ICW4); // ICW1 control word setup | just basic PIC stuff
   outportb(SLAVE, ICW1_INIT+ICW1_ICW4); // see pic.h for more details about the values

   outportb(MASTERDATA, pic1); // ICW2 maps IRQs 0-7 to whatever kernel passes
   outportb(SLAVEDATA, pic2); // and same here except with IRQs 8-15

   outportb(MASTERDATA, 0x04); // ICW3
   outportb(SLAVEDATA, 0x02);

   outportb(MASTERDATA, ICW4_8086); // ICW4 control word setup
   outportb(SLAVEDATA, ICW4_8086);

   outportb(MASTERDATA,md); // restore both MASTER DATA
   outportb(SLAVEDATA,sd); // restore SLAVE DATA
}
TheChuckster

Re:Unmapping IRQs causes panic.

Post by TheChuckster »

Oddly enough as soon as I unmask the IRQ, the panic occurs. I tried unmasking the keyboard IRQ -- same results.

This is my unmasking function.

void unmaskIRQ(byte irq)
{
irq = irq & (1<<irq);
if(irq < 8)
outportb(MASTERDATA, irq&0xFF);
else
outportb(SLAVEDATA, irq>>8);
}
Therx

Re:Unmapping IRQs causes panic.

Post by Therx »

So the panic happens before you press the key that means the problem is not in the ISR your unmasking code looks a bit weird. Try:-

Code: Select all

void unmaskIRQ(byte irq)
{
   byte picirq_m, picirq_s;
   if(irq > 7){
      picirq_m = 1 << 2;    //Cascade
      irq -= 8;
      picirq_s = 1 << irq;
   }else{
      picirq_m = 1 << irq;
   }

   picirq_m = ~picirq_m;
   picirq_s = ~picirq_s;

   outportb(MASTERDATA, picirq_m & inportb(MASTERDATA));
   outportb(SLAVEDATA, picirq_s & inportb(SLAVEDATA));
}
Beware this is off the top of my head. It may not work and I don't know which ports MASTERDATA and SLAVEDATA should be so if that's the problem this won't solve it.

Problems I can see with your original code:-
[0] If irq is > 7 then the shift will make it overflow
[0] The slave enable stuff definiately won't work because it doesn't enable IRQ 2 on the master (the
cascade)
[0] And the PIC takes it so that a bit set means mask not unmask.

Hope my tired brain is of use ;)

Pete
TheChuckster

Re:Unmapping IRQs causes panic.

Post by TheChuckster »

Well, now it unmasks properly, but as soon as it fires, Bochs panics again. I have tested this with IRQ0 and IRQ1 (pressing a key or waiting a tenth of a second causes it to panic). As you can see, my ISR code is posted. Please help me debug.
TheChuckster

Re:Unmapping IRQs causes panic.

Post by TheChuckster »

I don't even have an IDT entry for 0x21 and it panics. What gives?! ???
Slasher

Re:Unmapping IRQs causes panic.

Post by Slasher »

It panic cause you don't have an entry. int 0x21 is firing but there isn't an ISR to handle it
TheChuckster

Re:Unmapping IRQs causes panic.

Post by TheChuckster »

No, I added an entry and it still panics.
Slasher

Re:Unmapping IRQs causes panic.

Post by Slasher »

What does Bochs print out as the panic? Are you ending 0x20 to the pic ie acknowledging the interrupt?
TheChuckster

Re:Unmapping IRQs causes panic.

Post by TheChuckster »

My testint is:

void testint(void)
{
kprintf("TEST INT CALLED\n");
outportb (0x20, 0x20);
}

If that's what you mean by acknowledging it. Still panics :(

FFS, everything seems all right. Maybe it's my IDT.

Event type: PANIC
Device: [CPU ]
Message: exception(): 3rd (13) exception with no resolution
Slasher

Re:Unmapping IRQs causes panic.

Post by Slasher »

can we see all your code or the entire interrupt system ie idt setup and co
TheChuckster

Re:Unmapping IRQs causes panic.

Post by TheChuckster »

Hmm... Okay.

idt.c:

Code: Select all

/*
 * variable types
 */
#define byte unsigned char
#define word unsigned short
#define dword unsigned int

#define bool byte
#define true 1
#define false 0

// #define NULL 0x0

#define SUCCESS 1
#define FAIL 0

/*
 * Interrupt types
 */
#define INT_0 0x8E00     // 1000111000000000 = present,ring0,int_gate
#define INT_3 0xEE00     // 1110111000000000 = present,ring3,int_gate


/* structure for an interrupt */
typedef struct
{
   word low_offset;                         // low nibble of offset to handler of interrupt 
   word selector;                           // GDT selector used 
   word settings;                           // settings for int 
   word high_offset;                        // high nibble to handler code 
}  __attribute__ ((packed)) x86_interrupt;


/* structure for the IDTR */
typedef struct
{
     word limit;                             // limit or Size of IDT 
     x86_interrupt *base;                    // a pointer to the base of the IDT 
} __attribute__ ((packed)) idtr;


void loadIDTR();//sets up IDT by loading IDTR
void AddInt(int number, void (*handler)(), dword dpl); //add interrupt

idtr IDTR;
x86_interrupt IDT[256];// = (x86_interrupt*)0xD00;

void loadIDTR()
{
    IDTR.limit  = 256*(sizeof(x86_interrupt)-1);
    IDTR.base   = IDT;

   idtr *IDTRptr = &IDTR;

   /* load IDTR with lidt */
    asm volatile("LIDT (%0) ": :"p" (IDTRptr));
}


void AddInt(int number, void (*handler)(), dword dpl)
{
    word selector = 0x08;
    word settings;
     dword offset = (dword)handler;


    /* get CS selector */
     asm volatile("movw %%cs,%0" :"=g"(selector));


    /* set settings options depending on dpl */
    switch(dpl)
    {
    case 0: settings = INT_0; break;
    case 1:
    case 2:
    case 3: settings = INT_3; break;
    }
    
    /* set actual values of int */
    IDT[number].low_offset   = (offset & 0xFFFF);
    IDT[number].selector     = selector;
    IDT[number].settings     = settings;
     IDT[number].high_offset  = (offset >> 16);
}
Part of kernel.c (the important part):

Code: Select all

#define byte unsigned char
#define dword unsigned int

#define bool byte
#define true 1
#define false 0

// #define NULL 0x0

#define SUCCESS 1
#define FAIL 0

#define ALL 0xFF

extern int32;
extern timer_counter;

int k_main() // like main in a normal C program
{
   INTS(false);
   kprintf("Interrupts disabled.\n");

   init_pics(0x20, 0x28);
   maskIRQ(ALL);
   kprintf("PICs remapped: IRQs starting at interrupt 0x20.\n");

   AddInt(20, int32, 0);
   kprintf("Timer ISR added.\n");

   AddInt(21, int32, 0);
   kprintf("Keyboard ISR added.\n");

   loadIDTR();
   kprintf("IDT loaded!!!\n");

   INTS(true);
   kprintf("Interrupts enabled.\n");

   kprintf("Unmasking IRQ0.\n");
   
   unmaskIRQ(1);
   kprintf("Unmasked IRQ1 (keyboard).\n");

   for(;;);

   return 1;
};

void testint(void)
{
   kprintf("TEST INT CALLED\n");
   outportb (0x20, 0x20);
}
Post Reply