Arthur Heymans has uploaded this change for review.

View Change

[NEEDSTEST]cpu/amd/family15: Use parallel_mp

This now computes an MTRR solution based on coreboots allocation and
always uses that solution over the one set by AGESA.
Syncing MSR is now done in sipi_vector.S.

This also implement SMM in ASEG in the helper functions as some AGESA
targets have an SMI handler.

Change-Id: I33a5f93e3c2777fffb47400dfab9eedd774d3b2b
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
---
M src/cpu/amd/agesa/family15tn/model_15_init.c
M src/cpu/amd/smm/smm_helper.c
M src/include/cpu/amd/msr.h
M src/northbridge/amd/agesa/family15tn/Kconfig
M src/northbridge/amd/agesa/family15tn/northbridge.c
5 files changed, 57 insertions(+), 164 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/92/64892/1
diff --git a/src/cpu/amd/agesa/family15tn/model_15_init.c b/src/cpu/amd/agesa/family15tn/model_15_init.c
index a557407..a5cc5ef 100644
--- a/src/cpu/amd/agesa/family15tn/model_15_init.c
+++ b/src/cpu/amd/agesa/family15tn/model_15_init.c
@@ -18,42 +18,11 @@
printk(BIOS_DEBUG, "Model 15 Init.\n");

msr_t msr;
- int msrno;
unsigned int cpu_idx;
#if CONFIG(LOGICAL_CPUS)
u32 siblings;
#endif

- /*
- * AGESA sets the MTRRs main MTRRs. The shadow area needs to be set
- * by coreboot.
- */
- disable_cache();
- /* Enable access to AMD RdDram and WrDram extension bits */
- msr = rdmsr(SYSCFG_MSR);
- msr.lo |= SYSCFG_MSR_MtrrFixDramModEn;
- msr.lo &= ~SYSCFG_MSR_MtrrFixDramEn;
- wrmsr(SYSCFG_MSR, msr);
-
- // BSP: make a0000-bffff UC, c0000-fffff WB, same as OntarioApMtrrSettingsList for APs
- msr.lo = msr.hi = 0;
- wrmsr(MTRR_FIX_16K_A0000, msr);
- msr.lo = msr.hi = 0x1e1e1e1e;
- wrmsr(MTRR_FIX_64K_00000, msr);
- wrmsr(MTRR_FIX_16K_80000, msr);
- for (msrno = MTRR_FIX_4K_C0000; msrno <= MTRR_FIX_4K_F8000; msrno++)
- wrmsr(msrno, msr);
-
- msr = rdmsr(SYSCFG_MSR);
- msr.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
- msr.lo |= SYSCFG_MSR_MtrrFixDramEn;
- wrmsr(SYSCFG_MSR, msr);
-
- if (acpi_is_wakeup_s3())
- restore_mtrr();
-
- x86_mtrr_check();
- enable_cache();

/* zero the machine check error status registers */
mca_clear_status();
@@ -93,8 +62,9 @@
wrmsr(SMM_MASK_MSR, msr);
}

- /* Write protect SMM space with SMMLOCK. */
- lock_smm();
+ /* Write protect SMM space with SMMLOCK. Done by SMM setup if used. */
+ if (!CONFIG(HAVE_SMI_HANDLER))
+ lock_smm();
}

static struct device_operations cpu_dev_ops = {
diff --git a/src/cpu/amd/smm/smm_helper.c b/src/cpu/amd/smm/smm_helper.c
index 9dc8725..34035a6 100644
--- a/src/cpu/amd/smm/smm_helper.c
+++ b/src/cpu/amd/smm/smm_helper.c
@@ -63,6 +63,14 @@
wrmsr(SMM_MASK_MSR, mask);
}

+static void aseg_valid(void)
+{
+ msr_t mask = rdmsr(SMM_MASK_MSR);
+ mask.lo |= SMM_ASEG_VALID;
+
+ wrmsr(SMM_MASK_MSR, mask);
+}
+
void lock_smm(void)
{
msr_t hwcr = rdmsr(HWCR_MSR);
@@ -96,10 +104,8 @@
return 1 + (cpuid_ecx(0x80000008) & 0xff);
}

