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

Hal Finkel via cfe-dev cfe-dev at lists.llvm.org
Mon Sep 21 15:40:58 PDT 2015


----- Original Message -----
> From: "H.J. Lu via cfe-dev" <cfe-dev at lists.llvm.org>
> To: "GCC Development" <gcc at gcc.gnu.org>, cfe-dev at lists.llvm.org
> Sent: Monday, September 21, 2015 11:27:18 AM
> Subject: Re: [cfe-dev] RFC: Support x86 interrupt and exception handlers
> 
> On Thu, Sep 17, 2015 at 12:26 PM, H.J. Lu <hjl.tools at gmail.com>
> wrote:
> > On Tue, Sep 15, 2015 at 1:11 PM, H.J. Lu <hjl.tools at 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.
> 
> 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.
> 
> 
> --
> H.J.
> ---
> The interrupt and exception handlers are called by x86 processors.
>  X86
> hardware pushes information onto stack and calls the handler.  The
> requirements are
> 
> 1. Both interrupt and exception handlers must use the 'IRET'
> instruction,
> instead of the 'RET' instruction, to return from the handlers.
> 2. All registers are callee-saved in interrupt and exception
> handlers.
> 3. The difference between interrupt and exception handlers is the
> exception handler must pop 'ERROR_CODE' off the stack before the
> 'IRET'
> instruction.
> 
> The design goals of interrupt and exception handlers for x86
> processors
> are:
> 
> 1. No new calling convention in compiler.
> 2. Support both 32-bit and 64-bit modes.
> 3. Flexible for compilers to optimize.
> 4. Easy to use by programmers.
> 
> To implement interrupt and exception handlers for x86 processors, a
> compiler should support:
> 
> 1. void * __builtin_interrupt_data (void)
> 
> This function returns a pointer to the return address pushed onto the
> stack by processor.
> 
> The __builtin_frame_address builtin isn't suitable for interrupt and
> exception handlers since it returns the stack frame address on the
> callee side and compiler may generate a new stack frame for stack
> alignment.
> 
> 2. 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.

Instead of adding more builtins for these, why not simply model this by giving the handler function a non-trivial signature? So, for example, the interrupt handler would be:

 void handler(void *);

and the exception handler would be:

  void handler(size_t);

 -Hal

> 
> 3. 'interrupt' attribute
> 
> Use this attribute to indicate that the specified void function
> without
> arguments is an interrupt handler.  The compiler generates function
> entry
> and exit sequences suitable for use in an interrupt handler when this
> attribute is present.  The 'IRET' instruction, instead of the
> 'RET' instruction, is used to return from interrupt handlers.  All
> registers, except for the EFLAGS register which is restored by the
> 'IRET' instruction, are preserved by the compiler.  The red zone
> isn't supported in the interrupted function; that is an interrupt
> handler may access stack within 128 bytes of the current stack
> pointer.
> 
> You can use the builtin '__builtin_interrupt_data' function to access
> the interrupt data pushed onto the stack by processor:
> 
> void
> f () __attribute__ ((interrupt))
> {
>   void *p = __builtin_interrupt_data ();
>   ...
> }
> 
> 4. 'exception' attribute
> 
> Use 'exception' instead of 'interrupt' for handlers intended to be
> used for 'exception' (i.e. those that must pop 'ERROR_CODE' off the
> stack before the 'IRET' instruction).
> 
> You can use the builtin '__builtin_exception_error' function to
> access the exception error code pushed onto the stack by processor
> as well as the builtin '__builtin_interrupt_data' function to
> access the exception data on stack:
> 
> void
> f () __attribute__ ((exception))
> {
>   unsigned int error = __builtin_exception_error ();
>   void *p = __builtin_interrupt_data ();
>   ...
> }
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
> 

-- 
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory



More information about the cfe-dev mailing list