diff options
-rw-r--r-- | src/soc/amd/stoneyridge/Kconfig | 6 | ||||
-rw-r--r-- | src/soc/amd/stoneyridge/cpu.c | 56 | ||||
-rw-r--r-- | src/soc/amd/stoneyridge/include/soc/northbridge.h | 22 | ||||
-rw-r--r-- | src/soc/amd/stoneyridge/northbridge.c | 8 | ||||
-rw-r--r-- | src/soc/amd/stoneyridge/ramtop.c | 55 | ||||
-rw-r--r-- | src/soc/amd/stoneyridge/smihandler.c | 3 |
6 files changed, 146 insertions, 4 deletions
diff --git a/src/soc/amd/stoneyridge/Kconfig b/src/soc/amd/stoneyridge/Kconfig index f7087504e1..beba741c4f 100644 --- a/src/soc/amd/stoneyridge/Kconfig +++ b/src/soc/amd/stoneyridge/Kconfig @@ -51,6 +51,8 @@ config CPU_SPECIFIC_OPTIONS 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 @@ config SMM_TSEG_SIZE 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 0df3e30f56..0490137988 100644 --- a/src/soc/amd/stoneyridge/cpu.c +++ b/src/soc/amd/stoneyridge/cpu.c @@ -14,15 +14,30 @@ * GNU General Public License for more details. */ +#include <cpu/cpu.h> #include <cpu/x86/mp.h> #include <cpu/x86/mtrr.h> +#include <cpu/x86/msr.h> +#include <cpu/amd/amdfam15.h> #include <device/device.h> #include <soc/pci_devs.h> #include <soc/cpu.h> #include <soc/northbridge.h> +#include <soc/smi.h> #include <console/console.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 - * * 1. Prevent race condition in MTRR solution. Enable MTRRs on the BSP. This @@ -41,9 +56,50 @@ static int get_cpu_count(void) return (pci_read_config16(nb, D18F0_CPU_CNT) & CPU_CNT_MASK) + 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; + + /* 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 = ALIGN_DOWN(~(smm_size - 1), 128 * KiB); + 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 = ((1 << (cpu_phys_address_size() - 32)) - 1); + 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 7e9b51aa31..f952186d22 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 @@ -30,6 +31,27 @@ # define DRAM_HOIST_VALID (1 << 1) # define DRAM_HOLE_VALID (1 << 0) +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); +/* + * Fills in the start and size for the requested SMM subregion. Returns + * 0 on susccess, < 0 on failure. + */ +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 11fb336058..7ae252f33c 100644 --- a/src/soc/amd/stoneyridge/northbridge.c +++ b/src/soc/amd/stoneyridge/northbridge.c @@ -415,6 +415,8 @@ void domain_set_resources(device_t dev) 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) @@ -505,6 +507,12 @@ void domain_set_resources(device_t dev) */ 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; + reserved_ram_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 bdad8d6057..8268477a32 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 @@ -41,7 +45,54 @@ void *cbmem_top(void) if (!tom.lo) return 0; else - /* 16MB alignment to keep MTRR usage low */ + /* 8MB alignment to keep MTRR usage low */ return (void *)ALIGN_DOWN(restore_top_of_low_cacheable() - - CONFIG_SMM_TSEG_SIZE, 16*MiB); + - CONFIG_SMM_TSEG_SIZE, 8*MiB); +} + +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 a8ff96a3e1..9aff6905ee 100644 --- a/src/soc/amd/stoneyridge/smihandler.c +++ b/src/soc/amd/stoneyridge/smihandler.c @@ -109,8 +109,7 @@ static void process_smi_0x90(void) 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); |