Ok, here is the patch.

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. Support both 32-bit and 64-bit modes.
2. Flexible for compilers to optimize.
3. Easy to use by programmers.

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

'interrupt' attribute

Use this attribute to indicate that the specified function with
mandatory arguments is an interrupt or exception 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 or exception handlers.  All registers, except for the EFLAGS
register which is restored by the 'IRET' instruction, are preserved by
the compiler.

Any interruptible-without-stack-switch code must be compiled with
-mno-red-zone since interrupt handlers can and will, because of the
hardware design, touch the red zone.

1. interrupt handler must be declared with a mandatory pointer argument:

struct interrupt_frame;

__attribute__ ((interrupt))

void
f (struct interrupt_frame *frame)
{
...
}

and user must properly define the structure the pointer pointing to.

2. exception handler:

The exception handler is very similar to the interrupt handler with a
different mandatory function signature:

typedef unsigned long long int uword_t;
typedef unsigned int uword_t;

struct interrupt_frame;

__attribute__ ((interrupt))
void
f (struct interrupt_frame *frame, uword_t error_code)
{
 ...
}

and compiler pops the error code off stack before the 'IRET' instruction.

The exception handler should only be used for exceptions which push an
error code and all other exceptions must use the interrupt handler.

The system will crash if the wrong handler is used.

Bootstrapped/regtested on Linux/x86_64 and Linux/i686.

Ok for trunk?

2015-09-29  Julia Koval <jko...@intel.com>
                  H.J. Lu <hongjiu...@intel.com>

gcc/
                PR target/67630
                PR target/67634
                * config/i386/i386.c (ix86_frame): Add nbndregs and nmaskregs.
                (ix86_nsaved_bndregs): New function.
                (ix86_nsaved_maskregs): Likewise.
                (ix86_reg_save_area_size): Likewise.
                (ix86_nsaved_sseregs): Don't return 0 in interrupt handler.
                (ix86_compute_frame_layout): Set nbndregs and nmaskregs.  Set
                save_regs_using_mov to true to save bound and mask registers.
                Call ix86_reg_save_area_size to get register save area size.
                Allocate space to save full vector registers in
interrupt handler.
                (ix86_emit_save_reg_using_mov): Set alignment to word_mode
                alignment when saving full vector registers in
interrupt handler.
                (ix86_emit_save_regs_using_mov): Use regno_reg_rtx to get
                register size.
                (ix86_emit_restore_regs_using_mov): Likewise.
                (ix86_emit_save_sse_regs_using_mov): Save full vector
registers in
                interrupt handler.
                (ix86_emit_restore_sse_regs_using_mov): Restore full vector
                registers in interrupt handler.
                (ix86_expand_epilogue): Use move to restore bound registers.
                * config/i386/sse.md (*mov<mode>_internal): Handle misaligned
                SSE load and store in interrupt handler.

                PR target/66960
                * config/i386/i386-protos.h (ix86_epilogue_uses) New
function decl.
                * config/i386/i386.c (ix86_epilogue_uses) New function.
                (ix86_set_current_function): Set is_interrupt and is_exception.
                Mark arguments in interrupt handler as used.
                (ix86_function_ok_for_sibcall): Return false if in interrupt
                handler.
                (type_natural_mode): Don't warn ABI change for MMX in interrupt
                handler.
                (ix86_function_arg_advance): Skip for callee in interrupt
                handler.
                (ix86_function_arg): Handle arguments for callee in interrupt
                handler.
                (ix86_can_use_return_insn_p): Don't use `ret' instruction in
                interrupt handler.
                (ix86_save_reg): Preserve callee-saved and
caller-saved registers
                in interrupt handler if needed.
                (ix86_expand_epilogue): Generate interrupt return for
                interrupt handler and pop the 'ERROR_CODE' off the stack before
                interrupt return in exception handler.
                (ix86_expand_move): Disallow 80387 instructions in exception
                handler.
                (ix86_expand_vector_move): Disallow MMX/3Dnow instructions in
                exception handler.
                (ix86_expand_call): Set make_calls.
                (ix86_handle_interrupt_attribute): New function.
                (ix86_attribute_table): Add interrupt attribute.
                * config/i386/i386.h (EPILOGUE_USES) Set hook to
ix86_epilogue_uses.
                (machine_function): Add is_interrupt, is_exception and
                call_with_caller_saved_registers.
                * config/i386/i386.md (UNSPEC_INTERRUPT_RETURN): New.
                (interrupt_return): New pattern.
                * doc/extend.texi: Document x86 interrupt attribute.

gcc/testsuite/

                PR target/66960
                PR target/67630
                PR target/67634
                * gcc.target/i386/interrupt-1.c: New test.
                * gcc.target/i386/interrupt-2.c: Likewise.
                * gcc.target/i386/interrupt-3.c: Likewise.
                * gcc.target/i386/interrupt-4.c: Likewise.
                * gcc.target/i386/interrupt-5.c: Likewise.
                * gcc.target/i386/interrupt-6.c: Likewise.
                * gcc.target/i386/interrupt-7.c: Likewise.
                * gcc.target/i386/interrupt-8.c: Likewise.
                * gcc.target/i386/interrupt-9.c: Likewise.
                * gcc.target/i386/interrupt-10.c: Likewise.
                * gcc.target/i386/interrupt-11.c: Likewise.
                * gcc.target/i386/interrupt-12.c: Likewise.
                * gcc.target/i386/interrupt-13.c: Likewise.
                * gcc.target/i386/interrupt-14.c: Likewise.
                * gcc.target/i386/interrupt-387-err.c: Likewise.
                * gcc.target/i386/interrupt-bnd.c: Likewise.
                * gcc.target/i386/interrupt-iamcu.c: Likewise.
                * gcc.target/i386/interrupt-mmx-err.c: Likewise.
                * gcc.target/i386/interrupt-redzone-1.c: Likewise.
                * gcc.target/i386/interrupt-redzone-2.c: Likewise.
                * gcc.target/i386/interrupt-sibcall.c: Likewise.
                * gcc.target/i386/interrupt-switch-abi.c: Likewise.
                * gcc.target/i386/interrupt-xmm.c: Likewise.
                * gcc.target/i386/interrupt-ymm.c: Likewise.
                * gcc.target/i386/interrupt-zmm.c: Likewise.

Julia

On Thu, Oct 1, 2015 at 3:24 AM, H.J. Lu <hjl.to...@gmail.com> wrote:
> On Wed, Sep 30, 2015 at 12:53 PM, Yulia Koval <vaalfr...@gmail.com> wrote:
>> Done.
>>
>
> +  /* If true, the current function is an interrupt service
> +     routine as specified by the "interrupt" attribute.  */
> +  BOOL_BITFIELD is_interrupt : 1;
> +
> +  /* If true, the current function is an exception service
> +     routine as specified by the "interrupt" attribute.  */
> +  BOOL_BITFIELD is_exception : 1;
>
>
> It is not very clear what is the difference between is_interrupt
> and is_exception.  How about
>
>   /* If true, the current function is an interrupt service routine with
>      a pointer argument and an optional integer argument as specified by
>      the "interrupt" attribute.  */
>   BOOL_BITFIELD is_interrupt : 1;
>
>   /* If true, the current function is an interrupt service routine with
>      a pointer argument and an integer argument as specified by the
>      "interrupt" attribute.  */
>   BOOL_BITFIELD is_exception : 1;
>
> --
> H.J.

Attachment: patch_01.10_interrupt
Description: Binary data

Reply via email to