[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 18:51:17 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 83ec00a7b1742addc9e6a692302d8900a4c63232
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           |  12 ++++
 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 | 111 +++++++++++++++++++++++++++++
 src/soc/intel/apollolake/memmap.c          | 107 +++++++++++++++++++++++++--
 7 files changed, 391 insertions(+), 18 deletions(-)

diff --git a/src/soc/intel/apollolake/Kconfig b/src/soc/intel/apollolake/Kconfig
index efebe51..b8be1d1 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,8 @@ config CPU_SPECIFIC_OPTIONS
 	select UDELAY_TSC
 	select TSC_CONSTANT_RATE
 	select PLATFORM_USES_FSP2_0
+	select SMM_MODULES
+	select SMM_TSEG
 
 config MMCONF_BASE_ADDRESS
 	hex "PCI MMIO Base Address"
@@ -99,4 +103,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..e07010f 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..66cc5c3
--- /dev/null
+++ b/src/soc/intel/apollolake/include/soc/smm.h
@@ -0,0 +1,111 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Google Inc.
+ * Copyright (C) 2015 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#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..04a236d 100644
--- a/src/soc/intel/apollolake/memmap.c
+++ b/src/soc/intel/apollolake/memmap.c
@@ -1,13 +1,21 @@
 /*
  * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
  */
 
 #include <arch/io.h>
@@ -15,13 +23,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>
+
+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;
+}
 
-static uintptr_t smm_region_start(void)
+/* 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();
 }
+



More information about the coreboot-gerrit mailing list