Gentle ping.

-----Original Message-----
From: Koval, Julia 
Sent: Wednesday, April 20, 2016 4:42 PM
To: gcc-patches@gcc.gnu.org
Cc: Lu, Hongjiu <hongjiu...@intel.com>; vaalfr...@gmail.com; ubiz...@gmail.com; 
l...@redhat.com; Zamyatin, Igor <igor.zamya...@intel.com>
Subject: [PATCH] x86 interrupt attribute patch [2/2]

Hi,
Here is the new version of interrupt attribute patch. Bootstraped/regtested for 
Linux/x86_64. Ok for trunk?
    
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.
If the compiler generates MPX, SSE, MMX or x87 instructions in an interrupt or 
exception handler, or functions called from an interrupt or exception handler 
may contain MPX, SSE, MMX or x87 instructions, the compiler must save and 
restore the corresponding state.

Since the direction flag in the FLAGS register in interrupt (exception) 
handlers is undetermined, cld instruction must be emitted in function prologue 
if rep string instructions are used in interrupt (exception) handler or 
interrupt (exception) handler isn't a leaf function.

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 int uword_t __attribute__ ((mode (__word__)));

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.

'no_caller_saved_registers' attribute

Use this attribute to indicate that the specified function has no caller-saved 
registers.  That is, all registers are callee-saved.
The compiler generates proper function entry and exit sequences to save and 
restore any modified registers, except for the EFLAGS register.
If the compiler generates MPX, SSE, MMX or x87 instructions in a function with 
'no_caller_saved_registers' attribute or functions called from a function with 
'no_caller_saved_registers' attribute may contain MPX, SSE, MMX or x87 
instructions, the compiler must save and restore the corresponding state.

The user can call functions specified with 'no_caller_saved_registers'
attribute from an interrupt handler without saving and restoring all call 
clobbered registers.

On x86, interrupt handlers are only called by processors which push interrupt 
data onto stack at the address where the normal return address is.  Interrupt 
handlers must access interrupt data via pointers so that they can update 
interrupt data.
gcc/

        PR target/66960
        PR target/67630
        PR target/67634
        PR target/67841
        PR target/68037
        PR target/68618
        PR target/68661
        PR target/69575
        PR target/69596
        PR target/69734
        * config/i386/i386-protos.h (ix86_epilogue_uses): New prototype.
        * config/i386/i386.c (ix86_conditional_register_usage): Preserve
        all registers, except for function return registers if there are
        no caller-saved registers.
        (ix86_set_func_type): New function.
        (ix86_set_current_function): Call ix86_set_func_type to set
        no_caller_saved_registers and func_type.  Call reinit_regs if
        caller-saved registers are changed.  Don't allow MPX, SSE, MMX
        nor x87 instructions in interrupt handler nor function with
        no_caller_saved_registers attribute.
        (ix86_function_ok_for_sibcall): Return false if there are no
        caller-saved registers.
        (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): Return special arguments in interrupt
        handler.
        (ix86_promote_function_mode): Promote pointer to word_mode only
        for normal functions.
        (ix86_can_use_return_insn_p): Don't use `ret' instruction in
        interrupt handler.
        (ix86_epilogue_uses): New function.
        (ix86_hard_regno_scratch_ok): Likewise.
        (ix86_save_reg): Preserve all registers in interrupt handler
        after reload.  Preserve all registers, except for function
        return registers, if there are no caller-saved registers after
        reload.
        (find_drap_reg): Always use callee-saved register if there are
        no caller-saved registers.
        (ix86_minimum_incoming_stack_boundary): Return MIN_STACK_BOUNDARY
        for interrupt handler.
        (ix86_expand_prologue): Don't allow DRAP in interrupt handler.
        Emit cld instruction if stringops are used in interrupt handler
        or interrupt handler isn't a leaf function.
        (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_call): Disallow calling interrupt handler directly.
        If there are no caller-saved registers, mark all registers that
        are clobbered by the call which returns as clobbered.
        (ix86_handle_no_caller_saved_registers_attribute): New function.
        (ix86_handle_interrupt_attribute): Likewise.
        (ix86_attribute_table): Add interrupt and no_caller_saved_registers
        attributes.
        (TARGET_HARD_REGNO_SCRATCH_OK): Likewise.
        * config/i386/i386.h (ACCUMULATE_OUTGOING_ARGS): Use argument
        accumulation in interrupt function if stack may be realigned to
        avoid DRAP.
        (EPILOGUE_USES): New.
        (function_type): New enum.
        (machine_function): Add func_type and no_caller_saved_registers.
        * config/i386/i386.md (UNSPEC_INTERRUPT_RETURN): New.
        (interrupt_return): New pattern.
        * doc/extend.texi: Document x86 interrupt and
        no_caller_saved_registers attributes.

gcc/testsuite/

        PR target/66960
        PR target/67630
        PR target/67634
        PR target/67841
        PR target/68037
        PR target/68618
        PR target/68661
        PR target/69575
        PR target/69596
        PR target/69734
        * gcc.dg/guality/pr68037-1.c: New test.
        * gcc.dg/guality/pr68037-2.c: Likewise.
        * gcc.dg/guality/pr68037-3.c: Likewise.
        * gcc.dg/torture/pr68037-1.c: Likewise.
        * gcc.dg/torture/pr68037-2.c: Likewise.
        * gcc.dg/torture/pr68037-3.c: Likewise.
        * gcc.dg/torture/pr68661-1a.c: Likewise.
        * gcc.dg/torture/pr68661-1b.c: Likewise.
        * gcc.target/i386/interrupt-1.c: Likewise.
        * 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-15.c: Likewise.
        * gcc.target/i386/interrupt-16.c: Likewise.
        * gcc.target/i386/interrupt-17.c: Likewise.
        * gcc.target/i386/interrupt-18.c: Likewise.
        * gcc.target/i386/interrupt-19.c: Likewise.
        * gcc.target/i386/interrupt-20.c: Likewise.
        * gcc.target/i386/interrupt-21.c: Likewise.
        * gcc.target/i386/interrupt-22.c: Likewise.
        * gcc.target/i386/interrupt-23.c: Likewise.
        * gcc.target/i386/interrupt-24.c: Likewise.
        * gcc.target/i386/interrupt-25.c: Likewise.
        * gcc.target/i386/interrupt-26.c: Likewise.
        * gcc.target/i386/interrupt-27.c: Likewise.
        * gcc.target/i386/interrupt-28.c: Likewise.
        * gcc.target/i386/interrupt-387-err-1.c: Likewise.
        * gcc.target/i386/interrupt-387-err-2.c: Likewise.
        * gcc.target/i386/interrupt-bnd-err-1.c: Likewise.
        * gcc.target/i386/interrupt-bnd-err-2.c: Likewise.
        * gcc.target/i386/interrupt-iamcu.c: Likewise.
        * gcc.target/i386/interrupt-mmx-err-1.c: Likewise.
        * gcc.target/i386/interrupt-mmx-err-2.c: Likewise.
        * gcc.target/i386/interrupt-redzone-1.c: Likewise.
        * gcc.target/i386/interrupt-redzone-2.c: Likewise.
        * gcc.target/i386/interrupt-sibcall-1.c: Likewise.
        * gcc.target/i386/interrupt-sibcall-2.c: Likewise.
        * gcc.target/i386/interrupt-switch-abi.c: Likewise.

Reply via email to