[coreboot-gerrit] Patch set updated for coreboot: soc/apollolake: SOC specific SMM code

Hannah Williams (hannah.williams@intel.com) gerrit at coreboot.org
Tue May 17 03:03:23 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/14808

-gerrit

commit 94e8e3f516a21647237c9e754d965e8862f5ad93
Author: Hannah Williams <hannah.williams at intel.com>
Date:   Fri May 13 00:47:14 2016 -0700

    soc/apollolake: SOC specific SMM code
    
    Change-Id: Idefddaf41cf28240f5f8172b00462a7f893889e7
    Signed-off-by: Hannah Williams <hannah.williams at intel.com>
---
 src/soc/intel/apollolake/Kconfig           |  4 +-
 src/soc/intel/apollolake/Makefile.inc      |  6 +-
 src/soc/intel/apollolake/cpu.c             | 68 +++++++++++++++++++++
 src/soc/intel/apollolake/include/soc/nvs.h |  2 +
 src/soc/intel/apollolake/include/soc/smm.h | 39 ++++++++++++
 src/soc/intel/apollolake/memmap.c          | 13 ++++
 src/soc/intel/apollolake/smi.c             | 95 ++++++++++++++++++++++++++++++
 src/soc/intel/apollolake/smihandler.c      | 86 +++++++++++++++++++++++++++
 8 files changed, 308 insertions(+), 5 deletions(-)

diff --git a/src/soc/intel/apollolake/Kconfig b/src/soc/intel/apollolake/Kconfig
index 41a96c9..25b2f42 100644
--- a/src/soc/intel/apollolake/Kconfig
+++ b/src/soc/intel/apollolake/Kconfig
@@ -22,6 +22,7 @@ config CPU_SPECIFIC_OPTIONS
 	select COLLECT_TIMESTAMPS
 	select COMMON_FADT
 	select HAVE_INTEL_FIRMWARE
+	select HAVE_SMI_HANDLER
 	select MMCONF_SUPPORT
 	select MMCONF_SUPPORT_DEFAULT
 	select NO_FIXED_XIP_ROM_SIZE
@@ -35,7 +36,9 @@ config CPU_SPECIFIC_OPTIONS
 	select POSTCAR_STAGE
 	select REG_SCRIPT
 	select RELOCATABLE_RAMSTAGE	# Build fails if this is not selected
+	select SMM_TSEG
 	select SOC_INTEL_COMMON
+	select SOC_INTEL_COMMON_SMI
 	select SPI_FLASH
 	select UDELAY_TSC
 	select TSC_CONSTANT_RATE
@@ -43,7 +46,6 @@ config CPU_SPECIFIC_OPTIONS
 	select HAVE_MONOTONIC_TIMER
 	select PLATFORM_USES_FSP2_0
 	select HAVE_HARD_RESET
-	select SOC_INTEL_COMMON
 
 config TPM_ON_FAST_SPI
 	bool
diff --git a/src/soc/intel/apollolake/Makefile.inc b/src/soc/intel/apollolake/Makefile.inc
index 240d3c2..ddd2484 100644
--- a/src/soc/intel/apollolake/Makefile.inc
+++ b/src/soc/intel/apollolake/Makefile.inc
@@ -15,11 +15,9 @@ bootblock-y += car.c
 bootblock-y += gpio.c
 bootblock-y += lpc_lib.c
 bootblock-y += mmap_boot.c
-bootblock-y += placeholders.c
 bootblock-y += tsc_freq.c
 bootblock-$(CONFIG_SOC_UART_DEBUG) += uart_early.c
 
-romstage-y += placeholders.c
 romstage-y += car.c
 romstage-$(CONFIG_PLATFORM_USES_FSP2_0) += romstage.c
 romstage-y += gpio.c
@@ -31,13 +29,12 @@ romstage-y += mmap_boot.c
 romstage-y += tsc_freq.c
 romstage-y += pmutil.c
 
-smm-y += placeholders.c
 smm-y += pmutil.c