-static void get_smm_info(uintptr_t *perm_smbase, size_t *perm_smsize, size_t *smm_save_state_size)
+static enum cb_err check_tseg(void)
{
- printk(BIOS_DEBUG, "Setting up SMI for CPU\n");
-
uintptr_t tseg_base;
size_t tseg_size;

@@ -107,21 +113,36 @@

if (!IS_ALIGNED(tseg_base, tseg_size)) {
printk(BIOS_ERR, "TSEG base not aligned to TSEG size\n");
- return;
+ return CB_ERR;
}
if (tseg_size < (1 << 17)) {
printk(BIOS_ERR, "TSEG size too small\n");
- return;
+ return CB_ERR;
+ }
+ return CB_SUCCESS;
+}
+
+static void get_smm_info(uintptr_t *perm_smbase, size_t *perm_smsize, size_t *smm_save_state_size)
+{
+ printk(BIOS_DEBUG, "Setting up SMI for CPU\n");
+
+ if (CONFIG(SMM_TSEG)) {
+ if (check_tseg() != CB_SUCCESS)
+ return;
+
+ smm_subregion(SMM_SUBREGION_HANDLER, perm_smbase, perm_smsize);
+ } else { /* SMM_ASEG */
+ *perm_smbase = 0xa0000;
+ *perm_smsize = 0x10000;
}

-
- smm_subregion(SMM_SUBREGION_HANDLER, perm_smbase, perm_smsize);
*smm_save_state_size = sizeof(amd64_smm_state_save_area_t);
}

static void smm_relocation_trigger(void)
{
- setup_tseg();
+ if (CONFIG(SMM_TSEG))
+ setup_tseg();

uintptr_t smbase = smm_get_cpu_smbase(cpu_index());
msr_t msr = {
@@ -130,7 +151,11 @@
};
wrmsr(SMM_BASE_MSR, msr);

- tseg_valid();
+ if (CONFIG(SMM_TSEG))
+ tseg_valid();
+ else
+ aseg_valid();
+
lock_smm();
}

diff --git a/src/include/cpu/amd/msr.h b/src/include/cpu/amd/msr.h
index 37372d1..df88208 100644
--- a/src/include/cpu/amd/msr.h
+++ b/src/include/cpu/amd/msr.h
@@ -59,6 +59,7 @@
#define SMM_BASE_MSR 0xC0010111
#define SMM_ADDR_MSR 0xC0010112
#define SMM_MASK_MSR 0xC0010113
+#define SMM_ASEG_VALID (1 << 0)
#define SMM_TSEG_VALID (1 << 1)
#define SMM_TSEG_WB (6 << 12)

diff --git a/src/northbridge/amd/agesa/family15tn/Kconfig b/src/northbridge/amd/agesa/family15tn/Kconfig
index 5bb7cca..606ba42 100644
--- a/src/northbridge/amd/agesa/family15tn/Kconfig
+++ b/src/northbridge/amd/agesa/family15tn/Kconfig
@@ -2,7 +2,6 @@

config NORTHBRIDGE_AMD_AGESA_FAMILY15_TN
bool
- select LEGACY_SMP_INIT
select RESOURCE_ALLOCATOR_V3

if NORTHBRIDGE_AMD_AGESA_FAMILY15_TN
diff --git a/src/northbridge/amd/agesa/family15tn/northbridge.c b/src/northbridge/amd/agesa/family15tn/northbridge.c
index 046f875..77cf6dc 100644
--- a/src/northbridge/amd/agesa/family15tn/northbridge.c
+++ b/src/northbridge/amd/agesa/family15tn/northbridge.c
@@ -12,7 +12,7 @@
#include <lib.h>
#include <cpu/cpu.h>
#include <AGESA.h>
-#include <cpu/x86/lapic.h>
+#include <cpu/x86/mp.h>
#include <cpu/amd/msr.h>
#include <cpu/amd/mtrr.h>
#include <Porting.h>
@@ -577,8 +577,17 @@
.enable_dev = 0,
};

+static void sysconf_init(struct device *dev);
+
static void domain_read_resources(struct device *dev)
{
+ struct device *dev_mc = pcidev_on_root(DEV_CDB, 0);
+ if (!dev_mc) {
+ printk(BIOS_ERR, "0:%02x.0 not found", DEV_CDB);
+ die("");
+ }
+ sysconf_init(dev_mc);
+
unsigned int reg;

/* Find the already assigned resource pairs */
@@ -767,132 +776,21 @@
node_nums = ((pci_read_config32(dev, 0x60)>>4) & 7) + 1; //NodeCnt[2:0]
}

