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

From: H. Peter Anvin
Date: Wed Sep 08 2021 - 01:00:51 EST


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.

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.

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;
}