+smm-y += smihandler.c
 
 ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c
 ramstage-y += cpu.c
 ramstage-y += chip.c
-ramstage-y += placeholders.c
 ramstage-y += gpio.c
 ramstage-y += graphics.c
 ramstage-$(CONFIG_SOC_UART_DEBUG) += uart_early.c
@@ -51,6 +48,7 @@ ramstage-y += spi.c
 ramstage-y += tsc_freq.c
 ramstage-y += pmutil.c
 ramstage-y += pmc.c
+ramstage-y += smi.c
 
 postcar-y += exit_car.S
 postcar-y += memmap.c
diff --git a/src/soc/intel/apollolake/cpu.c b/src/soc/intel/apollolake/cpu.c
index 99cb5ad..fc1303b 100644
--- a/src/soc/intel/apollolake/cpu.c
+++ b/src/soc/intel/apollolake/cpu.c
@@ -25,6 +25,7 @@
 #include <device/device.h>
 #include <device/pci.h>
 #include <soc/cpu.h>
+#include <soc/smm.h>
 
 static struct device_operations cpu_dev_ops = {
 	.init = DEVICE_NOOP,
@@ -41,6 +42,18 @@ static const struct cpu_driver driver __cpu_driver = {
 	.id_table = cpu_table,
 };
 
+
+/*
+ * MP and SMM loading initialization.
+ */
+struct smm_relocation_attrs {
+	uint32_t smbase;
+	uint32_t smrr_base;
+	uint32_t smrr_mask;
+};
+
+static struct smm_relocation_attrs relo_attrs;
+
 static void read_cpu_topology(unsigned int *num_phys, unsigned int *num_virt)
 {
 	msr_t msr;
@@ -75,6 +88,55 @@ static int get_cpu_count(void)
 	return num_virt_cores;
 }
 
+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;
+
+	/* All range registers are aligned to 4KiB */
+	const uint32_t rmask = ~((1 << 12) - 1);
+
+	/* Initialize global tracking state. */
+	smm_region(&smm_base, &smm_size);
+	relo_attrs.smbase = (uint32_t)smm_base;
+	relo_attrs.smrr_base = relo_attrs.smbase | MTRR_TYPE_WRBACK;
+	relo_attrs.smrr_mask = ~(smm_size - 1) & rmask;
+	relo_attrs.smrr_mask |= MTRR_PHYS_MASK_VALID;
+
+	*perm_smbase = relo_attrs.smbase;
+	*perm_smsize = smm_size - CONFIG_SMM_RESERVED_SIZE;
+	*smm_save_state_size = sizeof(em64t100_smm_state_save_area_t);
+}
+
+/* Each id is separated by 2. */
+static int adjust_apic_id(int index, int apic_id)
+{
+	return 2 * index;
+}
+
+
+static void per_cpu_smm_trigger(void)
+{
+	/* Relocate SMM space. */
+	smm_initiate_relocation();
+}
+
+static void relocation_handler(int cpu, uintptr_t curr_smbase,
+				uintptr_t staggered_smbase)
+{
+	msr_t smrr;
+	em64t100_smm_state_save_area_t *smm_state;
+	/* Set up SMRR. */
+	smrr.lo = relo_attrs.smrr_base;
+	smrr.hi = 0;
+	wrmsr(SMRR_PHYS_BASE, smrr);
+	smrr.lo = relo_attrs.smrr_mask;
+	smrr.hi = 0;
+	wrmsr(SMRR_PHYS_MASK, smrr);
+	smm_state = (void *)(SMM_EM64T100_SAVE_STATE_OFFSET + curr_smbase);
+	smm_state->smbase = staggered_smbase;
+}
 /*
  * CPU initialization recipe
  *
@@ -85,6 +147,12 @@ static int get_cpu_count(void)
 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,
+	.adjust_cpu_apic_entry = adjust_apic_id,
+	.pre_mp_smm_init = southbridge_smm_clear_state,
+	.per_cpu_smm_trigger = per_cpu_smm_trigger,
+	.relocation_handler = relocation_handler,
+	.post_mp_init = southbridge_smm_enable_smi,
 };
 
 void apollolake_init_cpus(device_t dev)
diff --git a/src/soc/intel/apollolake/include/soc/nvs.h b/src/soc/intel/apollolake/include/soc/nvs.h
index 8b3a3af..3a6e7ba 100644
--- a/src/soc/intel/apollolake/include/soc/nvs.h
+++ b/src/soc/intel/apollolake/include/soc/nvs.h
@@ -34,4 +34,6 @@ struct global_nvs_t {
 	chromeos_acpi_t chromeos;
 } __attribute__((packed));
 
+struct global_nvs_t *smm_get_gnvs(void);
+
 #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..ed50958
--- /dev/null
+++ b/src/soc/intel/apollolake/include/soc/smm.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 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.
+ *
+ * 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>
+
+/* 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);
+
+
+/* Fills in the arguments for the entire SMM region covered by chipset
+ * protections. e.g. TSEG. */
+void smm_region(void **start, size_t *size);
+#endif
diff --git a/src/soc/intel/apollolake/memmap.c b/src/soc/intel/apollolake/memmap.c
index bf172cb..7b4521f 100644
--- a/src/soc/intel/apollolake/memmap.c
+++ b/src/soc/intel/apollolake/memmap.c
@@ -20,13 +20,26 @@
 #include <device/pci.h>
 #include <soc/northbridge.h>
 #include <soc/pci_devs.h>
