Page 1 of 5
Loading IDT
Posted: Tue Apr 12, 2005 2:35 am
by tm-
Ok, now it's the time for loading IDT and setting up interrupts. I have read those tutorials about this subject on BonaFide, and I think I got the idea, but I have some questions.
1) Should I remap the PIC first and after that load the IDT?
2) Loading the IDT seems to be done in assembly everywhere.. Do I have to load it then in the file that calls the kernel? Because my kernel is in C.
I couldn't find any example kernel (simple and small), which would have done that..
Re:Loading IDT
Posted: Tue Apr 12, 2005 3:41 am
by Pype.Clicker
(1) the order between PIC and IDT is irrelevant provided that you do both before you re-enable interrupts.
(2) you'll have to have assembler bits for interrupt handlers (the so-called interrupt wrappers). That remains the only clean way to do it. (see the
FAQ)
setting the IDTR at least is easier in asm though it can be done in C aswell (with proper care taken while accessing IDTR). You can perfectly fill the descriptor table from C.
That being said, my favourite approach remains to have a 'generic handler' called by the wrapper that will use the interrupt number to access a "list of actions" to be taken when the interrupt arises
Re:Loading IDT
Posted: Tue Apr 12, 2005 5:21 am
by tm-
Hmm.. I didn't really get the point of your answer.. Where should I put that IDT loader? Kernel c-code or to the file that loads the kernel(which is in asm)?
Let's take an example:
Calls main() (kernel loader)
Code: Select all
[BITS 32]
[global start]
[extern _main]
start:
call _main
cli
hlt
And the kernel
Code: Select all
void main(void)
{
char *str = "Welcome";
printf(str);
while(1);
}
Where do I load the IDT in these files? First I remap PIC in kernel main and what then?? It would help if one could use these code examples and show how its done.
Re:Loading IDT
Posted: Tue Apr 12, 2005 6:05 am
by AR
I determined the order of the inits by the dependencies, everything needs the screen, everything except the screen needs the physical manager, everything except the physical manager and Screen needs the Virtual Manager and so forth. ie. Screen, Physical Manager, Virtual Manager, Kernel Heap, GDT, PIC, IDT, ...
(All these are from int main(), my bootloader between GRUB and the Kernel does nothing besides activate paging and convert GRUBs multiboot data into something more useful)
Mapping the PIC in and of itself does absolutely nothing. Just like reprogramming the IDT in and of itself does absolutely nothing as well. Once both are done however and you enable interrupts then something happens, the order of the 2 is irrelevant as long as the third event (Enable interrupts) does not occur before the other 2.
Re:Loading IDT
Posted: Tue Apr 12, 2005 6:09 am
by Pype.Clicker
You could for instance have something like this:
Code: Select all
[BITS 32]
[global start]
[extern _main]
[global _idt_start]
; you may like to have it in BSS section
_idt_start:
resb 8*HOW_MANY_IDT_ENTRIES
idtr:
dw _idt_end - _idt_start
dd _idt_start
start:
lidt [idtr]
call _main
cli
hlt
Code: Select all
extern struct IDTDescr _idt_start[HOW_MANY_IDT_ENTRIES];
void main(void)
{
char *str = "Welcome";
setup_pic(0x20,0x28)
setup_timer(_idt_start+0x20);
printf(str);
while(1);
}
Re:Loading IDT
Posted: Tue Apr 12, 2005 6:47 am
by tm-
Thanks, now I got it.. Now just need to go and try to get it working
Re:Loading IDT
Posted: Tue Apr 12, 2005 8:16 am
by DruG5t0r3
Just setting up an IDT isn't enough to do a "sti" you need to setup some at least dummy fault and irq handlers.
Re:Loading IDT
Posted: Tue Apr 12, 2005 9:06 am
by AR
DruG5t0r3 wrote:
Just setting up an IDT isn't enough to do a "sti" you need to setup some at least dummy fault and irq handlers.
eh? What's the point of loading an empty IDT to begin with?
Re:Loading IDT
Posted: Tue Apr 12, 2005 9:14 am
by DruG5t0r3
AR wrote:
DruG5t0r3 wrote:
Just setting up an IDT isn't enough to do a "sti" you need to setup some at least dummy fault and irq handlers.
eh? What's the point of loading an empty IDT to begin with?
Well thats my point...an empty IDT = you will eventually crash your kernel.
Re:Loading IDT
Posted: Tue Apr 12, 2005 10:39 am
by tm-
What should I put to the offset of the idt-descriptor, which should determine the address of the ISR? Yes I know, the address where the ISR is, but if the ISR is in the kernel in C, how can I find out the address of it? It would be easy to do in asm but I want to put the ISR in the kernel.
Re:Loading IDT
Posted: Tue Apr 12, 2005 11:13 am
by AR
The IDT is on top of segments which are on top of paging, if you're using flat segments then the IDT address is whatever page the IDT is mapped on.
Creating the IDT Entry in C is easy:
Code: Select all
void CreateIDTEntry(void (*ISR)(), unsigned char intnum)
{
IDTEntry idte;
idte.ISRLow = (unsigned int)ISR & 0xFFFF;
idte.ISRHigh = (unsigned int)ISR & 0xFFFF0000 >> 16;
//Rest of entry
AddEntryToIDT(&idte, intnum);
}
You would operate this code something like:
Code: Select all
extern void AssemblyISRStub1();
CreateIDTEntry(AssemblyISRStub1, 1);
The ISR Stub has to be assembly, you can't enter the C code directly.
Re:Loading IDT
Posted: Wed Apr 13, 2005 2:29 am
by Pype.Clicker
Re:Loading IDT
Posted: Wed Apr 13, 2005 11:00 am
by tm-
I have read all the tutos in BonaFide and osfaq about the subject. But I can't see where's told about putting ISR's address to the offset in the descriptor? Or do I have to put the ISR to some location in memory and then put the memory address to the offset?
The way I do it:
Code: Select all
isr1:
pusha
push gs
push fs
push ds
push es
extern _keyboard_interrupt
call _keyboard_interrupt
pop es
pop ds
pop fs
pop gs
popa
iret
And the interrupt descriptor for keyboard IRQ:
Code: Select all
dw 0x0000
dw 0x08
dw 0x8E00
dw isr1
Both codes are in the file that loads the kernel, and what do I have to put to that offset so the isr1 gets called?
And thanks for help
Re:Loading IDT
Posted: Wed Apr 13, 2005 11:36 am
by AR
The pointer is 32bits but is unfortunately split in 2 parts:
Code: Select all
dw isr1 & 0xFFFF
dw 0x08
dw 0x8E00
dw (isr1 >> 16) & 0xFFFF
Whether or not this builds, I wouldn't know. I usually generate the ISRs in C/C++
Re:Loading IDT
Posted: Thu Apr 14, 2005 1:37 am
by Pype.Clicker
it will/won't compile depending on your assembler (nasm may require [tt](isr1 - $$)[/tt]) and depending on whether the IDT and ISRx are in the same file or not.
and it will/won't work depending on the offset of that specific file in your image (if you have it with ORG0, everything is fine ... otherwise, beware).
So you're _much_ better to fill your IDT at runtime with
Code: Select all
mov eax, isr1
mov [idt+<intnum>*8+OFFSET_LO],ax
shr eax,16
mov [idt+<intnum>*8+OFFSET_HI],ax