~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/kvm/x86_64/set_sregs_test.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * KVM_SET_SREGS tests
  4  *
  5  * Copyright (C) 2018, Google LLC.
  6  *
  7  * This is a regression test for the bug fixed by the following commit:
  8  * d3802286fa0f ("kvm: x86: Disallow illegal IA32_APIC_BASE MSR values")
  9  *
 10  * That bug allowed a user-mode program that called the KVM_SET_SREGS
 11  * ioctl to put a VCPU's local APIC into an invalid state.
 12  */
 13 #include <fcntl.h>
 14 #include <stdio.h>
 15 #include <stdlib.h>
 16 #include <string.h>
 17 #include <sys/ioctl.h>
 18 
 19 #include "test_util.h"
 20 
 21 #include "kvm_util.h"
 22 #include "processor.h"
 23 
 24 #define TEST_INVALID_CR_BIT(vcpu, cr, orig, bit)                                \
 25 do {                                                                            \
 26         struct kvm_sregs new;                                                   \
 27         int rc;                                                                 \
 28                                                                                 \
 29         /* Skip the sub-test, the feature/bit is supported. */                  \
 30         if (orig.cr & bit)                                                      \
 31                 break;                                                          \
 32                                                                                 \
 33         memcpy(&new, &orig, sizeof(sregs));                                     \
 34         new.cr |= bit;                                                          \
 35                                                                                 \
 36         rc = _vcpu_sregs_set(vcpu, &new);                                       \
 37         TEST_ASSERT(rc, "KVM allowed invalid " #cr " bit (0x%lx)", bit);        \
 38                                                                                 \
 39         /* Sanity check that KVM didn't change anything. */                     \
 40         vcpu_sregs_get(vcpu, &new);                                             \
 41         TEST_ASSERT(!memcmp(&new, &orig, sizeof(new)), "KVM modified sregs");   \
 42 } while (0)
 43 
 44 static uint64_t calc_supported_cr4_feature_bits(void)
 45 {
 46         uint64_t cr4;
 47 
 48         cr4 = X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | X86_CR4_DE |
 49               X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE | X86_CR4_PGE |
 50               X86_CR4_PCE | X86_CR4_OSFXSR | X86_CR4_OSXMMEXCPT;
 51         if (kvm_cpu_has(X86_FEATURE_UMIP))
 52                 cr4 |= X86_CR4_UMIP;
 53         if (kvm_cpu_has(X86_FEATURE_LA57))
 54                 cr4 |= X86_CR4_LA57;
 55         if (kvm_cpu_has(X86_FEATURE_VMX))
 56                 cr4 |= X86_CR4_VMXE;
 57         if (kvm_cpu_has(X86_FEATURE_SMX))
 58                 cr4 |= X86_CR4_SMXE;
 59         if (kvm_cpu_has(X86_FEATURE_FSGSBASE))
 60                 cr4 |= X86_CR4_FSGSBASE;
 61         if (kvm_cpu_has(X86_FEATURE_PCID))
 62                 cr4 |= X86_CR4_PCIDE;
 63         if (kvm_cpu_has(X86_FEATURE_XSAVE))
 64                 cr4 |= X86_CR4_OSXSAVE;
 65         if (kvm_cpu_has(X86_FEATURE_SMEP))
 66                 cr4 |= X86_CR4_SMEP;
 67         if (kvm_cpu_has(X86_FEATURE_SMAP))
 68                 cr4 |= X86_CR4_SMAP;
 69         if (kvm_cpu_has(X86_FEATURE_PKU))
 70                 cr4 |= X86_CR4_PKE;
 71 
 72         return cr4;
 73 }
 74 
 75 int main(int argc, char *argv[])
 76 {
 77         struct kvm_sregs sregs;
 78         struct kvm_vcpu *vcpu;
 79         struct kvm_vm *vm;
 80         uint64_t cr4;
 81         int rc, i;
 82 
 83         /*
 84          * Create a dummy VM, specifically to avoid doing KVM_SET_CPUID2, and
 85          * use it to verify all supported CR4 bits can be set prior to defining
 86          * the vCPU model, i.e. without doing KVM_SET_CPUID2.
 87          */
 88         vm = vm_create_barebones();
 89         vcpu = __vm_vcpu_add(vm, 0);
 90 
 91         vcpu_sregs_get(vcpu, &sregs);
 92 
 93         sregs.cr0 = 0;
 94         sregs.cr4 |= calc_supported_cr4_feature_bits();
 95         cr4 = sregs.cr4;
 96 
 97         rc = _vcpu_sregs_set(vcpu, &sregs);
 98         TEST_ASSERT(!rc, "Failed to set supported CR4 bits (0x%lx)", cr4);
 99 
100         vcpu_sregs_get(vcpu, &sregs);
101         TEST_ASSERT(sregs.cr4 == cr4, "sregs.CR4 (0x%llx) != CR4 (0x%lx)",
102                     sregs.cr4, cr4);
103 
104         /* Verify all unsupported features are rejected by KVM. */
105         TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_UMIP);
106         TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_LA57);
107         TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_VMXE);
108         TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_SMXE);
109         TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_FSGSBASE);
110         TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_PCIDE);
111         TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_OSXSAVE);
112         TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_SMEP);
113         TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_SMAP);
114         TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_PKE);
115 
116         for (i = 32; i < 64; i++)
117                 TEST_INVALID_CR_BIT(vcpu, cr0, sregs, BIT(i));
118 
119         /* NW without CD is illegal, as is PG without PE. */
120         TEST_INVALID_CR_BIT(vcpu, cr0, sregs, X86_CR0_NW);
121         TEST_INVALID_CR_BIT(vcpu, cr0, sregs, X86_CR0_PG);
122 
123         kvm_vm_free(vm);
124 
125         /* Create a "real" VM and verify APIC_BASE can be set. */
126         vm = vm_create_with_one_vcpu(&vcpu, NULL);
127 
128         vcpu_sregs_get(vcpu, &sregs);
129         sregs.apic_base = 1 << 10;
130         rc = _vcpu_sregs_set(vcpu, &sregs);
131         TEST_ASSERT(rc, "Set IA32_APIC_BASE to %llx (invalid)",
132                     sregs.apic_base);
133         sregs.apic_base = 1 << 11;
134         rc = _vcpu_sregs_set(vcpu, &sregs);
135         TEST_ASSERT(!rc, "Couldn't set IA32_APIC_BASE to %llx (valid)",
136                     sregs.apic_base);
137 
138         kvm_vm_free(vm);
139 
140         return 0;
141 }
142 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php