+#include <soc/smm.h>
 
 static uintptr_t smm_region_start(void)
 {
 	return ALIGN_DOWN(pci_read_config32(NB_DEV_ROOT, TSEG), 1*MiB);
 }
 
+static inline size_t smm_region_size(void)
+{
+	return (ALIGN_DOWN(pci_read_config32(NB_DEV_ROOT, BGSM), 1*MiB) -
+		smm_region_start());
+}
+
 void *cbmem_top(void)
 {
 	return (void *)smm_region_start();
 }
+
+void smm_region(void **start, size_t *size)
+{
+	*start = (void *)smm_region_start();
+	*size = smm_region_size();
+}
diff --git a/src/soc/intel/apollolake/smi.c b/src/soc/intel/apollolake/smi.c
new file mode 100644
index 0000000..48053e2
--- /dev/null
+++ b/src/soc/intel/apollolake/smi.c
@@ -0,0 +1,95 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 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.
+ *
+ * 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 <device/device.h>
+#include <device/pci.h>
+#include <console/console.h>
+#include <arch/io.h>
+#include <cpu/cpu.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/smm.h>
+#include <string.h>
+#include <soc/pm.h>
+#include <soc/smm.h>
+
+void southbridge_smm_clear_state(void)
+{
+	printk(BIOS_DEBUG, "Initializing Southbridge SMI...");
+
+	if (get_smi_en() & APMC_EN) {
+		printk(BIOS_INFO, "SMI# handler already enabled?\n");
+		return;
+	}
+
+	printk(BIOS_DEBUG, "Done\n");
+
+	/* Dump and clear status registers */
+	clear_smi_status();
+	clear_pm1_status();
+	clear_tco_status();
+	clear_gpe_status();
+}
+
+void southbridge_smm_enable_smi(void)
+{
+	printk(BIOS_DEBUG, "Enabling SMIs.\n");
+	/* Configure events */
+	enable_pm1(PWRBTN_EN | GBL_EN);
+	disable_gpe(PME_B0_EN);
+
+	/* Enable SMI generation */
+	enable_smi(APMC_EN | SLP_SMI_EN | GBL_SMI_EN | EOS);
+}
+
+void southbridge_trigger_smi(void)
+{
+	/* raise an SMI interrupt */
+	printk(BIOS_SPEW, "  ... raise SMI#\n");
+	outb(0x00, APM_CNT);
+}
+
+void southbridge_clear_smi_status(void)
+{
+	/* Clear SMI status */
+	clear_smi_status();
+
+	/* Clear PM1 status */
+	clear_pm1_status();
+
+	/* Set EOS bit so other SMIs can occur. */
+	enable_smi(EOS);
+}
+
+void smm_setup_structures(void *gnvs, void *tcg, void *smi1)
+{
+	/*
+	 * Issue SMI to set the gnvs pointer in SMM.
+	 * tcg and smi1 are unused.
+	 *
+	 * EAX = APM_CNT_GNVS_UPDATE
+	 * EBX = gnvs pointer
+	 * EDX = APM_CNT
+	 */
+	asm volatile (
+		"outb %%al, %%dx\n\t"
+		: /* ignore result */
+		: "a" (APM_CNT_GNVS_UPDATE),
+		  "b" ((u32)gnvs),
+		  "d" (APM_CNT)
+	);
+}
+
diff --git a/src/soc/intel/apollolake/smihandler.c b/src/soc/intel/apollolake/smihandler.c
new file mode 100644
index 0000000..1d74da6
--- /dev/null
+++ b/src/soc/intel/apollolake/smihandler.c
@@ -0,0 +1,86 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 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.
+ *
+ * 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/hlt.h>
+#include <arch/io.h>
+#include <console/console.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/smm.h>
+#include <device/pci_def.h>
+#include <elog.h>
+#include <soc/nvs.h>
+#include <soc/pm.h>
+#include <soc/gpio.h>
+#include <soc/iomap.h>
+#include <soc/pci_devs.h>
+#include <soc/intel/common/smi.h>
+#include <spi-generic.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+int smm_disable_busmaster(device_t dev)
+{
+	if (dev == PMC_DEV)
+		return 0;
+	return 1;
+}
+
+const struct smm_save_state_ops em64t100_smm_save_state_ops = {
+	.get_io_misc_info = em64t100_smm_save_state_get_io_misc_info,
+	.get_reg = em64t100_smm_save_state_get_reg,
+	.set_reg = em64t100_smm_save_state_set_reg,
+};
+
+const struct smm_save_state_ops *get_smm_save_state_ops(void)
+{
+	return &em64t100_smm_save_state_ops;
+}
+
+const smi_handler_t southbridge_smi[32] = {
+	NULL,			  /*  [0] reserved */
+	NULL,			  /*  [1] reserved */
+	NULL,			  /*  [2] BIOS_STS */
+	NULL,			  /*  [3] LEGACY_USB_STS */
+	southbridge_smi_sleep,	  /*  [4] SLP_SMI_STS */
+	southbridge_smi_apmc,	  /*  [5] APM_STS */
+	NULL,			  /*  [6] SWSMI_TMR_STS */
+	NULL,			  /*  [7] reserved */
+	southbridge_smi_pm1,	  /*  [8] PM1_STS */
+	southbridge_smi_gpe0,	  /*  [9] GPE0_STS */
+	NULL,			  /* [10] reserved */
+	NULL,			  /* [11] reserved */
+	NULL,			  /* [12] reserved */
+	southbridge_smi_tco,	  /* [13] TCO_STS */
+	southbridge_smi_periodic, /* [14] PERIODIC_STS */
+	NULL,			  /* [15] SERIRQ_SMI_STS */
+	NULL,			  /* [16] SMBUS_SMI_STS */
+	NULL,			  /* [17] LEGACY_USB2_STS */
+	NULL,			  /* [18] INTEL_USB2_STS */
+	NULL,			  /* [19] reserved */
+	NULL,			  /* [20] PCI_EXP_SMI_STS */
+	NULL,			  /* [21] reserved */
+	NULL,			  /* [22] reserved */
+	NULL,			  /* [23] reserved */
+	NULL,			  /* [24] reserved */
+	NULL,			  /* [25] reserved */
+	NULL,			  /* [26] SPI_STS */
+	NULL,			  /* [27] reserved */
+	NULL,			  /* [28] PUNIT */
+	NULL,			  /* [29] GUNIT */
+	NULL,			  /* [30] reserved */
+	NULL			  /* [31] reserved */
+};
+



More information about the coreboot-gerrit mailing list