Setting up an IDT
-
Whatever5k
Setting up an IDT
I'll have to write an IDT now.
I just wonder how I could manage this. How do *you* did that? Do you have any code examples where I could get inspired (except from KJ's)?
I just wonder how I could manage this. How do *you* did that? Do you have any code examples where I could get inspired (except from KJ's)?
-
drizzt
Re:Setting up an IDT
In this previous post I wrote an IDT for a particular use (using BIOS ints in protected mode) but you could also be inspired from this for general use:
http://www.mega-tokyo.com/forum/index.p ... eadid=1290
look at PMboot.asm file.
http://www.mega-tokyo.com/forum/index.p ... eadid=1290
look at PMboot.asm file.
-
Whatever5k
Re:Setting up an IDT
I've found this in KJ's code, but can't understand what it means:
For example, what is isr0 and isr1? And when he sets up all interrupt handlers, how does the CPU know which intterrupt handler is for which interrupt?
Code: Select all
; set up interrupt handlers, then load IDT register
mov ecx,(idt_end - idt) >> 3; number of exception handlers
mov edi,idt
mov esi,isr0 do_idt:
mov eax,esi; EAX=offset of entry point
mov [edi],ax; set low 16 bits of gate offset
shr eax,16
mov [edi + 6],ax; set high 16 bits of gate offset
add edi,8; 8 bytes/interrupt gate
add esi,(isr1 - isr0); bytes/stub
loop do_idt lidt [idt_ptr]
-
drizzt
Re:Setting up an IDT
1) isr0 and isr1 are addresses. I suppose they are the interrupt service routine addresses.
2) In protected mode after you set up the IDT, when a int or exception occurs, the CPU looks in the IDT (interrupt descriptor table) at the right location, gets the int handler address and jump to it.
For example if you specify a INT 10h instruction, CS selector and IP are pushed automatically into the stack. Then the CPU gets the 16th location of the IDT (0-based), calculates the handler address and jumps to it. When it finds an IRETD, CS & IP are popped from the stack and the execution returns to the code that has generated this int.
For every ints or exceptions you want to manage you must define an entry in the IDT.
This is an example of an IDT (NOTE: every entry is 8 bytes)
idt:
dw InterruptServiceRoutine0h ; entry point 15:0
dw SystemCodeSelector ; selector
db 0 ; word count
db 10001110b ; type (32-bit Ring 0 interrupt gate)
dw 0 ; entry point 31:16
dw InterruptServiceRoutine1h ; entry point 15:0
dw SystemCodeSelector ; selector
db 0 ; word count
db 10001110b ; type (32-bit Ring 0 interrupt gate)
dw 0 ; entry point 31:16
...
idt_end:
I hope I've been more clear as possible...
2) In protected mode after you set up the IDT, when a int or exception occurs, the CPU looks in the IDT (interrupt descriptor table) at the right location, gets the int handler address and jump to it.
For example if you specify a INT 10h instruction, CS selector and IP are pushed automatically into the stack. Then the CPU gets the 16th location of the IDT (0-based), calculates the handler address and jumps to it. When it finds an IRETD, CS & IP are popped from the stack and the execution returns to the code that has generated this int.
For every ints or exceptions you want to manage you must define an entry in the IDT.
This is an example of an IDT (NOTE: every entry is 8 bytes)
idt:
dw InterruptServiceRoutine0h ; entry point 15:0
dw SystemCodeSelector ; selector
db 0 ; word count
db 10001110b ; type (32-bit Ring 0 interrupt gate)
dw 0 ; entry point 31:16
dw InterruptServiceRoutine1h ; entry point 15:0
dw SystemCodeSelector ; selector
db 0 ; word count
db 10001110b ; type (32-bit Ring 0 interrupt gate)
dw 0 ; entry point 31:16
...
idt_end:
I hope I've been more clear as possible...
-
Whatever5k
Re:Setting up an IDT
But I cannot find any isr0 or isr1 in the source code. That's what makes me confused...
I understand/understood your text, but look at the code I've posted previously. Where is the address of the interrupt handler? I know he goes through each interrupt handler and therefore sets the address of the interrupt handler, but I cannot see where he does this...
I understand/understood your text, but look at the code I've posted previously. Where is the address of the interrupt handler? I know he goes through each interrupt handler and therefore sets the address of the interrupt handler, but I cannot see where he does this...
-
K.J.
Re:Setting up an IDT
isr1 and isr0 are made via macros(INTR and INTR_EC). I've actually replaced that code with some new stuff. What I was using before(and in the stuff in the CVS folder) was code from the OSD kernels(http://my.execpc.com/~geezer/osd/code/osd.zip). [tt]add esi,(isr1 - isr0)[/tt] just adds the length of the isr. This works only because the ISRs are the same size and come right after each other.
I hope that helps,
K.J.
I hope that helps,
K.J.
-
Whatever5k
Re:Setting up an IDT
Hm, I want to have 256 descriptors. At first, each of them should have the same interrupt handler. At runtime, I want to load the idt and then change the interrupt handler for those interrupts I want to use...
Look at my code, this is the idt in the .data section:
Ok, this is the code in .text:
Is this ok, is this possible? I think it is, but I want to hear the answer from more experienced people 
Look at my code, this is the idt in the .data section:
Code: Select all
; **** Interrupt Descriptor Table ****
; have 256 descriptor here, all having
; the same interrupt handler
; will change this at runtime
idt:
%rep 256
dw common_isr ; offset 15:0
dw CS_SELECTOR ; selector
db 0 ; (always 0 for interrupt gates)
db 8Eh ; present,ring 0,'386 interrupt gate
dw 0 ; offset 31:16
%endrep
idt_end:
idt_ptr:
dw idt_end - idt - 1; IDT limit
dd idt ; start of IDT
; **** End of Interrupt Descriptor Table ****
Code: Select all
; now, let's set up an IDT
; up to now, we have 256 descriptors
; each having the same interrupt service routine
; so we'll first load the idt and then
; change the isr for every interrupt we want
; to use
lidt [idt_ptr] ; ok, load it
; now change the interrupt handler for the keyboard interrupt
cli;no interruptions
mov ebx, 0x21;interrupt #
shl ebx, 3;multiply by 8
mov edx, IDT_BASE_ADDR
mov [edx + ebx], word keyhandler
sti
-
Whatever5k
Re:Setting up an IDT
Hm, I tried to link this, but there are 256 lines of following error message (I suppose ld prints an error message for each descriptor I've built):
boot/start.o(.data+0x5f6): relocation truncated to fit: R_386_16 .text
What does this mean, I've got no idea what is wrong...
boot/start.o(.data+0x5f6): relocation truncated to fit: R_386_16 .text
What does this mean, I've got no idea what is wrong...
-
Whatever5k
Re:Setting up an IDT
Ok, found the bug. I try to load a 32-bit address in a 16-bit variable.
So this is my code for now:
So this is my code for now:
Code: Select all
; now, let's set up an IDT
; up to now, we have 256 descriptors
; so first, fill every descriptor with
; a common interrupt handler routine
; afterwards, we'll change this
mov ecx,(idt_end - idt) >> 3 ; number of descriptors
mov edi,idt
mov esi,common_isr
fill_idt:
mov eax,esi
mov [edi],ax ; low offset
shr eax,16
mov [edi+6],ax ; high offset
add edi,8 ; descriptor length
loop fill_idt
lidt [idt_ptr] ; ok, load the IDT
; and now, let's set up a different interrupt
; service routine for some interrupts we want
; to implement
call setup_handlers