Setting up an IDT

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Whatever5k

Setting up an IDT

Post by Whatever5k »

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)?
drizzt

Re:Setting up an IDT

Post by drizzt »

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.
Whatever5k

Re:Setting up an IDT

Post by Whatever5k »

I've found this in KJ's code, but can't understand what it means:

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]
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?
drizzt

Re:Setting up an IDT

Post by drizzt »

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...
Whatever5k

Re:Setting up an IDT

Post by Whatever5k »

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...
K.J.

Re:Setting up an IDT

Post by K.J. »

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.
Whatever5k

Re:Setting up an IDT

Post by Whatever5k »

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:

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 ****
Ok, this is the code in .text:

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
Is this ok, is this possible? I think it is, but I want to hear the answer from more experienced people ;)
Whatever5k

Re:Setting up an IDT

Post by Whatever5k »

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...
Whatever5k

Re:Setting up an IDT

Post by Whatever5k »

Ok, found the bug. I try to load a 32-bit address in a 16-bit variable.

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
Post Reply