Re: [cfe-dev] RFC: Support x86 interrupt and exception handlers

2015-09-21 Thread John Criswell

On 9/21/15 12:27 PM, H.J. Lu via cfe-dev wrote:

On Thu, Sep 17, 2015 at 12:26 PM, H.J. Lu <hjl.to...@gmail.com> wrote:

On Tue, Sep 15, 2015 at 1:11 PM, H.J. Lu <hjl.to...@gmail.com> wrote:

To implement interrupt and exception handlers for x86 processors, a
compiler should support:

1. void * __builtin_ia32_interrupt_data (void)

I got a feedback on the name of this builtin function.  Since
it also works for 64-bit,  we should avoid ia32 in its name.
We'd like to change it to

void * __builtin_interrupt_data (void)


Here is the updated spec.


This updated spec adds

unsigned int __builtin_exception_error (void)
unsigned long long int __builtin_exception_error (void)

This function returns the exception error code pushed onto the stack by
processor.  Its return value is 64 bits in 64-bit mode and 32 bits in
32-bit mode.  This function can only be used in exception handler.


Exception handlers can, in general, call regular functions which, in 
turn, might want to access the error code.  Given that operating system 
kernels are always entered via an interrupt, trap, or system call, there 
should always be an error code available (on x86, non-error-code 
interrupts can just make up an error code).




It also changes the definition of

void * __builtin_interrupt_data (void)

so that it returns a pointer to the data layout pushed onto stack
by processor for both interrupt and exception handlers.




You might want to have a look at Secure Virtual Architecture (SVA). One 
of the things we discovered is that commodity operating systems access 
the most recently used interrupt data (which SVA calls an "interrupt 
context").  Over the years, we figured out that it's better to provide 
intrinsics (i.e., builtins) that implicitly access the top-most 
interrupt context.  We also found that we could limit the operations 
performed on interrupt contexts so that we could safely implement signal 
handlers and exception recovery without letting the operating system 
kernel have pointers to the interrupt context which would need to be 
checked.  In short, despite common belief, the OS does not need to do 
whatever it wants with interrupted program state.


I recommend you take a look at Appendix A of my dissertation 
(https://www.ideals.illinois.edu/handle/2142/50547).  It describes the 
SVA-OS instructions used to abstract away the hardware details. You'll 
also notice that the design is pretty processor transparent (MMU 
notwithstanding), so designing your builtins based on SVA may make them 
more portable if you decide to use another processor later on.  Chapter 
2 describes some of the rationale behind the design, though it's for the 
first version of SVA (Appendix A is the final instruction set after 4 
papers).


If the implementation is useful, SVA is publicly available at 
https://github.com/jtcriswell/SVA.


Finally, to echo Joerg's concerns, it's not clear that having 
exception/interrupt handlers declared as a special type is really 
helpful.  It's not immediately obvious that you get a benefit from doing 
that vs. doing what most system software does (having assembly code that 
saves processor state and calls a C function).  I think you should do 
some experiments to demonstrate the benefit that one can get with your 
method to see if it is worth adding complexity to the compiler.


Regards,

John Criswell

--
John Criswell
Assistant Professor
Department of Computer Science, University of Rochester
http://www.cs.rochester.edu/u/criswell



Re: [cfe-dev] RFC: Support x86 interrupt and exception handlers

2015-09-21 Thread John Criswell

On 9/21/15 4:45 PM, H.J. Lu wrote:

On Mon, Sep 21, 2015 at 11:52 AM, John Criswell <jtcris...@gmail.com> wrote:

On 9/21/15 12:27 PM, H.J. Lu via cfe-dev wrote:

On Thu, Sep 17, 2015 at 12:26 PM, H.J. Lu <hjl.to...@gmail.com> wrote:

On Tue, Sep 15, 2015 at 1:11 PM, H.J. Lu <hjl.to...@gmail.com> wrote:

To implement interrupt and exception handlers for x86 processors, a
compiler should support:

1. void * __builtin_ia32_interrupt_data (void)

I got a feedback on the name of this builtin function.  Since
it also works for 64-bit,  we should avoid ia32 in its name.
We'd like to change it to

void * __builtin_interrupt_data (void)


Here is the updated spec.


This updated spec adds

 unsigned int __builtin_exception_error (void)
 unsigned long long int __builtin_exception_error (void)

This function returns the exception error code pushed onto the stack by
processor.  Its return value is 64 bits in 64-bit mode and 32 bits in
32-bit mode.  This function can only be used in exception handler.


Exception handlers can, in general, call regular functions which, in turn,
might want to access the error code.  Given that operating system kernels
are always entered via an interrupt, trap, or system call, there should
always be an error code available (on x86, non-error-code interrupts can
just make up an error code).


It also changes the definition of

void * __builtin_interrupt_data (void)

so that it returns a pointer to the data layout pushed onto stack
by processor for both interrupt and exception handlers.



You might want to have a look at Secure Virtual Architecture (SVA). One of

I believe my x86 interrupt attribute is unrelated to SVA.


Actually, I really think that it is.  Part of the SVA work extended the 
LLVM IR to support an operating system kernel.  Your design for 
interrupt handlers and accessing interrupted program state looks very 
similar to my first draft of those extensions and has the exact same 
limitations (plus at least one limitation that my design did not have).  
It's pretty clear to me that you're redesigning a subset of the SVA-OS 
extensions from scratch; I find that unfortunate because you are 
literally reinventing the wheel.





If the implementation is useful, SVA is publicly available at
https://github.com/jtcriswell/SVA.

Finally, to echo Joerg's concerns, it's not clear that having
exception/interrupt handlers declared as a special type is really helpful.
It's not immediately obvious that you get a benefit from doing that vs.
doing what most system software does (having assembly code that saves
processor state and calls a C function).  I think you should do some
experiments to demonstrate the benefit that one can get with your method to
see if it is worth adding complexity to the compiler.


The main purpose of x86 interrupt attribute is to allow programmers
to write x86 interrupt/exception handlers in C WITHOUT assembly
stubs to avoid extra branch from assembly stubs to C functions.  I
want to keep the number of new intrinsics to minimum without sacrificing
handler performance. I leave faking error code in interrupt handler to
the programmer.



If you want to do that, there is another approach that should work just 
as well and will require only localized changes to the compiler.


Interrupt handlers are typically registered to some interrupt vector 
number using a registration function.  In FreeBSD, it's setidt(), and in 
Linux, I think it's set_gate().  You can write a compiler transform that 
looks for these registration functions, determines the function that is 
registered as an interrupt handler, and generate the more efficient code 
for that interrupt handler function as you describe.


This solution avoids language extensions to the C/C++ front-end (which 
requires getting approval from the Clang developers) yet should get you 
the performance that you want (provided that it does improve 
performance, for which I'm a little skeptical but open to convincing via 
performance measurements).  You can probably write this transform as a 
single LLVM MachineFunctionPass that your patched version of Clang runs 
during code generation.


In any event, that's my two cents.

Regards,

John Criswell

--
John Criswell
Assistant Professor
Department of Computer Science, University of Rochester
http://www.cs.rochester.edu/u/criswell