coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
sgx.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <cpu/x86/msr.h>
5 #include <cpu/x86/mtrr.h>
6 #include <cpu/intel/microcode.h>
8 #include <intelblocks/cpulib.h>
9 #include <intelblocks/msr.h>
10 #include <intelblocks/sgx.h>
12 #include <soc/cpu.h>
13 #include <soc/pci_devs.h>
14 
16 {
17  struct cpuid_result cpuid_regs;
18  msr_t msr;
19 
20  cpuid_regs = cpuid_ext(0x7, 0x0); /* EBX[2] is feature capability */
21  msr = rdmsr(MTRR_CAP_MSR); /* Bit 12 is PRMRR enablement */
22  return ((cpuid_regs.ebx & SGX_SUPPORTED) && (msr.lo & MTRR_CAP_PRMRR));
23 }
24 
26 {
27  union {
28  uint64_t data64;
29  struct {
30  uint32_t lo;
31  uint32_t hi;
32  } data32;
33  } prmrr_base, prmrr_mask;
34  msr_t msr;
35 
36  /*
37  * Software Developer's Manual Volume 4:
38  * Order Number: 335592-068US
39  * Chapter 2.16.1
40  * MSR_PRMRR_PHYS_MASK is in scope "Core"
41  * MSR_PRMRR_PHYS_BASE is in scope "Core"
42  * Return if Hyper-Threading is enabled and not thread 0
43  */
45  return;
46 
47  /* PRMRR_PHYS_MASK is in scope "Core" */
49  /* If it is locked don't attempt to write PRMRR MSRs. */
50  if (msr.lo & PRMRR_PHYS_MASK_LOCK)
51  return;
52 
53  /* PRMRR base and mask are read from the UNCORE PRMRR MSRs
54  * that are already set in FSP-M. */
55  if (soc_get_uncore_prmmr_base_and_mask(&prmrr_base.data64,
56  &prmrr_mask.data64) < 0) {
57  printk(BIOS_ERR, "SGX: Failed to get PRMRR base and mask\n");
58  return;
59  }
60 
61  if (!prmrr_base.data32.lo) {
62  printk(BIOS_ERR, "SGX Error: Uncore PRMRR is not set!\n");
63  return;
64  }
65 
66  printk(BIOS_INFO, "SGX: prmrr_base = 0x%llx\n", prmrr_base.data64);
67  printk(BIOS_INFO, "SGX: prmrr_mask = 0x%llx\n", prmrr_mask.data64);
68 
69  /* Program core PRMRR MSRs.
70  * - Set cache writeback mem attrib in PRMRR base MSR
71  * - Clear the valid bit in PRMRR mask MSR
72  * - Lock PRMRR MASK MSR */
73  prmrr_base.data32.lo |= MTRR_TYPE_WRBACK;
74  wrmsr(MSR_PRMRR_PHYS_BASE, (msr_t) {.lo = prmrr_base.data32.lo,
75  .hi = prmrr_base.data32.hi});
76  prmrr_mask.data32.lo &= ~PRMRR_PHYS_MASK_VALID;
77  prmrr_mask.data32.lo |= PRMRR_PHYS_MASK_LOCK;
78  wrmsr(MSR_PRMRR_PHYS_MASK, (msr_t) {.lo = prmrr_mask.data32.lo,
79  .hi = prmrr_mask.data32.hi});
80 }
81 
82 static int is_prmrr_set(void)
83 {
84  msr_t prmrr_base, prmrr_mask;
85  prmrr_base = rdmsr(MSR_PRMRR_PHYS_BASE);
86  prmrr_mask = rdmsr(MSR_PRMRR_PHYS_MASK);
87 
88  /* If PRMRR base is zero and PRMRR mask is locked
89  * then PRMRR is not set */
90  if ((prmrr_base.hi == 0) && (prmrr_base.lo == 0)
91  && (prmrr_mask.lo & PRMRR_PHYS_MASK_LOCK))
92  return 0;
93  return 1;
94 }
95 
96 static void enable_sgx(void)
97 {
98  msr_t msr;
99 
100  /*
101  * Intel 64 and IA-32 ArchitecturesSoftware Developer's ManualVolume 3C
102  * Order Number: 326019-060US
103  * Chapter 35.10.2 "Additional MSRs Supported by Intel"
104  * IA32_FEATURE_CONTROL is in scope "Thread"
105  */
107  /* Only enable it when it is not locked */
108  if ((msr.lo & FEATURE_CONTROL_LOCK_BIT) == 0) {
109  msr.lo |= SGX_GLOBAL_ENABLE; /* Enable it */
111  }
112 }
113 
114 static void lock_sgx(void)
115 {
116  msr_t msr;
117 
118  /*
119  * Intel 64 and IA-32 ArchitecturesSoftware Developer's ManualVolume 3C
120  * Order Number: 326019-060US
121  * Chapter 35.10.2 "Additional MSRs Supported by Intel"
122  * IA32_FEATURE_CONTROL is in scope "Thread"
123  */
125  /* If it is locked don't attempt to lock it again. */
126  if ((msr.lo & 1) == 0) {
127  msr.lo |= 1; /* Lock it */
129  }
130 }
131 
132 static int owner_epoch_update(void)
133 {
134  /* TODO - the Owner Epoch update mechanism is not determined yet,
135  * for PoC just write '0's to the MSRs. */
136  msr_t msr = {0, 0};
137 
138  /* SGX_OWNEREPOCH is in scope "Package" */
141  return 0;
142 }
143 
144 static void activate_sgx(void)
145 {
146  msr_t msr;
147 
148  /* Activate SGX feature by writing 1b to MSR 0x7A on all threads.
149  * BIOS must ensure bit 0 is set prior to writing to it, then read it
150  * back and verify the bit is cleared to confirm SGX activation. */
151  msr = rdmsr(MSR_BIOS_UPGD_TRIG);
152  if (msr.lo & SGX_ACTIVATE_BIT) {
154  (msr_t) {.lo = SGX_ACTIVATE_BIT, .hi = 0});
155  /* Read back to verify it is activated */
156  msr = rdmsr(MSR_BIOS_UPGD_TRIG);
157  if (msr.lo & SGX_ACTIVATE_BIT)
158  printk(BIOS_ERR, "SGX activation failed.\n");
159  else
160  printk(BIOS_INFO, "SGX activation was successful.\n");
161  } else {
162  printk(BIOS_ERR, "SGX feature is deactivated.\n");
163  }
164 }
165 
166 static int is_prmrr_approved(void)
167 {
168  msr_t msr;
169  msr = rdmsr(MSR_PRMRR_PHYS_MASK);
170  if (msr.lo & PRMRR_PHYS_MASK_VALID) {
171  printk(BIOS_INFO, "SGX: MCHECK approved SGX PRMRR\n");
172  return 1;
173  }
174 
175  printk(BIOS_INFO, "SGX: MCHECK did not approve SGX PRMRR\n");
176  return 0;
177 }
178 
179 /*
180  * Configures SGX according to "Intel Software Guard Extensions Technology"
181  * Document Number: 565432
182  */
183 void sgx_configure(void *unused)
184 {
185 
186  if (!is_sgx_supported() || !is_prmrr_set()) {
187  printk(BIOS_ERR, "SGX: not supported or pre-conditions not met\n");
188  return;
189  }
190 
191  /* Enable the SGX feature on all threads. */
192  enable_sgx();
193 
194  /* Update the owner epoch value */
195  if (owner_epoch_update() < 0)
196  return;
197 
198  /* Ensure to lock memory before reloading microcode patch */
199  if (CONFIG(SOC_INTEL_COMMON_BLOCK_SGX_LOCK_MEMORY))
201 
202  /*
203  * Update just on the first CPU in the core. Other siblings
204  * get the update automatically according to Document: 253668-060US
205  * Intel SDM Chapter 9.11.6.3
206  * "Update in a System Supporting Intel Hyper-Threading Technology"
207  * Intel Hyper-Threading Technology has implications on the loading of the
208  * microcode update. The update must be loaded for each core in a physical
209  * processor. Thus, for a processor supporting Intel Hyper-Threading
210  * Technology, only one logical processor per core is required to load the
211  * microcode update. Each individual logical processor can independently
212  * load the update. However, MP initialization must provide some mechanism
213  * (e.g. a software semaphore) to force serialization of microcode update
214  * loads and to prevent simultaneous load attempts to the same core.
215  */
216  if (!intel_ht_sibling()) {
217  const void *microcode_patch = intel_microcode_find();
219  }
220 
221  /* Lock the SGX feature on all threads. */
222  lock_sgx();
223 
224  /* Activate the SGX feature, if PRMRR config was approved by MCHECK */
225  if (is_prmrr_approved())
226  activate_sgx();
227 }
int soc_get_uncore_prmmr_base_and_mask(uint64_t *prmrr_base, uint64_t *prmrr_mask)
Definition: systemagent.c:48
static struct cpuid_result cpuid_ext(int op, unsigned int ecx)
Definition: cpu.h:59
#define printk(level,...)
Definition: stdlib.h:16
bool intel_ht_sibling(void)
#define MSR_PRMRR_PHYS_BASE
Definition: haswell.h:54
#define MSR_PRMRR_PHYS_MASK
Definition: haswell.h:55
void cpu_lt_lock_memory(void)
Definition: cpulib.c:392
@ CONFIG
Definition: dsi_common.h:201
static const void * microcode_patch
Definition: haswell_init.c:567
static __always_inline msr_t rdmsr(unsigned int index)
Definition: msr.h:146
#define IA32_FEATURE_CONTROL
Definition: msr.h:20
#define SGX_GLOBAL_ENABLE
Definition: msr.h:29
#define FEATURE_CONTROL_LOCK_BIT
Definition: msr.h:21
static __always_inline void wrmsr(unsigned int index, msr_t msr)
Definition: msr.h:157
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
void intel_microcode_load_unlocked(const void *microcode_patch)
Definition: microcode.c:71
const void * intel_microcode_find(void)
Definition: microcode.c:223
static void activate_sgx(void)
Definition: sgx.c:144
void prmrr_core_configure(void)
Definition: sgx.c:25
static int owner_epoch_update(void)
Definition: sgx.c:132
void sgx_configure(void *unused)
Definition: sgx.c:183
int is_sgx_supported(void)
Definition: sgx.c:15
static int is_prmrr_set(void)
Definition: sgx.c:82
static int is_prmrr_approved(void)
Definition: sgx.c:166
static void lock_sgx(void)
Definition: sgx.c:114
static void enable_sgx(void)
Definition: sgx.c:96
#define MSR_SGX_OWNEREPOCH0
Definition: msr.h:54
#define MSR_SGX_OWNEREPOCH1
Definition: msr.h:55
#define SGX_SUPPORTED
Definition: msr.h:107
#define PRMRR_PHYS_MASK_VALID
Definition: msr.h:47
#define MSR_BIOS_UPGD_TRIG
Definition: msr.h:17
#define PRMRR_PHYS_MASK_LOCK
Definition: msr.h:46
#define SGX_ACTIVATE_BIT
Definition: msr.h:18
unsigned int uint32_t
Definition: stdint.h:14
unsigned long long uint64_t
Definition: stdint.h:17
uint32_t ebx
Definition: cpu.h:31
unsigned int hi
Definition: msr.h:112
unsigned int lo
Definition: msr.h:111
#define MTRR_CAP_PRMRR
Definition: mtrr.h:19
#define MTRR_CAP_MSR
Definition: mtrr.h:17
#define MTRR_TYPE_WRBACK
Definition: mtrr.h:14