blob: e2cb6cd4dcc4cf31da32e6bb8316726c98904600 [file] [log] [blame]
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
Angel Pons01490252020-10-21 00:19:00 +02003#include <cf9_reset.h>
4#include <console/console.h>
5#include <cpu/intel/common/common.h>
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +01006#include <cpu/x86/cr.h>
7#include <cpu/x86/cache.h>
8#include <cpu/x86/mp.h>
Angel Pons01490252020-10-21 00:19:00 +02009#include <cpu/x86/msr.h>
Angel Pons52082be2020-10-05 12:34:29 +020010#include <types.h>
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +010011
12#include "txt_register.h"
13#include "txt_getsec.h"
14
15/**
16 * Check for SMX support and enable it if possible.
17 *
18 * Returns false on error, true on success.
19 */
20static bool getsec_enabled(void)
21{
22 unsigned int ecx = cpuid_ecx(1);
23 /*
24 * Check if SMX and VMX is supported by CPU.
25 */
Michał Żygowski257094a2021-11-21 13:13:15 +010026 if (!(ecx & CPUID_SMX) || !(ecx & CPUID_VMX)) {
27 printk(BIOS_ERR, "SMX/VMX not supported by CPU\n");
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +010028 return false;
Michał Żygowski257094a2021-11-21 13:13:15 +010029 }
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +010030 /*
Michał Żygowski257094a2021-11-21 13:13:15 +010031 * This requirement is not needed for ENTERACCS, but for SENTER (see SDM).
32 * Skip check in romstage because IA32_FEATURE_CONTROL cannot be unlocked
33 * even after a global reset e.g. on Sandy/IvyBridge. However the register
34 * gets set properly in ramstage where all CPUs are already initialized.
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +010035 */
Michał Żygowski257094a2021-11-21 13:13:15 +010036 if (!ENV_ROMSTAGE_OR_BEFORE) {
37 /*
38 * Check if SMX, VMX and GetSec instructions haven't been disabled.
39 */
40 msr_t msr = rdmsr(IA32_FEATURE_CONTROL);
41 if ((msr.lo & 0xff06) != 0xff06) {
42 printk(BIOS_ERR, "GETSEC not enabled in IA32_FEATURE_CONTROL MSR\n");
43 return false;
44 }
45 }
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +010046 /*
47 * Enable SMX. Required to execute GetSec instruction.
48 * Chapter 2.2.4.3
49 * Intel TXT Software Development Guide (Document: 315168-015)
50 */
51 write_cr4(read_cr4() | CR4_SMXE);
52
53 return true;
54}
55
Angel Pons01490252020-10-21 00:19:00 +020056void enable_getsec_or_reset(void)
57{
58 msr_t msr = rdmsr(IA32_FEATURE_CONTROL);
59
60 if (!(msr.lo & FEATURE_CONTROL_LOCK_BIT)) {
61 /*
62 * MSR not locked, enable necessary GETSEC and VMX settings.
63 * We do not lock this MSR here, though.
64 */
65 msr.lo |= 0xff06;
66 wrmsr(IA32_FEATURE_CONTROL, msr);
67
68 } else if ((msr.lo & 0xff06) != 0xff06) {
69 /*
70 * MSR is locked without necessary GETSEC and VMX settings.
71 * This can happen after internally reflashing a coreboot
72 * image with different settings, and then doing a warm
73 * reboot. Perform a full reset in order to unlock the MSR.
74 */
75 printk(BIOS_NOTICE,
76 "IA32_FEATURE_CONTROL MSR locked with GETSEC and/or VMX disabled.\n"
77 "Will perform a full reset to unlock this MSR.\n");
78
79 full_reset();
80 }
81}
82
Philipp Deppenwiese5f9f7762018-11-20 14:22:15 +010083/**
84 * Get information as returned by getsec[PARAMETER].
85 * Arguments can be set to NULL if not needed.
86 *
87 * Returns false on error, true on success.
88 */
89bool getsec_parameter(uint32_t *version_mask,
90 uint32_t *version_numbers_supported,
91 uint32_t *max_size_acm_area,
92 uint32_t *memory_type_mask,
93 uint32_t *senter_function_disable,
94 uint32_t *txt_feature_flags)
95{
96 uint32_t i, eax, ebx, ecx;
97
98 if (!getsec_enabled())
99 return false;
100
101 /*
102 * SAFER MODE EXTENSIONS REFERENCE.
103 * Intel 64 and IA-32 Architectures Software Developer Manuals Vol 2D
104 */
105 for (i = 0; i < 0x1f; i++) {
106 /* Getsec[PARAMETERS] */
107 asm volatile ("getsec\n"
108 : "=a" (eax), "=b" (ebx), "=c" (ecx)
109 : "a" (IA32_GETSEC_PARAMETERS), "b" (i) :);
110 switch (eax & 0x1f) {
111 case 0: /* NULL - Exit marker */
112 return true;
113 case 1: /* Supported AC module versions */
114 if (version_mask)
115 *version_mask = ebx;
116 if (version_numbers_supported)
117 *version_numbers_supported = ecx;
118 break;
119 case 2: /* Max size of authenticated code execution area */
120 if (max_size_acm_area)
121 *max_size_acm_area = eax & ~0x1f;
122 break;
123 case 3: /* External memory types supported during AC mode */
124 if (memory_type_mask)
125 *memory_type_mask = eax;
126 break;
127 case 4: /* Selective SENTER functionality control */
128 if (senter_function_disable)
129 *senter_function_disable = eax & (0x3f00);
130 break;
131 case 5: /* TXT extensions support */
132 if (txt_feature_flags)
133 *txt_feature_flags = eax & (0x60);
134 break;
135 }
136 }
137
138 return true;
139}
140
141/**
142 * Get capabilities as returned by getsec[CAPABILITIES].
143 *
144 * Returns false on error, true on success.
145 */
146
147bool getsec_capabilities(uint32_t *eax)
148{
149 if (!getsec_enabled())
150 return false;
151
152 asm volatile ("getsec\n"
153 : "=a" (*eax)
154 : "a" (IA32_GETSEC_CAPABILITIES), "b" (0) :);
155
156 return true;
157}