LCOV - code coverage report
Current view: top level - arch/x86/kernel/cpu - feat_ctl.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 61 0.0 %
Date: 2022-03-28 16:04:14 Functions: 0 2 0.0 %
Branches: 0 40 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : #include <linux/tboot.h>
       3                 :            : 
       4                 :            : #include <asm/cpufeature.h>
       5                 :            : #include <asm/msr-index.h>
       6                 :            : #include <asm/processor.h>
       7                 :            : #include <asm/vmx.h>
       8                 :            : 
       9                 :            : #undef pr_fmt
      10                 :            : #define pr_fmt(fmt)     "x86/cpu: " fmt
      11                 :            : 
      12                 :            : #ifdef CONFIG_X86_VMX_FEATURE_NAMES
      13                 :            : enum vmx_feature_leafs {
      14                 :            :         MISC_FEATURES = 0,
      15                 :            :         PRIMARY_CTLS,
      16                 :            :         SECONDARY_CTLS,
      17                 :            :         NR_VMX_FEATURE_WORDS,
      18                 :            : };
      19                 :            : 
      20                 :            : #define VMX_F(x) BIT(VMX_FEATURE_##x & 0x1f)
      21                 :            : 
      22                 :          0 : static void init_vmx_capabilities(struct cpuinfo_x86 *c)
      23                 :            : {
      24                 :          0 :         u32 supported, funcs, ept, vpid, ign;
      25                 :            : 
      26                 :          0 :         BUILD_BUG_ON(NVMXINTS != NR_VMX_FEATURE_WORDS);
      27                 :            : 
      28                 :            :         /*
      29                 :            :          * The high bits contain the allowed-1 settings, i.e. features that can
      30                 :            :          * be turned on.  The low bits contain the allowed-0 settings, i.e.
      31                 :            :          * features that can be turned off.  Ignore the allowed-0 settings,
      32                 :            :          * if a feature can be turned on then it's supported.
      33                 :            :          *
      34                 :            :          * Use raw rdmsr() for primary processor controls and pin controls MSRs
      35                 :            :          * as they exist on any CPU that supports VMX, i.e. we want the WARN if
      36                 :            :          * the RDMSR faults.
      37                 :            :          */
      38                 :          0 :         rdmsr(MSR_IA32_VMX_PROCBASED_CTLS, ign, supported);
      39                 :          0 :         c->vmx_capability[PRIMARY_CTLS] = supported;
      40                 :            : 
      41                 :          0 :         rdmsr_safe(MSR_IA32_VMX_PROCBASED_CTLS2, &ign, &supported);
      42                 :          0 :         c->vmx_capability[SECONDARY_CTLS] = supported;
      43                 :            : 
      44                 :          0 :         rdmsr(MSR_IA32_VMX_PINBASED_CTLS, ign, supported);
      45                 :          0 :         rdmsr_safe(MSR_IA32_VMX_VMFUNC, &ign, &funcs);
      46                 :            : 
      47                 :            :         /*
      48                 :            :          * Except for EPT+VPID, which enumerates support for both in a single
      49                 :            :          * MSR, low for EPT, high for VPID.
      50                 :            :          */
      51                 :          0 :         rdmsr_safe(MSR_IA32_VMX_EPT_VPID_CAP, &ept, &vpid);
      52                 :            : 
      53                 :            :         /* Pin, EPT, VPID and VM-Func are merged into a single word. */
      54         [ #  # ]:          0 :         WARN_ON_ONCE(supported >> 16);
      55         [ #  # ]:          0 :         WARN_ON_ONCE(funcs >> 4);
      56                 :          0 :         c->vmx_capability[MISC_FEATURES] = (supported & 0xffff) |
      57                 :          0 :                                            ((vpid & 0x1) << 16) |
      58                 :          0 :                                            ((funcs & 0xf) << 28);
      59                 :            : 
      60                 :            :         /* EPT bits are full on scattered and must be manually handled. */
      61         [ #  # ]:          0 :         if (ept & VMX_EPT_EXECUTE_ONLY_BIT)
      62                 :          0 :                 c->vmx_capability[MISC_FEATURES] |= VMX_F(EPT_EXECUTE_ONLY);
      63         [ #  # ]:          0 :         if (ept & VMX_EPT_AD_BIT)
      64                 :          0 :                 c->vmx_capability[MISC_FEATURES] |= VMX_F(EPT_AD);
      65         [ #  # ]:          0 :         if (ept & VMX_EPT_1GB_PAGE_BIT)
      66                 :          0 :                 c->vmx_capability[MISC_FEATURES] |= VMX_F(EPT_1GB);
      67                 :            : 
      68                 :            :         /* Synthetic APIC features that are aggregates of multiple features. */
      69         [ #  # ]:          0 :         if ((c->vmx_capability[PRIMARY_CTLS] & VMX_F(VIRTUAL_TPR)) &&
      70         [ #  # ]:          0 :             (c->vmx_capability[SECONDARY_CTLS] & VMX_F(VIRT_APIC_ACCESSES)))
      71                 :          0 :                 c->vmx_capability[MISC_FEATURES] |= VMX_F(FLEXPRIORITY);
      72                 :            : 
      73         [ #  # ]:          0 :         if ((c->vmx_capability[PRIMARY_CTLS] & VMX_F(VIRTUAL_TPR)) &&
      74         [ #  # ]:          0 :             (c->vmx_capability[SECONDARY_CTLS] & VMX_F(APIC_REGISTER_VIRT)) &&
      75                 :          0 :             (c->vmx_capability[SECONDARY_CTLS] & VMX_F(VIRT_INTR_DELIVERY)) &&
      76         [ #  # ]:          0 :             (c->vmx_capability[MISC_FEATURES] & VMX_F(POSTED_INTR)))
      77                 :          0 :                 c->vmx_capability[MISC_FEATURES] |= VMX_F(APICV);
      78                 :            : 
      79                 :            :         /* Set the synthetic cpufeatures to preserve /proc/cpuinfo's ABI. */
      80         [ #  # ]:          0 :         if (c->vmx_capability[PRIMARY_CTLS] & VMX_F(VIRTUAL_TPR))
      81                 :          0 :                 set_cpu_cap(c, X86_FEATURE_TPR_SHADOW);
      82         [ #  # ]:          0 :         if (c->vmx_capability[MISC_FEATURES] & VMX_F(FLEXPRIORITY))
      83                 :          0 :                 set_cpu_cap(c, X86_FEATURE_FLEXPRIORITY);
      84         [ #  # ]:          0 :         if (c->vmx_capability[MISC_FEATURES] & VMX_F(VIRTUAL_NMIS))
      85                 :          0 :                 set_cpu_cap(c, X86_FEATURE_VNMI);
      86         [ #  # ]:          0 :         if (c->vmx_capability[SECONDARY_CTLS] & VMX_F(EPT))
      87                 :          0 :                 set_cpu_cap(c, X86_FEATURE_EPT);
      88         [ #  # ]:          0 :         if (c->vmx_capability[MISC_FEATURES] & VMX_F(EPT_AD))
      89                 :          0 :                 set_cpu_cap(c, X86_FEATURE_EPT_AD);
      90         [ #  # ]:          0 :         if (c->vmx_capability[MISC_FEATURES] & VMX_F(VPID))
      91                 :          0 :                 set_cpu_cap(c, X86_FEATURE_VPID);
      92                 :          0 : }
      93                 :            : #endif /* CONFIG_X86_VMX_FEATURE_NAMES */
      94                 :            : 
      95                 :          0 : void init_ia32_feat_ctl(struct cpuinfo_x86 *c)
      96                 :            : {
      97                 :          0 :         bool tboot = tboot_enabled();
      98                 :          0 :         u64 msr;
      99                 :            : 
     100         [ #  # ]:          0 :         if (rdmsrl_safe(MSR_IA32_FEAT_CTL, &msr)) {
     101                 :          0 :                 clear_cpu_cap(c, X86_FEATURE_VMX);
     102                 :          0 :                 return;
     103                 :            :         }
     104                 :            : 
     105         [ #  # ]:          0 :         if (msr & FEAT_CTL_LOCKED)
     106                 :          0 :                 goto update_caps;
     107                 :            : 
     108                 :            :         /*
     109                 :            :          * Ignore whatever value BIOS left in the MSR to avoid enabling random
     110                 :            :          * features or faulting on the WRMSR.
     111                 :            :          */
     112                 :          0 :         msr = FEAT_CTL_LOCKED;
     113                 :            : 
     114                 :            :         /*
     115                 :            :          * Enable VMX if and only if the kernel may do VMXON at some point,
     116                 :            :          * i.e. KVM is enabled, to avoid unnecessarily adding an attack vector
     117                 :            :          * for the kernel, e.g. using VMX to hide malicious code.
     118                 :            :          */
     119                 :          0 :         if (cpu_has(c, X86_FEATURE_VMX) && IS_ENABLED(CONFIG_KVM_INTEL)) {
     120                 :            :                 msr |= FEAT_CTL_VMX_ENABLED_OUTSIDE_SMX;
     121                 :            : 
     122                 :            :                 if (tboot)
     123                 :            :                         msr |= FEAT_CTL_VMX_ENABLED_INSIDE_SMX;
     124                 :            :         }
     125                 :            : 
     126                 :          0 :         wrmsrl(MSR_IA32_FEAT_CTL, msr);
     127                 :            : 
     128                 :          0 : update_caps:
     129                 :          0 :         set_cpu_cap(c, X86_FEATURE_MSR_IA32_FEAT_CTL);
     130                 :            : 
     131         [ #  # ]:          0 :         if (!cpu_has(c, X86_FEATURE_VMX))
     132                 :            :                 return;
     133                 :            : 
     134                 :          0 :         if ( (tboot && !(msr & FEAT_CTL_VMX_ENABLED_INSIDE_SMX)) ||
     135         [ #  # ]:          0 :             (!tboot && !(msr & FEAT_CTL_VMX_ENABLED_OUTSIDE_SMX))) {
     136                 :          0 :                 if (IS_ENABLED(CONFIG_KVM_INTEL))
     137                 :            :                         pr_err_once("VMX (%s TXT) disabled by BIOS\n",
     138                 :            :                                     tboot ? "inside" : "outside");
     139                 :          0 :                 clear_cpu_cap(c, X86_FEATURE_VMX);
     140                 :            :         } else {
     141                 :            : #ifdef CONFIG_X86_VMX_FEATURE_NAMES
     142                 :          0 :                 init_vmx_capabilities(c);
     143                 :            : #endif
     144                 :            :         }
     145                 :            : }

Generated by: LCOV version 1.14