xref: /openbmc/linux/arch/x86/kernel/cpu/feat_ctl.c (revision dc6a81c3)
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 static void init_vmx_capabilities(struct cpuinfo_x86 *c)
23 {
24 	u32 supported, funcs, ept, vpid, ign;
25 
26 	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 	rdmsr(MSR_IA32_VMX_PROCBASED_CTLS, ign, supported);
39 	c->vmx_capability[PRIMARY_CTLS] = supported;
40 
41 	rdmsr_safe(MSR_IA32_VMX_PROCBASED_CTLS2, &ign, &supported);
42 	c->vmx_capability[SECONDARY_CTLS] = supported;
43 
44 	rdmsr(MSR_IA32_VMX_PINBASED_CTLS, ign, supported);
45 	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 	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 	WARN_ON_ONCE(supported >> 16);
55 	WARN_ON_ONCE(funcs >> 4);
56 	c->vmx_capability[MISC_FEATURES] = (supported & 0xffff) |
57 					   ((vpid & 0x1) << 16) |
58 					   ((funcs & 0xf) << 28);
59 
60 	/* EPT bits are full on scattered and must be manually handled. */
61 	if (ept & VMX_EPT_EXECUTE_ONLY_BIT)
62 		c->vmx_capability[MISC_FEATURES] |= VMX_F(EPT_EXECUTE_ONLY);
63 	if (ept & VMX_EPT_AD_BIT)
64 		c->vmx_capability[MISC_FEATURES] |= VMX_F(EPT_AD);
65 	if (ept & VMX_EPT_1GB_PAGE_BIT)
66 		c->vmx_capability[MISC_FEATURES] |= VMX_F(EPT_1GB);
67 
68 	/* Synthetic APIC features that are aggregates of multiple features. */
69 	if ((c->vmx_capability[PRIMARY_CTLS] & VMX_F(VIRTUAL_TPR)) &&
70 	    (c->vmx_capability[SECONDARY_CTLS] & VMX_F(VIRT_APIC_ACCESSES)))
71 		c->vmx_capability[MISC_FEATURES] |= VMX_F(FLEXPRIORITY);
72 
73 	if ((c->vmx_capability[PRIMARY_CTLS] & VMX_F(VIRTUAL_TPR)) &&
74 	    (c->vmx_capability[SECONDARY_CTLS] & VMX_F(APIC_REGISTER_VIRT)) &&
75 	    (c->vmx_capability[SECONDARY_CTLS] & VMX_F(VIRT_INTR_DELIVERY)) &&
76 	    (c->vmx_capability[MISC_FEATURES] & VMX_F(POSTED_INTR)))
77 		c->vmx_capability[MISC_FEATURES] |= VMX_F(APICV);
78 
79 	/* Set the synthetic cpufeatures to preserve /proc/cpuinfo's ABI. */
80 	if (c->vmx_capability[PRIMARY_CTLS] & VMX_F(VIRTUAL_TPR))
81 		set_cpu_cap(c, X86_FEATURE_TPR_SHADOW);
82 	if (c->vmx_capability[MISC_FEATURES] & VMX_F(FLEXPRIORITY))
83 		set_cpu_cap(c, X86_FEATURE_FLEXPRIORITY);
84 	if (c->vmx_capability[MISC_FEATURES] & VMX_F(VIRTUAL_NMIS))
85 		set_cpu_cap(c, X86_FEATURE_VNMI);
86 	if (c->vmx_capability[SECONDARY_CTLS] & VMX_F(EPT))
87 		set_cpu_cap(c, X86_FEATURE_EPT);
88 	if (c->vmx_capability[MISC_FEATURES] & VMX_F(EPT_AD))
89 		set_cpu_cap(c, X86_FEATURE_EPT_AD);
90 	if (c->vmx_capability[MISC_FEATURES] & VMX_F(VPID))
91 		set_cpu_cap(c, X86_FEATURE_VPID);
92 }
93 #endif /* CONFIG_X86_VMX_FEATURE_NAMES */
94 
95 void init_ia32_feat_ctl(struct cpuinfo_x86 *c)
96 {
97 	bool tboot = tboot_enabled();
98 	u64 msr;
99 
100 	if (rdmsrl_safe(MSR_IA32_FEAT_CTL, &msr)) {
101 		clear_cpu_cap(c, X86_FEATURE_VMX);
102 		return;
103 	}
104 
105 	if (msr & FEAT_CTL_LOCKED)
106 		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 	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 	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 	wrmsrl(MSR_IA32_FEAT_CTL, msr);
127 
128 update_caps:
129 	set_cpu_cap(c, X86_FEATURE_MSR_IA32_FEAT_CTL);
130 
131 	if (!cpu_has(c, X86_FEATURE_VMX))
132 		return;
133 
134 	if ( (tboot && !(msr & FEAT_CTL_VMX_ENABLED_INSIDE_SMX)) ||
135 	    (!tboot && !(msr & FEAT_CTL_VMX_ENABLED_OUTSIDE_SMX))) {
136 		if (IS_ENABLED(CONFIG_KVM_INTEL))
137 			pr_err_once("VMX (%s TXT) disabled by BIOS\n",
138 				    tboot ? "inside" : "outside");
139 		clear_cpu_cap(c, X86_FEATURE_VMX);
140 	} else {
141 #ifdef CONFIG_X86_VMX_FEATURE_NAMES
142 		init_vmx_capabilities(c);
143 #endif
144 	}
145 }
146