ISR not catching divide by 0 error*FIXED*

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.
brentS
Posts: 16
Joined: Sat Jun 27, 2009 5:41 pm

ISR not catching divide by 0 error*FIXED*

Post by brentS »

For my kernel I am at currently testing the Interrupt Service Routines but whenever I divide by 0 the machine resets instead of being caught by isr0. Here is the important snippets of my code. The idt_install is called in my main D method.

Code: Select all

void idt_install()
{
	idtp.limit = (8 * 256) - 1;
	idtp.base = cast(uint)&idt;
	memorySet(&idt,0,8 * 256);

	isrs_install();	

	idtFlush(cast(uint)&idtp);		

	console_print("idt installed");
}

Code: Select all

void isrs_install()
{
	idt_setGate(0,cast(ulong)&isr0, 0x08, 0x8E);
/*	idt_setGate(1,cast(ulong)&isr1, 0x08, 0x8E);
	idt_setGate(2,cast(ulong)&isr2, 0x08, 0x8E);
	idt_setGate(3,cast(ulong)&isr3, 0x08, 0x8E);
	idt_setGate(4,cast(ulong)&isr4, 0x08, 0x8E);
	idt_setGate(5,cast(ulong)&isr5, 0x08, 0x8E);
	idt_setGate(6,cast(ulong)&isr6, 0x08, 0x8E);
	idt_setGate(7,cast(ulong)&isr7, 0x08, 0x8E);

	idt_setGate(8,cast(uint)&isr8, 0x08, 0x8E);
	idt_setGate(9,cast(uint)&isr9, 0x08, 0x8E);
	idt_setGate(10,cast(uint)&isr10, 0x08, 0x8E);
	idt_setGate(11,cast(uint)&isr11, 0x08, 0x8E);
	idt_setGate(12,cast(uint)&isr12, 0x08, 0x8E);
	idt_setGate(13,cast(uint)&isr13, 0x08, 0x8E);
	idt_setGate(14,cast(uint)&isr14, 0x08, 0x8E);
	idt_setGate(15,cast(uint)&isr15, 0x08, 0x8E);

	idt_setGate(16,cast(uint)&isr16, 0x08, 0x8E);
	idt_setGate(17,cast(uint)&isr17, 0x08, 0x8E);
	idt_setGate(18,cast(uint)&isr18, 0x08, 0x8E);
	idt_setGate(19,cast(uint)&isr19, 0x08, 0x8E);
	idt_setGate(20,cast(uint)&isr20, 0x08, 0x8E);
	idt_setGate(21,cast(uint)&isr21, 0x08, 0x8E);
	idt_setGate(22,cast(uint)&isr22, 0x08, 0x8E);
	idt_setGate(23,cast(uint)&isr23, 0x08, 0x8E);

	idt_setGate(24,cast(uint)&isr24, 0x08, 0x8E);
	idt_setGate(25,cast(uint)&isr25, 0x08, 0x8E);
	idt_setGate(26,cast(uint)&isr26, 0x08, 0x8E);
	idt_setGate(27,cast(uint)&isr27, 0x08, 0x8E);
    	idt_setGate(28,cast(uint)&isr28, 0x08, 0x8E);
	idt_setGate(29,cast(uint)&isr29, 0x08, 0x8E);
	idt_setGate(30,cast(uint)&isr30, 0x08, 0x8E);
	idt_setGate(31,cast(uint)&isr31, 0x08, 0x8E);
*/
	console_print("isrs installed");
}

Code: Select all

void isr0()
{
	console_print("irs0 called");
	asm
	{
    		cli;
    		push 0;
		push 0;
	}
    	
	isr_common();
}

Code: Select all

isr_common:
   pusha  

   mov ax, ds              
   push eax                 

   mov ax, 0x10  
   mov ds, ax
   mov es, ax
   mov fs, ax
   mov gs, ax

   call faultHandler

   pop eax   
   mov ds, ax
   mov es, ax
   mov fs, ax
   mov gs, ax

   popa                   
   add esp, 8 
   sti
   iret     

Code: Select all

