Interrupt handling

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
2100-OS

Interrupt handling

Post by 2100-OS »

OK, I want to write the timer (IRQ0) interrupt routine:

As far as I know I need the following code to do so:

asm (NASM), something is needed like :-\:

[BITS 32]
[GLOBAL _ks_timerInterruptIRQ0]
[ALIGN 4]

_clock_isr:

push eax
push ds
push es
push fs
push gs

mov eax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

extern _ks_timerInterruptIRQ0
call _ks_timerInterruptIRQ0

mov eax, 0x20
out 0x20, al

pop gs
pop fs
pop es
pop ds
pop eax

iret


C:

void ks_timerInterruptIRQ0(void)
{
// Do something...
}


Till this part, it seems logical, but I can't find anything on how I can tell the processor to use _clock_isr, it seems to me, that I need a pointer to this procedure, somewhere in the memory, but how and where to set it I don't know, does anyone have an idea?
Whatever5k

Re:Interrupt handling

Post by Whatever5k »

Well, you have to build an entry in the IDT that points to _clock_isr, so be sure to make _clock_isr global, too.
By the way, you probably want to change

Code: Select all

[GLOBAL _ks_timerInterruptlIRQ0]
into

Code: Select all

[EXTERN _ks_timerInterruptlIRQ0]
Curufir

Re:Interrupt handling

Post by Curufir »

2100-OS wrote: Till this part, it seems logical, but I can't find anything on how I can tell the processor to use _clock_isr, it seems to me, that I need a pointer to this procedure, somewhere in the memory, but how and where to set it I don't know, does anyone have an idea?
Investigate these (Assuming x86 architecture):
IDT - Interrupt Descriptor Table, works similarily to the IVT in Real Mode.

PIC - Programmable Interrupt Controller. Takes signals (IRQs) from hardware devices and produces an interrupt in the processor.

PIT - Programmable Interval Timer. Consists of 3 separate timers, the first of which produces an interrupt in the processor.

Make sure you also know how to setup a GDT.

Read up on those things and it should become self evident what steps you need to take to have your routine called.
2100-OS

Re:Interrupt handling

Post by 2100-OS »

OK, I am seeing some puzzlepieces coming together (like 3, 4 of the 10000 :) )

I understand what's done right here (in ASM)

[section .text]
;load the IDT, this requires that the data section with
;the IDT exists
lidt [idt_pointer]

[section .data]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; the IDT with it's descriptors
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
start_of_idt:
;interrupt 0
dw 0x0000
dw 0x10
dw 0x8E00
dw 0x20

;interrupt 1
dw 0x0000
dw 0x10
dw 0x8E00
dw 0x20

;interrupt 2, intel reserved, we set the 'present' bit to 0 on this one
dw 0x0000
dw 0x10
dw 0xE00
dw 0x20

;interrupts 3-14 now, since we are making the descriptors
;identical, we are going to loop to get them all(12 total)
%rep 0xC
dw 0x0000
dw 0x10
dw 0x8E00
dw 0x20
%endrep

;interrupt 15, intel reserved, we set the 'present' bit to 0 on this one
dw 0x0000
dw 0x10
dw 0xE00
dw 0x20

;interrupt 16
dw 0x0000
dw 0x10
dw 0x8E00
dw 0x20
end_of_idt:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; now for the IDT pointer
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
idt_pointer:
dw end_of_idt - start_of_idt - 1
dd start_of_idt

What I don't understand is how I can link an interrupt with a basic assembler routine. Somewhere in each of these bytes there must be an address field. Is this the so called Code Selector? If so, it's just doing:
dw _irq_ptr or something similar?

tnx in advance
Whatever5k

Re:Interrupt handling

Post by Whatever5k »

Wait, don't mess up things - the Code Selector is s.th. completely different, it has to do with the GDT...
Somewhere in each of these bytes there must be an address field
Correct. Unfortunately, you cannot write something like this:

Code: Select all

; interrupt 1
dw my_int1_handler
dw selector
dw 0x8E00
...
Why not? Because the handler to be executed is split into two 16 bit addresses...the first double word stands for offset 15:0, the last double word for offset 31:16. Anyway, that's how you can implement it (and that's how I do it):

Code: Select all

[global idt]
idt:
%rep 256
        dw 0    ; offset 15:0
        dw CS_SELECTOR  ; selector
        db 0
        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
That is the IDT, 256 entries are built, but no handlers are defined yet...

Code: Select all

 mov ecx,(idt_end - idt) >> 3    ; number of descriptors
        mov edi,idt     ; idt location
        mov esi,common_isr      ; common handler to esi

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
This will setup a common ISR handler for all (256) interrupts...of course, you may want to change it...
common_isr is the function to execute...

good luck
2100-OS

Re:Interrupt handling

Post by 2100-OS »

I read the work again, you're right, about the code selector, the rest of the text seems to be complete :) enough to work with, btw handling 256, or at least most of them can be handled at the same spot, except the ones with extra values which need to be set O.T.S

tnx
2100-OS

Re:Interrupt handling

Post by 2100-OS »

OK one more thing:

I assume that I need to initialize this before I call the main kernel function (or I need to call it from the main kernel function), but which of the labels need to be jumped to, or called?
drizzt

Re:Interrupt handling

Post by drizzt »

You must do this basical steps:

1) Switch from real mode into protected mode.
2) Reprogram the PIC 8259
2) Load the GDT
3) Load the IDT
4) Go on with your kernel!

You can do it into your main routine or into an asm routine... the important is that you do it first of all.

When you link your output files you must ensure that this init-file is placed before any other files... ;)
drizzt

Re:Interrupt handling

Post by drizzt »

which of the labels need to be jumped to, or called?
..if you write this routine in an asm file you can call the C-main program simply by declaring it as [EXTERN _main] or [EXTERN main] ...according to your compiler, and call main!
Whatever5k

Re:Interrupt handling

Post by Whatever5k »

but which of the labels need to be jumped to, or called?
I don't know if I understand you correctly, so excuse me if my answer doesn't fit to your question...
Do you want to know how to jump to a C function? If so, drizzt has already told you how...
If you want to know how "make the IDT active", you have to load it...That is done by the instruction "lidt"...
Now let's take the code I posted before as an example...after setting up the descriptors, we would load the IDT like this:

Code: Select all

lidt [idt_ptr]
good luck...
Post Reply