1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <console/console.h>
4 #include <cpu/x86/msr.h>
5 #include <cpu/x86/mtrr.h>
6 #include <cpu/intel/microcode.h>
7 #include <cpu/intel/common/common.h>
8 #include <intelblocks/cpulib.h>
9 #include <intelblocks/msr.h>
10 #include <intelblocks/sgx.h>
11 #include <intelblocks/systemagent.h>
14 #include <soc/pci_devs.h>
16 static inline uint64_t sgx_resource(uint32_t low
, uint32_t high
)
19 val
= (uint64_t)(high
& SGX_RESOURCE_MASK_HI
) << 32;
20 val
|= low
& SGX_RESOURCE_MASK_LO
;
24 static int is_sgx_supported(void)
26 struct cpuid_result cpuid_regs
;
29 cpuid_regs
= cpuid_ext(0x7, 0x0); /* EBX[2] is feature capability */
30 msr
= rdmsr(MTRR_CAP_MSR
); /* Bit 12 is PRMRR enablement */
31 return ((cpuid_regs
.ebx
& SGX_SUPPORTED
) && (msr
.lo
& MTRR_CAP_PRMRR
));
34 void prmrr_core_configure(void)
42 } prmrr_base
, prmrr_mask
;
46 * Software Developer's Manual Volume 4:
47 * Order Number: 335592-068US
49 * MSR_PRMRR_PHYS_MASK is in scope "Core"
50 * MSR_PRMRR_PHYS_BASE is in scope "Core"
51 * Return if Hyper-Threading is enabled and not thread 0
53 if (!is_sgx_supported() || intel_ht_sibling())
56 /* PRMRR_PHYS_MASK is in scope "Core" */
57 msr
= rdmsr(MSR_PRMRR_PHYS_MASK
);
58 /* If it is locked don't attempt to write PRMRR MSRs. */
59 if (msr
.lo
& PRMRR_PHYS_MASK_LOCK
)
62 /* PRMRR base and mask are read from the UNCORE PRMRR MSRs
63 * that are already set in FSP-M. */
64 if (soc_get_uncore_prmmr_base_and_mask(&prmrr_base
.data64
,
65 &prmrr_mask
.data64
) < 0) {
66 printk(BIOS_ERR
, "SGX: Failed to get PRMRR base and mask\n");
70 if (!prmrr_base
.data32
.lo
) {
71 printk(BIOS_ERR
, "SGX Error: Uncore PRMRR is not set!\n");
75 printk(BIOS_INFO
, "SGX: prmrr_base = 0x%llx\n", prmrr_base
.data64
);
76 printk(BIOS_INFO
, "SGX: prmrr_mask = 0x%llx\n", prmrr_mask
.data64
);
78 /* Program core PRMRR MSRs.
79 * - Set cache writeback mem attrib in PRMRR base MSR
80 * - Clear the valid bit in PRMRR mask MSR
81 * - Lock PRMRR MASK MSR */
82 prmrr_base
.data32
.lo
|= MTRR_TYPE_WRBACK
;
83 wrmsr(MSR_PRMRR_PHYS_BASE
, (msr_t
) {.lo
= prmrr_base
.data32
.lo
,
84 .hi
= prmrr_base
.data32
.hi
});
85 prmrr_mask
.data32
.lo
&= ~PRMRR_PHYS_MASK_VALID
;
86 prmrr_mask
.data32
.lo
|= PRMRR_PHYS_MASK_LOCK
;
87 wrmsr(MSR_PRMRR_PHYS_MASK
, (msr_t
) {.lo
= prmrr_mask
.data32
.lo
,
88 .hi
= prmrr_mask
.data32
.hi
});
91 static int is_prmrr_set(void)
93 msr_t prmrr_base
, prmrr_mask
;
94 prmrr_base
= rdmsr(MSR_PRMRR_PHYS_BASE
);
95 prmrr_mask
= rdmsr(MSR_PRMRR_PHYS_MASK
);
97 /* If PRMRR base is zero and PRMRR mask is locked
98 * then PRMRR is not set */
99 if ((prmrr_base
.hi
== 0) && (prmrr_base
.lo
== 0)
100 && (prmrr_mask
.lo
& PRMRR_PHYS_MASK_LOCK
))
105 static void enable_sgx(void)
110 * Intel 64 and IA-32 ArchitecturesSoftware Developer's ManualVolume 3C
111 * Order Number: 326019-060US
112 * Chapter 35.10.2 "Additional MSRs Supported by Intel"
113 * IA32_FEATURE_CONTROL is in scope "Thread"
115 msr
= rdmsr(IA32_FEATURE_CONTROL
);
116 /* Only enable it when it is not locked */
117 if ((msr
.lo
& FEATURE_CONTROL_LOCK_BIT
) == 0) {
118 msr
.lo
|= SGX_GLOBAL_ENABLE
; /* Enable it */
119 wrmsr(IA32_FEATURE_CONTROL
, msr
);
123 static void lock_sgx(void)
128 * Intel 64 and IA-32 ArchitecturesSoftware Developer's ManualVolume 3C
129 * Order Number: 326019-060US
130 * Chapter 35.10.2 "Additional MSRs Supported by Intel"
131 * IA32_FEATURE_CONTROL is in scope "Thread"
133 msr
= rdmsr(IA32_FEATURE_CONTROL
);
134 /* If it is locked don't attempt to lock it again. */
135 if ((msr
.lo
& 1) == 0) {
136 msr
.lo
|= 1; /* Lock it */
137 wrmsr(IA32_FEATURE_CONTROL
, msr
);
141 static int owner_epoch_update(void)
143 /* TODO - the Owner Epoch update mechanism is not determined yet,
144 * for PoC just write '0's to the MSRs. */
147 /* SGX_OWNEREPOCH is in scope "Package" */
148 wrmsr(MSR_SGX_OWNEREPOCH0
, msr
);
149 wrmsr(MSR_SGX_OWNEREPOCH1
, msr
);
153 static void activate_sgx(void)
157 /* Activate SGX feature by writing 1b to MSR 0x7A on all threads.
158 * BIOS must ensure bit 0 is set prior to writing to it, then read it
159 * back and verify the bit is cleared to confirm SGX activation. */
160 msr
= rdmsr(MSR_BIOS_UPGD_TRIG
);
161 if (msr
.lo
& SGX_ACTIVATE_BIT
) {
162 wrmsr(MSR_BIOS_UPGD_TRIG
,
163 (msr_t
) {.lo
= SGX_ACTIVATE_BIT
, .hi
= 0});
164 /* Read back to verify it is activated */
165 msr
= rdmsr(MSR_BIOS_UPGD_TRIG
);
166 if (msr
.lo
& SGX_ACTIVATE_BIT
)
167 printk(BIOS_ERR
, "SGX activation failed.\n");
169 printk(BIOS_INFO
, "SGX activation was successful.\n");
171 printk(BIOS_ERR
, "SGX feature is deactivated.\n");
175 static int is_prmrr_approved(void)
178 msr
= rdmsr(MSR_PRMRR_PHYS_MASK
);
179 if (msr
.lo
& PRMRR_PHYS_MASK_VALID
) {
180 printk(BIOS_INFO
, "SGX: MCHECK approved SGX PRMRR\n");
184 printk(BIOS_INFO
, "SGX: MCHECK did not approve SGX PRMRR\n");
189 * Configures SGX according to "Intel Software Guard Extensions Technology"
190 * Document Number: 565432
192 void sgx_configure(void *unused
)
195 if (!is_sgx_supported() || !is_prmrr_set()) {
196 printk(BIOS_ERR
, "SGX: not supported or pre-conditions not met\n");
200 /* Enable the SGX feature on all threads. */
203 /* Update the owner epoch value */
204 if (owner_epoch_update() < 0)
207 /* Ensure to lock memory before reloading microcode patch */
208 if (CONFIG(SOC_INTEL_COMMON_BLOCK_SGX_LOCK_MEMORY
))
209 cpu_lt_lock_memory();
212 * Update just on the first CPU in the core. Other siblings
213 * get the update automatically according to Document: 253668-060US
214 * Intel SDM Chapter 9.11.6.3
215 * "Update in a System Supporting Intel Hyper-Threading Technology"
216 * Intel Hyper-Threading Technology has implications on the loading of the
217 * microcode update. The update must be loaded for each core in a physical
218 * processor. Thus, for a processor supporting Intel Hyper-Threading
219 * Technology, only one logical processor per core is required to load the
220 * microcode update. Each individual logical processor can independently
221 * load the update. However, MP initialization must provide some mechanism
222 * (e.g. a software semaphore) to force serialization of microcode update
223 * loads and to prevent simultaneous load attempts to the same core.
225 if (!intel_ht_sibling()) {
226 const void *microcode_patch
= intel_microcode_find();
227 intel_microcode_load_unlocked(microcode_patch
);
230 /* Lock the SGX feature on all threads. */
233 /* Activate the SGX feature, if PRMRR config was approved by MCHECK */
234 if (is_prmrr_approved())
238 void sgx_fill_gnvs(struct global_nvs
*gnvs
)
240 struct cpuid_result cpuid_regs
;
242 if (!is_sgx_supported()) {
244 "SGX: not supported. skip gnvs fill\n");
248 /* Get EPC base and size.
249 * Intel SDM: Table 36-6. CPUID Leaf 12H, Sub-Leaf Index 2 or
250 * Higher for enumeration of SGX Resources. Same Table mentions
251 * about return values of the CPUID */
252 cpuid_regs
= cpuid_ext(SGX_RESOURCE_ENUM_CPUID_LEAF
,
253 SGX_RESOURCE_ENUM_CPUID_SUBLEAF
);
255 if (cpuid_regs
.eax
& SGX_RESOURCE_ENUM_BIT
) {
256 /* EPC section enumerated */
258 gnvs
->emna
= sgx_resource(cpuid_regs
.eax
, cpuid_regs
.ebx
);
259 gnvs
->elng
= sgx_resource(cpuid_regs
.ecx
, cpuid_regs
.edx
);
263 "SGX: gnvs ECP status = %d base = 0x%llx len = 0x%llx\n",
264 gnvs
->epcs
, gnvs
->emna
, gnvs
->elng
);