Page 1 of 2
Interrupt handler hang
Posted: Tue May 12, 2009 10:01 am
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 ?
Re: Interrupt handler hang
Posted: Tue May 12, 2009 8:17 pm
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.
Re: Interrupt handler hang
Posted: Tue May 12, 2009 9:40 pm
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
}
Re: Interrupt handler hang
Posted: Wed May 13, 2009 12:43 am
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
Re: Interrupt handler hang
Posted: Wed May 13, 2009 3:42 am
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
Re: Interrupt handler hang
Posted: Wed May 13, 2009 7:30 am
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
by
The stack is ok but hang on iret
Re: Interrupt handler hang
Posted: Wed May 13, 2009 9:18 am
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
Re: Interrupt handler hang
Posted: Wed May 13, 2009 9:45 am
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
Re: Interrupt handler hang
Posted: Thu May 14, 2009 1:50 am
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 ?
Re: Interrupt handler hang
Posted: Thu May 14, 2009 3:37 am
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?
Re: Interrupt handler hang
Posted: Thu May 14, 2009 3:54 am
by gedd
It's an IDT Descriptor
0x0008 : 0x0c90 selector : offset low
0x0010 : 0x8E00 offset hight : flag - reserved
64 bits complete
Re: Interrupt handler hang
Posted: Thu May 14, 2009 6:15 am
by Combuster
complete contents
Re: Interrupt handler hang
Posted: Thu May 14, 2009 6:27 am
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
Re: Interrupt handler hang
Posted: Thu May 14, 2009 8:35 am
by Troy Martin
Then what's your IDT code???
I personally have had enough of this thread.
Re: Interrupt handler hang
Posted: Thu May 14, 2009 9:52 am
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