-static void cpu_bus_scan(struct device *dev)
+void mp_init_cpus(struct bus *cpu_bus)
{
- struct bus *cpu_bus;
- struct device *dev_mc;
- int i,j;
- int coreid_bits;
- int core_max = 0;
- unsigned int ApicIdCoreIdSize;
- unsigned int core_nums;
- int siblings = 0;
- unsigned int family;
-
- dev_mc = pcidev_on_root(DEV_CDB, 0);
- if (!dev_mc) {
- printk(BIOS_ERR, "0:%02x.0 not found", DEV_CDB);
- die("");
- }
- sysconf_init(dev_mc);
-
- /* Get Max Number of cores(MNC) */
- coreid_bits = (cpuid_ecx(0x80000008) & 0x0000F000) >> 12;
- core_max = 1 << (coreid_bits & 0x000F); //mnc
-
- ApicIdCoreIdSize = ((cpuid_ecx(0x80000008)>>12) & 0xF);
- if (ApicIdCoreIdSize) {
- core_nums = (1 << ApicIdCoreIdSize) - 1;
- } else {
- core_nums = 3; //quad core
- }
-
- /* Find which cpus are present */
- cpu_bus = dev->link_list;
- for (i = 0; i < node_nums; i++) {
- struct device *cdb_dev;
- unsigned int devn;
- struct bus *pbus;
-
- devn = DEV_CDB + i;
- pbus = dev_mc->bus;
-
- /* Find the cpu's pci device */
- cdb_dev = pcidev_on_root(devn, 0);
- if (!cdb_dev) {
- /* If I am probing things in a weird order
- * ensure all of the cpu's pci devices are found.
- */
- int fn;
- for (fn = 0; fn <= 5; fn++) { //FBDIMM?
- cdb_dev = pci_probe_dev(NULL, pbus,
- PCI_DEVFN(devn, fn));
- }
- cdb_dev = pcidev_on_root(devn, 0);
- } else {
- /* Ok, We need to set the links for that device.
- * otherwise the device under it will not be scanned
- */
- add_more_links(cdb_dev, 4);
- }
-
- family = cpuid_eax(1);
- family = (family >> 20) & 0xFF;
- if (family == 1) { //f10
- u32 dword;
- cdb_dev = pcidev_on_root(devn, 3);
- dword = pci_read_config32(cdb_dev, 0xe8);
- siblings = ((dword & BIT15) >> 13) | ((dword & (BIT13 | BIT12)) >> 12);
- } else if (family == 6) {//f15
- cdb_dev = pcidev_on_root(devn, 5);
- if (cdb_dev && cdb_dev->enabled) {
- siblings = pci_read_config32(cdb_dev, 0x84);
- siblings &= 0xFF;
- }
- } else {
- siblings = 0; //default one core
- }
- int enable_node = cdb_dev && cdb_dev->enabled;
- printk(BIOS_SPEW, "%s family%xh, core_max=0x%x, core_nums=0x%x, siblings=0x%x\n",
- dev_path(cdb_dev), 0x0f + family, core_max, core_nums, siblings);
-
- for (j = 0; j <= siblings; j++) {
- extern CONST OPTIONS_CONFIG_TOPOLOGY ROMDATA TopologyConfiguration;
- u32 modules = TopologyConfiguration.PlatformNumberOfModules;
- u32 lapicid_start = 0;
-
- /*
- * APIC ID calucation is tightly coupled with AGESA v5 code.
- * This calculation MUST match the assignment calculation done
- * in LocalApicInitializationAtEarly() function.
- * And reference GetLocalApicIdForCore()
- *
- * Apply APIC enumeration rules
- * For systems with >= 16 APICs, put the IO-APICs at 0..n and
- * put the local-APICs at m..z
- *
- * This is needed because many IO-APIC devices only have 4 bits
- * for their APIC id and therefore must reside at 0..15
- */
-
- u8 plat_num_io_apics = 3; /* FIXME */
-
- if ((node_nums * core_max) + plat_num_io_apics >= 0x10) {
- lapicid_start = (plat_num_io_apics - 1) / core_max;
- lapicid_start = (lapicid_start + 1) * core_max;
- printk(BIOS_SPEW, "lpaicid_start=0x%x ", lapicid_start);
- }
- u32 apic_id = (lapicid_start * (i/modules + 1)) + ((i % modules) ? (j + (siblings + 1)) : j);
- printk(BIOS_SPEW, "node 0x%x core 0x%x apicid=0x%x\n",
- i, j, apic_id);
-
- struct device *cpu = add_cpu_device(cpu_bus, apic_id, enable_node);
- if (cpu)
- amd_cpu_topology(cpu, i, j);
- } //j
- }
-}
-
-static void cpu_bus_init(struct device *dev)
-{
- initialize_cpus(dev->link_list);
+ extern const struct mp_ops amd_mp_ops;
+ extern const struct mp_ops amd_mp_ops_with_smm;
+ /* TODO: Handle mp_init_with_smm failure? */
+ if (CONFIG(HAVE_SMI_HANDLER))
+ mp_init_with_smm(cpu_bus, &amd_mp_ops_with_smm);
+ else
+ mp_init_with_smm(cpu_bus, &amd_mp_ops);
}

static struct device_operations cpu_bus_ops = {
.read_resources = noop_read_resources,
.set_resources = noop_set_resources,
- .init = cpu_bus_init,
- .scan_bus = cpu_bus_scan,
+ .init = mp_cpu_bus_init,
};

static void root_complex_enable_dev(struct device *dev)

To view, visit change 64892. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I33a5f93e3c2777fffb47400dfab9eedd774d3b2b
Gerrit-Change-Number: 64892
Gerrit-PatchSet: 1
Gerrit-Owner: Arthur Heymans <arthur@aheymans.xyz>
Gerrit-MessageType: newchange