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 <[email protected]>
---
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/selftests/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 += x86/hyperv_tlb_flush
 TEST_GEN_PROGS_x86 += x86/kvm_clock_test
 TEST_GEN_PROGS_x86 += x86/kvm_pv_test
 TEST_GEN_PROGS_x86 += x86/kvm_buslock_test
+TEST_GEN_PROGS_x86 += x86/lass_test
 TEST_GEN_PROGS_x86 += x86/monitor_mwait_test
 TEST_GEN_PROGS_x86 += x86/msrs_test
 TEST_GEN_PROGS_x86 += x86/nested_close_kvm_test
diff --git a/tools/testing/selftests/kvm/include/x86/processor.h 
b/tools/testing/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)
 
 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/selftests/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 = kvm_asm_safe("mov %[cr4], %%cr4",
+                             [cr4] "r"(get_cr4() | X86_CR4_LASS));
+       __GUEST_ASSERT(vector == 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 = 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/testing/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 |= X86_CR4_SMAP;
        if (kvm_cpu_has(X86_FEATURE_PKU))
                cr4 |= X86_CR4_PKE;
+       if (kvm_cpu_has(X86_FEATURE_LASS))
+               cr4 |= X86_CR4_LASS;
 
        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);
 
        for (i = 32; i < 64; i++)
                TEST_INVALID_SREG_BIT(vcpu, cr0, sregs, BIT(i));
-- 
2.43.0


Reply via email to