14 #define FXSAVE_SIZE 512
15 #define SMM_CODE_SEGMENT_SIZE 0x10000
20 __attribute__((aligned(16)));
39 #define SMM_MINIMUM_STACK_SIZE 32
93 unsigned int ss_size =
params->per_cpu_save_state_size, stub_size;
95 unsigned int seg_count = 0, segments = 0, available;
96 unsigned int cpus_in_segment = 0;
97 unsigned int base = smbase;
100 printk(
BIOS_ERR,
"%s: unable to get SMM module size\n", __func__);
106 available = 0xFFFF - smm_entry_offset - ss_size - stub_size;
108 cpus_in_segment = available / ss_size;
110 segments = num_cpus / cpus_in_segment + 1;
112 "%s: cpus allowed in one segment %d\n", __func__, cpus_in_segment);
114 "%s: min # of segments needed %d\n", __func__, segments);
116 printk(
BIOS_ERR,
"%s: not enough space in SMM to setup all CPUs\n", __func__);
124 "%s: increase MAX_CPUS in Kconfig\n", __func__);
128 for (i = 0; i < num_cpus; i++) {
142 if (seg_count >= cpus_in_segment) {
143 base -= smm_entry_offset;
161 if (cpu_num < CONFIG_MAX_CPUS) {
162 if (
cpus[cpu_num].active)
207 if (
cpus[num_cpus].active) {
221 for (i = 1; i < num_cpus; i++) {
222 memcpy((
int *)
cpus[i].code_start, (
int *)
cpus[0].code_start, size);
224 "SMM Module: placing smm entry code at %lx, cpu # 0x%x\n",
225 cpus[i].code_start, i);
227 __func__,
cpus[0].code_start,
cpus[i].code_start, size);
236 const unsigned int total_cpus,
const size_t stack_size)
244 const size_t total_stack_size = total_cpus * stack_size;
245 if (total_stack_size >= perm_smram_size) {
249 stack_top = perm_smbase + total_stack_size;
262 size_t stub_entry_offset;
268 if (
params->num_concurrent_save_states > 1 || stub_entry_offset != 0) {
270 params->num_concurrent_save_states,
300 void *
const fxsave_area)
302 size_t total_save_state_size;
314 if (
params->num_cpus > CONFIG_MAX_CPUS) {
326 total_save_state_size =
params->per_cpu_save_state_size *
327 params->num_concurrent_save_states;
328 if (total_save_state_size > size) {
330 "%s: more state save space needed:need -> %zx:available->%zx\n",
331 __func__, total_save_state_size, size);
335 size -= total_save_state_size;
339 printk(
BIOS_ERR,
"%s: encroachment over SMM entry point\n", __func__);
340 printk(
BIOS_ERR,
"%s: state save size: %zx : smm_entry_offset -> %zx\n",
367 printk(
BIOS_ERR,
"%s: staggered entry points failed\n", __func__);
380 "%s: stack_top = 0x%x\n", __func__, stub_params->
stack_top);
389 for (i = 0; i <
params->num_cpus; i++)
393 params->stub_params = stub_params;
396 smm_stub_loc,
params->handler);
412 if (
params->num_concurrent_save_states > 1)
421 if (
params->num_cpus == 0)
422 params->num_cpus = CONFIG_MAX_CPUS;
463 size_t total_stack_size;
465 size_t module_alignment;
466 size_t alignment_size;
469 size_t total_size = 0;
471 const struct cbmem_entry *cbmemc;
491 memset((
void *)smram_base, 0xcd, smram_size);
493 total_stack_size =
stack_top - smram_base;
494 total_size += total_stack_size;
499 base -= CONFIG_MSEG_SIZE + CONFIG_BIOS_RESOURCE_LIST_SIZE;
500 total_size += CONFIG_MSEG_SIZE + CONFIG_BIOS_RESOURCE_LIST_SIZE;
506 fxsave_area = (
char *)
base - fxsave_size;
508 total_size += fxsave_size;
515 base -= handler_size;
516 total_size += handler_size;
518 alignment_size = module_alignment - (
base % module_alignment);
519 if (alignment_size != module_alignment) {
520 handler_size += alignment_size;
521 base += alignment_size;
525 "%s: total_smm_space_needed %zx, available -> %zx\n",
526 __func__, total_size, smram_size);
529 if (total_size > smram_size) {
534 printk(
BIOS_ERR,
"%s: increase SMM_CODE_SEGMENT_SIZE: handler_size = %zx\n",
535 __func__, handler_size);
544 handler_mod_params->
smbase = smram_base;
545 handler_mod_params->
smm_size = smram_size;
554 handler_mod_params->
cbmemc = 0;
559 printk(
BIOS_DEBUG,
"%s: smram_end: %lx\n", __func__, smram_base + smram_size);
561 __func__,
params->handler);
563 __func__, handler_size);
565 __func__, fxsave_area);
567 __func__, fxsave_size);
569 __func__, CONFIG_MSEG_SIZE);
571 __func__, CONFIG_BIOS_RESOURCE_LIST_SIZE);
574 handler_mod_params->
smbase);
594 for (
int i = 0; i <
params->num_cpus; i++) {
648 if (fxsave_base <= entry0_end) {
649 printk(
BIOS_ERR,
"%s, fxsave %lx won't fit smram\n", __func__, fxsave_base);
657 if (module_base <= entry0_end) {
667 handler_mod_params->
smbase = smram_base;
668 handler_mod_params->
smm_size = smram_size;
673 for (
int i = 0; i <
params->num_cpus; i++) {
679 printk(
BIOS_DEBUG,
"%s: smram_end: %lx\n", __func__, smram_base + smram_size);
686 handler_mod_params->
smbase);
void * acpi_get_gnvs(void)
void * memcpy(void *dest, const void *src, size_t n)
void * memset(void *dstpp, int c, size_t len)
static struct sdram_info params
void * cbmem_entry_start(const struct cbmem_entry *entry)
const struct cbmem_entry * cbmem_entry_find(u32 id)
u64 cbmem_entry_size(const struct cbmem_entry *entry)
#define printk(level,...)
static size_t smm_stub_size(void)
unsigned char _binary_smm_start[]
#define BIOS_INFO
BIOS_INFO - Expected events.
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
#define BIOS_SPEW
BIOS_SPEW - Excessively verbose output.
int rmodule_entry_offset(const struct rmodule *m)
void * rmodule_entry(const struct rmodule *m)
int rmodule_parse(void *ptr, struct rmodule *m)
void * rmodule_parameters(const struct rmodule *m)
int rmodule_memory_size(const struct rmodule *m)
int rmodule_load(void *loc, struct rmodule *m)
int rmodule_load_alignment(const struct rmodule *m)
static int smm_module_setup_stub(const uintptr_t smbase, const size_t smm_size, struct smm_loader_params *params, void *const fxsave_area)
unsigned char _binary_smmstub_start[]
static int smm_place_entry_code(uintptr_t smbase, unsigned int num_cpus, uintptr_t stack_top, const struct smm_loader_params *params)
static int smm_load_module_aseg(const uintptr_t smram_base, const size_t smram_size, struct smm_loader_params *params)
int smm_setup_stack(const uintptr_t perm_smbase, const size_t perm_smram_size, const unsigned int total_cpus, const size_t stack_size)
static int smm_stub_place_staggered_entry_points(char *base, const struct smm_loader_params *params, const struct rmodule *smm_stub)
#define SMM_CODE_SEGMENT_SIZE
static int smm_create_map(uintptr_t smbase, unsigned int num_cpus, const struct smm_loader_params *params)
int smm_setup_relocation_handler(struct smm_loader_params *params)
struct cpu_smm_info cpus[CONFIG_MAX_CPUS]
#define SMM_MINIMUM_STACK_SIZE
static uintptr_t stack_top
static uint8_t fxsave_area_relocation[CONFIG_MAX_CPUS][FXSAVE_SIZE]
static size_t g_stack_size
u32 smm_get_cpu_smbase(unsigned int cpu_num)
int smm_load_module(const uintptr_t smram_base, const size_t smram_size, struct smm_loader_params *params)
uintptr_t save_state_top[CONFIG_MAX_CPUS]
u16 apic_id_to_cpu[CONFIG_MAX_CPUS]