interrupt handler & gcc

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
hartyl

interrupt handler & gcc

Post by hartyl »

hi there!

i've now coded my first-state-os to gcc & fasm, but i encounter problems when i want to write the service routines. is it possible to tell gcc that it sould preserve all used registers and use "iret" instead of "ret" at the end?
i tried the __attribute__-thingy, but i get a warning that the interrupt-attribute was ignored...

greets, hartyl
mikeleany

RE:interrupt handler & gcc

Post by mikeleany »

The gcc info says about the interrupt function attribute , "Use this attribute on the ARM, AVR, M32R/D and Xstormy16 ports . . .". It doesn't mention x86 (which I assume you're using), so it probably isn't for the x86. If you want to use C/C++ functions for your interrupts, you'll probably have to write a little function stub in assembly that pushes all registers, calls the C routine, pops all registers and does an iret. Either that, or you'll have to use a compiler that supports x86 interrupts directly. I recommend the first idea. But I would actually recommend writing the simplest interrupt routines completely in assembly.
jcmatias

RE:interrupt handler & gcc

Post by jcmatias »

My  gcc isr  looks like:

#define CLI asm("cli")
#define IRET("leave\n iret")
#define STI asm("sti")

         void Isr0x(void)
              {
                CLI
                do_something();
                STI
                IRET
              }
and works fine.
Note the leave and no parameters to isr
I set the isr in IDT  just passing the pointer to  ISR to my SetInterruption rountine
hartyl

RE:interrupt handler & gcc

Post by hartyl »

yeah, that the thing i'm somehow afraid of.
when you do it like that you somehow have to care about the stack-frame gcc generates. i think i'll do it like you, jcmatias, but i know that the thing will look like this then

isr0x00:
  push ebp
  mov ebp,esp
  sub esp,<someval>
  cli
  ;here's my code
  sti
  leave
  iret
  pop ebp ;gcc still generates the clean-up
  ret     ;-code after your code

it's also interesting: when you change the optimisation-level it will sometimes not use a stack-frame, and that your ISR-leave-and-iret-thing won't work anymore...
proxy

RE:interrupt handler & gcc

Post by proxy »

you're absolute light hartyl.  With typical settings, that's the result.  With -O2 and -fomit-frame-pointer it seems to consistantly move the stack setup to directly before usage.  (-O3 it inlines too much to be usable with inline asm).

anyway, the way i apprached this is like this:

void isr00(void) {
    __asm__ __volatile__ ("cli");
    // do stuff
    __asm__ __volatile__ ("sti");
    __asm__ __volatile__ ("iret");
}

now what this tends to do is create code _just before_ the "do stuff" and put the cleanup just after the "iret" emitted.  So i look at the kernel.lst file my mkaefile generates (usually just an "add %esp, $0x08" or somthing) and put the inline code for that directly _after_ the do stuff.  It is definitely workable, but it will be very compiler _and_ setting specific.

The reason why you want the restor code exactly after the do stuff and the setup directly before, is so yo ucan use push and pop operations elsewhere in the routine (such as saving segment values) without trashing things.

Keep in mind, that for this to work, you must use very specific optimization settings...

Also note, that i am planning on redoing my ISRs in ASM because this is too annoying for me ;)

proxy
User avatar
df
Member
Member
Posts: 1076
Joined: Fri Oct 22, 2004 11:00 pm
Contact:

RE:interrupt handler & gcc

Post by df »

what you really want, is an ASM stub


isr00:
stub setup

call d[_isr_00_jump]

stub cleanup
iret

repeat for all isrss etc.

and in you C code you can then set isr to anything (just put the address of the function into the _isr_00_jump array

setisr(void *isrroutine, int isr)
{
    my_isr_jump_table[isr] = isrroutine;
}

semi psuedo c/asm code ;)

its pretty rough, but you get the idea on how to use it.

I'm also _EXTREMLY_ against trying to do the isr in C with inline asm. its a lot easier + cleaner to do it in an asm stub, and correctly setup an isr, sane segment registers/stack whatever.
-- Stu --
hartyl

RE:interrupt handler & gcc

Post by hartyl »

ya, i now found out the problems. when enabling the optimisation, the ISR don't work anymore since the stack gets screwed up.
i somehow don't like using assembler-code for the isr which calls my c-routine. it blows up the code. however, its the universal version which works with every compiler-switches.
jcmatias

RE:interrupt handler & gcc

Post by jcmatias »

.
.
.
pop ebp ; gcc still generates the clean-up
ret     ; -code after your code

never will be executed. This is after IRET. The stack is cleaned by LEAVE
( I omit, but isr don't have any local data (if you need declare vars use "static" types ).
Post Reply