Interrupt handler hang

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.
gedd
Member
Member
Posts: 104
Joined: Thu Apr 10, 2008 1:47 am

Interrupt handler hang

Post by gedd »

Well

I try to develop an interrupt handler but each time the system call it , it faill
Some details :
- IDE = MSVC++
handler prototype :

Code: Select all

void _declspec(naked) IDTManager::DefaultHandler()
{
    __asm{
        /*try to manage stack */
        }
    // try to insert some c++ code
    __asm{
        iretd
    }
}
I try many things (like proposed in wiki) to manage stack but each time the system hang.
with debugger i can see that the handler is well called and execute, at the exit it seems to have problem with segment

worth if i try to insert some code before exit it fail too

does anyone have an idea ?
[ Grub 2 | Visual Studio 2013 | PE File ]
The OsDev E.T.
Don't send OsDev MIB !
User avatar
quanganht
Member
Member
Posts: 301
Joined: Fri May 16, 2008 7:13 pm
Location: Hanoi, Vietnam

Re: Interrupt handler hang

Post by quanganht »

I've seen your roadmap. I'm no expert but I suggest you to complete interupt handling and memory management before VESA support.
"Programmers are tools for converting caffeine into code."
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Interrupt handler hang

Post by neon »

I highly recommend NOT having your interrupt handler a part of the class. Keep it a static method with _cdecl for proper stack cleanup.

ie:

Code: Select all

static void _cdecl IDTManager::DefaultHandler() {

	_asm add esp, 12
	_asm pushad

	// code..

	_asm popad
	_asm iretd
}
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
gedd
Member
Member
Posts: 104
Joined: Thu Apr 10, 2008 1:47 am

Re: Interrupt handler hang

Post by gedd »

quanganht wrote:I've seen your roadmap. I'm no expert but I suggest you to complete interupt handling and memory management before VESA support.
Why ? There is a technical reason ?
The VESA driver is already done, it have been tested, it works but i have not published the release.
I will do it today
quanganht wrote:static void _cdecl IDTManager::DefaultHandler() {
neon wrote:I highly recommend NOT having your interrupt handler a part of the class. Keep it a static method with _cdecl for proper stack cleanup.

ie:

Code: Select all

static void _cdecl IDTManager::DefaultHandler() {

_asm add esp, 12
_asm pushad

// code..

_asm popad
_asm iretd
}
It's one of many solution that i have tested (from brokenthorn forum i remember ;o))
It's already a static method
Message from bochs : not a valid segment, and effectively the stack seems corrupted
[ Grub 2 | Visual Studio 2013 | PE File ]
The OsDev E.T.
Don't send OsDev MIB !
User avatar
quanganht
Member
Member
Posts: 301
Joined: Fri May 16, 2008 7:13 pm
Location: Hanoi, Vietnam

Re: Interrupt handler hang

Post by quanganht »

gedd wrote:
quanganht wrote:I've seen your roadmap. I'm no expert but I suggest you to complete interupt handling and memory management before VESA support.
Why ? There is a technical reason ?
The VESA driver is already done, it have been tested, it works but i have not published the release.
I will do it today
Oh, so I didn't know that. Actually there isn't any technical problems with it. But VESA is not the most important part. The others are.
Well, as you have done it, keep on going :)
"Programmers are tools for converting caffeine into code."
gedd
Member
Member
Posts: 104
Joined: Thu Apr 10, 2008 1:47 am

Re: Interrupt handler hang

Post by gedd »

Some details for the handler posted by neon

On bochs debugger

Code: Select all

