Angel Pons | 0612b27 | 2020-04-05 15:46:56 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 2 | |
| 3 | #include <console/console.h> |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 4 | #include <cpu/x86/msr.h> |
| 5 | #include <cpu/x86/mtrr.h> |
| 6 | #include <cpu/intel/microcode.h> |
Patrick Rudolph | 05bad43 | 2019-09-26 10:30:22 +0200 | [diff] [blame] | 7 | #include <cpu/intel/common/common.h> |
Michael Niewöhner | c5fc753 | 2019-09-22 21:56:17 +0200 | [diff] [blame] | 8 | #include <intelblocks/cpulib.h> |
Pratik Prajapati | b45b22f | 2017-09-13 13:45:31 -0700 | [diff] [blame] | 9 | #include <intelblocks/msr.h> |
Pratik Prajapati | a04aa3d | 2017-06-12 23:02:36 -0700 | [diff] [blame] | 10 | #include <intelblocks/sgx.h> |
Pratik Prajapati | 57c5af3 | 2017-08-28 15:21:52 -0700 | [diff] [blame] | 11 | #include <intelblocks/systemagent.h> |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 12 | #include <soc/cpu.h> |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 13 | #include <soc/pci_devs.h> |
Pratik Prajapati | b45b22f | 2017-09-13 13:45:31 -0700 | [diff] [blame] | 14 | |
Pratik Prajapati | 53d68b4 | 2017-08-14 11:46:47 -0700 | [diff] [blame] | 15 | void prmrr_core_configure(void) |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 16 | { |
Arthur Heymans | 407e00d | 2022-10-19 20:06:42 +0200 | [diff] [blame] | 17 | msr_t prmrr_base, prmrr_mask; |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 18 | |
Patrick Rudolph | 05bad43 | 2019-09-26 10:30:22 +0200 | [diff] [blame] | 19 | /* |
| 20 | * Software Developer's Manual Volume 4: |
| 21 | * Order Number: 335592-068US |
| 22 | * Chapter 2.16.1 |
| 23 | * MSR_PRMRR_PHYS_MASK is in scope "Core" |
| 24 | * MSR_PRMRR_PHYS_BASE is in scope "Core" |
| 25 | * Return if Hyper-Threading is enabled and not thread 0 |
| 26 | */ |
| 27 | if (!is_sgx_supported() || intel_ht_sibling()) |
Pratik Prajapati | 53d68b4 | 2017-08-14 11:46:47 -0700 | [diff] [blame] | 28 | return; |
| 29 | |
Patrick Rudolph | 05bad43 | 2019-09-26 10:30:22 +0200 | [diff] [blame] | 30 | /* PRMRR_PHYS_MASK is in scope "Core" */ |
Arthur Heymans | 407e00d | 2022-10-19 20:06:42 +0200 | [diff] [blame] | 31 | prmrr_mask = rdmsr(MSR_PRMRR_PHYS_MASK); |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 32 | /* If it is locked don't attempt to write PRMRR MSRs. */ |
Arthur Heymans | 407e00d | 2022-10-19 20:06:42 +0200 | [diff] [blame] | 33 | if (prmrr_mask.lo & PRMRR_PHYS_MASK_LOCK) |
Pratik Prajapati | 53d68b4 | 2017-08-14 11:46:47 -0700 | [diff] [blame] | 34 | return; |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 35 | |
Pratik Prajapati | 57c5af3 | 2017-08-28 15:21:52 -0700 | [diff] [blame] | 36 | /* PRMRR base and mask are read from the UNCORE PRMRR MSRs |
| 37 | * that are already set in FSP-M. */ |
Arthur Heymans | 407e00d | 2022-10-19 20:06:42 +0200 | [diff] [blame] | 38 | if (soc_get_uncore_prmmr_base_and_mask(&prmrr_base.raw, |
| 39 | &prmrr_mask.raw) < 0) { |
Pratik Prajapati | 57c5af3 | 2017-08-28 15:21:52 -0700 | [diff] [blame] | 40 | printk(BIOS_ERR, "SGX: Failed to get PRMRR base and mask\n"); |
| 41 | return; |
| 42 | } |
| 43 | |
Arthur Heymans | 407e00d | 2022-10-19 20:06:42 +0200 | [diff] [blame] | 44 | if (!prmrr_base.lo) { |
Pratik Prajapati | 57c5af3 | 2017-08-28 15:21:52 -0700 | [diff] [blame] | 45 | printk(BIOS_ERR, "SGX Error: Uncore PRMRR is not set!\n"); |
| 46 | return; |
| 47 | } |
| 48 | |
Arthur Heymans | 407e00d | 2022-10-19 20:06:42 +0200 | [diff] [blame] | 49 | printk(BIOS_INFO, "SGX: prmrr_base = 0x%llx\n", prmrr_base.raw); |
| 50 | printk(BIOS_INFO, "SGX: prmrr_mask = 0x%llx\n", prmrr_mask.raw); |
Pratik Prajapati | 57c5af3 | 2017-08-28 15:21:52 -0700 | [diff] [blame] | 51 | |
| 52 | /* Program core PRMRR MSRs. |
| 53 | * - Set cache writeback mem attrib in PRMRR base MSR |
| 54 | * - Clear the valid bit in PRMRR mask MSR |
| 55 | * - Lock PRMRR MASK MSR */ |
Arthur Heymans | 407e00d | 2022-10-19 20:06:42 +0200 | [diff] [blame] | 56 | prmrr_base.lo |= MTRR_TYPE_WRBACK; |
| 57 | wrmsr(MSR_PRMRR_PHYS_BASE, prmrr_base); |
| 58 | prmrr_mask.lo &= ~PRMRR_PHYS_MASK_VALID; |
| 59 | prmrr_mask.lo |= PRMRR_PHYS_MASK_LOCK; |
| 60 | wrmsr(MSR_PRMRR_PHYS_MASK, prmrr_mask); |
Pratik Prajapati | 53d68b4 | 2017-08-14 11:46:47 -0700 | [diff] [blame] | 61 | } |
| 62 | |
| 63 | static int is_prmrr_set(void) |
| 64 | { |
| 65 | msr_t prmrr_base, prmrr_mask; |
Elyes HAOUAS | f212cf3 | 2018-12-18 10:24:55 +0100 | [diff] [blame] | 66 | prmrr_base = rdmsr(MSR_PRMRR_PHYS_BASE); |
| 67 | prmrr_mask = rdmsr(MSR_PRMRR_PHYS_MASK); |
Pratik Prajapati | 53d68b4 | 2017-08-14 11:46:47 -0700 | [diff] [blame] | 68 | |
| 69 | /* If PRMRR base is zero and PRMRR mask is locked |
| 70 | * then PRMRR is not set */ |
| 71 | if ((prmrr_base.hi == 0) && (prmrr_base.lo == 0) |
| 72 | && (prmrr_mask.lo & PRMRR_PHYS_MASK_LOCK)) |
| 73 | return 0; |
| 74 | return 1; |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 75 | } |
| 76 | |
| 77 | static void enable_sgx(void) |
| 78 | { |
| 79 | msr_t msr; |
| 80 | |
Patrick Rudolph | 05bad43 | 2019-09-26 10:30:22 +0200 | [diff] [blame] | 81 | /* |
| 82 | * Intel 64 and IA-32 ArchitecturesSoftware Developer's ManualVolume 3C |
| 83 | * Order Number: 326019-060US |
| 84 | * Chapter 35.10.2 "Additional MSRs Supported by Intel" |
| 85 | * IA32_FEATURE_CONTROL is in scope "Thread" |
| 86 | */ |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 87 | msr = rdmsr(IA32_FEATURE_CONTROL); |
| 88 | /* Only enable it when it is not locked */ |
Elyes HAOUAS | 419bfbc | 2018-10-01 08:47:51 +0200 | [diff] [blame] | 89 | if ((msr.lo & FEATURE_CONTROL_LOCK_BIT) == 0) { |
Pratik Prajapati | a04aa3d | 2017-06-12 23:02:36 -0700 | [diff] [blame] | 90 | msr.lo |= SGX_GLOBAL_ENABLE; /* Enable it */ |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 91 | wrmsr(IA32_FEATURE_CONTROL, msr); |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | static void lock_sgx(void) |
| 96 | { |
| 97 | msr_t msr; |
| 98 | |
Patrick Rudolph | 05bad43 | 2019-09-26 10:30:22 +0200 | [diff] [blame] | 99 | /* |
| 100 | * Intel 64 and IA-32 ArchitecturesSoftware Developer's ManualVolume 3C |
| 101 | * Order Number: 326019-060US |
| 102 | * Chapter 35.10.2 "Additional MSRs Supported by Intel" |
| 103 | * IA32_FEATURE_CONTROL is in scope "Thread" |
| 104 | */ |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 105 | msr = rdmsr(IA32_FEATURE_CONTROL); |
| 106 | /* If it is locked don't attempt to lock it again. */ |
| 107 | if ((msr.lo & 1) == 0) { |
| 108 | msr.lo |= 1; /* Lock it */ |
| 109 | wrmsr(IA32_FEATURE_CONTROL, msr); |
| 110 | } |
| 111 | } |
| 112 | |
| 113 | static int owner_epoch_update(void) |
| 114 | { |
Pratik Prajapati | 53d68b4 | 2017-08-14 11:46:47 -0700 | [diff] [blame] | 115 | /* TODO - the Owner Epoch update mechanism is not determined yet, |
| 116 | * for PoC just write '0's to the MSRs. */ |
Arthur Heymans | 407e00d | 2022-10-19 20:06:42 +0200 | [diff] [blame] | 117 | msr_t msr = { .raw = 0 }; |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 118 | |
Patrick Rudolph | 05bad43 | 2019-09-26 10:30:22 +0200 | [diff] [blame] | 119 | /* SGX_OWNEREPOCH is in scope "Package" */ |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 120 | wrmsr(MSR_SGX_OWNEREPOCH0, msr); |
| 121 | wrmsr(MSR_SGX_OWNEREPOCH1, msr); |
| 122 | return 0; |
| 123 | } |
| 124 | |
| 125 | static void activate_sgx(void) |
| 126 | { |
| 127 | msr_t msr; |
| 128 | |
Pratik Prajapati | 53d68b4 | 2017-08-14 11:46:47 -0700 | [diff] [blame] | 129 | /* Activate SGX feature by writing 1b to MSR 0x7A on all threads. |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 130 | * BIOS must ensure bit 0 is set prior to writing to it, then read it |
Pratik Prajapati | 53d68b4 | 2017-08-14 11:46:47 -0700 | [diff] [blame] | 131 | * back and verify the bit is cleared to confirm SGX activation. */ |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 132 | msr = rdmsr(MSR_BIOS_UPGD_TRIG); |
Pratik Prajapati | a04aa3d | 2017-06-12 23:02:36 -0700 | [diff] [blame] | 133 | if (msr.lo & SGX_ACTIVATE_BIT) { |
| 134 | wrmsr(MSR_BIOS_UPGD_TRIG, |
| 135 | (msr_t) {.lo = SGX_ACTIVATE_BIT, .hi = 0}); |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 136 | /* Read back to verify it is activated */ |
| 137 | msr = rdmsr(MSR_BIOS_UPGD_TRIG); |
Pratik Prajapati | a04aa3d | 2017-06-12 23:02:36 -0700 | [diff] [blame] | 138 | if (msr.lo & SGX_ACTIVATE_BIT) |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 139 | printk(BIOS_ERR, "SGX activation failed.\n"); |
| 140 | else |
| 141 | printk(BIOS_INFO, "SGX activation was successful.\n"); |
| 142 | } else { |
| 143 | printk(BIOS_ERR, "SGX feature is deactivated.\n"); |
| 144 | } |
| 145 | } |
| 146 | |
Pratik Prajapati | 53d68b4 | 2017-08-14 11:46:47 -0700 | [diff] [blame] | 147 | static int is_prmrr_approved(void) |
| 148 | { |
| 149 | msr_t msr; |
Elyes HAOUAS | f212cf3 | 2018-12-18 10:24:55 +0100 | [diff] [blame] | 150 | msr = rdmsr(MSR_PRMRR_PHYS_MASK); |
Pratik Prajapati | 53d68b4 | 2017-08-14 11:46:47 -0700 | [diff] [blame] | 151 | if (msr.lo & PRMRR_PHYS_MASK_VALID) { |
Jonathan Neuschäfer | 5268b76 | 2018-02-12 12:24:25 +0100 | [diff] [blame] | 152 | printk(BIOS_INFO, "SGX: MCHECK approved SGX PRMRR\n"); |
Pratik Prajapati | 53d68b4 | 2017-08-14 11:46:47 -0700 | [diff] [blame] | 153 | return 1; |
| 154 | } |
| 155 | |
Jonathan Neuschäfer | 5268b76 | 2018-02-12 12:24:25 +0100 | [diff] [blame] | 156 | printk(BIOS_INFO, "SGX: MCHECK did not approve SGX PRMRR\n"); |
Pratik Prajapati | 53d68b4 | 2017-08-14 11:46:47 -0700 | [diff] [blame] | 157 | return 0; |
| 158 | } |
| 159 | |
Patrick Rudolph | 05bad43 | 2019-09-26 10:30:22 +0200 | [diff] [blame] | 160 | /* |
| 161 | * Configures SGX according to "Intel Software Guard Extensions Technology" |
| 162 | * Document Number: 565432 |
| 163 | */ |
Subrata Banik | 3337497 | 2018-04-24 13:45:30 +0530 | [diff] [blame] | 164 | void sgx_configure(void *unused) |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 165 | { |
Michael Niewöhner | 6e66d7b | 2019-10-08 12:00:24 +0200 | [diff] [blame] | 166 | if (!is_sgx_supported() || !is_prmrr_set()) { |
Michael Niewöhner | 7736bfc | 2019-10-22 23:05:06 +0200 | [diff] [blame] | 167 | printk(BIOS_ERR, "SGX: not supported or pre-conditions not met\n"); |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 168 | return; |
Pratik Prajapati | 53d68b4 | 2017-08-14 11:46:47 -0700 | [diff] [blame] | 169 | } |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 170 | |
Patrick Rudolph | 05bad43 | 2019-09-26 10:30:22 +0200 | [diff] [blame] | 171 | /* Enable the SGX feature on all threads. */ |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 172 | enable_sgx(); |
| 173 | |
| 174 | /* Update the owner epoch value */ |
| 175 | if (owner_epoch_update() < 0) |
| 176 | return; |
| 177 | |
Michael Niewöhner | 6e64c1a | 2020-08-05 21:36:11 +0200 | [diff] [blame] | 178 | /* Ensure to lock memory before reloading microcode patch */ |
Michael Niewöhner | c5fc753 | 2019-09-22 21:56:17 +0200 | [diff] [blame] | 179 | if (CONFIG(SOC_INTEL_COMMON_BLOCK_SGX_LOCK_MEMORY)) |
Michael Niewöhner | 6e64c1a | 2020-08-05 21:36:11 +0200 | [diff] [blame] | 180 | cpu_lt_lock_memory(); |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 181 | |
Patrick Rudolph | 05bad43 | 2019-09-26 10:30:22 +0200 | [diff] [blame] | 182 | /* |
| 183 | * Update just on the first CPU in the core. Other siblings |
| 184 | * get the update automatically according to Document: 253668-060US |
| 185 | * Intel SDM Chapter 9.11.6.3 |
| 186 | * "Update in a System Supporting Intel Hyper-Threading Technology" |
| 187 | * Intel Hyper-Threading Technology has implications on the loading of the |
| 188 | * microcode update. The update must be loaded for each core in a physical |
| 189 | * processor. Thus, for a processor supporting Intel Hyper-Threading |
| 190 | * Technology, only one logical processor per core is required to load the |
| 191 | * microcode update. Each individual logical processor can independently |
| 192 | * load the update. However, MP initialization must provide some mechanism |
| 193 | * (e.g. a software semaphore) to force serialization of microcode update |
| 194 | * loads and to prevent simultaneous load attempts to the same core. |
| 195 | */ |
| 196 | if (!intel_ht_sibling()) { |
Patrick Rudolph | 3fa23b8 | 2021-01-25 09:42:08 +0100 | [diff] [blame] | 197 | const void *microcode_patch = intel_microcode_find(); |
Patrick Rudolph | 05bad43 | 2019-09-26 10:30:22 +0200 | [diff] [blame] | 198 | intel_microcode_load_unlocked(microcode_patch); |
| 199 | } |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 200 | |
Patrick Rudolph | 05bad43 | 2019-09-26 10:30:22 +0200 | [diff] [blame] | 201 | /* Lock the SGX feature on all threads. */ |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 202 | lock_sgx(); |
| 203 | |
Jonathan Neuschäfer | 5268b76 | 2018-02-12 12:24:25 +0100 | [diff] [blame] | 204 | /* Activate the SGX feature, if PRMRR config was approved by MCHECK */ |
Pratik Prajapati | 53d68b4 | 2017-08-14 11:46:47 -0700 | [diff] [blame] | 205 | if (is_prmrr_approved()) |
| 206 | activate_sgx(); |
Robbie Zhang | 7de0317 | 2017-02-21 14:00:31 -0800 | [diff] [blame] | 207 | } |