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".
Using Stack Based interrupts
Re: Using Stack Based interrupts
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.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.
Code: Select all
uint32_t *parmlist = ((uint32_t *)curr_thread->esp3) + 1;
If a trainstation is where trains stop, what is a workstation ?
Re: Using Stack Based interrupts
Hi,
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
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.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.
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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.