Stack at the enter on interrupt
00000cc4  --> eip (low)
00000010     ... (hight
00000008 --> cs : code selector
00000000 
00000006 --> eflags 
00000000

Code: Select all

stack before iret
00000008
00000000 
00000006
00000000


Strange fact the disassembled code seems to be in 16bits and not 32

Code: Select all

In source code
add	esp, 12
in bochs
add          sp, 12
?????

The stack is clearly out, but if i replace

Code: Select all

_asm add esp, 12
by

Code: Select all

_asm add esp, 8
The stack is ok but hang on iret
[ Grub 2 | Visual Studio 2013 | PE File ]
The OsDev E.T.
Don't send OsDev MIB !
User avatar
Troy Martin
Member
Member
Posts: 1686
Joined: Fri Apr 18, 2008 4:40 pm
Location: Langley, Vancouver, BC, Canada
Contact:

Re: Interrupt handler hang

Post by Troy Martin »

Well, if bochs TFs, effectively rebooting the computer, it will drop back to real mode, making 32-bit code without a prefix into 16-bit code, making ESP effectively SP.

$0.02
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
gedd
Member
Member
Posts: 104
Joined: Thu Apr 10, 2008 1:47 am

Re: Interrupt handler hang

Post by gedd »

Not at all, the system jump to default handler with int n instruction or this with code

Code: Select all

int x = 0;
int y = 10 /x;   // divide by zero
no triple fault at this moment, the execution is normal.

I have also checked my IDT descriptor flag BITS32 | PRESENT --> 0x8E
[ Grub 2 | Visual Studio 2013 | PE File ]
The OsDev E.T.
Don't send OsDev MIB !
gedd
Member
Member
Posts: 104
Joined: Thu Apr 10, 2008 1:47 am

Re: Interrupt handler hang

Post by gedd »

Ok let's resume

My handler :

Code: Select all

void _cdecl IDTManager::DefaultHandler(){
    __asm{
        add    esp, 12
        pushad	
    }
    IDTManager::cs->Write("Exception fired !"); // cs : static pointer to static object console
    __asm{	
        popad
        iretd
    }
}
I try this test :

Call handler directly :

Code: Select all

IDT::IDTManager::DefaultHandler();
It works fine :
- write message "Exception fired !"
- hang on iretd // not an error for a classic call

call with int n or /0
hang directly , no message

I have put a breakpoint on my handler in bochs to trace and surprise ...

On the direct call i have this

Code: Select all

00100c90: (                    ): push ebp                  ; 55
00100c91: (                    ): mov ebp, esp              ; 8bec
00100c93: (                    ): push ebx                  ; 53
00100c94: (                    ): push esi                  ; 56
00100c95: (                    ): push edi                  ; 57
00100c96: (                    ): add esp, 0x0000000c       ; 83c40c
00100c99: (                    ): pushad                    ; 60       
00100c9a: (                    ): push 0x0010163c           ; 683c161000
00100c9f: (                    ): mov ecx, dword ptr ds:0x102248 ; 8b0d48221000
00100ca5: (                    ): call .+0xfffff806         ; e806f8ffff                                  <--- the call to cs->Write(...
00100caa: (                    ): popad                     ; 61
00100cab: (                    ): iretd                     ; cf
On int or /0 i have this :

Code: Select all

00100c90: (                    ): push bp                   ; 55
00100c91: (                    ): mov bp, sp                ; 8bec
00100c93: (                    ): push bx                   ; 53
00100c94: (                    ): push si                   ; 56
00100c95: (                    ): push di                   ; 57
00100c96: (                    ): add sp, 0x000c            ; 83c40c
00100c99: (                    ): pusha                     ; 60
00100c9a: (                    ): push 0x163c               ; 683c16
00100c9d: (                    ): adc byte ptr ds:[bx+si], al ; 1000
00100c9f: (                    ): mov cx, word ptr ds:[di]  ; 8b0d
00100ca1: (                    ): dec ax                    ; 48
00100ca2: (                    ): and dl, byte ptr ds:[bx+si] ; 2210
00100ca4: (                    ): add al, ch                ; 00e8
00100ca6: (                    ): push es                   ; 06
00100ca7: (                    ): clc                       ; f8
00100ca8: (                    ): (invalid)                 ; ffff                            ??? where is the call to cs->Write(...  ???
00100caa: (                    ): popa                      ; 61
00100cab: (                    ): iret                      ; cf
It's the same code , the only change is the way of call.
It seems like 16 bits code interpretation on int
My descriptors are
0x0008 : 0x0c90 selector : offset low
0x0010 : 0x8E00 offset hight : flag - reserved

I clearly think that there is a switch to 16bits mode , but why an how ?
Any idea ?
[ Grub 2 | Visual Studio 2013 | PE File ]
The OsDev E.T.
Don't send OsDev MIB !
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Interrupt handler hang

Post by Combuster »

You need to set a bit in the GDT for a code segment to be 32-bit. That or you have overwritten something

Could you post the complete descriptor contents for inspection?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
gedd
Member
Member
Posts: 104
Joined: Thu Apr 10, 2008 1:47 am

Re: Interrupt handler hang

Post by gedd »

It's an IDT Descriptor

0x0008 : 0x0c90 selector : offset low
0x0010 : 0x8E00 offset hight : flag - reserved

64 bits complete
[ Grub 2 | Visual Studio 2013 | PE File ]
The OsDev E.T.
Don't send OsDev MIB !
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Interrupt handler hang

Post by Combuster »

complete contents
:roll:
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
gedd
Member
Member
Posts: 104
Joined: Thu Apr 10, 2008 1:47 am

Re: Interrupt handler hang

Post by gedd »

Don't understand what you want
The IDT table is filled with the same descriptor 256 time

And GDT table is initialized in loader (16 bit asm) , before jump to protected mode

Code: Select all

gdt_data: 
	dd 0				; null descriptor
	dd 0 

; gdt code:				; code descriptor
	dw 0FFFFh			; limit low
	dw 0				; base low
	db 0				; base middle
	db 10011010b		; access
	db 11001111b		; granularity
	db 0				; base high

; gdt data:				; data descriptor
	dw 0FFFFh			; limit low (Same as code)10:56 AM 7/8/2007
	dw 0				; base low
	db 0				; base middle
	db 10010010b		; access
	db 11001111b		; granularity
	db 0				; base high
	
end_of_gdt:
toc: 
	dw end_of_gdt - gdt_data - 1	; limit (Size of GDT)
	dd gdt_data						; base of GDT

; give the descriptor offsets names

%define NULL_DESC 0
%define CODE_DESC 0x8
%define DATA_DESC 0x10
[ Grub 2 | Visual Studio 2013 | PE File ]
The OsDev E.T.
Don't send OsDev MIB !
User avatar
Troy Martin
Member
Member
Posts: 1686
Joined: Fri Apr 18, 2008 4:40 pm
Location: Langley, Vancouver, BC, Canada
Contact:

Re: Interrupt handler hang

Post by Troy Martin »

Then what's your IDT code???

:roll:

I personally have had enough of this thread.
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
gedd
Member
Member
Posts: 104
Joined: Thu Apr 10, 2008 1:47 am

Re: Interrupt handler hang

Post by gedd »

IDTManager.h

Code: Select all

#pragma once
#include <system/console/console.h>

namespace IDT{

#define MAX_INTERRUPTS 256

#define IDT_BIT16		0x06	//00000110
#define IDT_BIT32		0x0E	//00001110
#define IDT_RING1		0x40	//01000000
#define IDT_RING2		0x20	//00100000
#define IDT_RING3		0x60	//01100000
#define IDT_PRESENT		0x80	//10000000

#pragma pack (push,1)
	struct IDTDescriptor{
		unsigned __int16	BaseLow;
		unsigned __int16	Selector;
		unsigned __int8		Reserved;
		unsigned __int8		Flags;
		unsigned __int16	BaseHigh;
	};
#pragma pack (pop,1)

#pragma pack (push, 1)
struct idtr {
	unsigned __int16 Limit;
	unsigned __int32 Base;
};
#pragma pack (pop, 1)

typedef void (_cdecl *IRQ_HANDLER)(void);


class IDTManager
{
public:
	IDTManager(void);
	~IDTManager(void);
	static void LoadIDT();
	static __int32 InstallInterrupt(unsigned __int32 index, unsigned __int8 flags, unsigned __int16 selector, IRQ_HANDLER handler);
	static void /*_cdecl*/ DefaultHandler();//unsigned int cs, unsigned int eip, unsigned int eflags);//unsigned __int32 eip,unsigned __int32 cs,unsigned __int32 eflags);

	void GenerateInt (int n);
	void Init(unsigned __int16, Console * cons);
	static struct IDTDescriptor _idt[MAX_INTERRUPTS];
private:	
	static Console* cs;

	static struct idtr _idtr;	
};
}

IDTManager.cpp

Code: Select all

	/
#include <HAL/IDTManager.h>


namespace IDT{

struct IDTDescriptor IDTManager::_idt[MAX_INTERRUPTS] ={0} ;
struct idtr IDTManager::_idtr = {0};
Console *IDTManager::cs;


IDTManager::IDTManager(void)
{
}

IDTManager::~IDTManager(void)
{
}

void IDTManager::LoadIDT()
{
	__asm{
		//lea		eax, _idtr
		//lidt	[eax]
		lidt [_idtr]
	};
}
/*
 * Install an interrupt 
 * Return interrupt index or -1 on error
 */
__int32 IDTManager::InstallInterrupt(unsigned __int32 index, unsigned char flags, unsigned short selector, IRQ_HANDLER handler)
{
	
	if ((index>MAX_INTERRUPTS) || (!handler))
	{
		IDTManager::cs->SetForeColor(0x00880000);
		IDTManager::cs->Write("Error on int ");
		IDTManager::cs->WriteLine((int)index);
		IDTManager::cs->SetForeColor(0x00FFFFFF);
		return -1;
	}

	//! get base address of interrupt handler
	//unsigned long long base = (unsigned long long)&(*handler);
	unsigned __int64 base = (unsigned __int64)&(*handler);
	/*
	cs->Write("|");
	cs->Write((int)index);
	cs->Write(":");
	cs->WriteLine(selector);
	*/
	//! store base address into idt
	_idt[index].BaseLow	=	unsigned __int16(base & 0xffff);
	_idt[index].BaseHigh=	unsigned __int16((base >> 16) & 0xffff);
	_idt[index].Reserved=	0;
	_idt[index].Flags	=	unsigned __int8(flags);
	_idt[index].Selector=	selector;

	return	index;
}

void _declspec(naked) _cdecl IDTManager::DefaultHandler(){//unsigned int cs, unsigned int eip, unsigned int eflags){//unsigned __int32 eip,unsigned __int32 cs,unsigned __int32 eflags){
	__asm{
		cli
        pushad	
	}
	IDTManager::cs->SetBackColor(0x00FFFFFF);
	IDTManager::cs->SetBackColor(0x00FF0000);
	IDTManager::cs->WriteLine("!!!!!! Interrupt not handled !!!!!!!\nJust wait next version ;o) !");
	IDTManager::cs->SetBackColor(0x00000000);
	IDTManager::cs->SetBackColor(0x00FFFFFF);
	/* Restore the context */
	__asm{	
		popad
        iretd
	}
}
//! generate interrupt call
void IDTManager::GenerateInt (int n) {
	_asm {
		mov al, byte ptr [n]
		mov byte ptr [genint+1], al
		jmp genint
	genint:
		int 0	// above code modifies the 0 to int number to generate
	}
}

void IDTManager::Init(unsigned __int16 selector, Console * cons)
{
	// init console pointer
	*IDTManager::cs = *cons;
	IDTManager::cs->WriteLine("IDT initialization");
	//! set up idtr for processor
	_idtr.Limit = sizeof (struct IDTDescriptor) * (MAX_INTERRUPTS -1);
	_idtr.Base	= (unsigned __int32)&_idt[0];

	//! register default handlers
	for (int i=0; i<MAX_INTERRUPTS; i++)
	{
		_idt[i].BaseHigh = 0;
		_idt[i].BaseLow = 0;
		_idt[i].Flags = 0;
		_idt[i].Reserved = 0;
		_idt[i].Selector = 0;
		InstallInterrupt (i, IDT_PRESENT | IDT_BIT32,
		selector, 
		(IRQ_HANDLER)/*(void (__cdecl &)(void))*/IDTManager::DefaultHandler);
	}
	//! install our idt
	IDTManager::LoadIDT ();

}

}

I use my eyes on it
[ Grub 2 | Visual Studio 2013 | PE File ]
The OsDev E.T.
Don't send OsDev MIB !
Post Reply