extern(C) void faultHandler(registers r)
{
    //if ((*r).int_no < 32)
    //{
        console_print(exception_messages[r.int_no]);
        console_print(" Exception. System Halted!");
        while(true){}
    //}
}
I have been looking at this issue for several days and have no clue what the problem may be. Bochs is saying this "00085352371e[CPU ] interrupt(): vector must be within IDT table limits, IDT.limit = 0x0" but I could find no info on the message.
Last edited by brentS on Wed Jul 22, 2009 2:31 pm, edited 1 time in total.
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Re: ISR not catching divide by 0 error

Post by frank »

Is your IDT pointer structure packed correctly? Try adding __attribute__ ((packed)) to your structure.
brentS
Posts: 16
Joined: Sat Jun 27, 2009 5:41 pm

Re: ISR not catching divide by 0 error

Post by brentS »

Since I am using D align(1) is the equivalent. Here are my structs

Code: Select all

align(1)struct idt_entry
{
	ushort base_lo;
	ushort sel;
	ubyte always0;      
	ubyte flags;
	ushort base_hi;
}

align(1)struct idt_ptr
{
    ushort limit;
    uint base;
}
User avatar
Gman
Member
Member
Posts: 37
Joined: Tue Jun 23, 2009 10:12 pm

Re: ISR not catching divide by 0 error

Post by Gman »

