From patchwork Wed Apr 12 07:51:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Binbin Wu X-Patchwork-Id: 13208597 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0E967C77B6E for ; Wed, 12 Apr 2023 07:51:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229977AbjDLHvy (ORCPT ); Wed, 12 Apr 2023 03:51:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40306 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229974AbjDLHvs (ORCPT ); Wed, 12 Apr 2023 03:51:48 -0400 Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0BF535FE5 for ; Wed, 12 Apr 2023 00:51:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1681285907; x=1712821907; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=nkRjwGhxXGcTh2UbgeCl+DLC/p2fpGDlcCsCe5HekTQ=; b=AbUscfkPRfox/Xudhkpqfg/J/lnTep/RqIUmZms1zbgBvbElC3Tc91XX Ju4OYZib3kGkr534Ke0SnreDzobiHD4jYT7nZVF8o0/QQsWGew9/M/QZZ ERShsfDAF9ubNvlgO3M3OHmBzwHR45gL/W1JHhAUykelu9gGffFA5AfvB q03hd2ZvJ1RKNpQuQO6dzLVr1sh6nqX1ty+qXsT2MIQmm+l5as0Hqpp1Z LYDBc3M8ooHoZldHJoHNIDXHOFJhnl0DS3bAxUpmR7j+yjf2koAmRskRH Usxbl6gSasAYlUe6+XnGe6rK8kroyENxF3YLAneUdBp5ZirmIqzj2Jzg6 Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10677"; a="345623256" X-IronPort-AV: E=Sophos;i="5.98,338,1673942400"; d="scan'208";a="345623256" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Apr 2023 00:51:46 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10677"; a="812893659" X-IronPort-AV: E=Sophos;i="5.98,338,1673942400"; d="scan'208";a="812893659" Received: from binbinwu-mobl.ccr.corp.intel.com ([10.238.8.125]) by orsmga004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Apr 2023 00:51:44 -0700 From: Binbin Wu To: kvm@vger.kernel.org, seanjc@google.com, pbonzini@redhat.com Cc: binbin.wu@linux.intel.com, chao.gao@intel.com, robert.hu@linux.intel.com Subject: [kvm-unit-tests v3 1/4] x86: Allow setting of CR3 LAM bits if LAM supported Date: Wed, 12 Apr 2023 15:51:31 +0800 Message-Id: <20230412075134.21240-2-binbin.wu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230412075134.21240-1-binbin.wu@linux.intel.com> References: <20230412075134.21240-1-binbin.wu@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org If LAM is supported, VM entry allows CR3.LAM_U48 (bit 62) and CR3.LAM_U57 (bit 61) to be set in CR3 field. Change the test result expectations when setting CR3.LAM_U48 or CR3.LAM_U57 on vmlaunch tests when LAM is supported. Signed-off-by: Binbin Wu Reviewed-by: Chao Gao --- lib/x86/processor.h | 3 +++ x86/vmx_tests.c | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/x86/processor.h b/lib/x86/processor.h index 3d58ef7..e00a32b 100644 --- a/lib/x86/processor.h +++ b/lib/x86/processor.h @@ -55,6 +55,8 @@ #define X86_CR0_PG BIT(X86_CR0_PG_BIT) #define X86_CR3_PCID_MASK GENMASK(11, 0) +#define X86_CR3_LAM_U57_BIT (61) +#define X86_CR3_LAM_U48_BIT (62) #define X86_CR4_VME_BIT (0) #define X86_CR4_VME BIT(X86_CR4_VME_BIT) @@ -248,6 +250,7 @@ static inline bool is_intel(void) #define X86_FEATURE_SPEC_CTRL (CPUID(0x7, 0, EDX, 26)) #define X86_FEATURE_ARCH_CAPABILITIES (CPUID(0x7, 0, EDX, 29)) #define X86_FEATURE_PKS (CPUID(0x7, 0, ECX, 31)) +#define X86_FEATURE_LAM (CPUID(0x7, 1, EAX, 26)) /* * Extended Leafs, a.k.a. AMD defined diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index 7bba816..5ee1264 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -7000,7 +7000,11 @@ static void test_host_ctl_regs(void) cr3 = cr3_saved | (1ul << i); vmcs_write(HOST_CR3, cr3); report_prefix_pushf("HOST_CR3 %lx", cr3); - test_vmx_vmlaunch(VMXERR_ENTRY_INVALID_HOST_STATE_FIELD); + if (this_cpu_has(X86_FEATURE_LAM) && + ((i == X86_CR3_LAM_U57_BIT) || ( i == X86_CR3_LAM_U48_BIT))) + test_vmx_vmlaunch(0); + else + test_vmx_vmlaunch(VMXERR_ENTRY_INVALID_HOST_STATE_FIELD); report_prefix_pop(); } From patchwork Wed Apr 12 07:51:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Binbin Wu X-Patchwork-Id: 13208598 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C07DAC77B6E for ; Wed, 12 Apr 2023 07:51:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229516AbjDLHv5 (ORCPT ); Wed, 12 Apr 2023 03:51:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40322 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229985AbjDLHvx (ORCPT ); Wed, 12 Apr 2023 03:51:53 -0400 Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9B78E6596 for ; Wed, 12 Apr 2023 00:51:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1681285909; x=1712821909; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=UXHz3z2056/flVBE5ZxsMz0X0oVXSC9RttYzuy6z9g8=; b=joFsbCD+9KFYRNovCuL3CY2W79rE5fu+CKggiKGB3m7o0JGX/t4oymZU 32JzbPPi/JFR/7u5GZM4KBer5SOy+pNqVi7QuIPBOqeylulKknS3MaNbn 3/VTRxLgz2MlstdRuixG2LNUIqfIls9sgxnrhAqtop3+hZqEXy8oNHOhg nlVlAmQfWo/JyV5XgehFwq5ZV1aZLYrUnlj0uG58zRGNMquXedaMQNuXA Od3UHofA2zDt025WlH8iD7QwEdgMZlbo2uNP6zxmWQZ4GP8aXBMGXyZ+J 15Qrlw4VHkocIY4hXcIm+2SIIq85xNdBHVClT9A2C7ZsLknDzo52lqMeR w==; X-IronPort-AV: E=McAfee;i="6600,9927,10677"; a="345623263" X-IronPort-AV: E=Sophos;i="5.98,338,1673942400"; d="scan'208";a="345623263" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Apr 2023 00:51:49 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10677"; a="812893667" X-IronPort-AV: E=Sophos;i="5.98,338,1673942400"; d="scan'208";a="812893667" Received: from binbinwu-mobl.ccr.corp.intel.com ([10.238.8.125]) by orsmga004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Apr 2023 00:51:47 -0700 From: Binbin Wu To: kvm@vger.kernel.org, seanjc@google.com, pbonzini@redhat.com Cc: binbin.wu@linux.intel.com, chao.gao@intel.com, robert.hu@linux.intel.com Subject: [kvm-unit-tests v3 2/4] x86: Add test case for LAM_SUP Date: Wed, 12 Apr 2023 15:51:32 +0800 Message-Id: <20230412075134.21240-3-binbin.wu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230412075134.21240-1-binbin.wu@linux.intel.com> References: <20230412075134.21240-1-binbin.wu@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Robert Hoo This unit test covers: 1. CR4.LAM_SUP toggles. 2. Memory & MMIO access with supervisor mode address with LAM metadata. 3. INVLPG memory operand doesn't contain LAM meta data, if the address is non-canonical form then the INVLPG is the same as a NOP (no #GP). 4. INVPCID memory operand (descriptor pointer) could contain LAM meta data, however, the address in the descriptor should be canonical. In x86/unittests.cfg, add 2 test cases/guest conf, with and without LAM. LAM feature spec: https://cdrdv2.intel.com/v1/dl/getContent/671368, Chap 7 LINEAR ADDRESS MASKING (LAM) Signed-off-by: Robert Hoo Co-developed-by: Binbin Wu Signed-off-by: Binbin Wu Reviewed-by: Chao Gao --- lib/x86/processor.h | 2 + x86/Makefile.x86_64 | 1 + x86/lam.c | 244 ++++++++++++++++++++++++++++++++++++++++++++ x86/unittests.cfg | 10 ++ 4 files changed, 257 insertions(+) create mode 100644 x86/lam.c diff --git a/lib/x86/processor.h b/lib/x86/processor.h index e00a32b..4bb8cd7 100644 --- a/lib/x86/processor.h +++ b/lib/x86/processor.h @@ -107,6 +107,8 @@ #define X86_CR4_CET BIT(X86_CR4_CET_BIT) #define X86_CR4_PKS_BIT (24) #define X86_CR4_PKS BIT(X86_CR4_PKS_BIT) +#define X86_CR4_LAM_SUP_BIT (28) +#define X86_CR4_LAM_SUP BIT(X86_CR4_LAM_SUP_BIT) #define X86_EFLAGS_CF_BIT (0) #define X86_EFLAGS_CF BIT(X86_EFLAGS_CF_BIT) diff --git a/x86/Makefile.x86_64 b/x86/Makefile.x86_64 index f483dea..fa11eb3 100644 --- a/x86/Makefile.x86_64 +++ b/x86/Makefile.x86_64 @@ -34,6 +34,7 @@ tests += $(TEST_DIR)/rdpru.$(exe) tests += $(TEST_DIR)/pks.$(exe) tests += $(TEST_DIR)/pmu_lbr.$(exe) tests += $(TEST_DIR)/pmu_pebs.$(exe) +tests += $(TEST_DIR)/lam.$(exe) ifeq ($(CONFIG_EFI),y) tests += $(TEST_DIR)/amd_sev.$(exe) diff --git a/x86/lam.c b/x86/lam.c new file mode 100644 index 0000000..63c3fde --- /dev/null +++ b/x86/lam.c @@ -0,0 +1,244 @@ +/* + * Intel LAM unit test + * + * Copyright (C) 2023 Intel + * + * Author: Robert Hoo + * Binbin Wu + * + * This work is licensed under the terms of the GNU LGPL, version 2 or + * later. + */ + +#include "libcflat.h" +#include "processor.h" +#include "desc.h" +#include "vmalloc.h" +#include "alloc_page.h" +#include "vm.h" +#include "asm/io.h" +#include "ioram.h" + +#define LAM57_MASK GENMASK_ULL(62, 57) +#define LAM48_MASK GENMASK_ULL(62, 48) + +#define FLAGS_LAM_ACTIVE BIT_ULL(0) +#define FLAGS_LA57 BIT_ULL(1) + +struct invpcid_desc { + u64 pcid : 12; + u64 rsv : 52; + u64 addr; +}; + +static inline bool is_la57(void) +{ + return !!(read_cr4() & X86_CR4_LA57); +} + +static inline bool lam_sup_active(void) +{ + return !!(read_cr4() & X86_CR4_LAM_SUP); +} + +/* According to LAM mode, set metadata in high bits */ +static inline u64 set_metadata(u64 src, u64 metadata_mask) +{ + return (src & ~metadata_mask) | (NONCANONICAL & metadata_mask); +} + +static void cr4_set_lam_sup(void *data) +{ + unsigned long cr4; + + cr4 = read_cr4(); + write_cr4_safe(cr4 | X86_CR4_LAM_SUP); +} + +static void cr4_clear_lam_sup(void *data) +{ + unsigned long cr4; + + cr4 = read_cr4(); + write_cr4_safe(cr4 & ~X86_CR4_LAM_SUP); +} + +static void test_cr4_lam_set_clear(bool has_lam) +{ + bool fault; + + fault = test_for_exception(GP_VECTOR, &cr4_set_lam_sup, NULL); + report((fault != has_lam) && (lam_sup_active() == has_lam), + "Set CR4.LAM_SUP"); + + fault = test_for_exception(GP_VECTOR, &cr4_clear_lam_sup, NULL); + report(!fault, "Clear CR4.LAM_SUP"); +} + +/* Refer to emulator.c */ +static void do_mov(void *mem) +{ + unsigned long t1, t2; + + t1 = 0x123456789abcdefull & -1ul; + asm volatile("mov %[t1], (%[mem])\n\t" + "mov (%[mem]), %[t2]" + : [t2]"=r"(t2) + : [t1]"r"(t1), [mem]"r"(mem) + : "memory"); + report(t1 == t2, "Mov result check"); +} + +static u64 test_ptr(u64 arg1, u64 arg2, u64 arg3, u64 arg4) +{ + bool lam_active = !!(arg1 & FLAGS_LAM_ACTIVE); + u64 lam_mask = arg2; + u64 *ptr = (u64 *)arg3; + bool is_mmio = !!arg4; + bool fault; + + fault = test_for_exception(GP_VECTOR, do_mov, ptr); + report(!fault, "Test untagged addr (%s)", is_mmio ? "MMIO" : "Memory"); + + ptr = (u64 *)set_metadata((u64)ptr, lam_mask); + fault = test_for_exception(GP_VECTOR, do_mov, ptr); + report(fault != lam_active,"Test tagged addr (%s)", + is_mmio ? "MMIO" : "Memory"); + + return 0; +} + +static void do_invlpg(void *mem) +{ + invlpg(mem); +} + +static void do_invlpg_fep(void *mem) +{ + asm volatile(KVM_FEP "invlpg (%0)" ::"r" (mem) : "memory"); +} + +/* invlpg with tagged address is same as NOP, no #GP expected. */ +static void test_invlpg(u64 lam_mask, void *va, bool fep) +{ + bool fault; + u64 *ptr; + + ptr = (u64 *)set_metadata((u64)va, lam_mask); + if (fep) + fault = test_for_exception(GP_VECTOR, do_invlpg_fep, ptr); + else + fault = test_for_exception(GP_VECTOR, do_invlpg, ptr); + + report(!fault, "%sINVLPG with tagged addr", fep ? "fep: " : ""); +} + +static void do_invpcid(void *desc) +{ + unsigned long type = 0; + struct invpcid_desc *desc_ptr = (struct invpcid_desc *)desc; + + asm volatile("invpcid %0, %1" : + : "m" (*desc_ptr), "r" (type) + : "memory"); +} + +/* LAM doesn't apply to the target address in the descriptor of invpcid */ +static void test_invpcid(u64 flags, u64 lam_mask, void *data) +{ + /* + * Reuse the memory address for the descriptor since stack memory + * address in KUT doesn't follow the kernel address space partitions. + */ + struct invpcid_desc *desc_ptr = (struct invpcid_desc *)data; + bool lam_active = !!(flags & FLAGS_LAM_ACTIVE); + bool fault; + + if (!this_cpu_has(X86_FEATURE_PCID) || + !this_cpu_has(X86_FEATURE_INVPCID)) { + report_skip("INVPCID not supported"); + return; + } + + memset(desc_ptr, 0, sizeof(struct invpcid_desc)); + desc_ptr->addr = (u64)data; + + fault = test_for_exception(GP_VECTOR, do_invpcid, desc_ptr); + report(!fault, "INVPCID: untagged pointer + untagged addr"); + + desc_ptr->addr = set_metadata(desc_ptr->addr, lam_mask); + fault = test_for_exception(GP_VECTOR, do_invpcid, desc_ptr); + report(fault, "INVPCID: untagged pointer + tagged addr"); + + desc_ptr = (struct invpcid_desc *)set_metadata((u64)desc_ptr, lam_mask); + fault = test_for_exception(GP_VECTOR, do_invpcid, desc_ptr); + report(fault, "INVPCID: tagged pointer + tagged addr"); + + desc_ptr = (struct invpcid_desc *)data; + desc_ptr->addr = (u64)data; + desc_ptr = (struct invpcid_desc *)set_metadata((u64)desc_ptr, lam_mask); + fault = test_for_exception(GP_VECTOR, do_invpcid, desc_ptr); + report(fault != lam_active, "INVPCID: tagged pointer + untagged addr"); +} + +static void test_lam_sup(bool has_lam, bool fep_available) +{ + void *vaddr, *vaddr_mmio; + phys_addr_t paddr; + u64 lam_mask = LAM48_MASK; + u64 flags = 0; + bool fault; + + vaddr = alloc_vpage(); + vaddr_mmio = alloc_vpage(); + paddr = virt_to_phys(alloc_page()); + install_page(current_page_table(), paddr, vaddr); + install_page(current_page_table(), IORAM_BASE_PHYS, vaddr_mmio); + + test_cr4_lam_set_clear(has_lam); + + /* Set for the following LAM_SUP tests */ + if (has_lam) { + fault = test_for_exception(GP_VECTOR, &cr4_set_lam_sup, NULL); + report(!fault && lam_sup_active(), "Set CR4.LAM_SUP"); + } + + if (lam_sup_active()) + flags |= FLAGS_LAM_ACTIVE; + + if (is_la57()) { + flags |= FLAGS_LA57; + lam_mask = LAM57_MASK; + } + + /* Test for normal memory */ + test_ptr(flags, lam_mask, (u64)vaddr, false); + /* Test for MMIO to trigger instruction emulation */ + test_ptr(flags, lam_mask, (u64)vaddr_mmio, true); + test_invpcid(flags, lam_mask, vaddr); + test_invlpg(lam_mask, vaddr, false); + if (fep_available) + test_invlpg(lam_mask, vaddr, true); +} + +int main(int ac, char **av) +{ + bool has_lam; + bool fep_available = is_fep_available(); + + setup_vm(); + + has_lam = this_cpu_has(X86_FEATURE_LAM); + if (!has_lam) + report_info("This CPU doesn't support LAM feature\n"); + else + report_info("This CPU supports LAM feature\n"); + + if (!fep_available) + report_skip("Skipping tests the forced emulation, " + "use kvm.force_emulation_prefix=1 to enable\n"); + + test_lam_sup(has_lam, fep_available); + + return report_summary(); +} diff --git a/x86/unittests.cfg b/x86/unittests.cfg index f324e32..34b09eb 100644 --- a/x86/unittests.cfg +++ b/x86/unittests.cfg @@ -478,3 +478,13 @@ file = cet.flat arch = x86_64 smp = 2 extra_params = -enable-kvm -m 2048 -cpu host + +[intel-lam] +file = lam.flat +arch = x86_64 +extra_params = -enable-kvm -cpu host + +[intel-no-lam] +file = lam.flat +arch = x86_64 +extra_params = -enable-kvm -cpu host,-lam From patchwork Wed Apr 12 07:51:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Binbin Wu X-Patchwork-Id: 13208599 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1B04DC7619A for ; Wed, 12 Apr 2023 07:52:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229784AbjDLHwA (ORCPT ); Wed, 12 Apr 2023 03:52:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40308 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229499AbjDLHv6 (ORCPT ); Wed, 12 Apr 2023 03:51:58 -0400 Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 294576592 for ; Wed, 12 Apr 2023 00:51:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1681285912; x=1712821912; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=IywIAfr5npYtgqb/3fxobMj9A+PuAxFXW2BLlrcpFUg=; b=K5PMELTsGDOfTjsSD4GsVx59he6t9I0BWupNqHvWi2XxapPq/9VhCWNL I0oCRMbt5Aa/f8cjzd8gBLpjNFObH1QRTc0IhwF7fCTgD1BkkgtMapKYZ 8YsjC59fjMBd9n9uwOcpb/cDtDjPwHQ4wYkWMtatvZkMdEs1bogm+3PE+ Z06ZL2gPWfehqhER7FKj3W9J5rbkUnGv9vHcxK+xwVu5Qrj7CK1qGjim7 8F7siC4W/jSR8QemwfnxfRbkBuF/2KyMnbcSFz73wkx41C4GU9uCyFzNZ rE0fWWZToutczA4LG3uK0uf9miLwpBnM0bR0tJt071G+IQSknJBPaxNpU Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10677"; a="345623270" X-IronPort-AV: E=Sophos;i="5.98,338,1673942400"; d="scan'208";a="345623270" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Apr 2023 00:51:51 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10677"; a="812893682" X-IronPort-AV: E=Sophos;i="5.98,338,1673942400"; d="scan'208";a="812893682" Received: from binbinwu-mobl.ccr.corp.intel.com ([10.238.8.125]) by orsmga004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Apr 2023 00:51:49 -0700 From: Binbin Wu To: kvm@vger.kernel.org, seanjc@google.com, pbonzini@redhat.com Cc: binbin.wu@linux.intel.com, chao.gao@intel.com, robert.hu@linux.intel.com Subject: [kvm-unit-tests v3 3/4] x86: Add test cases for LAM_{U48,U57} Date: Wed, 12 Apr 2023 15:51:33 +0800 Message-Id: <20230412075134.21240-4-binbin.wu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230412075134.21240-1-binbin.wu@linux.intel.com> References: <20230412075134.21240-1-binbin.wu@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org This unit test covers: 1. CR3 LAM bits toggles. 2. Memory/MMIO access with user mode address containing LAM metadata. Signed-off-by: Binbin Wu Reviewed-by: Chao Gao --- lib/x86/processor.h | 2 ++ x86/lam.c | 71 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/lib/x86/processor.h b/lib/x86/processor.h index 4bb8cd7..a181e0b 100644 --- a/lib/x86/processor.h +++ b/lib/x86/processor.h @@ -56,7 +56,9 @@ #define X86_CR3_PCID_MASK GENMASK(11, 0) #define X86_CR3_LAM_U57_BIT (61) +#define X86_CR3_LAM_U57 BIT_ULL(X86_CR3_LAM_U57_BIT) #define X86_CR3_LAM_U48_BIT (62) +#define X86_CR3_LAM_U48 BIT_ULL(X86_CR3_LAM_U48_BIT) #define X86_CR4_VME_BIT (0) #define X86_CR4_VME BIT(X86_CR4_VME_BIT) diff --git a/x86/lam.c b/x86/lam.c index 63c3fde..50bcdf5 100644 --- a/x86/lam.c +++ b/x86/lam.c @@ -18,9 +18,11 @@ #include "vm.h" #include "asm/io.h" #include "ioram.h" +#include "usermode.h" #define LAM57_MASK GENMASK_ULL(62, 57) #define LAM48_MASK GENMASK_ULL(62, 48) +#define CR3_LAM_BITS_MASK (X86_CR3_LAM_U48 | X86_CR3_LAM_U57) #define FLAGS_LAM_ACTIVE BIT_ULL(0) #define FLAGS_LA57 BIT_ULL(1) @@ -41,6 +43,16 @@ static inline bool lam_sup_active(void) return !!(read_cr4() & X86_CR4_LAM_SUP); } +static inline bool lam_u48_active(void) +{ + return (read_cr3() & CR3_LAM_BITS_MASK) == X86_CR3_LAM_U48; +} + +static inline bool lam_u57_active(void) +{ + return !!(read_cr3() & X86_CR3_LAM_U57); +} + /* According to LAM mode, set metadata in high bits */ static inline u64 set_metadata(u64 src, u64 metadata_mask) { @@ -92,6 +104,7 @@ static void do_mov(void *mem) static u64 test_ptr(u64 arg1, u64 arg2, u64 arg3, u64 arg4) { bool lam_active = !!(arg1 & FLAGS_LAM_ACTIVE); + bool la_57 = !!(arg1 & FLAGS_LA57); u64 lam_mask = arg2; u64 *ptr = (u64 *)arg3; bool is_mmio = !!arg4; @@ -105,6 +118,17 @@ static u64 test_ptr(u64 arg1, u64 arg2, u64 arg3, u64 arg4) report(fault != lam_active,"Test tagged addr (%s)", is_mmio ? "MMIO" : "Memory"); + /* + * This test case is only triggered when LAM_U57 is active and 4-level + * paging is used. For the case, bit[56:47] aren't all 0 triggers #GP. + */ + if (lam_active && (lam_mask == LAM57_MASK) && !la_57) { + ptr = (u64 *)set_metadata((u64)ptr, LAM48_MASK); + fault = test_for_exception(GP_VECTOR, do_mov, ptr); + report(fault, "Test non-LAM-canonical addr (%s)", + is_mmio ? "MMIO" : "Memory"); + } + return 0; } @@ -221,6 +245,52 @@ static void test_lam_sup(bool has_lam, bool fep_available) test_invlpg(lam_mask, vaddr, true); } +static void test_lam_user_mode(bool has_lam, u64 lam_mask, u64 mem, u64 mmio) +{ + unsigned r; + bool raised_vector; + unsigned long cr3 = read_cr3() & ~CR3_LAM_BITS_MASK; + u64 flags = 0; + + if (is_la57()) + flags |= FLAGS_LA57; + + if (has_lam) { + if (lam_mask == LAM48_MASK) { + r = write_cr3_safe(cr3 | X86_CR3_LAM_U48); + report((r == 0) && lam_u48_active(), "Set LAM_U48"); + } else { + r = write_cr3_safe(cr3 | X86_CR3_LAM_U57); + report((r == 0) && lam_u57_active(), "Set LAM_U57"); + } + } + if (lam_u48_active() || lam_u57_active()) + flags |= FLAGS_LAM_ACTIVE; + + run_in_user((usermode_func)test_ptr, GP_VECTOR, flags, lam_mask, mem, + false, &raised_vector); + run_in_user((usermode_func)test_ptr, GP_VECTOR, flags, lam_mask, mmio, + true, &raised_vector); +} + +static void test_lam_user(bool has_lam) +{ + phys_addr_t paddr; + unsigned long cr3 = read_cr3(); + + /* + * The physical address width is within 36 bits, so that using identical + * mapping, the linear address will be considered as user mode address + * from the view of LAM. + */ + paddr = virt_to_phys(alloc_page()); + install_page((void *)cr3, paddr, (void *)paddr); + install_page((void *)cr3, IORAM_BASE_PHYS, (void *)IORAM_BASE_PHYS); + + test_lam_user_mode(has_lam, LAM48_MASK, paddr, IORAM_BASE_PHYS); + test_lam_user_mode(has_lam, LAM57_MASK, paddr, IORAM_BASE_PHYS); +} + int main(int ac, char **av) { bool has_lam; @@ -239,6 +309,7 @@ int main(int ac, char **av) "use kvm.force_emulation_prefix=1 to enable\n"); test_lam_sup(has_lam, fep_available); + test_lam_user(has_lam); return report_summary(); } From patchwork Wed Apr 12 07:51:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Binbin Wu X-Patchwork-Id: 13208600 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6586BC7619A for ; Wed, 12 Apr 2023 07:52:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229757AbjDLHwF (ORCPT ); Wed, 12 Apr 2023 03:52:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40758 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229499AbjDLHwE (ORCPT ); Wed, 12 Apr 2023 03:52:04 -0400 Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4E0B96589 for ; Wed, 12 Apr 2023 00:51:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1681285914; x=1712821914; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=MjKV4s8VGpZ1zEkznfY4jiS1d+KzIYwTcz+xV2KmVqM=; b=hld8OYlU/Bj8NY+PF9eWzeQY/rZAgyDooOiWn8D9qgZHlw2rFcZiqemV wIf6DsNesZKCShAX4HSCbXAdjR3l5wqrNKQx2HfOfZRrEIg1U9CtE5RHs mRE1nQfq2apc3lbek4UqAvcqnU1gVWPeinOtb7AIK+Ei9++WCZ2lKCh/q CCT+q98/Qex40pLyeTPYsA1wwhRjbHjRtSfktIJMBNIZun4eo3zGLsHoo h2yHIZSvXdw91Arf6n8RkoFn5ODQ/fqy+XNGw6Y4IsKDLiL4n9PEZKrWA /H/7BqNd9rB2AsHBTTdqTMva5rP80AqwVU08NL3BqGQGJZ+7sJGnUDXNb w==; X-IronPort-AV: E=McAfee;i="6600,9927,10677"; a="345623276" X-IronPort-AV: E=Sophos;i="5.98,338,1673942400"; d="scan'208";a="345623276" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Apr 2023 00:51:54 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10677"; a="812893691" X-IronPort-AV: E=Sophos;i="5.98,338,1673942400"; d="scan'208";a="812893691" Received: from binbinwu-mobl.ccr.corp.intel.com ([10.238.8.125]) by orsmga004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Apr 2023 00:51:51 -0700 From: Binbin Wu To: kvm@vger.kernel.org, seanjc@google.com, pbonzini@redhat.com Cc: binbin.wu@linux.intel.com, chao.gao@intel.com, robert.hu@linux.intel.com Subject: [kvm-unit-tests v3 4/4] x86: Add test case for INVVPID with LAM Date: Wed, 12 Apr 2023 15:51:34 +0800 Message-Id: <20230412075134.21240-5-binbin.wu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230412075134.21240-1-binbin.wu@linux.intel.com> References: <20230412075134.21240-1-binbin.wu@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org When LAM is on, the linear address of INVVPID operand can contain metadata, and the linear address in the INVVPID descriptor can contain metadata. The added cases use tagged descriptor address or/and tagged target invalidation address to make sure the behaviors are expected when LAM is on. Also, INVVPID cases can be used as the common test cases for VMX instruction VMExits. Signed-off-by: Binbin Wu Reviewed-by: Chao Gao --- x86/vmx_tests.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index 5ee1264..381ca1c 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -3225,6 +3225,65 @@ static void invvpid_test_not_in_vmx_operation(void) TEST_ASSERT(!vmx_on()); } +#define LAM57_MASK GENMASK_ULL(62, 57) +#define LAM48_MASK GENMASK_ULL(62, 48) + +static inline u64 set_metadata(u64 src, u64 metadata_mask) +{ + return (src & ~metadata_mask) | (NONCANONICAL & metadata_mask); +} + +/* LAM applies to the target address inside the descriptor of invvpid */ +static void invvpid_test_lam(void) +{ + void *vaddr; + struct invvpid_operand *operand; + u64 lam_mask = LAM48_MASK; + bool fault; + + if (!this_cpu_has(X86_FEATURE_LAM)) { + report_skip("LAM is not supported, skip INVVPID with LAM"); + return; + } + + if (this_cpu_has(X86_FEATURE_LA57) && read_cr4() & X86_CR4_LA57) + lam_mask = LAM57_MASK; + + vaddr = alloc_vpage(); + install_page(current_page_table(), virt_to_phys(alloc_page()), vaddr); + /* + * Since the stack memory address in KUT doesn't follow kernel address + * space partition rule, reuse the memory address for descriptor and + * the target address in the descriptor of invvpid. + */ + operand = (struct invvpid_operand *)vaddr; + operand->vpid = 0xffff; + operand->gla = (u64)vaddr; + + write_cr4_safe(read_cr4() | X86_CR4_LAM_SUP); + if (!(read_cr4() & X86_CR4_LAM_SUP)) { + report_skip("Failed to enable LAM_SUP"); + return; + } + + operand = (struct invvpid_operand *)vaddr; + operand->gla = set_metadata(operand->gla, lam_mask); + fault = test_for_exception(GP_VECTOR, ds_invvpid, operand); + report(!fault, "INVVPID (LAM on): untagged pointer + tagged addr"); + + operand = (struct invvpid_operand *)set_metadata((u64)operand, lam_mask); + operand->gla = (u64)vaddr; + fault = test_for_exception(GP_VECTOR, ds_invvpid, operand); + report(!fault, "INVVPID (LAM on): tagged pointer + untagged addr"); + + operand = (struct invvpid_operand *)set_metadata((u64)operand, lam_mask); + operand->gla = set_metadata(operand->gla, lam_mask); + fault = test_for_exception(GP_VECTOR, ds_invvpid, operand); + report(!fault, "INVVPID (LAM on): tagged pointer + tagged addr"); + + write_cr4_safe(read_cr4() & ~X86_CR4_LAM_SUP); +} + /* * This does not test real-address mode, virtual-8086 mode, protected mode, * or CPL > 0. @@ -3282,6 +3341,7 @@ static void invvpid_test(void) invvpid_test_pf(); invvpid_test_compatibility_mode(); invvpid_test_not_in_vmx_operation(); + invvpid_test_lam(); } /*