Extern "C" and inline assembly - A solution for ISRs on 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
lordio
Posts: 7
Joined: Tue Jan 22, 2013 6:37 pm

Extern "C" and inline assembly - A solution for ISRs on GCC?

Post by lordio »

I noticed the wiki explains that GCC doesn't have a way to make "naked" functions (without the normal function bounding instructions, enter, leave, and ret) for ISRs on x86. I wonder if I've discovered something novel in that case, though I hardly expect so.

Declare an extern "C" method,

Code: Select all

extern "C" void interrupt_handler();
then, in an assembly block,

Code: Select all

asm("interrupt_handler:\n
  call actual_handler\n
  iret");
Obviously, the method actual_handler will also have to be declared extern "C", and defined elsewhere in the kernel. One could further parameterize actual_handler according to their ABI.

Is this what people already use, and I just thought I devised it myself? Do people normally split the implementation into its own assembly source file? That would make sense for a more realistic ISR, probably -- one that takes note of its environment before calling into the kernel.
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Extern "C" and inline assembly - A solution for ISRs on

Post by bluemoon »

1. you did not preserve registers.
2. You gain nothing on the resulting binary, by putting the assembly stub within inline assembly.
3. You need to deal with non-trivial problems like optimization and non standard behaviours: you hijack a function to create another function, both the hosting function and inline asm block may get optimized away, or otherwise get hidden visibility

In short, you should just put the assembly stub in an assembly file.
lordio
Posts: 7
Joined: Tue Jan 22, 2013 6:37 pm

Re: Extern "C" and inline assembly - A solution for ISRs on

Post by lordio »

bluemoon wrote:1. you did not preserve registers.
Looking at my copy of the System V ABI (to which GCC adheres), and for AMD64, this would be all the GPRs other than rbp, rbx, and r12-r15?
bluemoon wrote:2. You gain nothing on the resulting binary, by putting the assembly stub within inline assembly.
Expected. It was kind of born of laziness anyway, with the admittedly flimsy excuse of source locality, rather than any machine-code benefit.
bluemoon wrote:3. You need to deal with non-trivial problems like optimization and non standard behaviours: you hijack a function to create another function, both the hosting function and inline asm block may get optimized away, or otherwise get hidden visibility
Even if a pointer to the function is used, in the kernel, as part of IDT initialization? I guess since GCC will probably notice it's not used directly in the source, that makes sense.

Also, for better or worse, and probably in a lot of places where it's not needed, I've been marking inline assembly blocks as volatile. From my reading of GCC's manual, it could still remove the block as unreachable, so I guess this is revealed as the hacky solution that it is.
bluemoon wrote:In short, you should just put the assembly stub in an assembly file.
Looks that way. Thanks for weighing in.
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Extern "C" and inline assembly - A solution for ISRs on

Post by bluemoon »

lordio wrote:
bluemoon wrote:1. you did not preserve registers.
Looking at my copy of the System V ABI (to which GCC adheres), and for AMD64, this would be all the GPRs other than rbp, rbx, and r12-r15?
You could define you own ABI for kernel call and decide what should be preserved, and who (kernel or user-space stub) preserve them.
But the general idea is that you should preserve everything for interrupts, but you could do less with syscall.
lordio wrote:Also, for better or worse, and probably in a lot of places where it's not needed, I've been marking inline assembly blocks as volatile.
Do not abuse the volatile keyword.
You should also read this.
lordio
Posts: 7
Joined: Tue Jan 22, 2013 6:37 pm

Re: Extern "C" and inline assembly - A solution for ISRs on

Post by lordio »

bluemoon wrote:You could define you own ABI for kernel call and decide what should be preserved, and who (kernel or user-space stub) preserve them.
But the general idea is that you should preserve everything for interrupts, but you could do less with syscall.
Well, I plan to only support syscall/sysret for direct kernel calls (no "int 80h" like Linux still supports), and I understand and accept that I'll have to define my ABI there. I referred to the System V spec only as far as parameter passing for methods, which is significant for the C++ portions of my kernel.
bluemoon wrote:Do not abuse the volatile keyword.
You should also read this.
Yikes. I can see what he was trying to do, but still. Duly noted.
Post Reply