Marshall Dawson has uploaded this change for review. ( https://review.coreboot.org/21501
Change subject: amd/stoneyridge: Enable SMM in TSEG ......................................................................
amd/stoneyridge: Enable SMM in TSEG
Add necessary features to allow mp_init_with_smm() to install and relocate an SMM handler.
SMM region functions are added to easily identify SMM the attributes. Add relocation attributes to be set by each core a relocation handler
Modify the definition of smi_southbridge_handler() to match TSEG prototype.
Change-Id: I4dc03ed27d0d109ab919a4f0861de9c7420d03ce Signed-off-by: Marshall Dawson marshalldawson3rd@gmail.com --- M src/soc/amd/stoneyridge/Kconfig M src/soc/amd/stoneyridge/cpu.c M src/soc/amd/stoneyridge/include/soc/northbridge.h M src/soc/amd/stoneyridge/northbridge.c M src/soc/amd/stoneyridge/ramtop.c M src/soc/amd/stoneyridge/smihandler.c 6 files changed, 136 insertions(+), 2 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/01/21501/1
diff --git a/src/soc/amd/stoneyridge/Kconfig b/src/soc/amd/stoneyridge/Kconfig index f708750..beba741 100644 --- a/src/soc/amd/stoneyridge/Kconfig +++ b/src/soc/amd/stoneyridge/Kconfig @@ -51,6 +51,8 @@ select BOOTBLOCK_CONSOLE select RELOCATABLE_MODULES select PARALLEL_MP + select HAVE_SMI_HANDLER + select SMM_TSEG
config VBOOT select AMDFW_OUTSIDE_CBFS @@ -286,6 +288,10 @@ default 0x800000 if SMM_TSEG && HAVE_SMI_HANDLER default 0x0
+config SMM_RESERVED_SIZE + hex + default 0x100000 + config ACPI_CPU_STRING string default "\_PR.P%03d" diff --git a/src/soc/amd/stoneyridge/cpu.c b/src/soc/amd/stoneyridge/cpu.c index 22e1a03..fe4ab9f 100644 --- a/src/soc/amd/stoneyridge/cpu.c +++ b/src/soc/amd/stoneyridge/cpu.c @@ -26,9 +26,21 @@ #include <soc/cpu.h> #include <soc/northbridge.h> #include <soc/southbridge.h> +#include <soc/smi.h> #include <console/console.h> #include <cpu/amd/amdfam15.h> #include <smp/node.h> + +/* + * MP and SMM loading initialization. + */ +struct smm_relocation_attrs { + uint32_t smbase; + uint32_t tseg_base; + uint32_t tseg_mask; +}; + +static struct smm_relocation_attrs relo_attrs;
/* * Do essential initialization tasks before APs can be fired up - @@ -49,9 +61,52 @@ return (pci_read_config16(nb, D18F0_CPU_CNT) & 0xf) + 1; }
+static void get_smm_info(uintptr_t *perm_smbase, size_t *perm_smsize, + size_t *smm_save_state_size) +{ + void *smm_base; + size_t smm_size; + void *handler_base; + size_t handler_size; + + const uint32_t rmask = ~((1 << 17) - 1); + + /* Initialize global tracking state. */ + smm_region_info(&smm_base, &smm_size); + smm_subregion(SMM_SUBREGION_HANDLER, &handler_base, &handler_size); + + relo_attrs.smbase = (uint32_t)smm_base; + relo_attrs.tseg_base = relo_attrs.smbase; + relo_attrs.tseg_mask = ~(smm_size - 1) & rmask; + relo_attrs.tseg_mask |= SMM_TSEG_WB | SMM_TSEG_VALID; + + *perm_smbase = (uintptr_t)handler_base; + *perm_smsize = handler_size; + *smm_save_state_size = sizeof(amd64_smm_state_save_area_t); +} + +static void relocation_handler(int cpu, uintptr_t curr_smbase, + uintptr_t staggered_smbase) +{ + msr_t tseg_base, tseg_mask; + amd64_smm_state_save_area_t *smm_state; + + tseg_base.lo = relo_attrs.tseg_base; + tseg_base.hi = 0; + wrmsr(MSR_TSEG_BASE, tseg_base); + tseg_mask.lo = relo_attrs.tseg_mask; + tseg_mask.hi = 0; + wrmsr(MSR_SMM_MASK, tseg_mask); + smm_state = (void *)(SMM_AMD64_SAVE_STATE_OFFSET + curr_smbase); + smm_state->smbase = staggered_smbase; +} + static const struct mp_ops mp_ops = { .pre_mp_init = pre_mp_init, .get_cpu_count = get_cpu_count, + .get_smm_info = get_smm_info, + .relocation_handler = relocation_handler, + .post_mp_init = enable_smi_generation, };
void stoney_init_cpus(struct device *dev) diff --git a/src/soc/amd/stoneyridge/include/soc/northbridge.h b/src/soc/amd/stoneyridge/include/soc/northbridge.h index 4f8707c..da5fa59 100644 --- a/src/soc/amd/stoneyridge/include/soc/northbridge.h +++ b/src/soc/amd/stoneyridge/include/soc/northbridge.h @@ -2,6 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2015 Advanced Micro Devices, Inc. + * Copyright (C) 2015 Intel Corp. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +21,21 @@ #include <arch/io.h> #include <device/device.h>
+enum { + /* SMM handler area. */ + SMM_SUBREGION_HANDLER, + /* SMM cache region. */ + SMM_SUBREGION_CACHE, + /* Chipset specific area. */ + SMM_SUBREGION_CHIPSET, + /* Total sub regions supported. */ + SMM_SUBREGION_NUM, +}; + +/* Fills in the arguments for the entire SMM region covered by chipset + * protections. e.g. TSEG. */ +void smm_region_info(void **start, size_t *size); +int smm_subregion(int sub, void **start, size_t *size); void domain_enable_resources(device_t dev); void domain_read_resources(device_t dev); void domain_set_resources(device_t dev); diff --git a/src/soc/amd/stoneyridge/northbridge.c b/src/soc/amd/stoneyridge/northbridge.c index ef075b6..d248c94 100644 --- a/src/soc/amd/stoneyridge/northbridge.c +++ b/src/soc/amd/stoneyridge/northbridge.c @@ -418,6 +418,8 @@ u32 hole; int idx; struct bus *link; + void *tseg_base; + size_t tseg_size;
pci_tolm = 0xffffffffUL; for (link = dev->link_list ; link ; link = link->next) @@ -501,6 +503,11 @@ */ mmio_resource(dev, 0xa0000, 0xa0000 / KiB, 0x20000 / KiB); reserved_ram_resource(dev, 0xc0000, 0xc0000 / KiB, 0x40000 / KiB); + + /* Reserve TSEG */ + smm_region_info(&tseg_base, &tseg_size); + idx += 0x10; + mmio_resource(dev, idx, (unsigned long)tseg_base/KiB, tseg_size/KiB); }
/********************************************************************* diff --git a/src/soc/amd/stoneyridge/ramtop.c b/src/soc/amd/stoneyridge/ramtop.c index bbe11d2..6a54710 100644 --- a/src/soc/amd/stoneyridge/ramtop.c +++ b/src/soc/amd/stoneyridge/ramtop.c @@ -1,6 +1,8 @@ /* * This file is part of the coreboot project. * + * Copyright (C) 2015 Intel Corp. + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. @@ -13,11 +15,13 @@
#define __SIMPLE_DEVICE__
+#include <assert.h> #include <stdint.h> #include <arch/io.h> #include <cpu/x86/msr.h> #include <cpu/amd/mtrr.h> #include <cbmem.h> +#include <soc/northbridge.h>
#define CBMEM_TOP_SCRATCHPAD 0x78
@@ -44,3 +48,50 @@ return (void *)ALIGN_DOWN(restore_top_of_low_cacheable() - CONFIG_SMM_TSEG_SIZE, 128*KiB); } + +static uintptr_t smm_region_start(void) +{ + return (uintptr_t)cbmem_top(); +} + +static size_t smm_region_size(void) +{ + return CONFIG_SMM_TSEG_SIZE; +} + +void smm_region_info(void **start, size_t *size) +{ + *start = (void *)smm_region_start(); + *size = smm_region_size(); +} + +int smm_subregion(int sub, void **start, size_t *size) +{ + uintptr_t sub_base; + size_t sub_size; + const size_t cache_size = CONFIG_SMM_RESERVED_SIZE; + + sub_base = smm_region_start(); + sub_size = smm_region_size(); + + assert(sub_size > CONFIG_SMM_RESERVED_SIZE); + + switch (sub) { + case SMM_SUBREGION_HANDLER: + /* Handler starts at the base of TSEG. */ + sub_size -= cache_size; + break; + case SMM_SUBREGION_CACHE: + /* External cache is in the middle of TSEG. */ + sub_base += sub_size - cache_size; + sub_size = cache_size; + break; + default: + return -1; + } + + *start = (void *)sub_base; + *size = sub_size; + + return 0; +} diff --git a/src/soc/amd/stoneyridge/smihandler.c b/src/soc/amd/stoneyridge/smihandler.c index a8ff96a..9aff690 100644 --- a/src/soc/amd/stoneyridge/smihandler.c +++ b/src/soc/amd/stoneyridge/smihandler.c @@ -109,8 +109,7 @@ smi_write32(0x90, status); }
-void southbridge_smi_handler(unsigned int node, - smm_state_save_area_t *state_save) +void southbridge_smi_handler(void) { const uint16_t smi_src = smi_read16(0x94);