blob: b6d778b4c96bb442b7f399b63b5a84ead844703d [file] [log] [blame]
Angel Pons32859fc2020-04-02 23:48:27 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Stefan Reinauerdebb11f2008-10-29 04:46:52 +00002
Sven Schnelle180f81e2011-06-28 08:06:18 +02003#ifndef CPU_X86_SMM_H
4#define CPU_X86_SMM_H
5
Edward O'Callaghanc4561e22014-06-26 15:02:40 +10006#include <arch/cpu.h>
Patrick Rudolph41fec862020-05-06 10:55:12 +02007#include <commonlib/region.h>
Edward O'Callaghanc4561e22014-06-26 15:02:40 +10008#include <types.h>
9
Aaron Durbin1fef1f52012-12-19 17:15:43 -060010#define SMM_DEFAULT_BASE 0x30000
11#define SMM_DEFAULT_SIZE 0x10000
12
Rudolf Marekb5b3b3b2011-07-02 16:36:17 +020013/* used only by C programs so far */
14#define SMM_BASE 0xa0000
15
Aaron Durbin62f100b2012-11-07 12:27:29 -060016#define SMM_ENTRY_OFFSET 0x8000
17#define SMM_SAVE_STATE_BEGIN(x) (SMM_ENTRY_OFFSET + (x))
18
Sven Schnellef4dc1a72011-06-05 11:33:41 +020019#define APM_CNT 0xb2
Kyösti Mälkkid1518312020-06-18 13:51:31 +030020#define APM_CNT_NOOP_SMI 0x00
Sven Schnellef4dc1a72011-06-05 11:33:41 +020021#define APM_CNT_ACPI_DISABLE 0x1e
22#define APM_CNT_ACPI_ENABLE 0xe1
Kyösti Mälkkib486f292020-06-18 14:05:35 +030023#define APM_CNT_ROUTE_ALL_XHCI 0xca
Duncan Laurie911cedf2013-07-30 16:05:55 -070024#define APM_CNT_FINALIZE 0xcb
Marc Jones9afc5c02014-09-24 10:53:48 -060025#define APM_CNT_LEGACY 0xcc
Kyösti Mälkkib8cf0392020-06-17 01:00:10 +030026#define APM_CNT_MBI_UPDATE 0xeb
Marshall Dawsond2d93822020-03-16 20:05:05 -060027#define APM_CNT_SMMINFO 0xec
Patrick Georgi9fca2972018-12-03 16:13:17 +010028#define APM_CNT_SMMSTORE 0xed
Patrick Georgid61839c2018-12-03 16:10:33 +010029#define APM_CNT_ELOG_GSMI 0xef
Sven Schnellef4dc1a72011-06-05 11:33:41 +020030#define APM_STS 0xb3
Stefan Reinauer3b387452009-03-06 19:52:36 +000031
Kyösti Mälkkib6585482020-06-01 15:11:14 +030032/* Send cmd to APM_CNT with HAVE_SMI_HANDLER checking. */
33int apm_control(u8 cmd);
Kyösti Mälkki9a1620f2021-01-08 13:27:33 +020034u8 apm_get_apmc(void);
Kyösti Mälkkib6585482020-06-01 15:11:14 +030035
Stefan Reinauerbe7f7982009-03-13 15:42:27 +000036void io_trap_handler(int smif);
Stefan Reinauer3b387452009-03-06 19:52:36 +000037int southbridge_io_trap_handler(int smif);
Kyösti Mälkki48b3dbc2014-12-29 19:36:50 +020038int mainboard_io_trap_handler(int smif);
Stefan Reinauer3b387452009-03-06 19:52:36 +000039
Stefan Reinauer348a1ba2010-03-17 01:51:11 +000040void southbridge_smi_set_eos(void);
41
Kyösti Mälkki21ba5ee2020-06-10 10:52:24 +030042void global_smi_enable(void);
43void global_smi_enable_no_pwrbtn(void);
44
Aaron Durbin50a34642013-01-03 17:38:47 -060045void cpu_smi_handler(void);
46void northbridge_smi_handler(void);
47void southbridge_smi_handler(void);
Kyösti Mälkkie31ec292019-08-10 17:27:01 +030048
Duncan Laurie0edc2242013-04-29 15:04:30 -070049void mainboard_smi_gpi(u32 gpi_sts);
Aaron Durbin50a34642013-01-03 17:38:47 -060050int mainboard_smi_apmc(u8 data);
51void mainboard_smi_sleep(u8 slp_typ);
Aseda Aboagye63356052021-06-17 12:10:33 -070052void mainboard_smi_finalize(void);
Stefan Reinauerbf34e942012-04-27 00:44:04 +020053
Raul E Rangele6cd6ca2022-02-25 12:40:32 -070054void smm_soc_early_init(void);
55void smm_soc_exit(void);
56
Kyösti Mälkki9d8adc02016-12-04 22:17:37 +020057/* This is the SMM handler. */
58extern unsigned char _binary_smm_start[];
59extern unsigned char _binary_smm_end[];
60
Aaron Durbin50a34642013-01-03 17:38:47 -060061struct smm_runtime {
62 u32 smbase;
Arthur Heymansa3eb3df2019-11-27 16:21:46 +010063 u32 smm_size;
Aaron Durbin50a34642013-01-03 17:38:47 -060064 u32 save_state_size;
Eugene Myersae438be2020-01-21 17:01:47 -050065 u32 num_cpus;
Kyösti Mälkkie769bce2020-06-16 21:37:05 +030066 u32 gnvs_ptr;
Raul E Rangelc5160982022-02-24 16:02:49 -070067 u32 cbmemc_size;
68 void *cbmemc;
Arthur Heymans64d9e852021-02-15 18:55:40 +010069 uintptr_t save_state_top[CONFIG_MAX_CPUS];
Stefan Reinauer6a001132017-07-13 02:20:27 +020070} __packed;
Aaron Durbin50a34642013-01-03 17:38:47 -060071
Aaron Durbin3eb8eb72014-03-10 16:13:58 -050072struct smm_module_params {
Patrick Rudolph24bb8032019-12-01 07:04:04 +010073 size_t cpu;
Raul E Rangeleb5d76a2018-06-25 14:22:27 -060074 /* A canary value that has been placed at the end of the stack.
75 * If (uintptr_t)canary != *canary then a stack overflow has occurred.
76 */
77 const uintptr_t *canary;
Aaron Durbin3eb8eb72014-03-10 16:13:58 -050078};
79
Arthur Heymans5dfb3312021-02-15 13:08:43 +010080/* These parameters are used by the SMM stub code. A pointer to the params
81 * is also passed to the C-base handler. */
82struct smm_stub_params {
83 u32 stack_size;
84 u32 stack_top;
85 u32 c_handler;
Arthur Heymans5dfb3312021-02-15 13:08:43 +010086 u32 fxsave_area;
87 u32 fxsave_area_size;
Arthur Heymansed4be452021-02-15 13:20:35 +010088 /* The apic_id_to_cpu provides a mapping from APIC id to CPU number.
89 * The CPU number is indicated by the index into the array by matching
90 * the default APIC id and value at the index. The stub loader
91 * initializes this array with a 1:1 mapping. If the APIC ids are not
92 * contiguous like the 1:1 mapping it is up to the caller of the stub
93 * loader to adjust this mapping. */
Wonkyu Kim26ab9bf2021-03-22 19:59:18 -070094 u16 apic_id_to_cpu[CONFIG_MAX_CPUS];
Arthur Heymans1dfa46e2021-02-15 16:19:33 +010095 /* STM's 32bit entry into SMI handler */
96 u32 start32_offset;
Arthur Heymans5dfb3312021-02-15 13:08:43 +010097} __packed;
98
Aaron Durbin3eb8eb72014-03-10 16:13:58 -050099/* smm_handler_t is called with arg of smm_module_params pointer. */
Lee Leahy746d4af2017-03-07 15:31:49 -0800100typedef asmlinkage void (*smm_handler_t)(void *);
Aaron Durbin50a34642013-01-03 17:38:47 -0600101
Aaron Durbin50a34642013-01-03 17:38:47 -0600102/* SMM Runtime helpers. */
Kyösti Mälkki239abaf2020-06-28 12:12:01 +0300103#if ENV_SMM
104extern struct global_nvs *gnvs;
105#endif
Aaron Durbin50a34642013-01-03 17:38:47 -0600106
107/* Entry point for SMM modules. */
Lee Leahy22c28e02017-03-07 15:47:44 -0800108asmlinkage void smm_handler_start(void *params);
Aaron Durbin50a34642013-01-03 17:38:47 -0600109
110/* Retrieve SMM save state for a given CPU. WARNING: This does not take into
111 * account CPUs which are configured to not save their state to RAM. */
112void *smm_get_save_state(int cpu);
113
Patrick Rudolph41fec862020-05-06 10:55:12 +0200114/* Returns true if the region overlaps with the SMM */
115bool smm_region_overlaps_handler(const struct region *r);
116
117/* Returns true if the memory pointed to overlaps with SMM reserved memory. */
118static inline bool smm_points_to_smram(const void *ptr, const size_t len)
119{
120 const struct region r = {(uintptr_t)ptr, len};
121
122 return smm_region_overlaps_handler(&r);
123}
124
Aaron Durbin50a34642013-01-03 17:38:47 -0600125/* SMM Module Loading API */
126
Martin Roth0cb07e32013-07-09 21:46:01 -0600127/* The smm_loader_params structure provides direction to the SMM loader:
Arthur Heymans2412c812021-10-28 15:19:39 +0200128 * - num_cpus - number of concurrent cpus in handler needing stack
Aaron Durbin50a34642013-01-03 17:38:47 -0600129 * optional for setting up relocation handler.
Arthur Heymans1684b0a2022-04-07 21:50:16 +0200130 * - cpu_save_state_size - the SMM save state size per cpu
Aaron Durbin50a34642013-01-03 17:38:47 -0600131 * - num_concurrent_save_states - number of concurrent cpus needing save state
132 * space
133 * - handler - optional handler to call. Only used during SMM relocation setup.
Aaron Durbin50a34642013-01-03 17:38:47 -0600134 * - runtime - this field is a result only. The SMM runtime location is filled
135 * into this field so the code doing the loading can manipulate the
Elyes HAOUASccf78f02016-08-21 10:49:19 +0200136 * runtime's assumptions. e.g. updating the APIC id to CPU map to
137 * handle sparse APIC id space.
Aaron Durbin50a34642013-01-03 17:38:47 -0600138 */
139struct smm_loader_params {
Arthur Heymans2412c812021-10-28 15:19:39 +0200140 size_t num_cpus;
Aaron Durbin50a34642013-01-03 17:38:47 -0600141
Arthur Heymans1684b0a2022-04-07 21:50:16 +0200142 size_t cpu_save_state_size;
Aaron Durbin25a885b2017-06-16 11:45:32 -0500143 size_t num_concurrent_save_states;
Aaron Durbin50a34642013-01-03 17:38:47 -0600144
145 smm_handler_t handler;
Aaron Durbin50a34642013-01-03 17:38:47 -0600146
Arthur Heymansed4be452021-02-15 13:20:35 +0100147 struct smm_stub_params *stub_params;
Aaron Durbin50a34642013-01-03 17:38:47 -0600148};
149
Arthur Heymans96451a72021-10-28 15:14:18 +0200150/* All of these return 0 on success, < 0 on failure. */
151int smm_setup_stack(const uintptr_t perm_smbase, const size_t perm_smram_size,
152 const unsigned int total_cpus, const size_t stack_size);
153int smm_setup_relocation_handler(struct smm_loader_params *params);
Arthur Heymanscfd32242021-10-28 13:59:54 +0200154int smm_load_module(uintptr_t smram_base, size_t smram_size, struct smm_loader_params *params);
Aaron Durbin50a34642013-01-03 17:38:47 -0600155
Rocky Phaguraafb7a812020-07-21 14:48:48 -0700156u32 smm_get_cpu_smbase(unsigned int cpu_num);
Rocky Phaguraafb7a812020-07-21 14:48:48 -0700157
Aaron Durbinb4b9eb32014-02-13 10:26:18 -0600158/* Backup and restore default SMM region. */
159void *backup_default_smm_area(void);
160void restore_default_smm_area(void *smm_save_area);
161
Kyösti Mälkkib2a5f0b2019-08-04 19:54:32 +0300162/*
163 * Fills in the arguments for the entire SMM region covered by chipset
164 * protections. e.g. TSEG.
165 */
Kyösti Mälkki14222d82019-08-05 15:10:18 +0300166void smm_region(uintptr_t *start, size_t *size);
Kyösti Mälkkib2a5f0b2019-08-04 19:54:32 +0300167
168enum {
169 /* SMM handler area. */
170 SMM_SUBREGION_HANDLER,
171 /* SMM cache region. */
172 SMM_SUBREGION_CACHE,
173 /* Chipset specific area. */
174 SMM_SUBREGION_CHIPSET,
175 /* Total sub regions supported. */
176 SMM_SUBREGION_NUM,
177};
178
179/* Fills in the start and size for the requested SMM subregion. Returns
180 * 0 on success, < 0 on failure. */
Kyösti Mälkki14222d82019-08-05 15:10:18 +0300181int smm_subregion(int sub, uintptr_t *start, size_t *size);
Kyösti Mälkkib2a5f0b2019-08-04 19:54:32 +0300182
Kyösti Mälkki7cdb0472019-08-08 11:16:06 +0300183/* Print the SMM memory layout on console. */
184void smm_list_regions(void);
185
Arthur Heymans342d0a82020-08-09 14:58:05 +0200186#define SMM_REVISION_OFFSET_FROM_TOP (0x8000 - 0x7efc)
187/* Return the SMM save state revision. The revision can be fetched from the smm savestate
188 which is always at the same offset downward from the top of the save state. */
189uint32_t smm_revision(void);
Arthur Heymans34280272020-09-29 11:51:34 +0200190/* Returns the PM ACPI SMI port. On Intel systems this typically not configurable (APM_CNT, 0xb2).
191 On AMD systems it is sometimes configurable. */
192uint16_t pm_acpi_smi_cmd_port(void);
Arthur Heymans342d0a82020-08-09 14:58:05 +0200193
Edward O'Callaghanc4561e22014-06-26 15:02:40 +1000194#endif /* CPU_X86_SMM_H */