[cfe-dev] RFC: Support x86 interrupt and exception handlers
H.J. Lu via cfe-dev
cfe-dev at lists.llvm.org
Mon Sep 21 15:19:14 PDT 2015
On Mon, Sep 21, 2015 at 2:23 PM, John Criswell <jtcriswel at gmail.com> wrote:
> On 9/21/15 4:45 PM, H.J. Lu wrote:
>>
>> On Mon, Sep 21, 2015 at 11:52 AM, John Criswell <jtcriswel at gmail.com>
>> wrote:
>>>
>>> On 9/21/15 12:27 PM, H.J. Lu via cfe-dev wrote:
>>>>
>>>> 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.
>>>
>>>
>>> Exception handlers can, in general, call regular functions which, in
>>> turn,
>>> might want to access the error code. Given that operating system kernels
>>> are always entered via an interrupt, trap, or system call, there should
>>> always be an error code available (on x86, non-error-code interrupts can
>>> just make up an error code).
>>>
>>>> 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.
>>>>
>>>>
>>> You might want to have a look at Secure Virtual Architecture (SVA). One
>>> of
>>
>> I believe my x86 interrupt attribute is unrelated to SVA.
>
>
> Actually, I really think that it is. Part of the SVA work extended the LLVM
> IR to support an operating system kernel. Your design for interrupt
> handlers and accessing interrupted program state looks very similar to my
> first draft of those extensions and has the exact same limitations (plus at
> least one limitation that my design did not have). It's pretty clear to me
> that you're redesigning a subset of the SVA-OS extensions from scratch; I
> find that unfortunate because you are literally reinventing the wheel.
>
>>
>>> If the implementation is useful, SVA is publicly available at
>>> https://github.com/jtcriswell/SVA.
>>>
>>> Finally, to echo Joerg's concerns, it's not clear that having
>>> exception/interrupt handlers declared as a special type is really
>>> helpful.
>>> It's not immediately obvious that you get a benefit from doing that vs.
>>> doing what most system software does (having assembly code that saves
>>> processor state and calls a C function). I think you should do some
>>> experiments to demonstrate the benefit that one can get with your method
>>> to
>>> see if it is worth adding complexity to the compiler.
>>>
>> The main purpose of x86 interrupt attribute is to allow programmers
>> to write x86 interrupt/exception handlers in C WITHOUT assembly
>> stubs to avoid extra branch from assembly stubs to C functions. I
>> want to keep the number of new intrinsics to minimum without sacrificing
>> handler performance. I leave faking error code in interrupt handler to
>> the programmer.
>>
>
> If you want to do that, there is another approach that should work just as
> well and will require only localized changes to the compiler.
>
> Interrupt handlers are typically registered to some interrupt vector number
> using a registration function. In FreeBSD, it's setidt(), and in Linux, I
> think it's set_gate(). You can write a compiler transform that looks for
> these registration functions, determines the function that is registered as
> an interrupt handler, and generate the more efficient code for that
> interrupt handler function as you describe.
>
> This solution avoids language extensions to the C/C++ front-end (which
> requires getting approval from the Clang developers) yet should get you the
> performance that you want (provided that it does improve performance, for
> which I'm a little skeptical but open to convincing via performance
> measurements). You can probably write this transform as a single LLVM
> MachineFunctionPass that your patched version of Clang runs during code
> generation.
We may discuss different things here. My proposal covers
writing interrupt/exception handlers in C. It doesn't deal with
interrupt/exception handler registration at all.
There are couple issues of writing x86 nterrupt/exception handlers in C:
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.
You need a way to tell compiler about them.
--
H.J.
More information about the cfe-dev
mailing list