exceptions are not being caught

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

exceptions are not being caught

Post by Andrew »

Hi,
what i am trying to do is to programm my exception handlers, but it is not workin, although i've done eveything according tutorials.
if we insert __asm__("int $0"); line in main function
and run it in bochs, we get such error:
Message: exception(): 3rd (14) exception with no resolution
and running on real PC (from floppy drive) it just keeps restarting :((( so plz help me. it is been 2 days we are searching for the bug, thank you in advance.

/// Int.h
#ifndef _INT_
#define _INT_

#include "../lib/stdio.h"
#include "../lib/Floppy.h"

static __u8 BITMAP1 = 0; // all enabled
static __u8 BITMAP2 = 0; // all enabled

// some structures for irq
// IDT descriptor format
typedef struct
{
unsigned short low_offset;
unsigned short selector;
unsigned short settings; // 15b - Present; 14-13b - Description Privelege Level
unsigned short high_offset;
}Idt;

typedef struct
{
unsigned short limit; // length of the IDT
__u32 base; // address fo the start of the IDT
}IdtP;

extern "C" void lidt(IdtP *);

class Int
{
private:
Idt IDT[256]; // maximum number of descriptors
IdtP IDTR;
...
};
#endif
Andrew

Re:exceptions are not being caught

Post by Andrew »

//Int.cpp
#include "../lib/Int.h"

void Int::loadIDT(){
IDTR.limit = 256*(sizeof(Idt)-1);
__u32 _DS; __asm__("movw %%ds, %0 \t\n":"=g"(_DS));
IDTR.base = ((__u32)_DS)<<4;
IDTR.base += (unsigned int) & IDT;

// lidt(&IDTR);
__asm__("lidt (%0) \t\n"::"p"(&IDTR));
}

//void Int::createInt(int num, void (*proc)(), __u16 set){
void Int::createInt(int num, __u32 offset, __u16 set){
__u32 address = offset;
__u16 code_selector;
__asm__("movw %%cs, %0 \t\n":"=g"(code_selector));

IDT[num].low_offset = address & 0xFFFF;
IDT[num].selector = code_selector;
IDT[num].settings = (set==0x8e00)?set:( (set==0xae00)?set:( (set==0xce00)?set:0x8e00 ) );
IDT[num].high_offset = address >> 16;
}

void Int::loadExceptions(){
createInt(0, (unsigned int)&isr0, 0);//and so on
}
Andrew

Re:exceptions are not being caught

Post by Andrew »

void Int::intExp(char *message, bool stop){
   __asm__("cli"); // testing
   __asm__("hlt");
}

extern "C" void int0(void){
   Int::intExp("Division by Zero Error", false);
}
//and so on
extern "C" void TimerIRQ(){
Floppy::TickCounter++;   
__u8 *scr;
scr = (__u8 *)(0x20*16 + 80*4+8*2);
scr[0]++;
__asm__("outb %%al, %%dx \t\n"::"a"(EOI), "d"(PIC1));
}

extern "C" void FloppyIRQ(){
   Floppy::FDD_intFlag = 1;
   __asm__("outb %%al, %%dx \t\n"::"a"(EOI), "d"(PIC1));
}

void Int::initInterrupts(){
   __asm__("cli \t\n");
   disableNMI();
   remapPIC(0x20, 0x28);    
   maskIRQ(ALL);

   loadExceptions();
//our hardware interrupts
      createInt(32, isr32, 0);
      createInt(38, isr38, 0);
//--------------
   loadIDT();
   unmaskIRQ(ALL);
   enableNMI();
   __asm__("sti \t\n");
}

//isr.asm
[extern _int0]
[global _isr0]
_isr0:
pusha
push gs
push fs
push ds
push es
mov ax, 10h
mov ds, ax
mov es, ax
cld
call _int0 ;Divide Error

pop es
pop ds
pop fs
pop gs
popa
iret
; and so on
; IRQ's
[extern _TimerIRQ]
[global _isr32]
_isr32:
pusha
push gs
push fs
push ds
push es
push ax
mov ax, 10h
mov ds, ax
mov es, ax
call _TimerIRQ ;testing

push ax
pop es
pop ds
pop fs
pop gs
popa
iret

[extern _FloppyIRQ]
[global _isr38]
_isr38:
pusha
push gs
push fs
push ds
push es
mov ax, 10h
mov ds, ax
mov es, ax
cld
call _FloppyIRQ ;testing

pop es
pop ds
pop fs
pop gs
popa
iret

[global _lidt]
_lidt:
push bp
mov bp, sp
push bx
mov bx, [ss:bp+4] ; ds:bx = pointer to IDTR structure
lidt [ds:bx] ; load IDTR
pop bx
pop bp
retn

i would be really appreciated if you took a look at my code and gave me a hint how to solve my problem.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:exceptions are not being caught

Post by Pype.Clicker »

okay, first ... please register to this forum, so that you'll be able to post your code rather than flooding a thread with poorly formatted code (there's a [ code ] [ /code ] style for short code fragments).

second. I'm afraid you have *not* "done eveything according tutorials" ... For instance:

Code: Select all

typedef struct
{
    unsigned short limit;  // length of the IDT
    __u32 base;  // address fo the start of the IDT
}IdtP;
has little chance to follow the 6 bytes packing intel requires. Instead, the compiler will actually implement the structure as

Code: Select all

{
    unsigned short limit;  
    short padding;
    __u32 base;  
}IdtP;
so that base will be 4bytes-aligned. Check your compiler's documentation to know how you can get around this. A possible trick is to put padding *then* limit and to tranmit ((void*)&IDTR)+2 to your lidt instruction.

Fix this first: until you have a valid IDTR, you cannot receive exception correctly.

third, please, for the sake of readability, consider declaring "outb()" and "inb()" macros rather than using ASM() commands everywhere... And if i were you, i would *not* restore the old masks after remapping because you're not sure of what interrupt you will receive. Unmask interrupts one by one, when you install handlers for them.

fourth (damn, i didn't plan to go that far), you should *not* issue several asm() commands and expect register values to be preserved from on to another.

Code: Select all

void Int::disableNMI(){
   __asm__("inb %%dx, %%al \t\n"::"d"(0x70));
   __asm__("andb 0x7f, %al \t\n");
   __asm__("outb %%al, %%dx \t\n"::"d"(0x70));
}
should rather be written

Code: Select all

void Int::disableNMI(){
   __asm__ volatile("inb %%dx, %%al \t\nandb 0x7f, %al \t\noutb %%al, %%dx \t\n"::"d"(0x70));
}
The 'volatile' keyword will force the compiler to issue the assembler statement even if it thinks these commands may be omitted for optimization purpose.
or better:

Code: Select all

//io.h
static inline __u8 inb(__u16 port)
{
   __u8 val;
   __asm__ volatile("inb %1, %0":"=a"(val):"d"(port));
}

// your file
void Int::disableNMI() {
    outb(0x70,inb(0x70)&0x7f);
}
Andrew

Re:exceptions are not being caught

Post by Andrew »

thank you for your post it is really informative.
i'm really sorry i didn't mean to flood. and i'll register later.
i'd like to ask a question about padding field (i found nothing about it in my tutorial). What should be values of this field?

thank you in advance.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:exceptions are not being caught

Post by Solar »

Andrew wrote: i'd like to ask a question about padding field (i found nothing about it in my tutorial). What should be values of this field?
Since ((void*)&IDTR)+2 will skip the padding field, the value doesn't matter at all. Best leave it uninitialized, since initialisation would imply you are actually using the value for something (which you don't).

You have understood the issue of padding / field alignment in general, haven't you?
Every good solution is obvious once you've found it.
Andrew

Re:exceptions are not being caught

Post by Andrew »

now i did, thanks
Andrew

Re:exceptions are not being caught

Post by Andrew »

came home and tried out your suggestions:
i didn't add field padding into structure IdtP
changed the line
lidt(&IDT); (which was commented)
into
lidt(((void *)&IDT)+2);
and got the error :
pointer of type `void *' used in arithmetic.
tried lidt(((unsigned char *)&IDT)+2); but still no exception caught :(
d*mn, what i am doing wrong
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:exceptions are not being caught

Post by Pype.Clicker »

if you do not convert your structure to

Code: Select all

{ 
    unsigned short padding;
    unsigned short limit;
    unsigned base;
} Idtp;
adjusting the address is useless ...
Andrew

Re:exceptions are not being caught

Post by Andrew »

well i added unsigned short padding; to my structure
and loaded idt this way:
__asm__("lidt (%0) \t\n"::"p"(((unsigned char*)&IDTR)+2));

but it didn't solve the problem, exception is not caught.
plz take a look at my code maybe i missed smth.

[attachment deleted by admin]
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:exceptions are not being caught

Post by Pype.Clicker »

but it didn't solve the problem, exception is not caught.
What could make you think the exception is/is not caught. What exactly occurs ??

btw, what is that

Code: Select all

   __u32 _DS; __asm__("movw %%ds, %0 \t\n":"=g"(_DS));
   IDTR.base = ((__u32)_DS)<<4;
in your code ? "everything from the tutorial", eh ? well, imho, your tutorial was programming the IDT from real mode while you're programming it from protected mode.

In protected mode, the selector for the datasegment is no longer base/16, so instead of having IDTR.base = _DS<<4, you should rather have IDTR.base = GDT.getFromSelector(_DS).getBase() ...
Andrew

Re:exceptions are not being caught

Post by Andrew »

but it didn't solve the problem, exception is not caught.

What could make you think the exception is/is not caught. What exactly occurs ??

i do this

Code: Select all

int a; int b; b = 1; a = 0; b = b/a;
btw, what is that

Code: Select all

???__u32 _DS; __asm__("movw %%ds, %0 \t\n":"=g"(_DS));
???IDTR.base = ((__u32)_DS)<<4;
actually my code is

Code: Select all

   __u16 _DS; __asm__("movw %%ds, %0 \t\n":"=g"(_DS));
   IDTR.base = ((__u32)_DS)<<4;
   IDTR.base += (unsigned int) & IDT;
and i am trying to load a linear address of the first IDT element
In protected mode, the selector for the datasegment is no longer base/16, so instead of having IDTR.base = _DS<<4, you should rather have IDTR.base = GDT.getFromSelector(_DS).getBase() ...
what that function getFromSelector should do? and why should i load the base of GDT instead of IDT?
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:exceptions are not being caught

Post by Pype.Clicker »

The linear address of your IDT is "offset of IDT within the current data segment" (which is &IDT) + "base address for that data segment".
In protected mode, where's the base of your data segment ? in your GDT.

So first find back the descriptor of your data segment (i assumed you had

Code: Select all

class DescriptorTable {
    Descriptor entries[];
    getFromSelector(word selector) {
        // throw BadTableException if bit 1 is set.
        // throw BadSelectorException if selector is beyond limit
        return entries[selector>>3];
    }
}
) and then retrieve the base address of that data segment (using

Code: Select all

struct Descriptor {
    union {
       byte b[8];
       word w[4];
    } raw;
    getLimit() {
        return raw.w[0]+...;
     }
     getBase() {
        return raw.w[1] + (raw.b[4]<<16) + (raw.b[7]<<24);
     }
};
).

Hope it's clearer now ...
Andrew

Re:exceptions are not being caught

Post by Andrew »

i did this:
loaded gdt this way:

Code: Select all

[BITS 32]

[global _loadGDT]
_loadGDT:
  lgdt [gdt_ptr]

  mov ax, DATA_SELECTOR
  mov ds, ax
  mov es, ax
  mov ss, ax
  mov fs, ax
  mov gs, ax
 retn

 SECTION .data
 gdt_start:
  ;null sectio
   dw 0
   dw 0
   db 0
   db 0
   db 0
   db 0
;not used because of some reasons :)
   dw 0
   dw 0
   db 0
   db 0
   db 0
   db 0
; DATA
DATA_SELECTOR EQU $-gdt_start
  dw 0ffffh
  dw 0
  db 0
  db 92h
  db 0xCF
  db 0
; CODE
CODE_SELECTOR EQU $-gdt_start
  dw 0ffffh
  dw 0
  db 0
  db 9ah
  db 0xCF
  db 0
 gdt_end:
 gdt_ptr:
   dw gdt_end - gdt_start - 1
   dd gdt_start
IdtP structure looks like

Code: Select all

typedef struct 
{
???unsigned short padding;
    unsigned short limit;  // length of the IDT
    __u32 base;   // address fo the start of the IDT
}IdtP;
IDT i load this way now:

Code: Select all

void Int::loadIDT(){
???IDTR.limit = 256*(sizeof(Idt)-1);
???IDTR.base = (unsigned int)&IDT; // + base address from gdt (but i use 0)

???__asm__("lidt (%0) \t\n"::"p"(((__u8*)&IDTR)+2));
}
and the main procedure looks like this

Code: Select all

???__asm__("cli \t\n"); 
???disableNMI();

???loadGDT();

???remapPIC(0x20, 0x28); ???
???maskIRQ(ALL);

???loadExceptions();
    //our hardware interrupts
??????createInt(32, (unsigned int)isr32, 0);
??????createInt(38, (unsigned int)isr38, 0);
    //--------------
???unmaskIRQ(0); unmaskIRQ(6);
???loadIDT();
???enableNMI();
???__asm__("sti \t\n");
and it is not working d*mn, now what is wrong
i check division by zero this way

Code: Select all

  int a;
  int b;
  a = 0;
  b = 1;
  b = 1/a;
  
and bochs tells me :
Message: exception(): 3rd (13) exception with no resolution
P.S. maybe this is incorrect? :(

Code: Select all

void Int::createInt(int num, __u32 offset, __u16 set){
???__u32 address = offset;
???__u16 code_selector;
???__asm__("movw %%cs, %0 \t\n":"=g"(code_selector));

???IDT[num].low_offset = address & 0xFFFF;
???IDT[num].selector = code_selector;
???IDT[num].settings = (set==0x8e00)?set:( (set==0xae00)?set:( (set==0xce00)?set:0x8e00 ) );
???IDT[num].high_offset = address >> 16;
}
//..... 
 createInt(0, (unsigned int)&isr0, 0);
Andrew

Re:exceptions are not being caught

Post by Andrew »

d*mn, i am starting to think that it is impossible to solve this problem. ??? maybe you know some commercial emulators whit trial that could give a hint on solving the problem or smth like that.
'cause bochs : Message: exception(): 3rd (13) exception with no resolution
tells me nothing.

[attachment deleted by admin]
Post Reply