Received: by 2002:ac0:8c9a:0:0:0:0:0 with SMTP id r26csp909674ima; Fri, 1 Feb 2019 12:58:30 -0800 (PST) X-Google-Smtp-Source: ALg8bN5c2dWf+37NL+DS0rCsuDoTIf8CfuifJdl1+7w9mKmXPrV2qL39h6gOwBNere0ABbMuf20P X-Received: by 2002:a17:902:b48b:: with SMTP id y11mr39565398plr.200.1549054710350; Fri, 01 Feb 2019 12:58:30 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549054710; cv=none; d=google.com; s=arc-20160816; b=aNt/BD3VOHsQlwuI63EN4FOtwEd6mpIzMbAyfuHOpJWv1FpqPsotOBc2/4xyVppNoe ysiIDnPE0GpRwfxXajkr6YXvaepRGAgk76K0RrYpaKTRqZTpmEBmr8l36Y/QoXjHwrsG TKUFbLLCCKtVsxGDZlHFpjXUEF9yvAKnOhPqWxJgZJ9U0qrQFHtaY1pkiCdlYAT98GR8 GFvv8PXkzaiKVY7xggVx2m6SNXDLmIL1Aa50RB86JmQz2fy81YZdLgRaSz1rSghg9s0t hM9odt1JqCCC/YuShgYlWzvgOWp4Pao1B/pa1Mtj7bYYHT6TqP9SCByzv17GwEGX2SZj +N6w== 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=R0Y+lZjvtJ5zNBU/ZtCK3u8uAiSl8YTKio56fW/9K6c=; b=EThbL7itPUmMf/pltRYbf6REdCuc0tKKUlodFtFitP+hP4GHK2vA+32VINPCccKTjA MywM9IiPU3uBcE5TxcWrvsIyOthpRmlg5wtbvlD1WmacAPxiE9+6p4WZ27COVC7dXHwQ jY/qAkr7lcm6xscslAcG9Il4pCp1JriyPij/JCtpCvzJQKc2UwLJUpeyUyJfMtJ7x0dS +Q8xz86xOyk+QUv8ahg36bEv9VJaqQJb/+g4Ja5HKDBNmDSbTIhMWDjUzMLZ48T7OL7U 4whz01yS7Vk7R06ZxonPKe5hQeKQsm0SkaIgSw0k2r3qygSOSSJQ5DAuiR1+VWOOwUc6 dYUQ== 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 o3si7846611pgm.441.2019.02.01.12.58.15; Fri, 01 Feb 2019 12:58:30 -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 S1730620AbfBAUzE (ORCPT + 99 others); Fri, 1 Feb 2019 15:55:04 -0500 Received: from mga07.intel.com ([134.134.136.100]:49750 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726925AbfBAUzD (ORCPT ); Fri, 1 Feb 2019 15:55:03 -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:55:02 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,549,1539673200"; d="scan'208";a="140866386" Received: from chang-linux-2.sc.intel.com ([10.3.52.165]) by fmsmga004.fm.intel.com with ESMTP; 01 Feb 2019 12:55:02 -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 Subject: [PATCH v5 10/13] selftests/x86/fsgsbase: Test WRGSBASE Date: Fri, 1 Feb 2019 12:53:16 -0800 Message-Id: <20190201205319.15995-12-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 From: Andy Lutomirski This validates that GS and GSBASE are independently preserved across context switches. [ chang: Use FSGSBASE instructions directly instead of .byte ] Signed-off-by: Andy Lutomirski Reviewed-by: Andi Kleen Signed-off-by: Chang S. Bae Cc: H. Peter Anvin Cc: Thomas Gleixner Cc: Ingo Molnar --- tools/testing/selftests/x86/fsgsbase.c | 102 ++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/x86/fsgsbase.c b/tools/testing/selftests/x86/fsgsbase.c index f249e042b3b5..5956475972f1 100644 --- a/tools/testing/selftests/x86/fsgsbase.c +++ b/tools/testing/selftests/x86/fsgsbase.c @@ -23,6 +23,7 @@ #include #include #include +#include #ifndef __x86_64__ # error This test is 64-bit only @@ -71,6 +72,43 @@ static void sigsegv(int sig, siginfo_t *si, void *ctx_void) } +static jmp_buf jmpbuf; + +static void sigill(int sig, siginfo_t *si, void *ctx_void) +{ + siglongjmp(jmpbuf, 1); +} + +static bool have_fsgsbase; + +static inline unsigned long rdgsbase(void) +{ + unsigned long gsbase; + + asm volatile("rdgsbase %0" : "=r" (gsbase) :: "memory"); + + return gsbase; +} + +static inline unsigned long rdfsbase(void) +{ + unsigned long fsbase; + + asm volatile("rdfsbase %0" : "=r" (fsbase) :: "memory"); + + return fsbase; +} + +static inline void wrgsbase(unsigned long gsbase) +{ + asm volatile("wrgsbase %0" :: "r" (gsbase) : "memory"); +} + +static inline void wrfsbase(unsigned long fsbase) +{ + asm volatile("wrfsbase %0" :: "r" (fsbase) : "memory"); +} + enum which_base { FS, GS }; static unsigned long read_base(enum which_base which) @@ -199,14 +237,16 @@ static void do_remote_base() to_set, hard_zero ? " and clear gs" : "", sel); } -void do_unexpected_base(void) +static __thread int set_thread_area_entry_number = -1; + +static void do_unexpected_base(void) { /* * The goal here is to try to arrange for GS == 0, GSBASE != * 0, and for the the kernel the think that GSBASE == 0. * * To make the test as reliable as possible, this uses - * explicit descriptorss. (This is not the only way. This + * explicit descriptors. (This is not the only way. This * could use ARCH_SET_GS with a low, nonzero base, but the * relevant side effect of ARCH_SET_GS could change.) */ @@ -239,7 +279,7 @@ void do_unexpected_base(void) MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0); memcpy(low_desc, &desc, sizeof(desc)); - low_desc->entry_number = -1; + low_desc->entry_number = set_thread_area_entry_number; /* 32-bit set_thread_area */ long ret; @@ -254,6 +294,8 @@ void do_unexpected_base(void) return; } printf("\tother thread: using GDT slot %d\n", desc.entry_number); + set_thread_area_entry_number = desc.entry_number; + asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)((desc.entry_number << 3) | 0x3))); } @@ -265,6 +307,34 @@ void do_unexpected_base(void) asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0)); } +void test_wrbase(unsigned short index, unsigned long base) +{ + unsigned short newindex; + unsigned long newbase; + + printf("[RUN]\tGS = 0x%hx, GSBASE = 0x%lx\n", index, base); + + asm volatile ("mov %0, %%gs" : : "rm" (index)); + wrgsbase(base); + + remote_base = 0; + ftx = 1; + syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0); + while (ftx != 0) + syscall(SYS_futex, &ftx, FUTEX_WAIT, 1, NULL, NULL, 0); + + asm volatile ("mov %%gs, %0" : "=rm" (newindex)); + newbase = rdgsbase(); + + if (newindex == index && newbase == base) { + printf("[OK]\tIndex and base were preserved\n"); + } else { + printf("[FAIL]\tAfter switch, GS = 0x%hx and GSBASE = 0x%lx\n", + newindex, newbase); + nerrs++; + } +} + static void *threadproc(void *ctx) { while (1) { @@ -371,6 +441,17 @@ int main() { pthread_t thread; + /* Probe FSGSBASE */ + sethandler(SIGILL, sigill, 0); + if (sigsetjmp(jmpbuf, 1) == 0) { + rdfsbase(); + have_fsgsbase = true; + printf("\tFSGSBASE instructions are enabled\n"); + } else { + printf("\tFSGSBASE instructions are disabled\n"); + } + clearhandler(SIGILL); + sethandler(SIGSEGV, sigsegv, 0); check_gs_value(0); @@ -417,6 +498,21 @@ int main() test_unexpected_base(); + if (have_fsgsbase) { + unsigned short ss; + + asm volatile ("mov %%ss, %0" : "=rm" (ss)); + + test_wrbase(0, 0); + test_wrbase(0, 1); + test_wrbase(0, 0x200000000); + test_wrbase(0, 0xffffffffffffffff); + test_wrbase(ss, 0); + test_wrbase(ss, 1); + test_wrbase(ss, 0x200000000); + test_wrbase(ss, 0xffffffffffffffff); + } + ftx = 3; /* Kill the thread. */ syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0); -- 2.19.1