Page 1 of 1
Interrupts are not working!
Posted: Mon Mar 02, 2009 1:44 pm
by mangaluve
Im having troubles getting interrupts to work. I've followed a tutorial on
http://www.jamesmolloy.co.uk/tutorial_h ... 20IDT.html. The problem occurs after kernel-main, when I use STI to enable interrupts. I get weird interrupts as soon as I enable them, and lots of them (interrupt after interrupt) without doing something that should trigger even one of them. This is my kernel code (it starts in kernel.asm, Im fairly positive that my boot loader works)
kernel.asm
Code: Select all
[BITS 32]
[global start]
[extern _k_main] ;this is in kernel.c
start:
call _k_main
sti ;this causes trouble, a large number of interrupt trigger
hlt
idt.asm
Code: Select all
[GLOBAL _idt_flush]
[GLOBAL _isr_handler]
[extern _isr_c_handler]
_idt_flush:
mov eax, [esp+4]
lidt [eax]
ret
_isr_handler:
pusha
push gs
push fs
push es
push ds
call _isr_c_handler ; Call the C interrupt handler
pop ds
pop es
pop fs
pop gs
popa
iret
kernel.c
Code: Select all
typedef unsigned int u32int;
typedef int s32int;
typedef unsigned short u16int;
typedef short s16int;
typedef unsigned char u8int;
typedef char s8int;
void k_clear_screen();
void putchar(char c);
int cursor_pos = 0;
extern void isr_handler();
void putchar(char c) {
char *vidmem = (char *) 0xb8000;
vidmem[2*cursor_pos + 1] = 0x07;
vidmem[2* (cursor_pos ++)] = c;
}
struct idt_entry_struct
{
u16int base_lo;
u16int sel;
u8int always0;
u8int flags;
u16int base_hi;
} __attribute__((packed));
typedef struct idt_entry_struct idt_entry_t;
struct idt_ptr_struct
{
u16int limit;
u32int base;
} __attribute__((packed));
typedef struct idt_ptr_struct idt_ptr_t;
idt_entry_t idt_entries[256];
idt_ptr_t idt_ptr;
static void idt_set_gate(u8int num, u32int base, u16int sel, u8int flags)
{
idt_entries[num].base_lo = base & 0xFFFF;
idt_entries[num].base_hi = (base >> 16) & 0xFFFF;
idt_entries[num].sel = sel;
idt_entries[num].always0 = 0;
idt_entries[num].flags = flags /* | 0x60 */;
}
static void init_idt()
{
int i;
idt_ptr.limit = sizeof(idt_entry_t) * 256 -1;
idt_ptr.base = (u32int)&idt_entries;
for(i = 0; i < 32 ; i++)
idt_set_gate(i, (u32int)isr_handler , 0x08, 0x8E);
idt_flush((u32int)&idt_ptr);
}
void isr_c_handler()
{
putchar('a');
}
k_main()
{
k_clear_screen();
init_idt();
};
void k_clear_screen()
{
char *vidmem = (char *) 0xb8000;
unsigned int i = 0;
while (i < (80* 25* 2 ) ) {
vidmem[i] = ' ';
i++;
vidmem[i] = 0x07;
i++;
};
};
Now you would expect no interrupt to be triggered, (unless I trigger it by myself). The interrupt handler isr_c_handler() (which is called from _isr_handler in idt.asm) should thus not print any a:s. But it's printing more than enough to fill the screen. Any help would be appreciated!
Re: Interrupts are not working!
Posted: Mon Mar 02, 2009 9:53 pm
by yemista
try "show int" in bochs to see what interrupt it is. Its probably the timer.
Re: Interrupts are not working!
Posted: Mon Mar 02, 2009 10:56 pm
by Troy Martin
Either that or a series of GPFs and other faults.
Re: Interrupts are not working!
Posted: Tue Mar 03, 2009 1:48 am
by mangaluve
Thanks!
How do I use show int int bochs?
I only get One interrupt if I replace the hlt-statement with a hang: jmp hang.. I mean I get PANIC and stuff, different message all the time. Sometime I get GPF:s, but why do they occur?
Re: Interrupts are not working!
Posted: Tue Mar 03, 2009 2:05 am
by 01000101
in the bochs debugger... type "show int" to see all the interrupts (yours AND the BIOS's startup interrupts).
Re: Interrupts are not working!
Posted: Tue Mar 03, 2009 2:09 am
by neonek
Maybe try cli before you call the main function.
Re: Interrupts are not working!
Posted: Tue Mar 03, 2009 2:54 am
by mangaluve
Well I have a CLI in my boot loader so it cannot be it. I haven't touched the PIC yet, so timer interrupts shouldnt be enabled?
But it's stranged, I looked at the wiki and used some test-code,
Code: Select all
int_handler:
mov ax, 010h
mov gs, ax
mov dword [gs:0xB8000],') : '
hlt
idt:
resd 50*2
idtr:
dw (50*8)-1
dd idt
test1:
lidt [idtr]
mov eax,int_handler
mov [idt+49*8],ax
mov word [idt+49*8+2],08h
mov word [idt+49*8+4],0x8E00
shr eax,16
mov [idt+49*8+6],ax
int 49
It works fine, it prints a smiley and then halts. But when I try an IRET in my isr, I get errors, something like "CS selector is null":
Code: Select all
int_handler:
iret
idt:
resd 50*2
idtr:
dw (50*8)-1
dd idt
test1:
lidt [idtr]
mov eax,int_handler
mov [idt+49*8],ax
mov word [idt+49*8+2],08h
mov word [idt+49*8+4],0x8E00
shr eax,16
mov [idt+49*8+6],ax
int 49
hlt
How can this be?
Another thing, after my kernel-main function (in my original code), I just have a HLT. What happens then if an ISR is called and then returned from? will the CPU return and continue on the HLT-statement? What should I have in the "end" of my kernel, in the state where I only wait for interrupts? A jmp $ or a hlt?
Re: Interrupts are not working!
Posted: Tue Mar 03, 2009 4:42 am
by jal
mangaluve wrote:I haven't touched the PIC yet, so timer interrupts shouldnt be enabled?
Of course it is, that's what the BIOS does for ya.
It works fine, it prints a smiley and then halts. But when I try an IRET in my isr, I get errors, something like "CS selector is null"
Which usually means you screwed up big time, some place.
How can this be?
We've all experienced strange things. Usually, it's our own fault (bug, anyone?).
Another thing, after my kernel-main function (in my original code), I just have a HLT. What happens then if an ISR is called and then returned from? will the CPU return and continue on the HLT-statement?
I'd say: check the HLT in the Intel manual. It should give you all the information you need (short answer: of course not!).
What should I have in the "end" of my kernel, in the state where I only wait for interrupts? A jmp $ or a hlt?
Both, of course. Although I'm not sure why you would want to do that.
JAL
Re: Interrupts are not working!
Posted: Tue Mar 03, 2009 9:45 am
by Troy Martin
Question: what interrupt is firing? If its 0Dh or 0Eh, then it's something went wrong in memory (GPF or PF, don't remember which.)
Re: Interrupts are not working!
Posted: Tue Mar 03, 2009 11:45 am
by mangaluve
Thanks for all the replies!
Over the course of the day I've been able to fix the problems. I dont really know what was wrong (I changed some things, then changed back and back and forth) but it's seems to be working now.
Re: Interrupts are not working!
Posted: Tue Mar 03, 2009 3:13 pm
by Helium
As far as I know, a simple HLT (while interrupts are enabled) only waits until
one interrupt has happend. When the interrupt handler returns, you get to the first instruction
after the HLT. I don't know how your code is linked, but probably you'll end up on one of your functions. When the function returns, it takes a "random" value off the stack and you're finally in the nirwana where everything (protection faults, interrupts) may happen.
I'd write the end of the kernel in this way:
The HLT is mainly needed to keep the CPU cool and save power: If you leave it out, the CPU will execute the loop in a very fast rate, but with HLT, it will wait for an interrupt every time before continuing.
Re: Interrupts are not working!
Posted: Tue Mar 03, 2009 3:19 pm
by kmtdk
well
first:
the cpu waits for an int if the command is hlt.
BUT what if the timer is very low ( = MANY interupt)
then the cpu will do a lot of work.
however if you use "cli", you disable all interupts, and with a "hlt" it will HALT, and dont do anything .
KMT dk
Re: Interrupts are not working!
Posted: Tue Mar 03, 2009 4:19 pm
by frazzledjazz
needs to use 'interrupt;' or similar construct, as BTW BP/TP I think v3 and up, as WELL AS FPC 1.x.x uses.
someone needs to correct the wiki.
Borland had support for this WAY back in the day. FPC just keep it.
putchar('a'); is oviously called from some interrupt that keeps getting called. putchar, effective hits int 10, though.[video memory for text mode] my guess would be the timer interrupt is getting called, thus 'putting chars everywhere'.
otherwise the code looks fine. I have similar code in project FPOS, though I'm not the maintainer.
Pascal, I'm sorry....It just reads easier. C 'structs' can be anything. Pascal clearly defines them as pointers, pchars, strings, records, etc... so if I seem outdated it is only your perception, pascal has been kicking since the days of CP/M and I don't think will ever stop. FPC and Lazarus IDE integration just makes it that much more valuable.[effectively VB/VC are obsolete because of it.] GPFs are virtually non-existent in Pascal as well. It ports better [even to MAC] than Python' Tkinter interface, which is C-based. C is losing ground as far as I'm concerned. Just thought I should point that out.
for example:
Procedure KeyboardHandler (r:trealregs); interrupt;
begin
// put something here
end;
without 'interrupt;' it calls 'return' in assembler wrong and supposedly triple-faults.
you need iret, not ret, which C (functions??) usually return with. I'm not sure, but i think there is a way to do this in C, try bran's kernel dev pages.
I am using his methods(Bran's) in pascal, almost as he shows them in C. implementing the interrupts already in use IE: mouse, etc. obviously needs a workaround, but mostly works this way, using his method. I would set up a GPF interrupt, though to be safe. Mario set one up already. It needs to be in the isr file to work properly.Try to keep interrupts SHORT and just let them return to otherwise running code[the proper handler] and let THAT code adjust for what it needs to.
IE: extended key codes on keyboard, actions for mouse buttons, etc.These would be in :
keyboard.pas[or .h and .c]
mouse.pas [or .h or .c]
ETC.
hope this helps.
cli
hlt
in assembler block will HALT the machine, leaving it on.you just told it to 'wait for no interrupts to come'.it does it VERY well.
Re: Interrupts are not working!
Posted: Wed Mar 04, 2009 12:57 pm
by Helium
If you want to test interrupt routines, you must have enabled the interrupts. CLI / HLT will never leave or execute some "nirvana" code, but no interrupt routine will ever be called. The CPU then does really nothing and doesn't react to anything (except NMIs).