I had a problem like this too. I don't know much about D, but make sure you're calling idt_install() from your main() function (again, I don't know any D). I forgot to do that, and got the same problem.
"For those about to rock, we salute you"
-Brian Johnson
brentS
Posts: 16
Joined: Sat Jun 27, 2009 5:41 pm

Re: ISR not catching divide by 0 error

Post by brentS »

[-X lol but could it possibly be a problem with my gdt ... or is that a whole separate realm.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: ISR not catching divide by 0 error

Post by Brendan »

Hi,
brentS wrote:[-X lol but could it possibly be a problem with my gdt ... or is that a whole separate realm.
If Bochs says that your IDT limit is zero, then I'd guess that your IDT limit is zero. Maybe the IDT base is also zero, maybe it's being overwritten, and maybe you forgot to do "lidt"...


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
brentS
Posts: 16
Joined: Sat Jun 27, 2009 5:41 pm

Re: ISR not catching divide by 0 error

Post by brentS »

I definately am calling lidt.

Code: Select all

idtFlush(cast(uint)&idtp);

Code: Select all

idtFlush:
	mov eax, [esp+4]
	lidt [eax]
	ret
*This code you can say was grabbed from here http://www.jamesmolloy.co.uk/tutorial_h ... 20IDT.html*

Nothing is being written after I install the IDT except some keyboard tests but that should not matter. What would the limit and base being 0 mean? that it sees my table as 0 of size?
User avatar
Zenith
Member
Member
Posts: 224
Joined: Tue Apr 10, 2007 4:42 pm

Re: ISR not catching divide by 0 error

Post by Zenith »

I'm wondering... can you verify using the Bochs debugger whether anything is actually being written to the IDT location? Also, is it right for us to presume that idt is idt_entry[256] idt?

Try replacing the call to idtFlush with some D inline ASM and see what happens:

Code: Select all

// Should work in GDC/LDC
auto ptr_idtp = &idtp;
asm {
	lidt ptr_idtp;
	sti;
}
"Sufficiently advanced stupidity is indistinguishable from malice."
User avatar
yemista
Member
Member
Posts: 299
Joined: Fri Dec 26, 2008 12:31 pm
Location: Boston
Contact:

Re: ISR not catching divide by 0 error

Post by yemista »

Are you using a virtual offset for your kernel? idt may be linked with a physical address that you are supplying for lidt, but maybe it should be at a virtual address
brentS
Posts: 16
Joined: Sat Jun 27, 2009 5:41 pm

Re: ISR not catching divide by 0 error

Post by brentS »

Zenith I tried that and still not luck unfortunately. Yemista I am still new to kernel development so I do not understand exactely how to look for that. This is my linker script if it helps.

Code: Select all

ENTRY(load)
SECTIONS
{
  .text 0x100000 :
  {
    code = .; _code = .; __code = .;
    *(.text)
    . = ALIGN(4096);
  }

  .data :
  {
     data = .; _data = .; __data = .;
     *(.data)
     *(.rodata)
     . = ALIGN(4096);
  }

  .bss :
  {
    bss = .; _bss = .; __bss = .;
    *(.bss)
    . = ALIGN(4096);
  }

  end = .; _end = .; __end = .;
} 
User avatar
Troy Martin
Member
Member
Posts: 1686
Joined: Fri Apr 18, 2008 4:40 pm
Location: Langley, Vancouver, BC, Canada
Contact:

Re: ISR not catching divide by 0 error

Post by Troy Martin »

Nope, that's pretty much my linker script, so it should be in working order :)

Could you pastebin or slexy your main() function? I'd like to take a look at that.
Image
Image
Solar wrote:It keeps stunning me how friendly we - as a community - are towards people who start programming "their first OS" who don't even have a solid understanding of pointers, their compiler, or how a OS is structured.
I wish I could add more tex
raghuk
Member
Member
Posts: 35
Joined: Tue Jun 30, 2009 2:47 am
Location: Bangalore, India

Re: ISR not catching divide by 0 error

Post by raghuk »

Do you have a higher half kernel? Do you load it at a virtual offset 0xc0100000 or something? If you run objdump -d <kernel binary> and look for lidt what address is it trying to load? It should be the linear address of idtp.
brentS
Posts: 16
Joined: Sat Jun 27, 2009 5:41 pm

Re: ISR not catching divide by 0 error

Post by brentS »

The addresses match but there is one thing is just wondered. In my makefile I use

Code: Select all

@cat $(BOCHSDIR)stage1 $(BOCHSDIR)stage2 $(BOCHSDIR)pad $(BINDIR)kernel.bin > $(BOCHSDIR)kernel.img
to run it in bochs. Would this affect anything?

My main

Code: Select all

extern(C) void main(uint magic, uint addr)
{
	
	console_setAttributes(ConsoleColors.BLUE,ConsoleColors.GREEN);
	console_clear();
	console_print("\t\t\t\t\t\t\tWelcome to the Kernel\n");
	gdt_install();
	idt_install();
	//isrs_install();
		
	int c=0;
	console_print("before /0 \n");	
	int b= 1/c;
	console_print("after /0 \n");
}
brentS
Posts: 16
Joined: Sat Jun 27, 2009 5:41 pm

Re: ISR not catching divide by 0 error

Post by brentS »

I am officially being driven crazy over this issue. I now have new bochs output that might help the cause.

Code: Select all

interrupt(): gate descriptor is not valid sys seg (vector=0x00)
User avatar
Creature
Member
Member
Posts: 548
Joined: Sat Dec 27, 2008 2:34 pm
Location: Belgium

Re: ISR not catching divide by 0 error

Post by Creature »

I'm not sure you're supposed to be defining the 'ISR0' function in D. As JamesM says in his tutorials, you should be defining them in Assembly, then passing the address of the assembly function as IDT function address.

For example, ISR0 should be something like this:

Code: Select all

[GLOBAL ISR0]

ISR0:
   cli ; Disable interrupts, your IsrHandler should iret to turn them on again.

   push byte 0 ; Push the number of this interrupt (in this case, 0 indicating a division-by-zero-exception).
   jmp YourIsrHandlerThatPossiblyCallsFaultHandler ; Go to your ISR handler that pops and pushes some things and calls 'FaultHandler'.
So it works like this:

You do

Code: Select all

SetIDTGate(0, cast(ulong) &ISR0, 0x08, 0x8E);
Where 'ISR0' is a function defined in assembly, like the one above. This function does what the above code does, moves to the ISR handler (isr_common for example), this function pushes and pops some things, calls your 'faultHandler', which can call a specific function based on what interrupts number was sent (like call a function called "DivideByZeroExc(registers r)" when the interrupt number for the ISR is 0). When you return from your faultHandler, assembly will pop some things off the stack and do some more things to finally 'iret', turning interrupts on again.
When the chance of succeeding is 99%, there is still a 50% chance of that success happening.
Post Reply