Arthur Heymans has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/64892 )
Change subject: [NEEDSTEST]cpu/amd/family15: Use parallel_mp ......................................................................
[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)