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.