drivers/wifi: Remove unnecessary data structure copy
[coreboot2.git] / src / cpu / x86 / smm / smm_module_handler.c
blob899ee2f6756d1256808ce3f6307577d9adf10a28
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <arch/io.h>
4 #include <commonlib/region.h>
5 #include <console/cbmem_console.h>
6 #include <console/console.h>
7 #include <cpu/cpu.h>
8 #include <cpu/x86/smm.h>
9 #include <rmodule.h>
10 #include <types.h>
11 #include <security/intel/stm/SmmStm.h>
13 #if CONFIG(SPI_FLASH_SMM)
14 #include <spi-generic.h>
15 #endif
17 static int do_driver_init = 1;
19 typedef enum { SMI_LOCKED, SMI_UNLOCKED } smi_semaphore;
21 /* SMI multiprocessing semaphore */
22 static volatile
23 __attribute__((aligned(4))) smi_semaphore smi_handler_status = SMI_UNLOCKED;
25 static const volatile
26 __attribute((aligned(4), __section__(".module_parameters"))) struct smm_runtime smm_runtime;
28 static int smi_obtain_lock(void)
30 u8 ret = SMI_LOCKED;
32 asm volatile (
33 "movb %2, %%al\n"
34 "xchgb %%al, %1\n"
35 "movb %%al, %0\n"
36 : "=g" (ret), "=m" (smi_handler_status)
37 : "g" (SMI_LOCKED)
38 : "eax"
41 return (ret == SMI_UNLOCKED);
44 static void smi_release_lock(void)
46 asm volatile (
47 "movb %1, %%al\n"
48 "xchgb %%al, %0\n"
49 : "=m" (smi_handler_status)
50 : "g" (SMI_UNLOCKED)
51 : "eax"
55 #if CONFIG(RUNTIME_CONFIGURABLE_SMM_LOGLEVEL)
56 int get_console_loglevel(void)
58 return smm_runtime.smm_log_level;
60 #endif
62 void smm_get_smmstore_com_buffer(uintptr_t *base, size_t *size)
64 *base = smm_runtime.smmstore_com_buffer_base;
65 *size = smm_runtime.smmstore_com_buffer_size;
68 void smm_get_cbmemc_buffer(void **buffer_out, size_t *size_out)
70 *buffer_out = smm_runtime.cbmemc;
71 *size_out = smm_runtime.cbmemc_size;
74 void io_trap_handler(int smif)
76 /* If a handler function handled a given IO trap, it
77 * shall return a non-zero value
79 printk(BIOS_DEBUG, "SMI function trap 0x%x: ", smif);
81 if (mainboard_io_trap_handler(smif))
82 return;
84 printk(BIOS_DEBUG, "Unknown function\n");
87 static u32 pci_orig;
89 /**
90 * @brief Backup PCI address to make sure we do not mess up the OS
92 static void smi_backup_pci_address(void)
94 pci_orig = inl(0xcf8);
97 /**
98 * @brief Restore PCI address previously backed up
100 static void smi_restore_pci_address(void)
102 outl(pci_orig, 0xcf8);
105 struct global_nvs *gnvs;
107 void *smm_get_save_state(int cpu)
109 if (cpu > smm_runtime.num_cpus)
110 return NULL;
112 return (void *)(smm_runtime.save_state_top[cpu] -
113 (smm_runtime.save_state_size - STM_PSD_SIZE));
116 uint32_t smm_revision(void)
118 const uintptr_t save_state = (uintptr_t)(smm_get_save_state(0));
120 return *(uint32_t *)(save_state + smm_runtime.save_state_size
121 - SMM_REVISION_OFFSET_FROM_TOP);
124 bool smm_region_overlaps_handler(const struct region *r)
126 const struct region r_smm = region_create(smm_runtime.smbase, smm_runtime.smm_size);
127 const struct region r_aseg = region_create(SMM_BASE, SMM_DEFAULT_SIZE);
129 return region_overlap(&r_smm, r) || region_overlap(&r_aseg, r);
132 asmlinkage void smm_handler_start(void *arg)
134 const struct smm_module_params *p;
135 int cpu;
136 uintptr_t actual_canary;
137 uintptr_t expected_canary;
139 p = arg;
140 cpu = p->cpu;
141 expected_canary = (uintptr_t)p->canary;
143 /* Make sure to set the global runtime. It's OK to race as the value
144 * will be the same across CPUs as well as multiple SMIs. */
145 gnvs = (void *)(uintptr_t)smm_runtime.gnvs_ptr;
147 if (cpu >= CONFIG_MAX_CPUS) {
148 /* Do not log messages to console here, it is not thread safe */
149 return;
152 /* Are we ok to execute the handler? */
153 if (!smi_obtain_lock()) {
154 /* For security reasons we don't release the other CPUs
155 * until the CPU with the lock is actually done */
156 while (smi_handler_status == SMI_LOCKED) {
157 asm volatile (
158 ".byte 0xf3, 0x90\n" /* PAUSE */
161 return;
164 smi_backup_pci_address();
166 smm_soc_early_init();
168 console_init();
170 printk(BIOS_SPEW, "\nSMI# #%d\n", cpu);
172 /* Allow drivers to initialize variables in SMM context. */
173 if (do_driver_init) {
174 #if CONFIG(SPI_FLASH_SMM)
175 spi_init();
176 #endif
177 do_driver_init = 0;
180 cpu_smi_handler();
181 northbridge_smi_handler();
182 southbridge_smi_handler();
184 smi_restore_pci_address();
186 actual_canary = *p->canary;
188 if (actual_canary != expected_canary) {
189 printk(BIOS_DEBUG, "canary 0x%lx != 0x%lx\n", actual_canary,
190 expected_canary);
192 // Don't die if we can't indicate an error.
193 if (CONFIG(DEBUG_SMI))
194 die("SMM Handler caused a stack overflow\n");
197 smm_soc_exit();
199 smi_release_lock();
201 /* De-assert SMI# signal to allow another SMI */
202 southbridge_smi_set_eos();
205 #if CONFIG(SMM_PCI_RESOURCE_STORE)
206 const volatile struct smm_pci_resource_info *smm_get_pci_resource_store(void)
208 return &smm_runtime.pci_resources[0];
210 #endif
212 RMODULE_ENTRY(smm_handler_start);
214 /* Provide a default implementation for all weak handlers so that relocation
215 * entries in the modules make sense. Without default implementations the
216 * weak relocations w/o a symbol have a 0 address which is where the modules
217 * are linked at. */
218 int __weak mainboard_io_trap_handler(int smif) { return 0; }
219 void __weak cpu_smi_handler(void) {}
220 void __weak northbridge_smi_handler(void) {}
221 void __weak southbridge_smi_handler(void) {}
222 void __weak mainboard_smi_gpi(u32 gpi_sts) {}
223 int __weak mainboard_smi_apmc(u8 data) { return 0; }
224 void __weak mainboard_smi_sleep(u8 slp_typ) {}
225 void __weak mainboard_smi_finalize(void) {}
227 void __weak smm_soc_early_init(void) {}
228 void __weak smm_soc_exit(void) {}