From nobody Sat Oct 3 03:45:34 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.14]) (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 957D438B157; Thu, 6 Aug 2026 01:18:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785979126; cv=none; b=OpFTM+3ngJsdwkPmb29b6eqmIcA38dmCJshMYveLdfRpnQYRGXT9urwgyUPJTHxZhrIdNYJHudb+6m+tVqOz2SH4mKdMhqPxV7bp3xpt/mpAQc8mZrN6vI9rm0clgzezXK7CnVOfKyYWmWQug/beofnw5qrqelXi6VRyA6/6vww= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785979126; c=relaxed/simple; bh=Knn5l140lFqaaJ/Gr+gnBzcJZqTLYOqtJFCFTuDq9ao=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=V1SZuhd7TzRBlyH3nO4mUNzitXlX17iu5gPHA6zqyJaOhOrzPOGVaR+5QX567DvtdwqWudNUefPvYJg8D3Mn6LVfOR8u5nk9gAMutfqPeSk2QAwzL9CiWL6fYrLDYavO1Yi4f224wgbRE59oWHeSKf1c4Ij2GSdkftmZN3HG5WA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=mmHf4mZR; arc=none smtp.client-ip=192.198.163.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="mmHf4mZR" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1785979124; x=1817515124; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Knn5l140lFqaaJ/Gr+gnBzcJZqTLYOqtJFCFTuDq9ao=; b=mmHf4mZRleuw6OYxCzg9NwF5InecaJnIxjsWAFINZ1pmW3dP7ZKSroC7 IsNn8cWsb1KPJgXTg65W5q17+JZalW1B6jb9p0XPrf1ZpzzGT2xEX4ki1 vVlG7O2IRUeR+Tl8xzxZqkozD87xWQXQ4cYgHW+1mM7VqTXmsTDk/pm+v 5PTxCPmjNSUkgBbQQC+VLti/h3b2eXuNt6hGpfqEVVFWDqNuYfZtK3un4 rqjmmnzr536Gt6qZlrTgaY1pIuSI+16TIei6yyQlN8wNVate7tYKvh19X +NkgG6VpMuuFIrMzhcgIjFjWio5YLIPxxU87JWMgMBHX+CQcvM31kReMW A==; X-CSE-ConnectionGUID: Ki4RSQkVQ8a7oDBU/6kY0Q== X-CSE-MsgGUID: BHijKYlBTSSpWKd3kmHsSg== X-IronPort-AV: E=McAfee;i="6800,10657,11866"; a="86593970" X-IronPort-AV: E=Sophos;i="6.25,207,1779174000"; d="scan'208";a="86593970" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by fmvoesa108.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Aug 2026 18:18:43 -0700 X-CSE-ConnectionGUID: ZJdDaGpwRdKP80VJGSfoyg== X-CSE-MsgGUID: L5tTlltwQWeRSQEl3SX43Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,207,1779174000"; d="scan'208";a="265804607" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa004.jf.intel.com with ESMTP; 05 Aug 2026 18:18:43 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Sean Christopherson , Paolo Bonzini , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Shuah Khan , Binbin Wu , Peter Zijlstra , "Chang S . Bae" , Kai Huang , Fuad Tabba , Chao Gao , Yosry Ahmed , Claudio Imbrenda , David Matlack , Bala-Vignesh-Reddy , Kishen Maloor , Rick Edgecombe , Sohil Mehta , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v4 1/7] KVM: x86: Add an emulator flag to differentiate branch targets from fetches Date: Wed, 5 Aug 2026 18:15:30 -0700 Message-ID: <20260806011536.4172258-2-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260806011536.4172258-1-sohil.mehta@intel.com> References: <20260806011536.4172258-1-sohil.mehta@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Binbin Wu Add a new emulator flag, X86EMUL_F_BRANCH, and use it instead of X86EMUL_F_FETCH in assign_eip() to distinguish between instruction fetch and branch target computation for features that handle them differently. For example, Linear Address Space Separation (LASS) applies to code fetches but not branch target calculations. A LASS violation occurs only when the branch target is used to fetch an instruction. X86EMUL_F_BRANCH is still a code access, so add it to the code segment readability check in __linearize() along with the Linear Address Masking (LAM) untagging exemption in vmx_get_untagged_addr(). For now, X86EMUL_F_BRANCH and X86EMUL_F_FETCH are identical as far as KVM is concerned. No functional change intended. Signed-off-by: Binbin Wu Signed-off-by: Sohil Mehta Tested-by: Farrah Chen Tested-by: Kishen Maloor --- v4: - Added LAM untagging exemption - Reworded the commit message --- arch/x86/kvm/emulate.c | 5 +++-- arch/x86/kvm/kvm_emulate.h | 1 + arch/x86/kvm/vmx/vmx.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 8071b372d233..8ff28643b2e3 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -672,7 +672,8 @@ static __always_inline int __linearize(struct x86_emula= te_ctxt *ctxt, (flags & X86EMUL_F_WRITE)) goto bad; /* unreadable code segment */ - if (!(flags & X86EMUL_F_FETCH) && (desc.type & 8) && !(desc.type & 2)) + if (!(flags & (X86EMUL_F_FETCH | X86EMUL_F_BRANCH)) && + (desc.type & 8) && !(desc.type & 2)) goto bad; lim =3D desc_limit_scaled(&desc); if (!(desc.type & 8) && (desc.type & 4)) { @@ -723,7 +724,7 @@ static inline int assign_eip(struct x86_emulate_ctxt *c= txt, ulong dst) if (ctxt->op_bytes !=3D sizeof(unsigned long)) addr.ea =3D dst & ((1UL << (ctxt->op_bytes << 3)) - 1); rc =3D __linearize(ctxt, addr, &max_size, 1, ctxt->mode, &linear, - X86EMUL_F_FETCH); + X86EMUL_F_BRANCH); if (rc =3D=3D X86EMUL_CONTINUE) ctxt->_eip =3D addr.ea; return rc; diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h index 3e375af15c03..97421b8dde13 100644 --- a/arch/x86/kvm/kvm_emulate.h +++ b/arch/x86/kvm/kvm_emulate.h @@ -105,6 +105,7 @@ struct x86_instruction_info { #define X86EMUL_F_INVLPG BIT(3) #define X86EMUL_F_MSR BIT(4) #define X86EMUL_F_DT_LOAD BIT(5) +#define X86EMUL_F_BRANCH BIT(6) =20 struct x86_emulate_ops { void (*vm_bugged)(struct x86_emulate_ctxt *ctxt); diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index e3bfe6aca1a0..973f7e95be65 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -8571,7 +8571,8 @@ gva_t vmx_get_untagged_addr(struct kvm_vcpu *vcpu, gv= a_t gva, unsigned int flags int lam_bit; unsigned long cr3_bits; =20 - if (flags & (X86EMUL_F_FETCH | X86EMUL_F_IMPLICIT | X86EMUL_F_INVLPG)) + if (flags & (X86EMUL_F_FETCH | X86EMUL_F_BRANCH | X86EMUL_F_IMPLICIT | + X86EMUL_F_INVLPG)) return gva; =20 if (!is_64_bit_mode(vcpu)) --=20 2.43.0 From nobody Sat Oct 3 03:45:34 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.14]) (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 1433C386575; Thu, 6 Aug 2026 01:18:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785979128; cv=none; b=gU3PqFOqSuCSMEyN92eBhIdYVK39TQiSxKuf54GRWTU4RnpFNn2d6+XhfbK4BwlSdvcNuGp023avXdOA9aFCanZIyC61NMnxezt95mEt53MWkAj+SWyv/0PtkznYOSOKUFSFdmi7wdAvot9LNDV5Dt7r25P9bfCFZdrC8x8rRGA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785979128; c=relaxed/simple; bh=S2TitmZwd4JpU98ZMVHZQlXK31LYwmA7iDIOrBEUlk4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=U/o1z7WYNH3U8SzckgTk5HE3srV6Z0qadj9LJ0qV0Ftew19YsAXEEH3bkf6cE+7NE2bmXU0Gh76RkqCWHz6/EsNEXXclqskExeHkYgnITloLzQDZ7gdO3Ena/JNB5lpvb3y+zTegRJpxYEHV1rx62efagJvkpnVGL2GAqY4ycEI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=SSsNf+lR; arc=none smtp.client-ip=192.198.163.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="SSsNf+lR" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1785979126; x=1817515126; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=S2TitmZwd4JpU98ZMVHZQlXK31LYwmA7iDIOrBEUlk4=; b=SSsNf+lRh5lxSPCyZDHjMEfg37JEfHDM8qb0+7U72tcDBAhhjhm67QPY +YRAeC42WGwHE3ajCw9dJlscAfny0CijA5dc5L7Ya+9o/Octtr7t5GSj4 xbqtBOZgES4++y0rhYqnb/FLyawNW1Vzp3QH198idoOzKLBYWRID11cGc +f89srOTYPegh6naYyYZZGGmY0FvtOoxT8JnQktTjQ0/ckSX1Iw0oTiuC g/GA0YBMWL2asxrbQafPDXpflitnElCjK7rFOSuZZerQtCT2776pi2zni 34fh0dJVOGkjdxLR4PtnlGv2nYwr4MIPqLyNrOdQ82rShiY2vuYxd8Uvz A==; X-CSE-ConnectionGUID: lRKrOrnRQuuDDp7Hpzfmig== X-CSE-MsgGUID: UoPsNI+BQdSo2U38/tumyw== X-IronPort-AV: E=McAfee;i="6800,10657,11866"; a="86593980" X-IronPort-AV: E=Sophos;i="6.25,207,1779174000"; d="scan'208";a="86593980" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by fmvoesa108.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Aug 2026 18:18:44 -0700 X-CSE-ConnectionGUID: pE8RSMmuT6+v4lS+kzg6bA== X-CSE-MsgGUID: ZtBLhCP8T8mV69Z4tqjtVw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,207,1779174000"; d="scan'208";a="265804610" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa004.jf.intel.com with ESMTP; 05 Aug 2026 18:18:43 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Sean Christopherson , Paolo Bonzini , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Shuah Khan , Binbin Wu , Peter Zijlstra , "Chang S . Bae" , Kai Huang , Fuad Tabba , Chao Gao , Yosry Ahmed , Claudio Imbrenda , David Matlack , Bala-Vignesh-Reddy , Kishen Maloor , Rick Edgecombe , Sohil Mehta , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v4 2/7] KVM: x86: Use linear_read_system() to read the TSS I/O bitmap Date: Wed, 5 Aug 2026 18:15:31 -0700 Message-ID: <20260806011536.4172258-3-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260806011536.4172258-1-sohil.mehta@intel.com> References: <20260806011536.4172258-1-sohil.mehta@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" TSS I/O permission bitmap reads are implicit supervisor accesses which are subject to Linear Address Space Separation (LASS) enforcement. Though highly unlikely, if a guest configures a TSS base in the user half, hardware would raise a #GP on access when LASS is enabled. Currently, the emulator reads the I/O permission bitmap from the TSS by calling read_std() directly which is inconsistent with other implicit accesses in the emulator such as IDT reads, GDT/LDT reads and TSS reads during task switch. An upcoming change will add a check to linear_read_system() to catch LASS violations. For consistency as well as to keep LASS enforcement centralized, switch both I/O bitmap reads to linear_read_system(). Note, emulator_io_port_access_allowed() doesn't propagate faults, so even though linear_read_system() will set the exception details they will be ignored. While at it, fix an off-by-one in the I/O bitmap bounds check to account for the 2-byte read and ensure both bytes are within the TSS limit. The SDM mandates a trailing 0xFF byte after the bitmap so any out-of-bounds access would be all 1s (denying access). Make the change primarily to ensure hardware fidelity. A correctly configured OS will not run into this issue. Signed-off-by: Sohil Mehta Tested-by: Farrah Chen Tested-by: Kishen Maloor --- v4: - New patch There could be a pre-existing issue here. It is unlikely that any OS demand-pages the I/O bitmap portion of the TSS. But if it does, the #PF details could get lost and the guest would get a #GP instead of a restartable #PF. Propagating the #PF to the callers is a larger change that is beyond the scope of this series. --- arch/x86/kvm/emulate.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 8ff28643b2e3..7f04544cfee5 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -2573,12 +2573,12 @@ static bool emulator_io_port_access_allowed(struct = x86_emulate_ctxt *ctxt, #ifdef CONFIG_X86_64 base |=3D ((u64)base3) << 32; #endif - r =3D ops->read_std(ctxt, base + 102, &io_bitmap_ptr, 2, NULL, true); + r =3D linear_read_system(ctxt, base + 102, &io_bitmap_ptr, 2); if (r !=3D X86EMUL_CONTINUE) return false; - if (io_bitmap_ptr + port/8 > desc_limit_scaled(&tr_seg)) + if (io_bitmap_ptr + port/8 + 1 > desc_limit_scaled(&tr_seg)) return false; - r =3D ops->read_std(ctxt, base + io_bitmap_ptr + port/8, &perm, 2, NULL, = true); + r =3D linear_read_system(ctxt, base + io_bitmap_ptr + port/8, &perm, 2); if (r !=3D X86EMUL_CONTINUE) return false; if ((perm >> bit_idx) & mask) --=20 2.43.0 From nobody Sat Oct 3 03:45:34 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.14]) (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 564903AA9F8; Thu, 6 Aug 2026 01:18:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785979128; cv=none; b=RcgT/wYtq+01VnSfl6Bk2FjPOdDPYZDQqgmJG0GqrenQ09eFdlFOTYT2qm4hGvcsFvAec4sniP1t0z3deKTKSq7dthjl6peTXT3ZXhJ83s7v0RECrx++g8qy2nhz6AVGmJtEAX9Fh4tDn+lqopu26QksnIZ/h/LGgjkxzz7j6Zg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785979128; c=relaxed/simple; bh=GQYT6sb5UlBNgU+qYqrDwbOdsyfYfWJMXudd9GDVMf4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JhLDYJ5ux2Gw02JJFEyhTreXyKrZoTUeGuHfgoYlBR6sDWnbMrxNzHtMYEI4S4b6YilAtPpQJWlxrd7i/0xdyEaFPQ3qnlSO/qxLcJ58dicwZt3UMdUgfJ+FytA8ZR8cjy4l7+2RTlmYno/tA/O7+QWtC09F8l02Nj8DKC34dRI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=L2g3XP1J; arc=none smtp.client-ip=192.198.163.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="L2g3XP1J" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1785979126; x=1817515126; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=GQYT6sb5UlBNgU+qYqrDwbOdsyfYfWJMXudd9GDVMf4=; b=L2g3XP1JaWD58PDOPARPdYt+FrhsNfv4bIh16n43nD516+bnnQRdHJ1H 1z0fWuqiwhDKQfAYhwsYLGVLpOxDVC414MuWx/tOfsS8sIuIjCliFCvf4 lxYkswxGV+qqnCdhQAdKStmTSAul94KEvtdqjTGLqT1SV5Hawr4xR8E58 QyL7ufJc5qs8rTMCQxhn3Sq34aG3hTEbfs4UWfdVygTEaYOcNGqUSHHiJ UKX1mXe44sxS8bIiU73mDDIHUAb4z6qWGWBrHQNLTImLYdTZCkxvaVgmF StqcB48InGKijy/5ExkVfdqiqV75mLlMXsGTYuaaZqPeW+gnuqyfq4A5/ w==; X-CSE-ConnectionGUID: Tc+iY2MKSju3r1yDCiEnPw== X-CSE-MsgGUID: YGTa24pVSreHTZys0IgFbQ== X-IronPort-AV: E=McAfee;i="6800,10657,11866"; a="86593990" X-IronPort-AV: E=Sophos;i="6.25,207,1779174000"; d="scan'208";a="86593990" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by fmvoesa108.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Aug 2026 18:18:44 -0700 X-CSE-ConnectionGUID: fcE+frd2RJq3S21b9ydyrA== X-CSE-MsgGUID: 5X1MAht6TbePGGGdveIxjg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,207,1779174000"; d="scan'208";a="265804614" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa004.jf.intel.com with ESMTP; 05 Aug 2026 18:18:44 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Sean Christopherson , Paolo Bonzini , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Shuah Khan , Binbin Wu , Peter Zijlstra , "Chang S . Bae" , Kai Huang , Fuad Tabba , Chao Gao , Yosry Ahmed , Claudio Imbrenda , David Matlack , Bala-Vignesh-Reddy , Kishen Maloor , Rick Edgecombe , Sohil Mehta , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v4 3/7] KVM: x86: Add LASS violation checks during instruction emulation Date: Wed, 5 Aug 2026 18:15:32 -0700 Message-ID: <20260806011536.4172258-4-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260806011536.4172258-1-sohil.mehta@intel.com> References: <20260806011536.4172258-1-sohil.mehta@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Zeng Guang When Linear Address Space Separation (LASS) is enabled, the processor applies a LASS violation check on every access to a linear address. To align with hardware behavior, KVM needs to perform the same check during instruction emulation before consulting the page tables. Add a new callback to x86_emulate_ops to let the emulator query whether an access would trigger a LASS violation. The callback takes the linear address and the size that describe the memory access, plus a set of flags that convey the type of access. Add the LASS violation check to __linearize() so that every explicit guest memory access is validated along with the other linear address checks. The SDM (June 2026), Vol3, Chapter 4, specifically states that there is no relative ordering between the canonicality check and the LASS violation check. Also, there is no prioritization specified between the faults generated by alignment checks and LASS violations. Implicit supervisor accesses bypass __linearize(). So, add LASS checks for those in linear_read_system() and linear_write_system() and tag the access as implicit. For now, emulator_is_lass_violation() is a no-op. Later, it will be wired up to the VMX implementation. Signed-off-by: Zeng Guang Signed-off-by: Binbin Wu Signed-off-by: Sohil Mehta Reviewed-by: Binbin Wu Tested-by: Farrah Chen Tested-by: Kishen Maloor --- v4: - Switched to using gva_t for the address parameter - Clarified LASS and canonicality checks and alignment checks ordering - Reworded the commit message - Use kvm_x86_call() instead of static_call() Note, internal AI review warns about missing canonicality checks during implicit accesses. A valid guest kernel shouldn't trigger canonicality faults. But for correctness, such checks could be considered. Though, that is beyond the scope of this series. --- arch/x86/include/asm/kvm-x86-ops.h | 1 + arch/x86/include/asm/kvm_host.h | 2 ++ arch/x86/kvm/emulate.c | 17 +++++++++++++++++ arch/x86/kvm/kvm_emulate.h | 3 ++- arch/x86/kvm/x86.c | 7 +++++++ 5 files changed, 29 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-= x86-ops.h index e213c9ae3e30..a82b20281f31 100644 --- a/arch/x86/include/asm/kvm-x86-ops.h +++ b/arch/x86/include/asm/kvm-x86-ops.h @@ -146,6 +146,7 @@ KVM_X86_OP(complete_emulated_msr) KVM_X86_OP(vcpu_deliver_sipi_vector) KVM_X86_OP_OPTIONAL_RET0(vcpu_get_apicv_inhibit_reasons); KVM_X86_OP_OPTIONAL(get_untagged_addr) +KVM_X86_OP_OPTIONAL_RET0(is_lass_violation) KVM_X86_OP_OPTIONAL(alloc_apic_backing_page) #ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT KVM_X86_OP_OPTIONAL_RET0(gmem_make_private) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index 283847619ff8..d2181a805ace 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1727,6 +1727,8 @@ struct kvm_x86_ops { unsigned long (*vcpu_get_apicv_inhibit_reasons)(struct kvm_vcpu *vcpu); =20 gva_t (*get_untagged_addr)(struct kvm_vcpu *vcpu, gva_t gva, unsigned int= flags); + bool (*is_lass_violation)(struct kvm_vcpu *vcpu, gva_t gva, + unsigned int size, unsigned int flags); void *(*alloc_apic_backing_page)(struct kvm_vcpu *vcpu); #ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT int (*gmem_make_private)(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 7f04544cfee5..9cbfde649064 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -693,6 +693,16 @@ static __always_inline int __linearize(struct x86_emul= ate_ctxt *ctxt, } break; } + + /* + * LASS and canonicality checks generate the same fault and + * their relative order is not architecturally defined. Also, + * the SDM doesn't prioritize LASS violations against + * alignment-check faults, so any order is legal. + */ + if (ctxt->ops->is_lass_violation(ctxt, la, size, flags)) + goto bad; + if (la & (insn_alignment(ctxt, size) - 1)) return emulate_gp(ctxt, 0); return X86EMUL_CONTINUE; @@ -799,6 +809,9 @@ static inline int jmp_rel(struct x86_emulate_ctxt *ctxt= , int rel) static int linear_read_system(struct x86_emulate_ctxt *ctxt, ulong linear, void *data, unsigned size) { + if (ctxt->ops->is_lass_violation(ctxt, linear, size, X86EMUL_F_IMPLICIT)) + return emulate_gp(ctxt, 0); + return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception, tr= ue); } =20 @@ -806,6 +819,10 @@ static int linear_write_system(struct x86_emulate_ctxt= *ctxt, ulong linear, void *data, unsigned int size) { + if (ctxt->ops->is_lass_violation(ctxt, linear, size, + X86EMUL_F_IMPLICIT | X86EMUL_F_WRITE)) + return emulate_gp(ctxt, 0); + return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception, t= rue); } =20 diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h index 97421b8dde13..f136d3d0ba42 100644 --- a/arch/x86/kvm/kvm_emulate.h +++ b/arch/x86/kvm/kvm_emulate.h @@ -249,7 +249,8 @@ struct x86_emulate_ops { =20 gva_t (*get_untagged_addr)(struct x86_emulate_ctxt *ctxt, gva_t addr, unsigned int flags); - + bool (*is_lass_violation)(struct x86_emulate_ctxt *ctxt, gva_t addr, + unsigned int size, unsigned int flags); bool (*is_canonical_addr)(struct x86_emulate_ctxt *ctxt, gva_t addr, unsigned int flags); =20 diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index d94b59140c45..70c8439312c3 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5800,6 +5800,12 @@ static gva_t emulator_get_untagged_addr(struct x86_e= mulate_ctxt *ctxt, addr, flags); } =20 +static bool emulator_is_lass_violation(struct x86_emulate_ctxt *ctxt, gva_= t addr, + unsigned int size, unsigned int flags) +{ + return kvm_x86_call(is_lass_violation)(emul_to_vcpu(ctxt), addr, size, fl= ags); +} + static bool emulator_is_canonical_addr(struct x86_emulate_ctxt *ctxt, gva_t addr, unsigned int flags) { @@ -5859,6 +5865,7 @@ static const struct x86_emulate_ops emulate_ops =3D { .get_xcr =3D emulator_get_xcr, .set_xcr =3D emulator_set_xcr, .get_untagged_addr =3D emulator_get_untagged_addr, + .is_lass_violation =3D emulator_is_lass_violation, .is_canonical_addr =3D emulator_is_canonical_addr, .page_address_valid =3D emulator_page_address_valid, }; --=20 2.43.0 From nobody Sat Oct 3 03:45:34 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.14]) (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 75EAF3ACF17; Thu, 6 Aug 2026 01:18:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785979128; cv=none; b=MI4QF+OJzHCwR9PkvubyXTpXsdwC9M2N9MCmwUaZa/Y6e6DlG9HZFOpLNUYTdj7wLrfm/wvU3dDUllCV63cOcopwXHySG84ShmOaq0PdjCOjeyA6VBZSwo96Mtwy3lrHkFuWYu2mH0lOKInNU5fyxEIYTUyqnjFIlLJEuG8Kr74= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785979128; c=relaxed/simple; bh=4o9xDC7SR3KpJwNEh2CBq2GIjuP6VSzx+X5j5D6K6yg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ENXBYHTCoAc9Ey9KLR3re2kFBgmgPm54OGxAWaaW8Gth6c2fcGfmsOawFPXcCfxASGNa7J4pGGTnrfIDplOxLHphqb5+o7oL9NXnMSY8db9J0kx8BF+9RYjbstAnH3mDCLtFkw8pNoHHbri3YhaeV2I2ilK6A8UTxmF9jFrJ7IA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=AN/jrht7; arc=none smtp.client-ip=192.198.163.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="AN/jrht7" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1785979126; x=1817515126; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=4o9xDC7SR3KpJwNEh2CBq2GIjuP6VSzx+X5j5D6K6yg=; b=AN/jrht77tQRkp7WF/3Tvc9EPFJNkrTHwik8fxIc35p4dnzA2uNgi52n XyeMitcFoRIUCJJieSoTCUJrmhZJVrXQLkCXZxH6bLL7rrVDjECnmdxwV RTOb5P+/09hX4UTPQlei5dyjr40utcM2kf4JHnJ9QL64TajveUdwsuY+b VZLk4co546FqQlBX0cqBepcyeZR8K3XcpHubzeaTzbd2OJr1736lzEdwL rh59RMls6ayCRLYURHggZPDJ1bzXMoLTuVVSKcFM/XEP3ix1MgAQPVCvp 53/5wo7T/7NGcx35ZPUBWuT9YfwRpkkuQLOf5ngnG06KOXjMLf3z7U/qc Q==; X-CSE-ConnectionGUID: E9IBveVtR32LtU6+tVqMmw== X-CSE-MsgGUID: 5BfVq1WrTPKoYuLScjs77Q== X-IronPort-AV: E=McAfee;i="6800,10657,11866"; a="86594000" X-IronPort-AV: E=Sophos;i="6.25,207,1779174000"; d="scan'208";a="86594000" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by fmvoesa108.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Aug 2026 18:18:45 -0700 X-CSE-ConnectionGUID: NAdYo6EMSDK6ROnkxKKcxw== X-CSE-MsgGUID: b61DikfoS5eK38XeXodP1Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,207,1779174000"; d="scan'208";a="265804618" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa004.jf.intel.com with ESMTP; 05 Aug 2026 18:18:45 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Sean Christopherson , Paolo Bonzini , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Shuah Khan , Binbin Wu , Peter Zijlstra , "Chang S . Bae" , Kai Huang , Fuad Tabba , Chao Gao , Yosry Ahmed , Claudio Imbrenda , David Matlack , Bala-Vignesh-Reddy , Kishen Maloor , Rick Edgecombe , Sohil Mehta , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v4 4/7] KVM: VMX: Implement LASS violation check Date: Wed, 5 Aug 2026 18:15:33 -0700 Message-ID: <20260806011536.4172258-5-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260806011536.4172258-1-sohil.mehta@intel.com> References: <20260806011536.4172258-1-sohil.mehta@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Zeng Guang Add a VMX implementation of the is_lass_violation() hook to let KVM detect Linear Address Space Separation (LASS) violations on linear addresses generated during emulation. LASS uses bit 63 of the linear address to determine which half of the address space is being targeted, and reports a violation when that half doesn't match the current privilege level. Note, LASS takes effect only in IA-32e mode; it is ignored in legacy mode. LASS enforcement for supervisor-mode data accesses additionally requires SMAP to be enabled, and is suppressed for explicit accesses when RFLAGS.AC=3D1. Enforce LASS violations on emulated instruction fetches and data accesses, including implicit supervisor accesses, so that the mode-based protections are applied before paging. Also enforce LASS on the linear addresses consumed by emulated VMX and SGX ENCLS instructions. Linear addresses used for TLB invalidation (INVLPG, INVPCID, and INVVPID) and branch targets are not subject to LASS enforcement. Signed-off-by: Zeng Guang Signed-off-by: Binbin Wu Signed-off-by: Sohil Mehta Reviewed-by: Binbin Wu Tested-by: Farrah Chen Tested-by: Kishen Maloor --- v4: - Switch to using gva_t for the address argument - Split patch diff and reworded the commit message --- arch/x86/kvm/vmx/main.c | 1 + arch/x86/kvm/vmx/nested.c | 11 ++++----- arch/x86/kvm/vmx/sgx.c | 3 ++- arch/x86/kvm/vmx/vmx.c | 47 +++++++++++++++++++++++++++++++++++++++ arch/x86/kvm/vmx/vmx.h | 3 +++ arch/x86/kvm/x86.c | 2 +- 6 files changed, 60 insertions(+), 7 deletions(-) diff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c index 0ff3230fd95e..3580aada8d2c 100644 --- a/arch/x86/kvm/vmx/main.c +++ b/arch/x86/kvm/vmx/main.c @@ -1031,6 +1031,7 @@ struct kvm_x86_ops vt_x86_ops __initdata =3D { .vcpu_deliver_sipi_vector =3D kvm_vcpu_deliver_sipi_vector, =20 .get_untagged_addr =3D vmx_get_untagged_addr, + .is_lass_violation =3D vmx_is_lass_violation, =20 .mem_enc_ioctl =3D vt_op_tdx_only(mem_enc_ioctl), .vcpu_mem_enc_ioctl =3D vt_op_tdx_only(vcpu_mem_enc_ioctl), diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 7ed79894d11d..61cf20cc4705 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -5299,11 +5299,12 @@ int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsi= gned long exit_qualification, *ret =3D off; =20 *ret =3D vmx_get_untagged_addr(vcpu, *ret, 0); - /* Long mode: #GP(0)/#SS(0) if the memory address is in a - * non-canonical form. This is the only check on the memory - * destination for long mode! + /* + * Long mode: #GP(0)/#SS(0) if the memory address is in a + * non-canonical form, or if the access violates LASS. */ - exn =3D is_noncanonical_address(*ret, vcpu, 0); + exn =3D is_noncanonical_address(*ret, vcpu, 0) || + vmx_is_lass_violation(vcpu, *ret, len, 0); } else { /* * When not in long mode, the virtual/linear address is @@ -6108,7 +6109,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) if (type !=3D VMX_VPID_EXTENT_ALL_CONTEXT && !operand.vpid) return nested_vmx_fail(vcpu, VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); =20 - /* LAM doesn't apply to addresses that are inputs to TLB invalidation. */ + /* LAM and LASS don't apply to addresses that are inputs to TLB invalidat= ion. */ if (type =3D=3D VMX_VPID_EXTENT_INDIVIDUAL_ADDR && is_noncanonical_invlpg_address(operand.gla, vcpu)) return nested_vmx_fail(vcpu, VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); diff --git a/arch/x86/kvm/vmx/sgx.c b/arch/x86/kvm/vmx/sgx.c index 771c75a58343..4ac305ed6dea 100644 --- a/arch/x86/kvm/vmx/sgx.c +++ b/arch/x86/kvm/vmx/sgx.c @@ -39,7 +39,8 @@ static int sgx_get_encls_gva(struct kvm_vcpu *vcpu, unsig= ned long offset, fault =3D true; } else if (likely(is_64_bit_mode(vcpu))) { *gva =3D vmx_get_untagged_addr(vcpu, *gva, 0); - fault =3D is_noncanonical_address(*gva, vcpu, 0); + fault =3D is_noncanonical_address(*gva, vcpu, 0) || + vmx_is_lass_violation(vcpu, *gva, size, 0); } else { *gva &=3D 0xffffffff; fault =3D (s.unusable) || diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 973f7e95be65..ecd105f35c78 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -8604,6 +8604,53 @@ gva_t vmx_get_untagged_addr(struct kvm_vcpu *vcpu, g= va_t gva, unsigned int flags return (sign_extend64(gva, lam_bit) & ~BIT_ULL(63)) | (gva & BIT_ULL(63)); } =20 +bool vmx_is_lass_violation(struct kvm_vcpu *vcpu, gva_t gva, + unsigned int size, unsigned int flags) +{ + const bool is_supervisor_address =3D !!(gva & BIT_ULL(63)); + const bool implicit_supervisor =3D !!(flags & X86EMUL_F_IMPLICIT); + const bool fetch =3D !!(flags & X86EMUL_F_FETCH); + + if (!kvm_is_cr4_bit_set(vcpu, X86_CR4_LASS) || !is_long_mode(vcpu)) + return false; + + /* + * INVLPG isn't subject to LASS, e.g. to allow invalidating userspace + * addresses without toggling RFLAGS.AC. Branch targets aren't subject + * to LASS in order to simplify far control transfers (the subsequent + * fetch will enforce LASS as appropriate). + */ + if (flags & (X86EMUL_F_BRANCH | X86EMUL_F_INVLPG)) + return false; + + if (!implicit_supervisor && vmx_get_cpl(vcpu) =3D=3D 3) + return is_supervisor_address; + + /* + * LASS enforcement for supervisor-mode data accesses depends on SMAP + * being enabled, and like SMAP ignores explicit accesses if RFLAGS.AC=3D= 1. + */ + if (!fetch) { + if (!kvm_is_cr4_bit_set(vcpu, X86_CR4_SMAP)) + return false; + + if (!implicit_supervisor && (kvm_get_rflags(vcpu) & X86_EFLAGS_AC)) + return false; + } + + /* + * The entire access must be in the appropriate address space. Note, + * if LAM is supported, @gva has already been untagged, so barring a + * massive architecture change to expand the canonical address range, + * it's impossible for a user access to straddle user and supervisor + * address spaces. + */ + if (size && !((gva + size - 1) & BIT_ULL(63))) + return true; + + return !is_supervisor_address; +} + static unsigned int vmx_handle_intel_pt_intr(void) { struct kvm_vcpu *vcpu =3D kvm_get_running_vcpu(); diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index dc8517f15bc4..43df725a77f0 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -397,6 +397,9 @@ u64 vmx_get_l2_tsc_multiplier(struct kvm_vcpu *vcpu); =20 gva_t vmx_get_untagged_addr(struct kvm_vcpu *vcpu, gva_t gva, unsigned int= flags); =20 +bool vmx_is_lass_violation(struct kvm_vcpu *vcpu, gva_t gva, + unsigned int size, unsigned int flags); + void vmx_update_cpu_dirty_logging(struct kvm_vcpu *vcpu); =20 u64 vmx_get_supported_debugctl(struct kvm_vcpu *vcpu, bool host_initiated); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 70c8439312c3..a6ea736fd48f 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -10752,7 +10752,7 @@ int kvm_handle_invpcid(struct kvm_vcpu *vcpu, unsig= ned long type, gva_t gva) switch (type) { case INVPCID_TYPE_INDIV_ADDR: /* - * LAM doesn't apply to addresses that are inputs to TLB + * LAM and LASS don't apply to addresses that are inputs to TLB * invalidation. */ if ((!pcid_enabled && (operand.pcid !=3D 0)) || --=20 2.43.0 From nobody Sat Oct 3 03:45:34 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.14]) (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 65DB63B101D; Thu, 6 Aug 2026 01:18:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785979130; cv=none; b=kUlluO1gCIJ+asOu3/L3DERtQ/ylSGpIIQI9aDq0lb4BiQFVb+Y2riPaFj08kL4cQzPhC54U/zKhjLpidAIoPSzdt2AkGDpJGMs22FPRn6K3RTQuN6/0EejX8ychT4dgzUN+KkoIbgk7Id9Kmz0R6WNzFunK1esrkkNCHjB5uUE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785979130; c=relaxed/simple; bh=+RfBcLbFUN/D147MllSCMMdSCWzEhZhyPSzs2MYGYSk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rNmMjd61wzXKGZKjahBC4ReMYpnGmhkxdw5xT+WNwXNU9QUILgEIRxHGaBJ/zNtRyFkYYLQiaCIOyLx8VrsWHxTm9rFNUN6vWejmg8SqrRBlY9fzUr3Tecb9+aIKUL9rySuBk0IItftvHN4nr/xvXsyn+TP4wTCndXmbdEf6e6E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=BwUzRKKC; arc=none smtp.client-ip=192.198.163.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="BwUzRKKC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1785979128; x=1817515128; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+RfBcLbFUN/D147MllSCMMdSCWzEhZhyPSzs2MYGYSk=; b=BwUzRKKCu41AH884yTuqFjitLZ47QK8HzNW3Y2CUTCn0NbflPLGhA1sa Ep2bpFx5TkK1Vgy7ihZ7USbpLl2hkyaPEX0/J+qQQ1iZiIMiRjvfjC8M3 o9lJS+rU/CCcpoh3/1KACmaTElxfN+Gk+/pw+jbbsWwPBSGc23/DPdxYT FyoAJag0v+N+xWnZXUvOnbJN3rKg+KP26iscH5E5czZ/jXOukvbOadJJ0 OKyvkAb7aqPtrR5vbM34jUr1U57iroLrmKYIHhF8aW7IzLaqA/Pa+6R6v OXF3OmlXO1lys6q5f7jSKfhgiX7YBErX30NrfTwRf0App5rrEealytQvM Q==; X-CSE-ConnectionGUID: 9QBGUUy/SMGOQX+xbh4JXA== X-CSE-MsgGUID: AAO/zvUlQ2CXyml/o2vgbA== X-IronPort-AV: E=McAfee;i="6800,10657,11866"; a="86594011" X-IronPort-AV: E=Sophos;i="6.25,207,1779174000"; d="scan'208";a="86594011" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by fmvoesa108.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Aug 2026 18:18:45 -0700 X-CSE-ConnectionGUID: vKvQF3FESPq+xNZNHLGJpg== X-CSE-MsgGUID: if5boMr+Re+jXBBz1kRseA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,207,1779174000"; d="scan'208";a="265804622" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa004.jf.intel.com with ESMTP; 05 Aug 2026 18:18:45 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Sean Christopherson , Paolo Bonzini , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Shuah Khan , Binbin Wu , Peter Zijlstra , "Chang S . Bae" , Kai Huang , Fuad Tabba , Chao Gao , Yosry Ahmed , Claudio Imbrenda , David Matlack , Bala-Vignesh-Reddy , Kishen Maloor , Rick Edgecombe , Sohil Mehta , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v4 5/7] KVM: x86: Virtualize LASS and advertise support to userspace Date: Wed, 5 Aug 2026 18:15:34 -0700 Message-ID: <20260806011536.4172258-6-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260806011536.4172258-1-sohil.mehta@intel.com> References: <20260806011536.4172258-1-sohil.mehta@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Zeng Guang Virtualize Linear Address Space Separation (LASS) by letting the guest enable CR4.LASS[bit 27]. Allow the guest to set CR4.LASS only if LASS is enumerated in the guest's CPUID. Set CR4.LASS in the emulated IA32_VMX_CR4_FIXED1 MSR so that LASS can be enabled in nested VMX operation as well. Keep CR4.LASS KVM-owned instead of making it guest-owned. LASS is expected to be enabled once per vCPU at boot and rarely toggled at runtime. LASS is enumerated by CPUID.(EAX=3D07H,ECX=3D1):EAX.LASS[bit 6] and only works in IA-32e mode. Advertise LASS to userspace on 64-bit kernels and only when it is supported by the host. Notably, it will not be exposed to userspace if the deprecated vsyscall=3Demulate mode is set on the kernel command line. Signed-off-by: Zeng Guang Signed-off-by: Binbin Wu Signed-off-by: Sohil Mehta Reviewed-by: Binbin Wu Tested-by: Farrah Chen Tested-by: Kishen Maloor --- v4: - Split patch diffs and reworded the commit message - Use X86_64_F() instead of F() --- arch/x86/kvm/cpuid.c | 1 + arch/x86/kvm/regs.h | 4 +++- arch/x86/kvm/vmx/vmx.c | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 9e9cf6538a96..c4dbd00f5e4e 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -1029,6 +1029,7 @@ void kvm_initialize_cpu_caps(void) F(SM4), F(AVX_VNNI), F(AVX512_BF16), + X86_64_F(LASS), F(CMPCCXADD), F(FZRM), F(FSRS), diff --git a/arch/x86/kvm/regs.h b/arch/x86/kvm/regs.h index 447f0ec3e63e..be8621695c41 100644 --- a/arch/x86/kvm/regs.h +++ b/arch/x86/kvm/regs.h @@ -28,7 +28,7 @@ static_assert(!(KVM_POSSIBLE_CR0_GUEST_BITS & X86_CR0_PDP= TR_BITS)); | X86_CR4_OSXSAVE | X86_CR4_SMEP | X86_CR4_FSGSBASE \ | X86_CR4_OSXMMEXCPT | X86_CR4_LA57 | X86_CR4_VMXE \ | X86_CR4_SMAP | X86_CR4_PKE | X86_CR4_UMIP \ - | X86_CR4_LAM_SUP | X86_CR4_CET)) + | X86_CR4_LAM_SUP | X86_CR4_CET | X86_CR4_LASS)) =20 #define CR8_RESERVED_BITS (~(unsigned long)X86_CR8_TPR) =20 @@ -405,6 +405,8 @@ static inline bool __kvm_is_valid_cr4(struct kvm_vcpu *= vcpu, unsigned long cr4) __reserved_bits |=3D X86_CR4_PCIDE; \ if (!__cpu_has(__c, X86_FEATURE_LAM)) \ __reserved_bits |=3D X86_CR4_LAM_SUP; \ + if (!__cpu_has(__c, X86_FEATURE_LASS)) \ + __reserved_bits |=3D X86_CR4_LASS; \ if (!__cpu_has(__c, X86_FEATURE_SHSTK) && \ !__cpu_has(__c, X86_FEATURE_IBT)) \ __reserved_bits |=3D X86_CR4_CET; \ diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index ecd105f35c78..3082195906da 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -7885,6 +7885,7 @@ static void nested_vmx_cr_fixed1_bits_update(struct k= vm_vcpu *vcpu) =20 entry =3D kvm_find_cpuid_entry_index(vcpu, 0x7, 1); cr4_fixed1_update(X86_CR4_LAM_SUP, eax, feature_bit(LAM)); + cr4_fixed1_update(X86_CR4_LASS, eax, feature_bit(LASS)); =20 #undef cr4_fixed1_update } --=20 2.43.0 From nobody Sat Oct 3 03:45:34 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.14]) (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 A5EFF3AE189; Thu, 6 Aug 2026 01:18:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785979131; cv=none; b=Kg/DsnqbhUTVnHJ0SgwxpzR7lNKgYHGxtdOajP3joTDXs9ULYo1Gp2dnpNa999hdCFAINEOWrfOtFj5rGZmgxH/yIZs+oCtQFXUVBS41M1sprOow9ZUE5gSCO5VeLyb7JgD81Wt/u2fyZcgcKS0EGgJFug5GnMTvIgOXzBBt3MI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785979131; c=relaxed/simple; bh=BxOfS5hgTAajTtSDCNTFao/0xEiji6AJ9kG7+J2yQ08=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dpQgUcfCjN/EVB9ntHxGsAn+hChaf8bjyypZpPIgpd/Ej59VwawNw7tfhVgpKH6hj3BJwq++242BMlJOJrlHywZqgzBZZKKZwDfBzU/Q/ebMTl/CejSLxW0NNFW+1GllqYi8bHiRzQaBdU2siuUp2Tu0xK5w5kqKv7Dgc/qjg6A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Bosx+33v; arc=none smtp.client-ip=192.198.163.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Bosx+33v" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1785979128; x=1817515128; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=BxOfS5hgTAajTtSDCNTFao/0xEiji6AJ9kG7+J2yQ08=; b=Bosx+33vhBHJYj4t+1d3UWSp1uO4KjaKTt6QPHi0azNRjjgZOmzI1jen eKEEGtLrbOJTYLmT2s5vXUv+4OGpzFV3OtYWR03KFmQLr4mzzZNjy/h+x s+TPTAghia2pzOb4ZWkfzAFBzKo69gEn9LoUE07LkY7JSgc9ar8T4OrNh l60EEe4nwC0DwKZx1yNvDjoyz334pM1aK6w+VVAKfcS2wHoHn6HwvABwc orzYUT7bzBKjscSRa4XYUd3NRddNyXQlCKbSu81hBTsCNzNaEtlpv75lb JVx9yoEBf4ezHeTcrniBtXijfZI19+cux9eJh2vlPBMuWKEx+SxHhvaJV Q==; X-CSE-ConnectionGUID: JQJaupxkQ7u7mEV78OFlOg== X-CSE-MsgGUID: vZ1+xjy3R4iCkvWVUoUZBQ== X-IronPort-AV: E=McAfee;i="6800,10657,11866"; a="86594021" X-IronPort-AV: E=Sophos;i="6.25,207,1779174000"; d="scan'208";a="86594021" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by fmvoesa108.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Aug 2026 18:18:46 -0700 X-CSE-ConnectionGUID: sf82Y9u0Ss+9BJmr2eJvyg== X-CSE-MsgGUID: eDfMpPsyTKmzAQeKgq3NYA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,207,1779174000"; d="scan'208";a="265804625" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa004.jf.intel.com with ESMTP; 05 Aug 2026 18:18:46 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Sean Christopherson , Paolo Bonzini , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Shuah Khan , Binbin Wu , Peter Zijlstra , "Chang S . Bae" , Kai Huang , Fuad Tabba , Chao Gao , Yosry Ahmed , Claudio Imbrenda , David Matlack , Bala-Vignesh-Reddy , Kishen Maloor , Rick Edgecombe , Sohil Mehta , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v4 6/7] KVM: selftests: Add coverage for LASS CPUID and CR4 handling Date: Wed, 5 Aug 2026 18:15:35 -0700 Message-ID: <20260806011536.4172258-7-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260806011536.4172258-1-sohil.mehta@intel.com> References: <20260806011536.4172258-1-sohil.mehta@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a LASS selftest for KVM's handling of CPUID advertisement and CR4.LASS. Verify that a guest write to CR4.LASS generates #GP, and leaves CR4 unchanged, when LASS isn't enumerated in the guest's CPUID. Extend set_sregs_test to cover CR4.LASS and verify that KVM_SET_SREGS accepts CR4.LASS when LASS is supported, and rejects it, without modifying sregs, when it isn't. Don't try running with CR4.LASS enabled in the guest or attempt to trigger LASS violations. Selftests run guest code in the lower half of the address space at CPL0, so enabling CR4.LASS would make the next instruction fetch a violation and triple-fault the guest. Assisted-by: Claude:claude-opus-5 Signed-off-by: Sohil Mehta Reviewed-by: Binbin Wu Tested-by: Farrah Chen Tested-by: Kishen Maloor --- v4: - New patch lass_test.c doesn't really test LASS enforcement or any other LASS functionality. It just tests that a guest write to CR4.LASS generates a #GP when LASS isn't enumerated. There could be a generic test which covers such CPUID/CR4 interactions. For now, I added something for LASS because I couldn't find one. --- tools/testing/selftests/kvm/Makefile.kvm | 1 + .../selftests/kvm/include/x86/processor.h | 2 + tools/testing/selftests/kvm/x86/lass_test.c | 56 +++++++++++++++++++ .../selftests/kvm/x86/set_sregs_test.c | 3 + 4 files changed, 62 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/lass_test.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index 00123169a190..86fa93e0f6c0 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -91,6 +91,7 @@ TEST_GEN_PROGS_x86 +=3D x86/hyperv_tlb_flush TEST_GEN_PROGS_x86 +=3D x86/kvm_clock_test TEST_GEN_PROGS_x86 +=3D x86/kvm_pv_test TEST_GEN_PROGS_x86 +=3D x86/kvm_buslock_test +TEST_GEN_PROGS_x86 +=3D x86/lass_test TEST_GEN_PROGS_x86 +=3D x86/monitor_mwait_test TEST_GEN_PROGS_x86 +=3D x86/msrs_test TEST_GEN_PROGS_x86 +=3D x86/nested_close_kvm_test diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/te= sting/selftests/kvm/include/x86/processor.h index 6e6f70035508..f425166174f9 100644 --- a/tools/testing/selftests/kvm/include/x86/processor.h +++ b/tools/testing/selftests/kvm/include/x86/processor.h @@ -79,6 +79,7 @@ const char *ex_str(int vector); #define X86_CR4_SMEP (1ul << 20) #define X86_CR4_SMAP (1ul << 21) #define X86_CR4_PKE (1ul << 22) +#define X86_CR4_LASS (1ul << 27) =20 struct xstate_header { u64 xstate_bv; @@ -195,6 +196,7 @@ struct kvm_x86_cpu_feature { #define X86_FEATURE_SPEC_CTRL KVM_X86_CPU_FEATURE(0x7, 0, EDX, 26) #define X86_FEATURE_ARCH_CAPABILITIES KVM_X86_CPU_FEATURE(0x7, 0, EDX, 29) #define X86_FEATURE_PKS KVM_X86_CPU_FEATURE(0x7, 0, ECX, 31) +#define X86_FEATURE_LASS KVM_X86_CPU_FEATURE(0x7, 1, EAX, 6) #define X86_FEATURE_XTILECFG KVM_X86_CPU_FEATURE(0xD, 0, EAX, 17) #define X86_FEATURE_XTILEDATA KVM_X86_CPU_FEATURE(0xD, 0, EAX, 18) #define X86_FEATURE_XSAVES KVM_X86_CPU_FEATURE(0xD, 1, EAX, 3) diff --git a/tools/testing/selftests/kvm/x86/lass_test.c b/tools/testing/se= lftests/kvm/x86/lass_test.c new file mode 100644 index 000000000000..7c5cfa24c2bd --- /dev/null +++ b/tools/testing/selftests/kvm/x86/lass_test.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Linear Address Space Separation (LASS) test + * + * Copyright (C) 2026, Intel Corporation. + * + * Only test that the guest can't set CR4.LASS when LASS isn't + * enumerated in the guest's CPUID. KVM's handling of CR4.LASS via + * KVM_SET_SREGS is covered by set_sregs_test. + * + * Testing LASS enforcement requires running supervisor code in the + * upper half of the address space, which the KVM selftests framework + * doesn't support. Enabling CR4.LASS in the current framework would + * make the next instruction fetch a violation and triple-fault the + * guest. + */ +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" + +/* + * Without LASS in CPUID, a guest write must generate #GP without + * changing CR4. Reserved bits are owned by KVM so the write is + * guaranteed to exit to KVM. + */ +static void guest_code(void) +{ + u8 vector; + + GUEST_ASSERT(!this_cpu_has(X86_FEATURE_LASS)); + + vector =3D kvm_asm_safe("mov %[cr4], %%cr4", + [cr4] "r"(get_cr4() | X86_CR4_LASS)); + __GUEST_ASSERT(vector =3D=3D GP_VECTOR, + "Wanted #GP on CR4.LASS, got %s", ex_str(vector)); + GUEST_ASSERT(!(get_cr4() & X86_CR4_LASS)); + + GUEST_DONE(); +} + +int main(int argc, char *argv[]) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_LASS)); + + vm =3D vm_create_with_one_vcpu(&vcpu, guest_code); + vcpu_clear_cpuid_feature(vcpu, X86_FEATURE_LASS); + + vcpu_run(vcpu); + TEST_ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_DONE); + + kvm_vm_free(vm); + return 0; +} diff --git a/tools/testing/selftests/kvm/x86/set_sregs_test.c b/tools/testi= ng/selftests/kvm/x86/set_sregs_test.c index 603226ffe437..8b375fea84d0 100644 --- a/tools/testing/selftests/kvm/x86/set_sregs_test.c +++ b/tools/testing/selftests/kvm/x86/set_sregs_test.c @@ -72,6 +72,8 @@ static u64 calc_supported_cr4_feature_bits(void) cr4 |=3D X86_CR4_SMAP; if (kvm_cpu_has(X86_FEATURE_PKU)) cr4 |=3D X86_CR4_PKE; + if (kvm_cpu_has(X86_FEATURE_LASS)) + cr4 |=3D X86_CR4_LASS; =20 return cr4; } @@ -128,6 +130,7 @@ static void test_cr_bits(struct kvm_vcpu *vcpu, u64 cr4) TEST_INVALID_SREG_BIT(vcpu, cr4, sregs, X86_CR4_SMEP); TEST_INVALID_SREG_BIT(vcpu, cr4, sregs, X86_CR4_SMAP); TEST_INVALID_SREG_BIT(vcpu, cr4, sregs, X86_CR4_PKE); + TEST_INVALID_SREG_BIT(vcpu, cr4, sregs, X86_CR4_LASS); =20 for (i =3D 32; i < 64; i++) TEST_INVALID_SREG_BIT(vcpu, cr0, sregs, BIT(i)); --=20 2.43.0 From nobody Sat Oct 3 03:45:34 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.14]) (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 16D4E3AAF6F; Thu, 6 Aug 2026 01:18:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785979132; cv=none; b=Q4g8YBHFm+AWhkSj8xLYsPZfRsb0Vvk9ANzNEqJxoLIvdjebtaetuz+PCoMX5hkHoNedOXRVnaPClHj4bhjSTQ3dB8c/mty0xpyOiXeJFi1+r6v5bu2b3flUqmYrmJmH2VZ4DnSoypzTlNVUq4HzuPwJdDeKbWEklItQJL/t7w0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785979132; c=relaxed/simple; bh=JwrLBmLPZiV7n39tRdGSdaQ9o/LklC1Ew4xirHM6vSA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mnVxHiWqgYQkKEu0B3qSooJyWYVGvl9CzP7zWr64F+mw9Pfpy9xBt3NhpX/PFaBTwPnDVPSET65y6Kxbv2PyvQ6VwufsYJxFj0kQ+Kn0ZTPrC3o74vF4IOTQNFRnXfi1VQLZgZ33N34HVm75vFscpduuumSrAMjuOd2aXzMrp9s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=d/Y+nZ6x; arc=none smtp.client-ip=192.198.163.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="d/Y+nZ6x" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1785979129; x=1817515129; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=JwrLBmLPZiV7n39tRdGSdaQ9o/LklC1Ew4xirHM6vSA=; b=d/Y+nZ6xGdzMNMuTtpwzCf72iGDD36Ma7Mi1otssEv41LKGuGTJViRtK Rw4qCPVnizec+BnYWNowNwX2wQYLrCeBkRH/Vdq/Gz1QlVhOORxlYHiSP 7II0pyMSRknH4iIwB4gX0+E8L1/PogHz/8bTTlHevvS6Tbkoo6ud3Gg4F 3dwpXZD7YqcnhBuQhJsXKoLyry0bumccfsrXGYcFdTT7/eeFMpsi1gQ2C mVclU+byk1++26Mu3pOpnym3w/+t+pG0xi3z1USt21zUiklj+NpwcAD2I H75ij92eW5o/QTMp4R3HQ1YUbseAuW0voI+xrftN8J6eCmrzpaktS+joL Q==; X-CSE-ConnectionGUID: knVl1waRQf+jiNMAJNGMJg== X-CSE-MsgGUID: deVjvGVHSpOXZFrkdZqT4g== X-IronPort-AV: E=McAfee;i="6800,10657,11866"; a="86594031" X-IronPort-AV: E=Sophos;i="6.25,207,1779174000"; d="scan'208";a="86594031" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by fmvoesa108.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Aug 2026 18:18:47 -0700 X-CSE-ConnectionGUID: Ep1FntngSqmeM4Ec48xFjg== X-CSE-MsgGUID: 6fWDtsFsRW2jKrc7HwDcxA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,207,1779174000"; d="scan'208";a="265804628" Received: from sohilmeh.sc.intel.com ([172.25.103.65]) by orviesa004.jf.intel.com with ESMTP; 05 Aug 2026 18:18:46 -0700 From: Sohil Mehta To: kvm@vger.kernel.org, x86@kernel.org Cc: Sean Christopherson , Paolo Bonzini , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Shuah Khan , Binbin Wu , Peter Zijlstra , "Chang S . Bae" , Kai Huang , Fuad Tabba , Chao Gao , Yosry Ahmed , Claudio Imbrenda , David Matlack , Bala-Vignesh-Reddy , Kishen Maloor , Rick Edgecombe , Sohil Mehta , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v4 7/7] selftests/x86: Add a userspace test for LASS enforcement Date: Wed, 5 Aug 2026 18:15:36 -0700 Message-ID: <20260806011536.4172258-8-sohil.mehta@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260806011536.4172258-1-sohil.mehta@intel.com> References: <20260806011536.4172258-1-sohil.mehta@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" With LASS enabled, a user-mode access to a kernel address raises a #GP instead of the #PF that SMAP/SMEP would produce. Nothing in the x86 selftests specifically tests for a LASS violation. The vsyscall selftest exercises this flow but doesn't verify the resulting #GP. Add a test that reads, writes and executes at a canonical kernel address and verifies each one faults with a #GP and a null error code. For the instruction fetch, also verify the fault is reported at the target, since LASS does not check the target of a branch. Skip the test unless /proc/cpuinfo reports the lass flag. The CPUID bit alone does not say whether the kernel enabled LASS. Assisted-by: Claude:claude-opus-5 Signed-off-by: Sohil Mehta Reviewed-by: Binbin Wu Tested-by: Farrah Chen Tested-by: Kishen Maloor --- v4: - New patch --- tools/testing/selftests/x86/Makefile | 3 +- tools/testing/selftests/x86/lass.c | 196 +++++++++++++++++++++++++++ 2 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/x86/lass.c diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests= /x86/Makefile index 434065215d12..252d757fc1b2 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -19,7 +19,8 @@ TARGETS_C_32BIT_ONLY :=3D entry_from_vm86 test_syscall_vd= so unwind_vdso \ test_FCMOV test_FCOMI test_FISTTP \ vdso_restorer TARGETS_C_64BIT_ONLY :=3D fsgsbase sysret_rip syscall_numbering \ - corrupt_xstate_header amx lam test_shadow_stack avx apx + corrupt_xstate_header amx lam test_shadow_stack avx apx \ + lass # Some selftests require 32bit support enabled also on 64bit systems TARGETS_C_32BIT_NEEDED :=3D ldt_gdt ptrace_syscall =20 diff --git a/tools/testing/selftests/x86/lass.c b/tools/testing/selftests/x= 86/lass.c new file mode 100644 index 000000000000..3dd3dc8e41d1 --- /dev/null +++ b/tools/testing/selftests/x86/lass.c @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * lass.c - Test Linear Address Space Separation (LASS) enforcement + * + * With LASS enabled, a user-mode read, write or instruction fetch at a + * kernel address raises a #GP instead of the #PF that SMAP/SMEP would + * produce. + */ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +#include "helpers.h" + +#ifndef __x86_64__ +# error This test is 64-bit only +#endif + +/* + * LASS rejects an address based on bit 63 alone, but a non-canonical + * address raises the very same #GP for a different reason, so the + * address has to be canonical to attribute the fault to LASS. + * + * Bits 63:47 are all set here, which is canonical with 4-level paging + * as well as 5-level paging. + */ +#define KERNEL_ADDR 0xffff800000000000UL + +static sigjmp_buf jmpbuf; + +static volatile unsigned long fault_trapno, fault_err, fault_rip; + +/* Handle SIGSEGV (#GP and #PF) as well as SIGBUS (#SS) */ +static void fault_handler(int sig, siginfo_t *info, void *ctx_void) +{ + ucontext_t *ctx =3D (ucontext_t *)ctx_void; + + fault_trapno =3D ctx->uc_mcontext.gregs[REG_TRAPNO]; + fault_err =3D ctx->uc_mcontext.gregs[REG_ERR]; + fault_rip =3D ctx->uc_mcontext.gregs[REG_RIP]; + siglongjmp(jmpbuf, 1); +} + +static bool is_lass_active(void) +{ + static const char delims[] =3D " \n"; + unsigned int eax, ebx, ecx, edx; + bool found =3D false; + char line[4096]; + FILE *cpuinfo; + + /* + * Only the cpuinfo flag reflects whether the kernel actually + * enabled LASS. + */ + cpuinfo =3D fopen("/proc/cpuinfo", "r"); + if (!cpuinfo) + ksft_exit_fail_msg("failed to open /proc/cpuinfo\n"); + + while (!found && fgets(line, sizeof(line), cpuinfo)) { + char *flag; + + if (strncmp(line, "flags", 5)) + continue; + + /* Match whole words only, not a substring of another flag. */ + for (flag =3D strtok(line, delims); flag; flag =3D strtok(NULL, delims))= { + if (!strcmp(flag, "lass")) { + found =3D true; + break; + } + } + } + + fclose(cpuinfo); + + if (found) + return true; + + /* Check CPUID.(EAX=3D07H,ECX=3D1):EAX.LASS[bit 6] */ + __cpuid_count(0x7, 0x1, eax, ebx, ecx, edx); + if (eax & (1 << 6)) + ksft_print_msg("LASS is supported by the CPU but not enabled by the kern= el\n"); + + return false; +} + +/* General Protection Fault (trapnr.h is not exported to uapi) */ +#define X86_TRAP_GP 13 + +/* A LASS violation raises a #GP with a null error code. */ +static bool is_lass_violation(void) +{ + return fault_trapno =3D=3D X86_TRAP_GP && !fault_err; +} + +static void test_kernel_read(void) +{ + if (sigsetjmp(jmpbuf, 1) =3D=3D 0) { + *(volatile unsigned long *)KERNEL_ADDR; + ksft_test_result_fail("the read did not fault\n"); + return; + } + + ksft_test_result(is_lass_violation(), + "the read faulted with trap=3D%ld, error=3D0x%lx\n", + fault_trapno, fault_err); +} + +static void test_kernel_write(void) +{ + if (sigsetjmp(jmpbuf, 1) =3D=3D 0) { + *(volatile unsigned long *)KERNEL_ADDR =3D 0x1a55; + ksft_test_result_fail("the write did not fault\n"); + return; + } + + ksft_test_result(is_lass_violation(), + "the write faulted with trap=3D%ld, error=3D0x%lx\n", + fault_trapno, fault_err); +} + +/* + * Use inline asm rather than a call through a function pointer: a direct + * 'call rel32' cannot reach a kernel address, and letting the compiler lo= wer + * the indirect branch risks routing it through a thunk, or eliding it + * altogether, either of which would stop testing the fetch. + */ +static void do_fetch(unsigned long addr) +{ + asm volatile ("call *%[fn]" + : : [fn] "r" (addr) + : "memory", "cc", "rax", "rcx", "rdx", "rsi", "rdi", + "r8", "r9", "r10", "r11"); +} + +static void test_kernel_fetch(void) +{ + if (sigsetjmp(jmpbuf, 1) =3D=3D 0) { + do_fetch(KERNEL_ADDR); + + /* + * Execution resumed at an unknown point with an undefined + * register state, so don't try to run the rest of the tests. + */ + ksft_exit_fail_msg("the fetch returned without faulting\n"); + } + + /* + * Branch instructions do not check their target against LASS. The + * violation happens when the target address is used to fetch the + * next instruction, so the fault must be reported at the target + * rather than at the branch. + */ + if (fault_rip !=3D KERNEL_ADDR) { + ksft_test_result_fail("the fetch faulted at RIP 0x%lx instead of 0x%lx\n= ", + fault_rip, (unsigned long)KERNEL_ADDR); + return; + } + + ksft_test_result(is_lass_violation(), + "the fetch faulted with trap=3D%ld, error=3D0x%lx\n", + fault_trapno, fault_err); +} + +#define TOTAL_TESTS 3 + +int main(void) +{ + ksft_print_header(); + + if (!is_lass_active()) + ksft_exit_skip("LASS is not enabled\n"); + + ksft_set_plan(TOTAL_TESTS); + + sethandler(SIGSEGV, fault_handler, 0); + /* Only to report a #SS; LASS shouldn't cause one here. */ + sethandler(SIGBUS, fault_handler, 0); + + ksft_print_msg("Accessing the kernel address 0x%lx from userspace\n", + (unsigned long)KERNEL_ADDR); + test_kernel_read(); + test_kernel_write(); + test_kernel_fetch(); + + clearhandler(SIGBUS); + clearhandler(SIGSEGV); + + ksft_finished(); +} --=20 2.43.0