Arthur Heymans has uploaded this change for review. ( https://review.coreboot.org/25597
Change subject: nb/intel/x4x: Use common code for SMM in TSEG ......................................................................
nb/intel/x4x: Use common code for SMM in TSEG
Untested
Change-Id: I317c5ca34bd38c3d42bf0d4e929b2a225a8a82dc Signed-off-by: Arthur Heymans arthur@aheymans.xyz --- M src/cpu/x86/smm/smmrelocate.S M src/northbridge/intel/x4x/Kconfig M src/northbridge/intel/x4x/northbridge.c M src/northbridge/intel/x4x/ram_calc.c M src/northbridge/intel/x4x/x4x.h M src/southbridge/intel/i82801jx/Makefile.inc D src/southbridge/intel/i82801jx/smi.c 7 files changed, 63 insertions(+), 202 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/97/25597/1
diff --git a/src/cpu/x86/smm/smmrelocate.S b/src/cpu/x86/smm/smmrelocate.S index ed556db..c2a0698 100644 --- a/src/cpu/x86/smm/smmrelocate.S +++ b/src/cpu/x86/smm/smmrelocate.S @@ -27,8 +27,6 @@ #include "../../../southbridge/intel/i82801dx/i82801dx.h" #elif IS_ENABLED(CONFIG_SOUTHBRIDGE_INTEL_I82801IX) #include "../../../southbridge/intel/i82801ix/i82801ix.h" -#elif IS_ENABLED(CONFIG_SOUTHBRIDGE_INTEL_I82801JX) -#include "../../../southbridge/intel/i82801jx/i82801jx.h"
#else #error "Southbridge needs SMM handler support." diff --git a/src/northbridge/intel/x4x/Kconfig b/src/northbridge/intel/x4x/Kconfig index 9239637..087edad 100644 --- a/src/northbridge/intel/x4x/Kconfig +++ b/src/northbridge/intel/x4x/Kconfig @@ -28,6 +28,7 @@ select RELOCATABLE_RAMSTAGE select HAVE_LINEAR_FRAMEBUFFER if MAINBOARD_DO_NATIVE_VGA_INIT select HAVE_VGA_TEXT_FRAMEBUFFER if MAINBOARD_DO_NATIVE_VGA_INIT + select SMM_TSEG
config CBFS_SIZE hex diff --git a/src/northbridge/intel/x4x/northbridge.c b/src/northbridge/intel/x4x/northbridge.c index 6ba45fe..52454cf 100644 --- a/src/northbridge/intel/x4x/northbridge.c +++ b/src/northbridge/intel/x4x/northbridge.c @@ -28,14 +28,15 @@ #include <northbridge/intel/x4x/iomap.h> #include <northbridge/intel/x4x/chip.h> #include <northbridge/intel/x4x/x4x.h> +#include <cpu/intel/smm/gen1/smi.h>
static const int legacy_hole_base_k = 0xa0000 / 1024;
static void mch_domain_read_resources(device_t dev) { - u8 index, reg8; + u8 index; u64 tom, touud; - u32 tomk, tseg_sizek = 0, tolud; + u32 tomk, tolud; u32 pcie_config_base, pcie_config_size; u32 uma_sizek = 0;
@@ -79,20 +80,8 @@ uma_sizek += gsm_sizek;
printk(BIOS_DEBUG, "TSEG decoded, subtracting "); - reg8 = pci_read_config8(dev, D0F0_ESMRAMC); - reg8 >>= 1; - reg8 &= 3; - switch (reg8) { - case 0: - tseg_sizek = 1024; - break; /* TSEG = 1M */ - case 1: - tseg_sizek = 2048; - break; /* TSEG = 2M */ - case 2: - tseg_sizek = 8192; - break; /* TSEG = 8M */ - } + const u32 tseg_sizek = decode_tseg_size( + pci_read_config8(dev, D0F0_ESMRAMC)); uma_sizek += tseg_sizek; tomk -= tseg_sizek;
@@ -156,6 +145,43 @@ pci_write_config32(dev, PCI_COMMAND, reg32); }
+u32 northbridge_get_tseg_size(void) +{ + const u8 esmramc = pci_read_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), + D0F0_ESMRAMC); + return decode_tseg_size(esmramc); +} + +u32 northbridge_get_tseg_base(void) +{ + return pci_read_config32(dev_find_slot(0, PCI_DEVFN(0, 0)), D0F0_TSEG); +} + +void northbridge_write_smram(u8 smram) +{ + pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), D0F0_SMRAM, smram); +} + +/* + * Really doesn't belong here but will go away with parallel mp init, + * so let it be here for a while... + */ +int cpu_get_apic_id_map(int *apic_id_map) +{ + unsigned int i; + + /* Logical processors (threads) per core */ + const struct cpuid_result cpuid1 = cpuid(1); + /* Read number of cores. */ + const char cores = (cpuid1.ebx >> 16) & 0xf; + + /* TODO in parallel MP cpuid(1).ebx */ + for (i = 0; i < cores; i++) + apic_id_map[i] = i; + + return cores; +} + static struct device_operations pci_domain_ops = { .read_resources = mch_domain_read_resources, .set_resources = mch_domain_set_resources, diff --git a/src/northbridge/intel/x4x/ram_calc.c b/src/northbridge/intel/x4x/ram_calc.c index 1009372..9783242 100644 --- a/src/northbridge/intel/x4x/ram_calc.c +++ b/src/northbridge/intel/x4x/ram_calc.c @@ -52,6 +52,25 @@ return ggc2gtt[gsm] << 10; }
+/** Decodes used TSEG size to bytes. */ +u32 decode_tseg_size(const u32 esmramc) +{ + if (!(esmramc & 1)) + return 0; + + switch ((esmramc >> 1) & 3) { + case 0: + return 1 << 20; + case 1: + return 2 << 20; + case 2: + return 8 << 20; + case 3: + default: + die("Bad TSEG setting.\n"); + } +} + u8 decode_pciebar(u32 *const base, u32 *const len) { *base = 0; diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h index cbb1853..5c9682b 100644 --- a/src/northbridge/intel/x4x/x4x.h +++ b/src/northbridge/intel/x4x/x4x.h @@ -329,6 +329,7 @@ void x4x_late_init(int s3resume); u32 decode_igd_memory_size(u32 gms); u32 decode_igd_gtt_size(u32 gsm); +u32 decode_tseg_size(const u32 esmramc); u8 decode_pciebar(u32 *const base, u32 *const len); void sdram_initialize(int boot_path, const u8 *spd_map); void raminit_ddr2(struct sysinfo *); diff --git a/src/southbridge/intel/i82801jx/Makefile.inc b/src/southbridge/intel/i82801jx/Makefile.inc index d6a3a7d..e70932c 100644 --- a/src/southbridge/intel/i82801jx/Makefile.inc +++ b/src/southbridge/intel/i82801jx/Makefile.inc @@ -32,8 +32,6 @@ ramstage-y += ../i82801gx/reset.c ramstage-y += ../i82801gx/watchdog.c
-ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smi.c -ramstage-$(CONFIG_HAVE_SMI_HANDLER) += ../../../cpu/x86/smm/smmrelocate.S smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c
romstage-y += early_smbus.c diff --git a/src/southbridge/intel/i82801jx/smi.c b/src/southbridge/intel/i82801jx/smi.c deleted file mode 100644 index d55ad0e..0000000 --- a/src/southbridge/intel/i82801jx/smi.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008-2009 coresystems GmbH - * 2012 secunet Security Networks AG - * - * 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 <device/device.h> -#include <device/pci.h> -#include <console/console.h> -#include <arch/io.h> -#include <arch/acpi.h> -#include <cpu/cpu.h> -#include <cpu/x86/cache.h> -#include <cpu/x86/smm.h> -#include <string.h> -#include <southbridge/intel/common/pmutil.h> -#include "i82801jx.h" - -/* I945/GM45 */ -#define SMRAM 0x9d -#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)) - -/* While we read PMBASE dynamically in case it changed, let's - * initialize it with a sane value - */ -static u16 pmbase = DEFAULT_PMBASE; - -extern uint8_t smm_relocation_start, smm_relocation_end; -static void *default_smm_area = NULL; - -static void smm_relocate(void) -{ - u32 smi_en; - u16 pm1_en; - - printk(BIOS_DEBUG, "Initializing SMM handler..."); - - pmbase = pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x1f, 0)), D31F0_PMBASE) & 0xfffc; - printk(BIOS_SPEW, " ... pmbase = 0x%04x\n", pmbase); - - smi_en = inl(pmbase + SMI_EN); - if (smi_en & GBL_SMI_EN) { - printk(BIOS_INFO, "SMI# handler already enabled?\n"); - return; - } - - default_smm_area = backup_default_smm_area(); - - /* copy the SMM relocation code */ - memcpy((void *)0x38000, &smm_relocation_start, - &smm_relocation_end - &smm_relocation_start); - wbinvd(); - - printk(BIOS_DEBUG, "\n"); - dump_smi_status(reset_smi_status()); - dump_pm1_status(reset_pm1_status()); - dump_gpe0_status(reset_gpe0_status()); - dump_alt_gp_smi_status(reset_alt_gp_smi_status()); - dump_tco_status(reset_tco_status()); - - /* Enable SMI generation: - * - on TCO events - * - on APMC writes (io 0xb2) - * - on writes to GBL_RLS (bios commands) - * No SMIs: - * - on microcontroller writes (io 0x62/0x66) - */ - - smi_en = 0; /* reset SMI enables */ - - smi_en |= TCO_EN; - smi_en |= APMC_EN; -#if DEBUG_PERIODIC_SMIS - /* Set DEBUG_PERIODIC_SMIS in i82801jx.h to debug using - * periodic SMIs. - */ - smi_en |= PERIODIC_EN; -#endif - smi_en |= BIOS_EN; - - /* The following need to be on for SMIs to happen */ - smi_en |= EOS | GBL_SMI_EN; - - outl(smi_en, pmbase + SMI_EN); - - pm1_en = 0; - pm1_en |= PWRBTN_EN; - pm1_en |= GBL_EN; - outw(pm1_en, pmbase + PM1_EN); - - /** - * There are several methods of raising a controlled SMI# via - * software, among them: - * - Writes to io 0xb2 (APMC) - * - Writes to the Local Apic ICR with Delivery mode SMI. - * - * Using the local apic is a bit more tricky. According to - * AMD Family 11 Processor BKDG no destination shorthand must be - * used. - * The whole SMM initialization is quite a bit hardware specific, so - * I'm not too worried about the better of the methods at the moment - */ - - /* raise an SMI interrupt */ - printk(BIOS_SPEW, " ... raise SMI#\n"); - outb(0x00, 0xb2); -} - -static int smm_handler_copied = 0; - -static void smm_install(void) -{ - /* The first CPU running this gets to copy the SMM handler. But not all - * of them. - */ - if (smm_handler_copied) - return; - smm_handler_copied = 1; - - - /* if we're resuming from S3, the SMM code is already in place, - * so don't copy it again to keep the current SMM state */ - - if (!acpi_is_wakeup_s3()) { - /* enable the SMM memory window */ - pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM, - D_OPEN | G_SMRAME | C_BASE_SEG); - - /* copy the real SMM handler */ - memcpy((void *)0xa0000, _binary_smm_start, - _binary_smm_end - _binary_smm_start); - wbinvd(); - } - - /* close the SMM memory window and enable normal SMM */ - pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM, - G_SMRAME | C_BASE_SEG); -} - -void smm_init(void) -{ - /* Put SMM code to 0xa0000 */ - smm_install(); - - /* Put relocation code to 0x38000 and relocate SMBASE */ - smm_relocate(); - - /* We're done. Make sure SMIs can happen! */ - smi_set_eos(); -} - -void smm_init_completion(void) -{ - restore_default_smm_area(default_smm_area); -} - -void smm_lock(void) -{ - /* LOCK the SMM memory window and enable normal SMM. - * After running this function, only a full reset can - * make the SMM registers writable again. - */ - printk(BIOS_DEBUG, "Locking SMM.\n"); - pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM, - D_LCK | G_SMRAME | C_BASE_SEG); -}