I've been lurking here for the past week reading this and that, and i have my own IRQ question now.. I've read lots of different material, and am getting to understand what I'm doing (I think). I followed and implemented many thigns that have been discussed on the five page thread a while ago about setting up the IDT. Here's my code, and it doesn't work. I get a "3rd (13) exception with no resolution" error in bochs (v 2.0).
I also boot from Grub, and have had no problems with it really. Everything is complied in gcc, and i can post the linker script/makefile if requested.
There is probably some really dumb mistake in here that someone will be able to tell me right away, but alas... my code:
void create_idt( unsigned long num, void (*handler)(void) );
void init_idt( void );
void keyboard_handler( void );
void default_func( void );
typedef struct {
unsigned short offset_low;
unsigned short selector;
unsigned char param_count;
unsigned char access;
unsigned short offset_high;
} __attribute__ ((packed)) idt_entry;
typedef struct {
unsigned short size;
unsigned long base;
} __attribute__ ((packed)) gate;
gate idtr;
idt_entry IDT[256];
void KernelMain( void ) {
char *prompt;
__clear_screen();
printf( "Adam's OS\n" );
printf( "version 0.01b\t\t\tBuild 1100\n" );
printf( "Jan 03 Development\n" );
printf( "Initlizing \"kernel\" services...\n" );
printf( "Disabling interrupts...\n" );
cli();
init_idt();
while(1) {
/*printf( "] " );
prompt = getline();
printf( "\n" );
if( strcmp( prompt, "exit" ) == 0 ) {
printf( "We cannot reboot right now, sorry!\n" );
*/
}
}
void create_idt( unsigned long num, void (*handler)(void) ) {
idt_entry *idt_temp;
idt_temp = (idt_entry *)(idtr.base + (num *8));
idt_temp->offset_low = (unsigned short) (((unsigned long)handler & 0xFFFF));
idt_temp->selector = (unsigned short)0x10;
idt_temp->access = (unsigned char) 0x8E;
idt_temp->param_count = (unsigned char)0;
idt_temp->offset_high = (unsigned short)(((unsigned long)handler >> 16));
}
void init_idt( void ) {
int n;
idtr.size = 256*8-1;
idtr.base = 0x00001000;
printf( "Creating IDT's...\n" );
for( n = 0; n < 256; n++ ) {
create_idt(n, &default_func);
}
printf( "Creating keyboard IDT...\n" );
create_idt(32, &keyboard_handler);
printf( "LIDT idtr\n" );
asm volatile ( "LIDT idtr");
printf( "STI" );
asm( "STI" );
printf( "init_idt() complete.\n" );
}
void default_func( void ) {
//_printc( "x" );
asm( "popl %eax" );
asm( "popl %eax" );
asm( "cli" );
asm( "hlt" );
}
void keyboard_handler( void ) {
printf( "key\n" );
outportb( 0x20, 0x20 );
asm( "MOV %ebp, %esp" );
asm( "POP %ebp" );
asm( "IRET" );
}
------------
There's a lot more in the kernel of course, printf and getline, etc... but none of that should matter.
Oh, and the tripple fault happens when I "STI". The message "init_idt complete." never appears.
Thanks for your help!
- Simrook
Another IRQ Question... WITH CODE!
Re:Another IRQ Question... WITH CODE!
Well my C knowledge is quite...actually let's be honest and say extremely...limited. 2 things I noticed though.
How can you be sure that the IDT base is actually 0x1000 linear? I see where you set up the structure, but are you sure it's doing what you think it is. Guess one of the C gurus, or you, could answer that in a microsecond.
Have you remapped the PICS? If so have you unmasked IRQ0? Because not handling the timer interrupt properly might explain why the error occurs immediately after STI.
Aside from that it's the standard questions of is your GDT setup right, are you trashing the stack etc.
One of the C gurus will be able to give better advice on the actual code, I just wanted to mention the IRQ0 thing because that's what the STI followed by triple fault error felt like (At least I've done that myself in the past :-[).
How can you be sure that the IDT base is actually 0x1000 linear? I see where you set up the structure, but are you sure it's doing what you think it is. Guess one of the C gurus, or you, could answer that in a microsecond.
Have you remapped the PICS? If so have you unmasked IRQ0? Because not handling the timer interrupt properly might explain why the error occurs immediately after STI.
Aside from that it's the standard questions of is your GDT setup right, are you trashing the stack etc.
One of the C gurus will be able to give better advice on the actual code, I just wanted to mention the IRQ0 thing because that's what the STI followed by triple fault error felt like (At least I've done that myself in the past :-[).
Re:Another IRQ Question... WITH CODE!
Code: Select all
00000020 <_keyboard_handler>:
20:???55 ???push %ebp
21:???89 e5 ???mov %esp,%ebp
23:???83 ec 08 ???sub $0x8,%esp
26:???83 ec 0c ???sub $0xc,%esp
29:???68 1b 00 00 00 ???push $0x1b
2e:???e8 e3 ff ff ff ???call 16 <_printf>
33:???83 c4 10 ???add $0x10,%esp
36:???83 ec 08 ???sub $0x8,%esp
39:???6a 20 ???push $0x20
3b:???6a 20 ???push $0x20
3d:???e8 be ff ff ff ???call 0 <_outportb>
42:???83 c4 10 ???add $0x10,%esp
45:???89 ec ???mov %ebp,%esp
47:???5d ???pop %ebp
48:???cf ???iret
49:???c9 ???leave
4a:???c3 ???ret
EDIT - shouldn't your idtr.base = (unsigned long int) IDT ;
Re:Another IRQ Question... WITH CODE!
Well, I have implemented a wrapper handler in asm, and have remapped the PIC.
I'm still getting a tripple fault however. I've figured out now that Bochs has a nice little debugger built into it, and have found that it is not faulting on the STI asm routine. Here is what the code is being executed to execute STI in a c function enable_sti:
push ebp
mov ebp, esp
sti
leave
ret_near
Thanks to Bochs, i've figured out that it is 3xFaulting on the execution of ret_near.
The question now is, why? Do I need to add something to my compile command line perhaps? If so, what?
In responce to curufir, I tell the complier to put the IDT structures at 0xWhatever. I'm pretty sure that I've unmasked IRQ0, and being now that I'm sure the 3xFault does not occure right after the STI, I'm more confident I have. I lifted the code for my pic remapping from the FAQ. And hopefully Grub did setup the GDT right.
Thanks for your help so far... any idea nows?
- Simrook
I'm still getting a tripple fault however. I've figured out now that Bochs has a nice little debugger built into it, and have found that it is not faulting on the STI asm routine. Here is what the code is being executed to execute STI in a c function enable_sti:
push ebp
mov ebp, esp
sti
leave
ret_near
Thanks to Bochs, i've figured out that it is 3xFaulting on the execution of ret_near.
The question now is, why? Do I need to add something to my compile command line perhaps? If so, what?
In responce to curufir, I tell the complier to put the IDT structures at 0xWhatever. I'm pretty sure that I've unmasked IRQ0, and being now that I'm sure the 3xFault does not occure right after the STI, I'm more confident I have. I lifted the code for my pic remapping from the FAQ. And hopefully Grub did setup the GDT right.
Thanks for your help so far... any idea nows?
- Simrook
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Another IRQ Question... WITH CODE!
* you must exit your interrupt/exception handler using IRET, not ret_near ...
* you must pusha/popa registers (and possibly do the same with segment registers) around your ISR. If you don't do it, your "normal" code may see its registers changing randomly and it will surely crash as soon as pointers will be involved.
* you must pusha/popa registers (and possibly do the same with segment registers) around your ISR. If you don't do it, your "normal" code may see its registers changing randomly and it will surely crash as soon as pointers will be involved.