LCOV - code coverage report
Current view: top level - arch/x86/kernel/cpu - feat_ctl.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 26 78 33.3 %
Date: 2021-04-22 12:43:58 Functions: 2 4 50.0 %

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

Generated by: LCOV version 1.14