From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=3.0 tests=DATE_IN_PAST_06_12, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BA81CC04AAB for ; Wed, 8 May 2019 17:03:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 9780821530 for ; Wed, 8 May 2019 17:03:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728676AbfEHRDK (ORCPT ); Wed, 8 May 2019 13:03:10 -0400 Received: from mga03.intel.com ([134.134.136.65]:5321 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728978AbfEHRDF (ORCPT ); Wed, 8 May 2019 13:03:05 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 08 May 2019 10:03:04 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.60,446,1549958400"; d="scan'208";a="169697583" Received: from chang-linux-3.sc.intel.com ([172.25.66.171]) by fmsmga002.fm.intel.com with ESMTP; 08 May 2019 10:03:03 -0700 From: "Chang S. Bae" To: Andy Lutomirski , Thomas Gleixner , Ingo Molnar , "H . Peter Anvin" , Andi Kleen Cc: Ravi Shankar , "Chang S . Bae" , LKML , Dave Hansen Subject: [PATCH v7 11/18] x86/fsgsbase/64: Introduce the FIND_PERCPU_BASE macro Date: Wed, 8 May 2019 03:02:26 -0700 Message-Id: <1557309753-24073-12-git-send-email-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1557309753-24073-1-git-send-email-chang.seok.bae@intel.com> References: <1557309753-24073-1-git-send-email-chang.seok.bae@intel.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On the paranoid entry, by far, SWAPGS is needed when entering from user space. A positive GSBASE means it is a user value and a negative GSBASE means it is a kernel value. When FSGSBASE is enabled, however, user space can write arbitrary values to GSBASE, so it will break the existing logic to differentiate kernel and user GSBASE. So, what the new GSBASE handling needs to do on the entry is: original_GSBASE = RDGSBASE() kernel_GSBASE = FIND_PERCPU_BASE() WRGSBASE(kernel_GSBASE) The new macro will be useful to retrieve the kernel GSBASE, and will be used on following patches. The way used to retrieve per-CPU base is reading the per_cpu_offset table with a CPU NR as an index. The CPU NR is obtained by the RDPID instruction, or (if not available) it can be extracted from the limit field of the CPUNODE entry in GDT. Also, the GAS-compatible RDPID macro is added, as binutils 2.27 seems to start to support the instruction. The minimum build requirement for binutils is the 2.21 version, at this point. Suggested-by: H. Peter Anvin Signed-off-by: Chang S. Bae Cc: Andy Lutomirski Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Dave Hansen Cc: Andi Kleen --- arch/x86/entry/calling.h | 34 ++++++++++++++++++++++++++++++++++ arch/x86/include/asm/inst.h | 15 +++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h index d119729..6cbf793 100644 --- a/arch/x86/entry/calling.h +++ b/arch/x86/entry/calling.h @@ -6,6 +6,7 @@ #include #include #include +#include /* @@ -337,6 +338,39 @@ For 32-bit we have the following conventions - kernel is built with #endif .endm +#ifdef CONFIG_SMP + +/* + * CPU/node NR is loaded from the limit (size) field of a special segment + * descriptor entry in GDT. + */ +.macro LOAD_CPU_AND_NODE_SEG_LIMIT reg:req + movq $__CPUNODE_SEG, \reg + lsl \reg, \reg +.endm + +/* + * Fetch the per-CPU GSBASE value for this processor and put it in @reg. + * We normally use %gs for accessing per-CPU data, but we are setting up + * %gs here and obviously can not use %gs itself to access per-CPU data. + */ +.macro GET_PERCPU_BASE reg:req + ALTERNATIVE \ + "LOAD_CPU_AND_NODE_SEG_LIMIT \reg", \ + "RDPID \reg", \ + X86_FEATURE_RDPID + andq $VDSO_CPUNODE_MASK, \reg + movq __per_cpu_offset(, \reg, 8), \reg +.endm + +#else + +.macro GET_PERCPU_BASE reg:req + movq pcpu_unit_offsets(%rip), \reg +.endm + +#endif /* CONFIG_SMP */ + .macro READ_MSR_GSBASE save_reg:req movl $MSR_GS_BASE, %ecx /* Read MSR specified by %ecx into %edx:%eax */ diff --git a/arch/x86/include/asm/inst.h b/arch/x86/include/asm/inst.h index f5a796d..d063841 100644 --- a/arch/x86/include/asm/inst.h +++ b/arch/x86/include/asm/inst.h @@ -306,6 +306,21 @@ .endif MODRM 0xc0 movq_r64_xmm_opd1 movq_r64_xmm_opd2 .endm + +.macro RDPID opd + REG_TYPE rdpid_opd_type \opd + .if rdpid_opd_type == REG_TYPE_R64 + R64_NUM rdpid_opd \opd + .else + R32_NUM rdpid_opd \opd + .endif + .byte 0xf3 + .if rdpid_opd > 7 + PFX_REX rdpid_opd 0 + .endif + .byte 0x0f, 0xc7 + MODRM 0xc0 rdpid_opd 0x7 +.endm #endif #endif -- 2.7.4