From 2e2f1661bb306d7b00b4f121148e9613c5d14e72 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Fri, 14 Jul 2023 22:58:49 +0200 Subject: [PATCH] soc/amd/genoa: Hook SMP and SMM init All CPUs properly come out of reset and relocate SMM. Signed-off-by: Arthur Heymans Change-Id: I8c2d976addacd5a2ba70eb629510128853b9f847 Reviewed-on: https://review.coreboot.org/c/coreboot/+/76523 Tested-by: build bot (Jenkins) Reviewed-by: Felix Held --- src/soc/amd/genoa/Kconfig | 6 ++ src/soc/amd/genoa/Makefile.inc | 4 ++ src/soc/amd/genoa/chipset.cb | 3 +- src/soc/amd/genoa/cpu.c | 26 ++++++++ src/soc/amd/genoa/include/soc/cpu.h | 9 +++ src/soc/amd/genoa/smihandler.c | 96 +++++++++++++++++++++++++++++ 6 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 src/soc/amd/genoa/cpu.c create mode 100644 src/soc/amd/genoa/include/soc/cpu.h create mode 100644 src/soc/amd/genoa/smihandler.c diff --git a/src/soc/amd/genoa/Kconfig b/src/soc/amd/genoa/Kconfig index 2e30df749c5..397a81f6202 100644 --- a/src/soc/amd/genoa/Kconfig +++ b/src/soc/amd/genoa/Kconfig @@ -7,8 +7,10 @@ config SOC_SPECIFIC_OPTIONS def_bool y select ARCH_X86 select HAVE_EXP_X86_64_SUPPORT + select HAVE_SMI_HANDLER select RESET_VECTOR_IN_RAM select SOC_AMD_COMMON + select SOC_AMD_COMMON_BLOCK_ACPI select SOC_AMD_COMMON_BLOCK_ACPIMMIO select SOC_AMD_COMMON_BLOCK_AOAC select SOC_AMD_COMMON_BLOCK_BANKED_GPIOS @@ -25,6 +27,7 @@ config SOC_SPECIFIC_OPTIONS select SOC_AMD_COMMON_BLOCK_PSP_GEN2 select SOC_AMD_COMMON_BLOCK_PSP_SPL select SOC_AMD_COMMON_BLOCK_SMI + select SOC_AMD_COMMON_BLOCK_SMM select SOC_AMD_COMMON_BLOCK_SMU select SOC_AMD_COMMON_BLOCK_SMU_SX_ENTRY select SOC_AMD_COMMON_BLOCK_TSC @@ -151,6 +154,9 @@ config PSP_SOFTFUSE_BITS See #57299 (NDA) for additional bit definitions. endmenu +config SMM_TSEG_SIZE + hex + default 0x800000 #TODO: Check if the value of HEAP_SIZE is optimal config HEAP_SIZE diff --git a/src/soc/amd/genoa/Makefile.inc b/src/soc/amd/genoa/Makefile.inc index 506f6cf2798..96acc43b310 100644 --- a/src/soc/amd/genoa/Makefile.inc +++ b/src/soc/amd/genoa/Makefile.inc @@ -14,8 +14,12 @@ romstage-y += romstage.c ramstage-y += aoac.c ramstage-y += chip.c +ramstage-y += cpu.c ramstage-y += domain.c ramstage-y += root_complex.c +ramstage-y += smihandler.c + +smm-y += smihandler.c CPPFLAGS_common += -I$(src)/soc/amd/genoa/include diff --git a/src/soc/amd/genoa/chipset.cb b/src/soc/amd/genoa/chipset.cb index e2d0e2ec85c..58c11561a5c 100644 --- a/src/soc/amd/genoa/chipset.cb +++ b/src/soc/amd/genoa/chipset.cb @@ -1,8 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only chip soc/amd/genoa - device cpu_cluster 0 on - end + device cpu_cluster 0 on ops amd_cpu_bus_ops end device domain 0 on ops genoa_pci_domain_ops diff --git a/src/soc/amd/genoa/cpu.c b/src/soc/amd/genoa/cpu.c new file mode 100644 index 00000000000..8a7d8e9245f --- /dev/null +++ b/src/soc/amd/genoa/cpu.c @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include + +static void model_19_init(struct device *dev) +{ + set_cstate_io_addr(); +} + +static struct device_operations cpu_dev_ops = { + .init = model_19_init, +}; + +static struct cpu_device_id cpu_table[] = { + { X86_VENDOR_AMD, GENOA_A0_CPUID, CPUID_ALL_STEPPINGS_MASK }, + { X86_VENDOR_AMD, GENOA_B0_CPUID, CPUID_ALL_STEPPINGS_MASK }, + CPU_TABLE_END +}; + +static const struct cpu_driver model_19 __cpu_driver = { + .ops = &cpu_dev_ops, + .id_table = cpu_table, +}; diff --git a/src/soc/amd/genoa/include/soc/cpu.h b/src/soc/amd/genoa/include/soc/cpu.h new file mode 100644 index 00000000000..836c9877bad --- /dev/null +++ b/src/soc/amd/genoa/include/soc/cpu.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef AMD_GENOA_CPU_H +#define AMD_GENOA_CPU_H + +#define GENOA_A0_CPUID CPUID_FROM_FMS(0x19, 0x10, 0) +#define GENOA_B0_CPUID CPUID_FROM_FMS(0x19, 0x11, 0) + +#endif /* AMD_GENOA_CPU_H */ diff --git a/src/soc/amd/genoa/smihandler.c b/src/soc/amd/genoa/smihandler.c new file mode 100644 index 00000000000..4d93baa4083 --- /dev/null +++ b/src/soc/amd/genoa/smihandler.c @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Both the psp_notify_sx_info and the smu_sx_entry call will clobber the SMN index register + * during the SMN accesses. Since the SMI handler is the last thing that gets called before + * entering S3, this won't interfere with any indirect SMN accesses via the same register pair. + */ +static void fch_slp_typ_handler(void) +{ + uint32_t pci_ctrl; + uint16_t pm1cnt; + uint8_t slp_typ, rst_ctrl; + + /* Figure out SLP_TYP */ + pm1cnt = acpi_read16(MMIO_ACPI_PM1_CNT_BLK); + printk(BIOS_SPEW, "SMI#: SLP = 0x%04x\n", pm1cnt); + slp_typ = acpi_sleep_from_pm1(pm1cnt); + + /* Do any mainboard sleep handling */ + mainboard_smi_sleep(slp_typ); + + switch (slp_typ) { + case ACPI_S0: + printk(BIOS_DEBUG, "SMI#: Entering S0 (On)\n"); + break; + case ACPI_S3: + printk(BIOS_DEBUG, "SMI#: Entering S3 (Suspend-To-RAM)\n"); + break; + case ACPI_S4: + printk(BIOS_DEBUG, "SMI#: Entering S4 (Suspend-To-Disk)\n"); + break; + case ACPI_S5: + printk(BIOS_DEBUG, "SMI#: Entering S5 (Soft Power off)\n"); + break; + default: + printk(BIOS_DEBUG, "SMI#: ERROR: SLP_TYP reserved\n"); + break; + } + + if (slp_typ >= ACPI_S3) { + wbinvd(); + + clear_all_smi_status(); + + /* Do not send SMI before AcpiPm1CntBlkx00[SlpTyp] */ + pci_ctrl = pm_read32(PM_PCI_CTRL); + pci_ctrl &= ~FORCE_SLPSTATE_RETRY; + pm_write32(PM_PCI_CTRL, pci_ctrl); + + /* Enable SlpTyp */ + rst_ctrl = pm_read8(PM_RST_CTRL1); + rst_ctrl |= SLPTYPE_CONTROL_EN; + pm_write8(PM_RST_CTRL1, rst_ctrl); + + smu_sx_entry(); /* Leave SlpTypeEn clear, SMU will set */ + printk(BIOS_ERR, "System did not go to sleep\n"); + hlt(); + } +} + +/* + * Table of functions supported in the SMI handler. Note that SMI source setup + * in fch.c is unrelated to this list. + */ +static const struct smi_sources_t smi_sources[] = { + { .type = SMITYPE_SMI_CMD_PORT, .handler = fch_apmc_smi_handler }, + { .type = SMITYPE_SLP_TYP, .handler = fch_slp_typ_handler}, +}; + +void *get_smi_source_handler(int source) +{ + size_t i; + + for (i = 0 ; i < ARRAY_SIZE(smi_sources) ; i++) + if (smi_sources[i].type == source) + return smi_sources[i].handler; + + return NULL; +}