Messages in this thread Patch in this message | | | From | Lai Jiangshan <> | Subject | [PATCH V2 23/41] x86/entry: Add the C version ist_switch_to_kernel_gsbase() | Date | Sun, 26 Sep 2021 23:08:20 +0800 |
| |
From: Lai Jiangshan <laijs@linux.alibaba.com>
It implements the second half of paranoid_entry() whose functionality is to switch to kernel gsbase.
Not functional difference intended.
Signed-off-by: Lai Jiangshan <laijs@linux.alibaba.com> --- arch/x86/entry/entry64.c | 44 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
diff --git a/arch/x86/entry/entry64.c b/arch/x86/entry/entry64.c index b939b56d985d..1a0d5d703ad6 100644 --- a/arch/x86/entry/entry64.c +++ b/arch/x86/entry/entry64.c @@ -229,3 +229,47 @@ static __always_inline unsigned long get_percpu_base(void) return pcpu_unit_offsets; } #endif + +/* + * Handle GSBASE depends on the availability of FSGSBASE. + * + * Without FSGSBASE the kernel enforces that negative GSBASE + * values indicate kernel GSBASE. With FSGSBASE no assumptions + * can be made about the GSBASE value when entering from user + * space. + */ +static __always_inline unsigned long ist_switch_to_kernel_gsbase(void) +{ + unsigned long gsbase; + + if (static_cpu_has(X86_FEATURE_FSGSBASE)) { + /* + * Read the current GSBASE for return. + * Retrieve and set the current CPUs kernel GSBASE. + * + * The unconditional write to GS base below ensures that + * no subsequent loads based on a mispredicted GS base can + * happen, therefore no LFENCE is needed here. + */ + gsbase = rdgsbase(); + wrgsbase(get_percpu_base()); + return gsbase; + } + + gsbase = __rdmsr(MSR_GS_BASE); + + /* + * The kernel-enforced convention is a negative GSBASE indicates + * a kernel value. No SWAPGS needed on entry and exit. + */ + if ((long)gsbase < 0) { + kernel_entry_fence_no_swapgs(); + /* no SWAPGS required on exit */ + return 1; + } + + user_entry_swapgs_and_fence(); + + /* SWAPGS required on exit */ + return 0; +} -- 2.19.1.6.gb485710b
| |