On Tue, May 10, 2016 at 4:54 PM, Koval, Julia <julia.ko...@intel.com> wrote:
> 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.

OK for mainline, but please commit patch [1/2] first.

Thanks,
Uros.

Reply via email to