Re: [PATCH 25/24] x86/traps: Rewrite native_load_gs_index in C code

From: Lai Jiangshan
Date: Wed Sep 08 2021 - 03:12:21 EST




On 2021/9/8 13:00, H. Peter Anvin wrote:
On 9/7/21 9:42 PM, H. Peter Anvin wrote:


On 9/7/21 6:38 PM, H. Peter Anvin wrote:
On 9/2/21 3:50 AM, Lai Jiangshan wrote:
From: Lai Jiangshan <laijs@xxxxxxxxxxxxxxxxx>

There is no constrain/limition to force native_load_gs_index() to be in
ASM code.

Hi,

First of all, let me say I really like your patchset, and I will try to
review it in detail ASAP (most of the initial read pass looks very sane
to me.

Hello

Thank you for your review.


However, I would like to object in part this specific patch. It adds a
fair bit of extra code to the exception path, and adds jumps between
files which makes the code much harder to read.

I tried putting all code into a single C function.
But I didn't know how to use a C-label in _ASM_EXTABLE and then I split it.

Your code is much better.

Thanks
Lai



You end up doing one swapgs in assembly and one in C, which would seem
to be a very good indication that really isn't an improvement.

Note that this entire sequence is scheduled to be obsoleted by a single
atomic hardware instruction, LKGS, which will replace ALL of
native_load_gs_index(); it will no longer be necessary even to disable
interrupts as there is no non-atomic state. In that sense, doing this as
an out-of-line C function (with some inline assembly) is great, because
it makes it far easier to use LKGS as an alternative; the only (small)
disadvantage is that it ends up clobbering a lot of registers
unnecessarily (in assembly it can be implemented clobbering only two
registers; one if one uses pushf/popf to save the interrupt flag.)


OK, here is a version which actually compiles:


... slightly shorter and minimally better compiled code ...

noinstr void native_load_gs_index(unsigned int selector)
{
    unsigned long flags;

    local_irq_save(flags);
    native_swapgs();
do_mov_gs:
    asm_volatile_goto("1: mov %[seg],%%gs\n"
              "2:\n"
              _ASM_EXTABLE(1b,%l[bad_seg])
              : : [seg] "r" (selector) : : bad_seg);
    alternative("", "mfence", X86_BUG_SWAPGS_FENCE);
    native_swapgs();
    local_irq_restore(flags);
    return;

bad_seg:
    /* The exception dispatch will have restored kernel GS */
    native_swapgs();
    alternative_input("", "mov %[seg],%%gs",
              X86_BUG_NULL_SEG, [seg] "r" (__USER_DS));
    selector = 0;
    goto do_mov_gs;
}