[coreboot-gerrit] Patch set updated for coreboot: soc/apollolake: Enable SMI handling
Hannah Williams (hannah.williams@intel.com)
gerrit at coreboot.org
Mon Apr 11 23:17:40 CEST 2016
Hannah Williams (hannah.williams at intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14314
-gerrit
commit 04360ccfb3bacaf93032d76ce12057e720e00edf
Author: Ravi Sarawadi <ravishankar.sarawadi at intel.com>
Date: Mon Apr 4 15:01:50 2016 -0700
soc/apollolake: Enable SMI handling
Add appololake SoC specific SMI feature components.
CQ-DEPEND=CL:6359
Change-Id: I42013ba118add3ea845cfdc60c4e5b1d5a1fcbd0
Signed-off-by: Ravi Sarawadi <ravishankar.sarawadi at intel.com>
Signed-off-by: Hannah Williams <hannah.williams at intel.com>
---
src/soc/intel/apollolake/Kconfig | 13 ++++
src/soc/intel/apollolake/Makefile.inc | 3 +-
src/soc/intel/apollolake/cpu.c | 80 +++++++++++++++++++--
src/soc/intel/apollolake/include/soc/cpu.h | 61 ++++++++++++++--
src/soc/intel/apollolake/include/soc/nvs.h | 35 ++++++++++
src/soc/intel/apollolake/include/soc/smm.h | 107 +++++++++++++++++++++++++++++
src/soc/intel/apollolake/memmap.c | 103 +++++++++++++++++++++++++--
src/soc/intel/apollolake/placeholders.c | 4 --
8 files changed, 384 insertions(+), 22 deletions(-)
diff --git a/src/soc/intel/apollolake/Kconfig b/src/soc/intel/apollolake/Kconfig
index efebe51..1b178aa 100644
--- a/src/soc/intel/apollolake/Kconfig
+++ b/src/soc/intel/apollolake/Kconfig
@@ -11,6 +11,7 @@ config CPU_SPECIFIC_OPTIONS
select ARCH_RAMSTAGE_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_VERSTAGE_X86_32
+ select BACKUP_DEFAULT_SMM_REGION
# CPU specific options
select CPU_INTEL_FIRMWARE_INTERFACE_TABLE
select IOAPIC
@@ -21,6 +22,7 @@ config CPU_SPECIFIC_OPTIONS
select C_ENVIRONMENT_BOOTBLOCK
select COLLECT_TIMESTAMPS
select HAVE_INTEL_FIRMWARE
+ select HAVE_SMI_HANDLER
select MMCONF_SUPPORT
select MMCONF_SUPPORT_DEFAULT
select PARALLEL_MP
@@ -37,6 +39,9 @@ config CPU_SPECIFIC_OPTIONS
select UDELAY_TSC
select TSC_CONSTANT_RATE
select PLATFORM_USES_FSP2_0
+ select SMM_COMMON
+ select SMM_MODULES
+ select SMM_TSEG
config MMCONF_BASE_ADDRESS
hex "PCI MMIO Base Address"
@@ -99,4 +104,12 @@ config ROMSTAGE_ADDR
help
The base address (in CAR) where romstage should be linked
+config SMM_RESERVED_SIZE
+ hex
+ default 0x200000
+
+config SMM_TSEG_SIZE
+ hex
+ default 0x800000
+
endif
diff --git a/src/soc/intel/apollolake/Makefile.inc b/src/soc/intel/apollolake/Makefile.inc
index 70ab515..29bc394 100644
--- a/src/soc/intel/apollolake/Makefile.inc
+++ b/src/soc/intel/apollolake/Makefile.inc
@@ -4,7 +4,6 @@ subdirs-y += ../../../cpu/intel/microcode
subdirs-y += ../../../cpu/intel/turbo
subdirs-y += ../../../cpu/x86/lapic
subdirs-y += ../../../cpu/x86/mtrr
-subdirs-y += ../../../cpu/x86/smm
subdirs-y += ../../../cpu/x86/tsc
subdirs-y += ../../../cpu/x86/cache
@@ -27,6 +26,8 @@ romstage-y += memmap.c
romstage-y += mmap_boot.c
smm-y += placeholders.c
+smm-y += uart_early.c
+smm-y += tsc_freq.c
ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c
ramstage-y += cpu.c
diff --git a/src/soc/intel/apollolake/cpu.c b/src/soc/intel/apollolake/cpu.c
index 0724439..3e381eb 100644
--- a/src/soc/intel/apollolake/cpu.c
+++ b/src/soc/intel/apollolake/cpu.c
@@ -16,13 +16,38 @@
#include <cpu/x86/cache.h>
#include <cpu/x86/mp.h>
#include <cpu/x86/msr.h>
+#include <cpu/x86/lapic.h>
#include <cpu/x86/mtrr.h>
+#include <cpu/x86/smm.h>
#include <device/device.h>
#include <device/pci.h>
#include <soc/cpu.h>
+#include <soc/smm.h>
+
+static void enable_lapic_tpr(void)
+{
+ msr_t msr;
+
+ msr = rdmsr(MSR_PIC_MSG_CONTROL);
+ msr.lo &= ~(1 << 10); /* Enable APIC TPR updates */
+ wrmsr(MSR_PIC_MSG_CONTROL, msr);
+}
+
+static void cpu_core_init(device_t cpu)
+{
+ /* Turn on cache */
+ x86_enable_cache();
+ /* Set up Memory Type Range Registers */
+ x86_setup_mtrrs();
+ x86_mtrr_check();
+
+ /* Enable the local cpu apics */
+ enable_lapic_tpr();
+ setup_lapic();
+}
static struct device_operations cpu_dev_ops = {
- .init = DEVICE_NOOP,
+ .init = cpu_core_init,
};
static struct cpu_device_id cpu_table[] = {
@@ -57,6 +82,34 @@ static void bsp_pre_mp_setup(void)
x86_mtrr_check();
}
+int ht_disabled;
+static int adjust_apic_id_ht_disabled(int index, int apic_id)
+{
+ return 2 * index;
+}
+
+static void relocate(void *unused)
+{
+ /* Relocate the SMM handler. */
+ smm_relocate();
+}
+
+static void enable_smis(void *unused)
+{
+ /*
+ * Now that all APs have been relocated as well as the BSP let SMIs
+ * start flowing.
+ */
+ southbridge_smm_enable_smi();
+
+ /* Lock down the SMRAM space. */
+#if IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)
+ smm_lock();
+#endif
+}
+
+
+
/*
* CPU initialization recipe
*
@@ -65,33 +118,50 @@ static void bsp_pre_mp_setup(void)
* the BSP and all APs will come up with the same microcode revision.
*/
static struct mp_flight_record flight_plan[] = {
+ MP_FR_NOBLOCK_APS(relocate, NULL,
+ relocate, NULL),
/* NOTE: MTRR solution must be calculated before firing up the APs */
- MP_FR_NOBLOCK_APS(mp_initialize_cpu, NULL, mp_initialize_cpu, NULL),
+ MP_FR_BLOCK_APS(mp_initialize_cpu, NULL, mp_initialize_cpu, NULL),
+ MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL),
};
void apollolake_init_cpus(device_t dev)
{
unsigned int num_virt_cores, num_phys_cores;
+ void *smm_save_area;
/* Pre-flight check */
bsp_pre_mp_setup();
+/* Save default SMM area before relocation occurs. */
+ if (IS_ENABLED(CONFIG_HAVE_SMI_HANDLER))
+ smm_save_area = backup_default_smm_area();
+ else
+ smm_save_area = NULL;
+
/* Find CPU topology */
read_cpu_topology(&num_phys_cores, &num_virt_cores);
printk(BIOS_DEBUG, "Detected %u core, %u thread CPU.\n",
num_phys_cores, num_virt_cores);
+ ht_disabled = num_phys_cores == num_virt_cores;
/* Systems check */
struct mp_params flight_data_recorder = {
.num_cpus = num_virt_cores,
- .parallel_microcode_load = 0,
- .microcode_pointer = NULL,
- .adjust_apic_id = NULL,
+ .adjust_apic_id =
+ ht_disabled ? adjust_apic_id_ht_disabled:NULL,
.flight_plan = flight_plan,
.num_records = ARRAY_SIZE(flight_plan),
};
+/* Load relocation and permanent handlers. Then initiate relocation.*/
+ if (smm_initialize())
+ printk(BIOS_CRIT, "SMM Initialization failed...\n");
/* Clear for take-off */
if (mp_init(dev->link_list, &flight_data_recorder) < 0)
printk(BIOS_ERR, "MP initialization failure.\n");
+
+ /* Restore the default SMM region. */
+ if (IS_ENABLED(CONFIG_HAVE_SMI_HANDLER))
+ restore_default_smm_area(smm_save_area);
}
diff --git a/src/soc/intel/apollolake/include/soc/cpu.h b/src/soc/intel/apollolake/include/soc/cpu.h
index 7c3228e..0a87798 100644
--- a/src/soc/intel/apollolake/include/soc/cpu.h
+++ b/src/soc/intel/apollolake/include/soc/cpu.h
@@ -17,17 +17,64 @@
#include <cpu/x86/msr.h>
#include <device/device.h>
+/*
+ * Remark the cache as executable. This works around a silicon bug where
+ * updating a cache line makes it non-executable.
+ */
+static inline void bxt_remark_cache_exec(void)
+{
+ msr_t msr = rdmsr(0x120);
+ msr.lo |= (1 << 8);
+ wrmsr(0x120, msr);
+}
+
void apollolake_init_cpus(struct device *dev);
+
+/*
+ * Determine if HyperThreading is disabled.
+ * The variable is not valid until setup_ap_init() has been called.
+ */
+extern int ht_disabled;
+
#endif
-#define CPUID_APOLLOLAKE_A0 0x506c8
-#define CPUID_APOLLOLAKE_B0 0x506c9
-#define MSR_PLATFORM_INFO 0xce
-#define MSR_POWER_MISC 0x120
-#define MSR_CORE_THREAD_COUNT 0x35
-#define MSR_EVICT_CTL 0x2e0
+#define CPUID_APOLLOLAKE_A0 0x506c8
+#define CPUID_APOLLOLAKE_B0 0x506c9
+
+#define MSR_CORE_THREAD_COUNT 0x35
+#define MSR_PIC_MSG_CONTROL 0x2e
+#define MSR_PLATFORM_INFO 0xce
+#define MSR_POWER_MISC 0x120
+#define MSR_EVICT_CTL 0x2e0
+
+#define MSR_SMM_MCA_CAP 0x17d
+#define SMM_CPU_SVRSTR_BIT 57
+#define SMM_CPU_SVRSTR_MASK (1 << (SMM_CPU_SVRSTR_BIT - 32))
+#define MSR_UNCORE_PRMRR_PHYS_BASE 0x2f4
+#define MSR_UNCORE_PRMRR_PHYS_MASK 0x2f5
+#define MSR_SMM_FEATURE_CONTROL 0x4e0
+#define SMM_CPU_SAVE_EN (1 << 1)
+/* SMM save state MSRs */
+#define MSR_SMBASE 0xc20
+#define MSR_IEDBASE 0xc22
+
+/* MTRR_CAP_MSR bits */
+#define SMRR_SUPPORTED (1<<11)
+
+#define BASE_CLOCK_MHZ 100
+
+/* System Management RAM Control */
+#define SMRAM 0x88
+#define D_OPEN (1 << 6)
+#define D_CLS (1 << 5)
+#define D_LCK (1 << 4)
+#define G_SMRAME (1 << 3)
+#define C_BASE_SEG ((0 << 2) | (1 << 1) | (0 << 0))
-#define BASE_CLOCK_MHZ 100
+/* Base GTT Stolen Memory */
+#define BGSM 0xb4
+/* TSEG base */
+#define TSEG 0xb8
#endif /* _SOC_APOLLOLAKE_CPU_H_ */
diff --git a/src/soc/intel/apollolake/include/soc/nvs.h b/src/soc/intel/apollolake/include/soc/nvs.h
new file mode 100644
index 0000000..583a5d7
--- /dev/null
+++ b/src/soc/intel/apollolake/include/soc/nvs.h
@@ -0,0 +1,35 @@
+/*
+ * NOTE: The layout of the global_nvs_t structure below must match the layout
+ * in soc/intel/apollolake/acpi/globalnvs.asl !!!
+ *
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao at intel.com> for 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef _SOC_APOLLOLAKE_NVS_H_
+#define _SOC_APOLLOLAKE_NVS_H_
+
+#include <vendorcode/google/chromeos/gnvs.h>
+
+struct global_nvs_t {
+ /* Miscellaneous */
+ uint8_t unused[256];
+
+ /* ChromeOS specific (0x100 - 0xfff) */
+ chromeos_acpi_t chromeos;
+} __attribute__((packed));
+
+#if ENV_SMM
+/* Used in SMM to find the ACPI GNVS address */
+struct global_nvs_t *smm_get_gnvs(void);
+#endif
+
+
+#endif /* _SOC_APOLLOLAKE_NVS_H_ */
diff --git a/src/soc/intel/apollolake/include/soc/smm.h b/src/soc/intel/apollolake/include/soc/smm.h
new file mode 100644
index 0000000..866b4c6
--- /dev/null
+++ b/src/soc/intel/apollolake/include/soc/smm.h
@@ -0,0 +1,107 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corporation.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_SMM_H_
+#define _SOC_SMM_H_
+
+#include <stdint.h>
+#include <cpu/x86/msr.h>
+#include <soc/gpio.h>
+
+struct ied_header {
+ char signature[10];
+ u32 size;
+ u8 reserved[34];
+} __attribute__ ((packed));
+
+struct smm_relocation_params {
+ u32 smram_base;
+ u32 smram_size;
+ u32 ied_base;
+ u32 ied_size;
+ msr_t smrr_base;
+ msr_t smrr_mask;
+ msr_t emrr_base;
+ msr_t emrr_mask;
+ msr_t uncore_emrr_base;
+ msr_t uncore_emrr_mask;
+ /*
+ * The smm_save_state_in_msrs field indicates if SMM save state
+ * locations live in MSRs. This indicates to the CPUs how to adjust
+ * the SMMBASE and IEDBASE
+ */
+ int smm_save_state_in_msrs;
+};
+
+/* Mainboard handler for GPI SMIs*/
+//void mainboard_smi_gpi_handler(const struct gpi_status *sts);
+
+
+#if IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)
+int smm_initialize(void);
+void smm_relocate(void);
+
+/* These helpers are for performing SMM relocation. */
+void southbridge_trigger_smi(void);
+void southbridge_clear_smi_status(void);
+
+/*
+ * The initialization of the southbridge is split into 2 compoments. One is
+ * for clearing the state in the SMM registers. The other is for enabling
+ * SMIs.
+ */
+void southbridge_smm_clear_state(void);
+void southbridge_smm_enable_smi(void);
+#else /* CONFIG_HAVE_SMI_HANDLER */
+static inline int smm_initialize(void)
+{
+ return 0;
+}
+
+static inline void smm_relocate(void) {}
+static inline void southbridge_trigger_smi(void) {}
+static inline void southbridge_clear_smi_status(void) {}
+static inline void southbridge_smm_clear_state(void) {}
+static inline void southbridge_smm_enable_smi(void) {}
+#endif /* CONFIG_HAVE_SMI_HANDLER */
+
+/*
+ * mmap_region_granularity must to return a size which is a positive non-zero
+ * integer multiple of the SMM size when SMM is in use. When not using SMM,
+ * this value should be set to 8 MiB.
+ */
+size_t mmap_region_granularity(void);
+
+/* Fills in the arguments for the entire SMM region covered by chipset
+ * protections. e.g. TSEG. */
+void smm_region(void **start, size_t *size);
+
+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 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);
+
+#endif
diff --git a/src/soc/intel/apollolake/memmap.c b/src/soc/intel/apollolake/memmap.c
index bfff965..f209d20 100644
--- a/src/soc/intel/apollolake/memmap.c
+++ b/src/soc/intel/apollolake/memmap.c
@@ -1,13 +1,17 @@
/*
* This file is part of the coreboot project.
*
- * Copyright (C) 2015 Intel Corp.
- * (Written by Andrey Petrov <andrey.petrov at intel.com> for Intel Corp.)
+ * Copyright (C) 2014 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corporation.
*
* 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; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*/
#include <arch/io.h>
@@ -15,13 +19,102 @@
#include <device/pci.h>
#include <soc/northbridge.h>
#include <soc/pci_devs.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <soc/romstage.h>
+#include <soc/smm.h>
+#include <soc/cpu.h>
+#include "chip.h"
+#include <stdlib.h>
-static uintptr_t smm_region_start(void)
+size_t mmap_region_granularity(void)
+{
+ if (IS_ENABLED(CONFIG_HAVE_SMI_HANDLER))
+ /* Align to TSEG size when SMM is in use */
+ if (CONFIG_SMM_TSEG_SIZE != 0)
+ return CONFIG_SMM_TSEG_SIZE;
+
+ /* Make it 8MiB by default. */
+ return 8*MiB;
+}
+
+/* Returns base of requested region encoded in the system agent. */
+static inline uintptr_t system_agent_region_base(size_t reg)
{
return ALIGN_DOWN(pci_read_config32(NB_DEV_ROOT, TSEG), 1*MiB);
}
+static inline uintptr_t smm_region_start(void)
+{
+#if ENV_RAMSTAGE
+ return read32((void *)(CONFIG_MMCONF_BASE_ADDRESS + TSEG)) &
+ 0xfff00000;
+#else
+ return pci_read_config32(PCI_DEV(0, 0, 0), TSEG) & 0xfff00000;
+#endif
+}
+
+static inline size_t smm_region_size(void)
+{
+ return system_agent_region_base(BGSM) - smm_region_start();
+}
+
+void smm_region(void **start, size_t *size)
+{
+ *start = (void *)smm_region_start();
+ *size = smm_region_size();
+}
+
+/*
+ * Subregions within SMM
+ * +-------------------------+ BGSM
+ * | IED | IED_REGION_SIZE
+ * +-------------------------+
+ * | External Stage Cache | SMM_RESERVED_SIZE
+ * +-------------------------+
+ * | code and data |
+ * | (TSEG) |
+ * +-------------------------+ TSEG
+ */
+int smm_subregion(int sub, void **start, size_t *size)
+{
+ uintptr_t sub_base;
+ size_t sub_size;
+ const size_t ied_size = CONFIG_IED_REGION_SIZE;
+ const size_t cache_size = CONFIG_SMM_RESERVED_SIZE;
+
+ sub_base = smm_region_start();
+ sub_size = smm_region_size();
+
+ switch (sub) {
+ case SMM_SUBREGION_HANDLER:
+ /* Handler starts at the base of TSEG. */
+ sub_size -= ied_size;
+ sub_size -= cache_size;
+ break;
+ case SMM_SUBREGION_CACHE:
+ /* External cache is in the middle of TSEG. */
+ sub_base += sub_size - (ied_size + cache_size);
+ sub_size = cache_size;
+ break;
+ case SMM_SUBREGION_CHIPSET:
+ /* IED is at the top. */
+ sub_base += sub_size - ied_size;
+ sub_size = ied_size;
+ break;
+ default:
+ return -1;
+ }
+
+ *start = (void *)sub_base;
+ *size = sub_size;
+
+ return 0;
+}
+
void *cbmem_top(void)
{
return (void *)smm_region_start();
}
+
diff --git a/src/soc/intel/apollolake/placeholders.c b/src/soc/intel/apollolake/placeholders.c
index 808bd54..3a02390 100644
--- a/src/soc/intel/apollolake/placeholders.c
+++ b/src/soc/intel/apollolake/placeholders.c
@@ -3,10 +3,6 @@
#include <delay.h>
#include <rules.h>
-void southbridge_smi_set_eos(void)
-{
-}
-
#if ENV_BOOTBLOCK
void init_timer(void)
{
More information about the coreboot-gerrit
mailing list