Received: by 2002:ac0:8c9a:0:0:0:0:0 with SMTP id r26csp909965ima; Fri, 1 Feb 2019 12:58:50 -0800 (PST) X-Google-Smtp-Source: ALg8bN6l++6NVdBmHhahhLvvJq9dDh/JwdiWU2MbiZu68Fj2cv0COZbcUUEl4fbw7zLztQXGMaZa X-Received: by 2002:a62:26c7:: with SMTP id m190mr41677188pfm.79.1549054730175; Fri, 01 Feb 2019 12:58:50 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549054730; cv=none; d=google.com; s=arc-20160816; b=Fpku1/T8kvxpXq7ebQ0haLjmxchErQoC+4p/3eoNhgtDMSKd19wTzh4nymIWvXLosw acTJOIiaXSlNUMMwYzJhGx1KS8G+apIc7tW8om5vkr2Kk+kVrlBVqZ+ucOu8Ew+E+t5n wO+N7HgIwUQ+XIoo4GePJvSnztM3OESz/NfGWdyWdmdCxDUw7sghKZ+c1JmuMSoi1VXH 3LsFoABsZbx+Ge2jFOSIym3p19VSnTJgEWELAa9cqMGDvBopzGJi8knBZ2k+FecZDynY QCR1oK1v8O6/cLZpFAmBGalL4S0wMUnlEIuFhlJM1RyKNnQxRcnHQ8W5WjJDYqnxvuA6 bwoA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=silHIn3FI84w7WhdKzcjVj0+/jCfdv7eFVVQf3X7Bo0=; b=H7O1xRGAY6G9XsAtdLBDuiW0RSB7VIpFjpEVEezaeAr3kFG3fwHeOAtzvINJXEyHf3 fgiZqaft/BkEXqLVcDBq714PFFftHC42nT6R7qrlEaXL2aCG4OFPrwz0CvSYcUycOCVR C/MAQFXrFrl56YeynrT3om60ZyFWeHFhCVu1c6bI99+NKNRkhauvHje77Pi3kBDLuxk5 nK+oCu37ImMbTlntlhxD65AX9G+wEmoXHkWWsAzxgFabL74f0L+F3TjWO4HkePYqD2hp usOOC0KbD2UXB68f4EsaUyP8cAVskVCavVzu123PaQQ6aEaeHFkJ9UaTfu2IilVmOMo6 C+KQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b5si8219071pfg.121.2019.02.01.12.58.35; Fri, 01 Feb 2019 12:58:50 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730039AbfBAUy6 (ORCPT + 99 others); Fri, 1 Feb 2019 15:54:58 -0500 Received: from mga07.intel.com ([134.134.136.100]:49739 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729678AbfBAUy4 (ORCPT ); Fri, 1 Feb 2019 15:54:56 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 01 Feb 2019 12:54:55 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,549,1539673200"; d="scan'208";a="140866359" Received: from chang-linux-2.sc.intel.com ([10.3.52.165]) by fmsmga004.fm.intel.com with ESMTP; 01 Feb 2019 12:54:55 -0800 From: "Chang S. Bae" To: Andy Lutomirski , Thomas Gleixner , Ingo Molnar , "H . Peter Anvin" , Andi Kleen Cc: Markus T Metzger , Ravi Shankar , "Chang S . Bae" , LKML , Andrew Cooper Subject: [PATCH v5 05/13] x86/fsgsbase/64: Enable FSGSBASE instructions in the helper functions Date: Fri, 1 Feb 2019 12:53:11 -0800 Message-Id: <20190201205319.15995-7-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190201205319.15995-1-chang.seok.bae@intel.com> References: <20190201205319.15995-1-chang.seok.bae@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The helper functions will switch on faster accesses to FSBASE and GSBASE when the FSGSBASE feature is enabled. Accessing user GSBASE needs a couple of SWAPGS operations. It is avoidable if the user GSBASE is saved at kernel entry, being updated as changes, and restored back at kernel exit. However, it seems to spend more cycles for savings and restorations. Little or no benefit was measured from experiments. Also, introduce __{rd,wr}gsbase_inactive() as helpers to access user GSBASE with SWAPGS. Note, for Xen PV, paravirt hooks can be added, since it may allow a very efficient but different implementation. [ Use NOKPROBE_SYMBOL instead of __kprobes ] Signed-off-by: Chang S. Bae Cc: Any Lutomirski Cc: H. Peter Anvin Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Andrew Cooper --- arch/x86/include/asm/fsgsbase.h | 27 +++++++------- arch/x86/kernel/process_64.c | 62 +++++++++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 17 deletions(-) diff --git a/arch/x86/include/asm/fsgsbase.h b/arch/x86/include/asm/fsgsbase.h index fdd1177499b4..aefd53767a5d 100644 --- a/arch/x86/include/asm/fsgsbase.h +++ b/arch/x86/include/asm/fsgsbase.h @@ -49,35 +49,32 @@ static __always_inline void wrgsbase(unsigned long gsbase) asm volatile("wrgsbase %0" :: "r" (gsbase) : "memory"); } +#include + /* Helper functions for reading/writing FS/GS base */ static inline unsigned long x86_fsbase_read_cpu(void) { unsigned long fsbase; - rdmsrl(MSR_FS_BASE, fsbase); + if (static_cpu_has(X86_FEATURE_FSGSBASE)) + fsbase = rdfsbase(); + else + rdmsrl(MSR_FS_BASE, fsbase); return fsbase; } -static inline unsigned long x86_gsbase_read_cpu_inactive(void) -{ - unsigned long gsbase; - - rdmsrl(MSR_KERNEL_GS_BASE, gsbase); - - return gsbase; -} - static inline void x86_fsbase_write_cpu(unsigned long fsbase) { - wrmsrl(MSR_FS_BASE, fsbase); + if (static_cpu_has(X86_FEATURE_FSGSBASE)) + wrfsbase(fsbase); + else + wrmsrl(MSR_FS_BASE, fsbase); } -static inline void x86_gsbase_write_cpu_inactive(unsigned long gsbase) -{ - wrmsrl(MSR_KERNEL_GS_BASE, gsbase); -} +extern unsigned long x86_gsbase_read_cpu_inactive(void); +extern void x86_gsbase_write_cpu_inactive(unsigned long gsbase); #endif /* CONFIG_X86_64 */ diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 6a62f4af9fcf..ebc55ed31fe7 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -160,6 +160,42 @@ enum which_selector { GS }; +/* + * Interrupts are disabled here. Out of line to be protected + * from kprobes. It is not used on Xen paravirt. When paravirt + * support is needed, it needs to be renamed with native_ prefix. + */ +static noinline unsigned long __rdgsbase_inactive(void) +{ + unsigned long gsbase, flags; + + local_irq_save(flags); + native_swapgs(); + gsbase = rdgsbase(); + native_swapgs(); + local_irq_restore(flags); + + return gsbase; +} +NOKPROBE_SYMBOL(__rdgsbase_inactive); + +/* + * Interrupts are disabled here. Out of line to be protected + * from kprobes. It is not used on Xen paravirt. When paravirt + * support is needed, it needs to be renamed with native_ prefix. + */ +static noinline void __wrgsbase_inactive(unsigned long gsbase) +{ + unsigned long flags; + + local_irq_save(flags); + native_swapgs(); + wrgsbase(gsbase); + native_swapgs(); + local_irq_restore(flags); +} +NOKPROBE_SYMBOL(__wrgsbase_inactive); + /* * Saves the FS or GS base for an outgoing thread if FSGSBASE extensions are * not available. The goal is to be reasonably fast on non-FSGSBASE systems. @@ -338,13 +374,34 @@ static unsigned long x86_fsgsbase_read_task(struct task_struct *task, return base; } +unsigned long x86_gsbase_read_cpu_inactive(void) +{ + unsigned long gsbase; + + if (static_cpu_has(X86_FEATURE_FSGSBASE)) + gsbase = __rdgsbase_inactive(); + else + rdmsrl(MSR_KERNEL_GS_BASE, gsbase); + + return gsbase; +} + +void x86_gsbase_write_cpu_inactive(unsigned long gsbase) +{ + if (static_cpu_has(X86_FEATURE_FSGSBASE)) + __wrgsbase_inactive(gsbase); + else + wrmsrl(MSR_KERNEL_GS_BASE, gsbase); +} + unsigned long x86_fsbase_read_task(struct task_struct *task) { unsigned long fsbase; if (task == current) fsbase = x86_fsbase_read_cpu(); - else if (task->thread.fsindex == 0) + else if (static_cpu_has(X86_FEATURE_FSGSBASE) || + (task->thread.fsindex == 0)) fsbase = task->thread.fsbase; else fsbase = x86_fsgsbase_read_task(task, task->thread.fsindex); @@ -358,7 +415,8 @@ unsigned long x86_gsbase_read_task(struct task_struct *task) if (task == current) gsbase = x86_gsbase_read_cpu_inactive(); - else if (task->thread.gsindex == 0) + else if (static_cpu_has(X86_FEATURE_FSGSBASE) || + (task->thread.gsindex == 0)) gsbase = task->thread.gsbase; else gsbase = x86_fsgsbase_read_task(task, task->thread.gsindex); -- 2.19.1