flat assembler
Message board for the users of flat assembler.

Index > OS Construction > The interrupts question

Author
Thread Post new topic Reply to topic
Artlav



Joined: 23 Dec 2004
Posts: 188
Location: Moscow, Russia
Artlav 15 Feb 2007, 16:24
In short: How interrupt handler can find out which interrupt called it?

There is an OS, working in PM, all IDT entryes is occupied and points to 4 interrupt handlers (IRQprime, IRQsecond, exception with error code, exception without error code) in form of TSS gates.

Normally, to determine interrupt number either 256 separate int handlers are needed, each forwarding it's number to the main handler, or mapping all of them to abovementioned types of dummyes, and remap the needed ones only.

First approach requires some big amount of memory(~30Kb, mostly due to TSS's), second approach requires altering gdt, which breaks the simplicity of design.

So, is there any other ways to determine interrupt number?
Probing interrupt controller, MSR's, something undocumented?
Post 15 Feb 2007, 16:24
View user's profile Send private message Visit poster's website Reply with quote
tantrikwizard



Joined: 13 Dec 2006
Posts: 142
tantrikwizard 16 Feb 2007, 00:08
Artlav wrote:
In short: How interrupt handler can find out which interrupt called it?


This is the same as real mode (sort of). Each interrupt has a seperate entry in the IDT starting at 0 to 255. The IDT entry contains the entry to the handler routine. Create a seperate handler routine for each interrupt and you will know which interrupt occured. It doesnt take so much memory, a few dozen bytes per entry at most. Also, all interrupts do not need to be serviced, processor exceptions are the only requirement (i think). You can always mask off hardware IRQs and not service them. Actually, youre not forced to service processor exceptions, but the system will not be very useful without at least process exceptions and IRQ handling. For a fully functional system, you will want a seperate handler to handle each specific interrupt anyway, so is best to create specific functions to handle each interrupt and set the entry points in the IDT.
Post 16 Feb 2007, 00:08
View user's profile Send private message Visit poster's website Yahoo Messenger MSN Messenger Reply with quote
Artlav



Joined: 23 Dec 2004
Posts: 188
Location: Moscow, Russia
Artlav 18 Feb 2007, 18:33
The question is not how to implement it, but how to implement it the most compact way. That is, is there a way to explicitly identify the just-occured software interrupt?

For IRQ's you can get the number of currently processed interrupt by sending 00001011b to 20h/0A0h port (interrupt controller) then reading same port. Is there any similar thing for software interrupts?



104 bytes per TSS, 8 bytes GDT, 8 bytes IDT, and 20 bytes of code for each interrupt, or 140 bytes. Times 256 that's 35Kb. Brute-force way.
Or 32 exceptions + 16 IRQ's + service interrupt + dummy for the rest = 4640 bytes.
Post 18 Feb 2007, 18:33
View user's profile Send private message Visit poster's website Reply with quote
tantrikwizard



Joined: 13 Dec 2006
Posts: 142
tantrikwizard 18 Feb 2007, 20:43
Artlav wrote:
The question is not how to implement it, but how to implement it the most compact way. That is, is there a way to explicitly identify the just-occured software interrupt?

For IRQ's you can get the number of currently processed interrupt by sending 00001011b to 20h/0A0h port (interrupt controller) then reading same port. Is there any similar thing for software interrupts?



104 bytes per TSS, 8 bytes GDT, 8 bytes IDT, and 20 bytes of code for each interrupt, or 140 bytes. Times 256 that's 35Kb. Brute-force way.
Or 32 exceptions + 16 IRQ's + service interrupt + dummy for the rest = 4640 bytes.


I'm not sure if the processor informs and ISR that the ISR was invoked. One way is to get the return address from the stack and disassemble the instruction.

You cannot escape the need for GDT and IDT entires for your ISR, TSS is optional depending on implementation, so the amount of memory will be the same in these structures regardless of the ISR implementation. The memory requirements for ISRs depend on the ISR implementation. There's a lot of minimal ISR examples running around. try http://osdever.net/bkerndev/index.php for a pretty good minimal implementation.
Code:
; Service Routines (ISRs) right here!
global _isr0
global _isr1
global _isr2
...                ; Fill in the rest here!
global _isr30
global _isr31

;  0: Divide By Zero Exception
_isr0:
    cli
    push byte 0    ; A normal ISR stub that pops a dummy error code to keep a
                   ; uniform stack frame
    push byte 0
    jmp isr_common_stub

;  1: Debug Exception
_isr1:
    cli
    push byte 0
    push byte 1
    jmp isr_common_stub
    
...                ; Fill in from 2 to 7 here!

;  8: Double Fault Exception (With Error Code!)
_isr8:
    cli
    push byte 8        ; Note that we DON'T push a value on the stack in this one!
                   ; It pushes one already! Use this type of stub for exceptions
                   ; that pop error codes!
    jmp isr_common_stub

...                ; You should fill in from _isr9 to _isr31 here. Remember to
                   ; use the correct stubs to handle error codes and push dummies!

; We call a C function in here. We need to let the assembler know
; that '_fault_handler' exists in another file
extern _fault_handler

; This is our common ISR stub. It saves the processor state, sets
; up for kernel mode segments, calls the C-level fault handler,
; and finally restores the stack frame.
isr_common_stub:
    pusha
    push ds
    push es
    push fs
    push gs
    mov ax, 0x10   ; Load the Kernel Data Segment descriptor!
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov eax, esp   ; Push us the stack
    push eax
    mov eax, _fault_handler
    call eax       ; A special call, preserves the 'eip' register
    pop eax
    pop gs
    pop fs
    pop es
    pop ds
    popa
    add esp, 8     ; Cleans up the pushed error code and pushed ISR number
    iret           ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP!
    

thats about 25 bytes per interrupt, not a memory hog.
Post 18 Feb 2007, 20:43
View user's profile Send private message Visit poster's website Yahoo Messenger MSN Messenger Reply with quote
Artlav



Joined: 23 Dec 2004
Posts: 188
Location: Moscow, Russia
Artlav 18 Feb 2007, 22:35
tantrikwizard wrote:

One way is to get the return address from the stack and disassemble the instruction.


That's a good idea. That makes IRQ's and software interrupts covered.
Now, what about exceptions?
Exception can happen in any part of the code, not only int instruction.
Half of them can be covered by checking for error code in the stack (by setting stack empty in the TSS before), still it can't name them.

Checking the whole system context may be a solution, but exception interrupt overhead will be too big...
Post 18 Feb 2007, 22:35
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.