From patchwork Mon Jan 22 08:53:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Binbin Wu X-Patchwork-Id: 13524967 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 37E8239FDB for ; Mon, 22 Jan 2024 08:54:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.10 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705913644; cv=none; b=CB6LaH5DPANqXCGrazKAUkedKvNPGdD7yiPiQ3pEKNjJ1mfPSGxOPSargbx5FH1hzhBRnOCp/ETrMqfZWt7EOhHhClXGWVXoJQCJb2UkCFWH1hVQrxtcPc/KOwR4v8X2vPSTQ03I1bJY1ovuOuwnXj0HOj0Nqi3IUS3r1ebyFCE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705913644; c=relaxed/simple; bh=frwpTGgMSezeZ0vMWcnbys3sHXx7SiQwveJFiwqz2rY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=l0PSZhz/lN/2/un0du5NvQqQDVBJ8+eHyHp6df9vMkiVKzLQr4uQ85L9rOab6/NVI901p4ZergngHbWeH2sQEQ7CNi0VJTs2N8VXPhj/uVlzJ/S5DFoPmf8RfVKLJxyZn/vubzHrIulBphxKeRJqRH3GaHTr+eXcSB2N8e5Go5I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=SfTQsCB4; arc=none smtp.client-ip=192.198.163.10 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="SfTQsCB4" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1705913643; x=1737449643; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=frwpTGgMSezeZ0vMWcnbys3sHXx7SiQwveJFiwqz2rY=; b=SfTQsCB4C0HH8g0IWRu56cikBD2vBUehjcfoqipEuxc7KUX3VIF6W62r YsUHBtnPd6TYRpbtiiQx0du8DprVDmBn+ebZnTwo3cZU+bDehU2py05pR rvFm0NQEB5Jz2NGB2ALbJfqqS3twvTbjgeyE+ovYUmmZyu2Q58ZqSrYE0 sNa6DloD6zT8KS2ekriL03il4uJkr0FjEIid6c1yytb038tjMZAynn9Hu Wpi9sgoTZ06VFmXnz501DbtNMdxBcV20RJb0LEGfbnpR+x4Q/ebpW51PC Fil3SjbO91mSRSgFtifthFk/HORqhKqFb6pi6s5edueea6f0wC6ZQpS8d w==; X-IronPort-AV: E=McAfee;i="6600,9927,10960"; a="8536149" X-IronPort-AV: E=Sophos;i="6.05,211,1701158400"; d="scan'208";a="8536149" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmvoesa104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jan 2024 00:54:03 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10960"; a="785611595" X-IronPort-AV: E=Sophos;i="6.05,211,1701158400"; d="scan'208";a="785611595" Received: from binbinwu-mobl.ccr.corp.intel.com (HELO binbinwu-mobl.sh.intel.com) ([10.238.10.49]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jan 2024 00:54:00 -0800 From: Binbin Wu To: kvm@vger.kernel.org Cc: seanjc@google.com, pbonzini@redhat.com, chao.gao@intel.com, robert.hu@linux.intel.com, binbin.wu@linux.intel.com Subject: [kvm-unit-tests PATCH v6 1/4] x86: Allow setting of CR3 LAM bits if LAM supported Date: Mon, 22 Jan 2024 16:53:51 +0800 Message-Id: <20240122085354.9510-2-binbin.wu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240122085354.9510-1-binbin.wu@linux.intel.com> References: <20240122085354.9510-1-binbin.wu@linux.intel.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 If LINEAR ADDRESS MASKING (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 44f4fd1e..ca8665b3 100644 --- a/lib/x86/processor.h +++ b/lib/x86/processor.h @@ -68,6 +68,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) @@ -262,6 +264,7 @@ static inline bool is_intel(void) #define X86_FEATURE_FLUSH_L1D (CPUID(0x7, 0, EDX, 28)) #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 c1540d39..63080361 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -7012,7 +7012,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 Mon Jan 22 08:53:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Binbin Wu X-Patchwork-Id: 13524968 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9DDB739FF2 for ; Mon, 22 Jan 2024 08:54:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.10 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705913647; cv=none; b=AyHr52Ubtcm+pyIYhQJjrqhpgKjrqbJ/Lo27S2CzMiOJHrX/dNV5E4VF0FPCZJiFy4nyLjH2QVbpfFNgTrCdON3a/EwDCPjCNh5g7MVd6BRuHdxnEnw/EtmcRnV4RgZuUS6Qnt32lCFU1E5UEGAxbgXFE6dYF/CBTVGuFPEgqok= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705913647; c=relaxed/simple; bh=L9qg4OBLN9P2ovFin71m4mQDbQBCQx4tHeGkeL4Mk1A=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Qa/UUqLonkGX2kZKaRyCB03bX3FHOXHC0wKaAEZ+w6i52p1fyWnRrNMfDk3VZ8G5yIPY0xI3h0F1zRzStoGEKmqz+Uuays/lMp8wRcco7kpWqsXWJLHMGQzwD6uCEtqq3tUxXccK4Z3K2zh0dkThrXHLOHt4QXgIrVOIzYzuxOQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=JGrSxK/K; arc=none smtp.client-ip=192.198.163.10 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="JGrSxK/K" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1705913646; x=1737449646; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=L9qg4OBLN9P2ovFin71m4mQDbQBCQx4tHeGkeL4Mk1A=; b=JGrSxK/K7DMukgTtBuftrzS0p16cbdep/PcfQnKjbYWi/AHjmRYTKz7r zfj8KWBr8KrUxTulBbEdF34NLYzgK4QpP097IOMPSLY+fyW/h/M9qOMzf JK5vfUyspyRpL9mo/NbV4q9ma+YD638mgYPO2plo9k+C922Pl44oTdtj9 uYyjdMRuAEBHfOtWB512zJSRXetNEOwjD1ilZLMfDzWN9I5K1eSMNlSX1 sbqcDzUU3i9rbUPM3JWCO5cyv7kelQQyCWAxm1dwNemvMwniWI1tMoiVe 6/BCPLGY4i1EXC/5v+AdH2xYtvPE0ixEl67F1z2kRx+fAS9slU8XgVjGO g==; X-IronPort-AV: E=McAfee;i="6600,9927,10960"; a="8536155" X-IronPort-AV: E=Sophos;i="6.05,211,1701158400"; d="scan'208";a="8536155" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmvoesa104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jan 2024 00:54:05 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10960"; a="785611601" X-IronPort-AV: E=Sophos;i="6.05,211,1701158400"; d="scan'208";a="785611601" Received: from binbinwu-mobl.ccr.corp.intel.com (HELO binbinwu-mobl.sh.intel.com) ([10.238.10.49]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jan 2024 00:54:02 -0800 From: Binbin Wu To: kvm@vger.kernel.org Cc: seanjc@google.com, pbonzini@redhat.com, chao.gao@intel.com, robert.hu@linux.intel.com, binbin.wu@linux.intel.com Subject: [kvm-unit-tests PATCH v6 2/4] x86: Add test case for LAM_SUP Date: Mon, 22 Jan 2024 16:53:52 +0800 Message-Id: <20240122085354.9510-3-binbin.wu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240122085354.9510-1-binbin.wu@linux.intel.com> References: <20240122085354.9510-1-binbin.wu@linux.intel.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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, Chapter 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 | 10 ++ x86/Makefile.x86_64 | 1 + x86/lam.c | 243 ++++++++++++++++++++++++++++++++++++++++++++ x86/unittests.cfg | 10 ++ 4 files changed, 264 insertions(+) create mode 100644 x86/lam.c diff --git a/lib/x86/processor.h b/lib/x86/processor.h index ca8665b3..2d1fe3f5 100644 --- a/lib/x86/processor.h +++ b/lib/x86/processor.h @@ -8,6 +8,14 @@ #include #define NONCANONICAL 0xaaaaaaaaaaaaaaaaull +#define LAM57_MASK GENMASK_ULL(62, 57) +#define LAM48_MASK GENMASK_ULL(62, 48) + +/* Set metadata with non-canonical pattern in mask bits of a linear address */ +static inline u64 set_la_non_canonical(u64 src, u64 mask) +{ + return (src & ~mask) | (NONCANONICAL & mask); +} #ifdef __x86_64__ # define R "r" @@ -120,6 +128,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 2771a6fa..e5db2365 100644 --- a/x86/Makefile.x86_64 +++ b/x86/Makefile.x86_64 @@ -38,6 +38,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 00000000..0ad16be5 --- /dev/null +++ b/x86/lam.c @@ -0,0 +1,243 @@ +/* + * 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 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); +} + +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_la_non_canonical((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_la_non_canonical((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) +{ + struct invpcid_desc *desc_ptr = (struct invpcid_desc *)desc; + + asm volatile("invpcid %0, %1" : + : "m" (*desc_ptr), "r" (0UL) + : "memory"); +} + +/* LAM doesn't apply to the linear 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_la_non_canonical(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_la_non_canonical((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_la_non_canonical((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; + + /* + * KUT initializes vfree_top to 0 for X86_64, and each virtual address + * allocation decreases the size from vfree_top. It's guaranteed that + * the return value of alloc_vpage() is considered as kernel mode + * address and canonical since only a small mount virtual address range + * is allocated in this test. + */ + 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 3fe59449..224df45b 100644 --- a/x86/unittests.cfg +++ b/x86/unittests.cfg @@ -491,3 +491,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 Mon Jan 22 08:53:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Binbin Wu X-Patchwork-Id: 13524969 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 035AB39FE0 for ; Mon, 22 Jan 2024 08:54:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.10 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705913648; cv=none; b=R079vsuqzO4qHhL4h8e1C1nRZeTY/3x+T2/W5fZbEPMq4hYmMyS+PXF0F9y07KJdUB9oJ5Hj13hMfYOwTWYWr9U6XX5Q95E9db/Hw2TjpqdOkEllUmsdtChJNG5QxndG5XsXPcmQVnGiUhtmMHCNqe/5QQWsWw1wyQxgwSE6tTU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705913648; c=relaxed/simple; bh=FFUtOoz1bz1HFvQ2r50Dm9krPc8fCfiZlQcI23sRTDQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=qmZFyeypV1BI0l9PVZbb6uVYU6We2ou7ElRYwT/nzlgwjKLSz9nqn+FGAAAdAd+WiKH+NeTClFgz4OShwT7hecQC8iOqxko/DciujF88STIy+ifD/7FTXoN7vvV+hh2dw5rN2fNERthfIHVo0hVHhtnKP5fVWpz9e1OWLiEBoLk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=RcXx1sFR; arc=none smtp.client-ip=192.198.163.10 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="RcXx1sFR" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1705913647; x=1737449647; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=FFUtOoz1bz1HFvQ2r50Dm9krPc8fCfiZlQcI23sRTDQ=; b=RcXx1sFR5xZ0iYwfYAiK3vmTqUmEPgNyJpxq64Z6XDJc5Z2YqQc6xmGF ZSkDIfRF8kuMGyuoKBRUW40dOsQk+5mTMKOndgXBCH57Vdp6VLeKci8R9 axLrZrWSWo/us1LUarC+2oiMpASXoDeJt7CCs6rYDxsRWyR8/bZtAM4z8 IHsM5jWAk5pu35QHu5hTJ3GYmkfIUkr215KILmSesBJMRMTVkvb8qU603 sMWMothF6b3W1w8tNBQCCv7Oy3UQY+S7TbJcPrbc/UYVafWRjQ3o5XU7k yzcVd8HSHAoQUndCn6IEbDUONxbfnhztxk4juK9m/R1yJy3cY1XdT2XVw w==; X-IronPort-AV: E=McAfee;i="6600,9927,10960"; a="8536162" X-IronPort-AV: E=Sophos;i="6.05,211,1701158400"; d="scan'208";a="8536162" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmvoesa104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jan 2024 00:54:07 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10960"; a="785611608" X-IronPort-AV: E=Sophos;i="6.05,211,1701158400"; d="scan'208";a="785611608" Received: from binbinwu-mobl.ccr.corp.intel.com (HELO binbinwu-mobl.sh.intel.com) ([10.238.10.49]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jan 2024 00:54:04 -0800 From: Binbin Wu To: kvm@vger.kernel.org Cc: seanjc@google.com, pbonzini@redhat.com, chao.gao@intel.com, robert.hu@linux.intel.com, binbin.wu@linux.intel.com Subject: [kvm-unit-tests PATCH v6 3/4] x86: Add test cases for LAM_{U48,U57} Date: Mon, 22 Jan 2024 16:53:53 +0800 Message-Id: <20240122085354.9510-4-binbin.wu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240122085354.9510-1-binbin.wu@linux.intel.com> References: <20240122085354.9510-1-binbin.wu@linux.intel.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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 | 76 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/lib/x86/processor.h b/lib/x86/processor.h index 2d1fe3f5..e3340f13 100644 --- a/lib/x86/processor.h +++ b/lib/x86/processor.h @@ -77,7 +77,9 @@ static inline u64 set_la_non_canonical(u64 src, u64 mask) #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 0ad16be5..3aa6b313 100644 --- a/x86/lam.c +++ b/x86/lam.c @@ -18,6 +18,9 @@ #include "vm.h" #include "asm/io.h" #include "ioram.h" +#include "usermode.h" + +#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) @@ -38,6 +41,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); +} + static void cr4_set_lam_sup(void *data) { unsigned long cr4; @@ -83,6 +96,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; @@ -96,6 +110,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_la_non_canonical((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; } @@ -220,6 +245,56 @@ 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; + + /* + * The physical address of AREA_NORMAL is within 36 bits, so that using + * identical mapping, the linear address will be considered as user mode + * address from the view of LAM, and the metadata bits are not used as + * address for both LAM48 and LAM57. + */ + paddr = virt_to_phys(alloc_pages_flags(0, AREA_NORMAL)); + _Static_assert((AREA_NORMAL_PFN & GENMASK(63, 47)) == 0UL, + "Identical mapping range check"); + + /* + * Physical memory & MMIO have already been identical mapped in + * setup_mmu(). + */ + 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; @@ -238,6 +313,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 Mon Jan 22 08:53:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Binbin Wu X-Patchwork-Id: 13524970 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8F79B3A1BA for ; Mon, 22 Jan 2024 08:54:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.10 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705913651; cv=none; b=Rr57KZoyFIbaPyez9TCG4UrnFd9jSD00QQV9Mpsf7tLO8VgCZmP3nrk855u7u6xKkqJLDlWBtS6DuN9RfwTc5PSAN3si4rHSHEJsxOvpQSHU9k5IFhO+Udktld6yEyDeqTRVlWpVQXi5f9bSWXHntppPZ0Zx+N4vhaRjcf+qfpA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705913651; c=relaxed/simple; bh=zcz9i0X15s3PV0duA+ICGHzuXb7jOBap7F3wzrHILgQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=G1ZUfkW6itaBbDdpCiaByiO7do3a1HlhMe2N4NFnJfhvVUC7/AxIrul4fNE60yvlQcAetJ9PzMJ9JC1avLk0dkyx9AxKc3oJ3iDihMoBZ4TAwQtcRduki3C3FV2IaJJhKFi5tlhyA++YxVTNOXs8mjof2uupYwQwglcEy86u5eg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=LxLNmZ2F; arc=none smtp.client-ip=192.198.163.10 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="LxLNmZ2F" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1705913650; x=1737449650; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=zcz9i0X15s3PV0duA+ICGHzuXb7jOBap7F3wzrHILgQ=; b=LxLNmZ2F70SjpnT6eztezmA6vWRmNqDIM6qQIPyhx9zkmC0oR1pxG1+T XwqkLHl+xrkzBf9+cQlnqQLETYunAGQx7LTcHORSsjb3bTD6DzxC6qU2Z PRMf3Z5rRXm8S7YzcFOhbhTpn4adw5i6lJmHjyIMlRA44dLNlsNqQkyrM Srb58UWsAztxEQvf+LDlZ8jQNihjeYPmJre3lROgy3ny8bIbqTik5sf6C qE5gjVHzdwlrVRWhPCoHNx9AVJ5wy1ehRnTrkSzyW5bb1/Kvb4WpbQFGZ F4OETEe6HBMpA0r/8vs8H9ixEOflb3AVvgFBkbmwDX9V2X3pnsGEV2uZT g==; X-IronPort-AV: E=McAfee;i="6600,9927,10960"; a="8536178" X-IronPort-AV: E=Sophos;i="6.05,211,1701158400"; d="scan'208";a="8536178" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmvoesa104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jan 2024 00:54:09 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10960"; a="785611618" X-IronPort-AV: E=Sophos;i="6.05,211,1701158400"; d="scan'208";a="785611618" Received: from binbinwu-mobl.ccr.corp.intel.com (HELO binbinwu-mobl.sh.intel.com) ([10.238.10.49]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jan 2024 00:54:06 -0800 From: Binbin Wu To: kvm@vger.kernel.org Cc: seanjc@google.com, pbonzini@redhat.com, chao.gao@intel.com, robert.hu@linux.intel.com, binbin.wu@linux.intel.com Subject: [kvm-unit-tests PATCH v6 4/4] x86: Add test case for INVVPID with LAM Date: Mon, 22 Jan 2024 16:53:54 +0800 Message-Id: <20240122085354.9510-5-binbin.wu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240122085354.9510-1-binbin.wu@linux.intel.com> References: <20240122085354.9510-1-binbin.wu@linux.intel.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 LAM applies to the linear address of INVVPID operand, however, it doesn't apply to the linear address in the INVVPID descriptor. The added cases use tagged operand or tagged target invalidation address to make sure the behaviors are expected when LAM is on. Also, INVVPID case using tagged operand 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 | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index 63080361..a855bdcb 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -3220,6 +3220,48 @@ static void invvpid_test_not_in_vmx_operation(void) TEST_ASSERT(!vmx_on()); } +/* LAM doesn't apply to the linear 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; + } + write_cr4(read_cr4() | X86_CR4_LAM_SUP); + + 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; + operand = (struct invvpid_operand *)set_la_non_canonical((u64)operand, + lam_mask); + fault = test_for_exception(GP_VECTOR, ds_invvpid, operand); + report(!fault, "INVVPID (LAM on): tagged operand"); + + /* + * Verify that LAM doesn't apply to the address inside the descriptor + * even when LAM is enabled. i.e., the address in the descriptor should + * be canonical. + */ + try_invvpid(INVVPID_ADDR, 0xffff, (u64)operand); + + write_cr4(read_cr4() & ~X86_CR4_LAM_SUP); +} + /* * This does not test real-address mode, virtual-8086 mode, protected mode, * or CPL > 0. @@ -3269,8 +3311,10 @@ static void invvpid_test(void) /* * The gla operand is only validated for single-address INVVPID. */ - if (types & (1u << INVVPID_ADDR)) + if (types & (1u << INVVPID_ADDR)) { try_invvpid(INVVPID_ADDR, 0xffff, NONCANONICAL); + invvpid_test_lam(); + } invvpid_test_gp(); invvpid_test_ss();