Timothy Pearson (tpearson(a)raptorengineeringinc.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/12070
-gerrit
commit c3ef91d5ff7bb97df1db3f047af58b00699779e0
Author: Timothy Pearson <tpearson(a)raptorengineeringinc.com>
Date: Mon Sep 7 18:07:43 2015 -0500
nb/amd/amdht: Fix XCS buffer count setup on AMD Family 15h CPUs
The existing code re-used the Family 10h XCS buffer setup on
Family 15h CPUs, which set incorrect values leading to random
system lockups.
Use the Family 15h XCS buffer setup shown in the BKDG.
Change-Id: Ie4bc8b3ea6b110bc507beda025de53d828118f55
Signed-off-by: Timothy Pearson <tpearson(a)raptorengineeringinc.com>
---
src/northbridge/amd/amdht/h3ncmn.c | 94 +++++++++++++++++++++++++++++++++++++-
1 file changed, 92 insertions(+), 2 deletions(-)
diff --git a/src/northbridge/amd/amdht/h3ncmn.c b/src/northbridge/amd/amdht/h3ncmn.c
index 7937c6e..cbe90e0 100644
--- a/src/northbridge/amd/amdht/h3ncmn.c
+++ b/src/northbridge/amd/amdht/h3ncmn.c
@@ -2,6 +2,7 @@
* This file is part of the coreboot project.
*
* Copyright (C) 2007 Advanced Micro Devices, Inc.
+ * Copyright (C) 2015 Timothy Pearson <tpearson(a)raptorengineeringinc.com>, Raptor Engineering
*
* 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
@@ -1389,6 +1390,75 @@ static uint32_t fam10NorthBridgeFreqMask(u8 node, cNorthBridge *nb)
/***************************************************************************//**
*
+ * static u16
+ * fam15NorthBridgeFreqMask(u8 NodeID, cNorthBridge *nb)
+ *
+ * Description:
+ * Return a mask that eliminates HT frequencies that cannot be used due to a slow
+ * northbridge frequency.
+ *
+ * Parameters:
+ * @param[in] node = Result could (later) be for a specific node
+ * @param[in] *nb = this northbridge
+ * @return = Frequency mask
+ *
+ ******************************************************************************/
+static uint32_t fam15NorthBridgeFreqMask(u8 node, cNorthBridge *nb)
+{
+ u8 nbCOF;
+ uint32_t supported;
+
+ nbCOF = getMinNbCOF();
+ /*
+ * nbCOF is minimum northbridge speed in hundreds of MHz.
+ * HT can not go faster than the minimum speed of the northbridge.
+ */
+ if ((nbCOF >= 6) && (nbCOF < 10))
+ {
+ /* Generation 1 HT link frequency */
+ /* Convert frequency to bit and all less significant bits,
+ * by setting next power of 2 and subtracting 1.
+ */
+ supported = ((uint32_t)1 << ((nbCOF >> 1) + 2)) - 1;
+ }
+ else if ((nbCOF >= 10) && (nbCOF <= 32))
+ {
+ /* Generation 3 HT link frequency
+ * Assume error retry is enabled on all Gen 3 links
+ */
+ nbCOF *= 2;
+ if (nbCOF > 32)
+ nbCOF = 32;
+
+ /* Convert frequency to bit and all less significant bits,
+ * by setting next power of 2 and subtracting 1.
+ */
+ supported = ((uint32_t)1 << ((nbCOF >> 1) + 2)) - 1;
+ }
+ else if (nbCOF > 32)
+ {
+ supported = HT_FREQUENCY_LIMIT_3200M;
+ }
+ /* unlikely cases, but include as a defensive measure, also avoid trick above */
+ else if (nbCOF == 4)
+ {
+ supported = HT_FREQUENCY_LIMIT_400M;
+ }
+ else if (nbCOF == 2)
+ {
+ supported = HT_FREQUENCY_LIMIT_200M;
+ }
+ else
+ {
+ STOP_HERE;
+ supported = HT_FREQUENCY_LIMIT_200M;
+ }
+
+ return (fixEarlySampleFreqCapability(supported));
+}
+
+/***************************************************************************//**
+ *
* static void
* gatherLinkData(sMainData *pDat, cNorthBridge *nb)
*
@@ -2266,6 +2336,26 @@ static void fam10BufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb)
}
}
+/***************************************************************************//**
+ *
+ * static void
+ * fam15BufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb)
+ *
+ * Description:
+ * Buffer tunings are inherently northbridge specific. Check for specific configs
+ * which require adjustments and apply any standard workarounds to this node.
+ *
+ * Parameters:
+ * @param[in] node = the node to tune
+ * @param[in] *pDat = global state
+ * @param[in] nb = this northbridge
+ *
+ ******************************************************************************/
+static void fam15BufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb)
+{
+ /* Buffer count setup on Family 15h is currently handled in cpuSetAMDPCI */
+}
+
/*
* North Bridge 'constructor'.
*
@@ -2324,11 +2414,11 @@ void newNorthBridge(u8 node, cNorthBridge *nb)
ht3SetCFGAddrMap,
convertBitsToWidth,
convertWidthToBits,
- fam10NorthBridgeFreqMask,
+ fam15NorthBridgeFreqMask,
gatherLinkData,
setLinkData,
ht3WriteTrafficDistribution,
- fam10BufferOptimizations,
+ fam15BufferOptimizations,
0x00000001,
0x00000200,
18,
Michael Tasche (michael.tasche(a)esd.eu) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/12579
-gerrit
commit 047c1e4dca03d7ab74c402f66b845c7c0d50c04b
Author: Michael Tasche <michael.tasche(a)esd.eu>
Date: Tue Dec 1 13:54:23 2015 +0100
pci_device: IRQ swizzling for pci2pci bridges corrected
On ATOM E38xx we have 4 PCIe lanes seen as one
multifunction device with function 0-3.
The swizzling was correct for lane 0(function 0) only.
Change-Id: I669b7f5244a7f8cc23df5e9020f26510e778c64d
Signed-off-by: Michael Tasche <michael.tasche(a)esd.eu>
---
src/device/pci_device.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/device/pci_device.c b/src/device/pci_device.c
index 5123229..3f799a8 100644
--- a/src/device/pci_device.c
+++ b/src/device/pci_device.c
@@ -1340,7 +1340,7 @@ static int swizzle_irq_pins(device_t dev, device_t *parent_bridge)
child_devfn = child->path.pci.devfn;
/* Swizzle the INT_PIN for any bridges not on root bus */
- swizzled_pin = (PCI_SLOT(child_devfn) + swizzled_pin) % 4;
+ swizzled_pin = (PCI_SLOT(child_devfn) + PCI_FUNC(parent_devfn) + swizzled_pin) % 4;
printk(BIOS_SPEW, "\tWith INT_PIN swizzled to %s\n"
"\tAttached to bridge device %01X:%02Xh.%02Xh\n",
pin_to_str(swizzled_pin + 1), parent_bus,
Michael Tasche (michael.tasche(a)esd.eu) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/12579
-gerrit
commit f631a4ed64f250cb37ebed7e23e30c73a00faf7c
Author: Michael Tasche <michael.tasche(a)esd.eu>
Date: Tue Dec 1 13:54:23 2015 +0100
pci_device: IRQ swizzling for pci2pci bridges corrected
On ATOM E38xx we have 4 PCIe lanes seen as one
multifunction device with function 0-3.
The swizzling was correct for lane 0(function 0) only.
Change-Id: I669b7f5244a7f8cc23df5e9020f26510e778c64d
Signed-off-by: Michael Tasche <michael.tasche(a)esd.eu>
---
src/device/pci_device.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/device/pci_device.c b/src/device/pci_device.c
index 5123229..04a1050 100644
--- a/src/device/pci_device.c
+++ b/src/device/pci_device.c
@@ -1340,7 +1340,7 @@ static int swizzle_irq_pins(device_t dev, device_t *parent_bridge)
child_devfn = child->path.pci.devfn;
/* Swizzle the INT_PIN for any bridges not on root bus */
- swizzled_pin = (PCI_SLOT(child_devfn) + swizzled_pin) % 4;
+ swizzled_pin = (PCI_SLOT(child_devfn) + PCI_FUNC(parent_devfn) + swizzled_pin) % 4;
printk(BIOS_SPEW, "\tWith INT_PIN swizzled to %s\n"
"\tAttached to bridge device %01X:%02Xh.%02Xh\n",
pin_to_str(swizzled_pin + 1), parent_bus,
Damien Zammit (damien(a)zamaudio.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/6311
-gerrit
commit 0ee119f315ac41a82d66cdf856cd4e2532e0b3b1
Author: Damien Zammit <damien(a)zamaudio.com>
Date: Sat Nov 28 21:27:05 2015 +1100
x86/smm: Initialize SMM on some CPUs one-by-one
We currently race in SMM init on Atom 230 (and potentially
other CPUs). At least on the 230, this leads to a hang on
RSM, likely because both hyperthreads mess around with
SMBASE and other SMM state variables in parallel without
coordination. The same behaviour occurs with Atom D5xx.
Change it so first APs are spun up and sent to sleep, then
BSP initializes SMM, then every CPU, one after another.
Only do this when SERIALIZE_SMM_INITIALIZATION is set.
Set the flag for Atom CPUs.
Change-Id: I1ae864e37546298ea222e81349c27cf774ed251f
Signed-off-by: Patrick Georgi <patrick(a)georgi-clan.de>
Signed-off-by: Damien Zammit <damien(a)zamaudio.com>
---
src/arch/x86/cpu.c | 3 +++
src/cpu/intel/model_106cx/Kconfig | 1 +
src/cpu/x86/Kconfig | 11 +++++++++
src/cpu/x86/lapic/lapic_cpu_init.c | 47 +++++++++++++++++++++++++++++++++++++-
4 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/src/arch/x86/cpu.c b/src/arch/x86/cpu.c
index ceed077..52b5681 100644
--- a/src/arch/x86/cpu.c
+++ b/src/arch/x86/cpu.c
@@ -234,6 +234,9 @@ void cpu_initialize(unsigned int index)
die("CPU: missing cpu device structure");
}
+ if (cpu->initialized)
+ return;
+
post_log_path(cpu);
/* Find what type of cpu we are dealing with */
diff --git a/src/cpu/intel/model_106cx/Kconfig b/src/cpu/intel/model_106cx/Kconfig
index 09acfd9..a005ba2 100644
--- a/src/cpu/intel/model_106cx/Kconfig
+++ b/src/cpu/intel/model_106cx/Kconfig
@@ -11,6 +11,7 @@ config CPU_INTEL_MODEL_106CX
select AP_IN_SIPI_WAIT
select TSC_SYNC_MFENCE
select SUPPORT_CPU_UCODE_IN_CBFS
+ select SERIALIZED_SMM_INITIALIZATION
if CPU_INTEL_MODEL_106CX
diff --git a/src/cpu/x86/Kconfig b/src/cpu/x86/Kconfig
index 131cbf2..94225a3 100644
--- a/src/cpu/x86/Kconfig
+++ b/src/cpu/x86/Kconfig
@@ -96,6 +96,17 @@ config SMM_LAPIC_REMAP_MITIGATION
default y if NORTHBRIDGE_INTEL_NEHALEM
default n
+config SERIALIZED_SMM_INITIALIZATION
+ bool
+ default n
+ help
+ On some CPUs, there is a race condition in SMM.
+ This can occur when both hyperthreads change SMM state
+ variables in parallel without coordination.
+ Setting this option serializes the SMM initialization
+ to avoid an ugly hang in the boot process at the cost
+ of a slightly longer boot time.
+
config X86_AMD_FIXED_MTRRS
bool
default n
diff --git a/src/cpu/x86/lapic/lapic_cpu_init.c b/src/cpu/x86/lapic/lapic_cpu_init.c
index ef150a5..bf63517 100644
--- a/src/cpu/x86/lapic/lapic_cpu_init.c
+++ b/src/cpu/x86/lapic/lapic_cpu_init.c
@@ -458,6 +458,39 @@ static void start_other_cpus(struct bus *cpu_bus, struct device *bsp_cpu)
}
+static void smm_other_cpus(struct bus *cpu_bus, device_t bsp_cpu)
+{
+ device_t cpu;
+ int pre_count = atomic_read(&active_cpus);
+
+ /* Loop through the cpus once to let them run through SMM relocator */
+
+ for(cpu = cpu_bus->children; cpu ; cpu = cpu->sibling) {
+ if (cpu->path.type != DEVICE_PATH_APIC) {
+ continue;
+ }
+
+ printk(BIOS_ERR, "considering CPU 0x%02x for SMM init\n",
+ cpu->path.apic.apic_id);
+
+ if (cpu == bsp_cpu)
+ continue;
+
+ if (!cpu->enabled) {
+ continue;
+ }
+
+ if (!start_cpu(cpu)) {
+ /* Record the error in cpu? */
+ printk(BIOS_ERR, "CPU 0x%02x would not start!\n",
+ cpu->path.apic.apic_id);
+ }
+
+ /* FIXME: endless loop */
+ while (atomic_read(&active_cpus) != pre_count) ;
+ }
+}
+
static void wait_other_cpus_stop(struct bus *cpu_bus)
{
struct device *cpu;
@@ -528,7 +561,8 @@ void initialize_cpus(struct bus *cpu_bus)
#endif
#if CONFIG_HAVE_SMI_HANDLER
- smm_init();
+ if (!IS_ENABLED(CONFIG_SERIALIZED_SMM_INITIALIZATION))
+ smm_init();
#endif
#if CONFIG_SMP && CONFIG_MAX_CPUS > 1
@@ -547,4 +581,15 @@ void initialize_cpus(struct bus *cpu_bus)
/* Now wait the rest of the cpus stop*/
wait_other_cpus_stop(cpu_bus);
#endif
+
+ if (IS_ENABLED(CONFIG_SERIALIZED_SMM_INITIALIZATION)) {
+ /* At this point, all APs are sleeping:
+ * smm_init() will queue a pending SMI on all cpus
+ * and smm_other_cpus() will start them one by one */
+ smm_init();
+#if CONFIG_SMP && CONFIG_MAX_CPUS > 1
+ last_cpu_index = 0;
+ smm_other_cpus(cpu_bus, info->cpu);
+#endif
+ }
}