Page 1 of 1

Using Stack Based interrupts

Posted: Tue Aug 24, 2010 12:03 am
by Primis
I was reading a freeBSD article about using the stack to pass arguments to an interrupt handler, specifically, interrupt 80h. The page can be located at http://www.freebsd.org/doc/en/books/dev ... calls.html

I was wondering if there is a way to use stack based interrupts as opposed to register based ones that many OS tutorials suggest. I first thought that I could just back trace the stack after what was pushed to it, but knowing the correct number of bytes to take off the top would be like throwing darts in the dark.

Any feedback would be nice. (And yes I checked Google, and your forum search filters out the word "interrupt".

Re: Using Stack Based interrupts

Posted: Tue Aug 24, 2010 12:27 am
by gerryg400
I first thought that I could just back trace the stack after what was pushed to it, but knowing the correct number of bytes to take off the top would be like throwing darts in the dark.
That will work. But if you are moving from ring 3 to ring 0 then you need to reach back to the ring 3 stack to get the system call arguments. The arguments are found by getting the ring 3 stack pointer off the ring 0 interrupt stack and adding 4. The result is a pointer to an array containing the arguments.

Code: Select all

   uint32_t *parmlist = ((uint32_t *)curr_thread->esp3) + 1;
The usual caveats about kernel accessing the user address space apply and you need to make sure your fault handlers are smart enough to blame the user if something goes wrong.

Re: Using Stack Based interrupts

Posted: Tue Aug 24, 2010 1:01 am
by Brendan
Hi,
Primis wrote:I was wondering if there is a way to use stack based interrupts as opposed to register based ones that many OS tutorials suggest.
A better idea (at least for 32-bit 80x86) might be to use call gates instead; where the CPU automatically copies "n dwords" from one stack to the next if a privilege level change is involved.

However, despite what the article you linked to says, copying arguments to the stack is usually slower (even when there isn't a privilege change involved). That's why most compilers support some sort of "fastcall" optimisation, and why the "AMD64 ABI" passes most arguments in registers.

I'd assume FreeBSD supports the register based calling convention by pushing the registers onto the stack and then calling functions designed for the stack based calling convention (rather than doing the opposite - e.g. for the stack based calling convention, loading values from the stack into registers and calling functions designed for the register based calling convention); and that this is the reason why the register based calling convention is slower on FreeBSD. I'd also assume that a large part of the problem is that compilers suck (e.g. there isn't a well defined "fastcall" standard that all compilers follow, so it's hard to use a register based calling convention without risking compatibility problems).

The main problem with using registers is that there's no direct way to support a variable number of arguments and no direct way to support more arguments than you have registers. For kernels (especially micro-kernels) both of these problems don't happen often, and (for the rare occasions when it's unavoidable) you just pass a pointer to a structure or something instead.


Cheers,

Brendan