cpu/amd/agesa/family15tn: Add initial support for SMM mode

This is the minimal setup needed to be able to execute SMI handlers.
Only support for ASEG handlers is added, which should be sufficient
for Trinity (up to 4 cores).

There are a few hacks which need to be introduced in generic code in
order to make this work properly, but these hacks are self-contained.
They are a not a result of any special needs of this CPU, but rather
from a poorly designed infrastructure. Comments are added to explain
how such code could be refactored in the future.

Change-Id: Iefd4ae17cf0206cae8848cadba3a12cbe3b2f8b6
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Reviewed-on: http://review.coreboot.org/5493
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@gmail.com>
This commit is contained in:
Alexandru Gagniuc
2014-04-12 21:57:18 -05:00
parent 342ac64a5d
commit 53072d869a
5 changed files with 29 additions and 1 deletions

View File

@@ -21,6 +21,7 @@ ramstage-y += chip_name.c
ramstage-y += model_15_init.c ramstage-y += model_15_init.c
subdirs-y += ../../mtrr subdirs-y += ../../mtrr
subdirs-y += ../../smm
subdirs-y += ../../../x86/tsc subdirs-y += ../../../x86/tsc
subdirs-y += ../../../x86/lapic subdirs-y += ../../../x86/lapic
subdirs-y += ../../../x86/cache subdirs-y += ../../../x86/cache

View File

@@ -19,6 +19,7 @@
#include <console/console.h> #include <console/console.h>
#include <cpu/x86/msr.h> #include <cpu/x86/msr.h>
#include <cpu/x86/smm.h>
#include <cpu/amd/mtrr.h> #include <cpu/amd/mtrr.h>
#include <device/device.h> #include <device/device.h>
#include <string.h> #include <string.h>
@@ -43,6 +44,7 @@ static void model_15_init(device_t dev)
u8 i; u8 i;
msr_t msr; msr_t msr;
int msrno; int msrno;
unsigned int cpu_idx;
#if CONFIG_LOGICAL_CPUS #if CONFIG_LOGICAL_CPUS
u32 siblings; u32 siblings;
#endif #endif
@@ -110,6 +112,20 @@ static void model_15_init(device_t dev)
msr.hi &= ~(1 << (46 - 32)); msr.hi &= ~(1 << (46 - 32));
wrmsr(NB_CFG_MSR, msr); wrmsr(NB_CFG_MSR, msr);
if (IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)) {
cpu_idx = cpu_info()->index;
printk(BIOS_INFO, "Initializing SMM for CPU %u\n", cpu_idx);
/* Set SMM base address for this CPU */
msr = rdmsr(MSR_SMM_BASE);
msr.lo = SMM_BASE - (cpu_idx * 0x400);
wrmsr(MSR_SMM_BASE, msr);
/* Enable the SMM memory window */
msr = rdmsr(MSR_SMM_MASK);
msr.lo |= (1 << 0); /* Enable ASEG SMRAM Range */
wrmsr(MSR_SMM_MASK, msr);
}
/* Write protect SMM space with SMMLOCK. */ /* Write protect SMM space with SMMLOCK. */
msr = rdmsr(HWCR_MSR); msr = rdmsr(HWCR_MSR);

View File

@@ -105,6 +105,14 @@ smm_handler_start:
movl (%esi), %ecx movl (%esi), %ecx
shr $24, %ecx shr $24, %ecx
/* This is an ugly hack, and we should find a way to read the CPU index
* without relying on the LAPIC ID.
*/
#if IS_ENABLED(CONFIG_CPU_AMD_AGESA_FAMILY15_TN)
/* LAPIC IDs start from 0x10; map that to the proper core index */
subl $0x10, %ecx
#endif
/* calculate stack offset by multiplying the APIC ID /* calculate stack offset by multiplying the APIC ID
* by 1024 (0x400), and save that offset in ebp. * by 1024 (0x400), and save that offset in ebp.
*/ */

View File

@@ -23,7 +23,8 @@
#define __PRE_RAM__ #define __PRE_RAM__
/* On AMD's platforms we can set SMBASE by writing an MSR */ /* On AMD's platforms we can set SMBASE by writing an MSR */
#if !CONFIG_NORTHBRIDGE_AMD_AMDK8 && !CONFIG_NORTHBRIDGE_AMD_AMDFAM10 #if !CONFIG_NORTHBRIDGE_AMD_AMDK8 && !CONFIG_NORTHBRIDGE_AMD_AMDFAM10 \
&& !CONFIG_CPU_AMD_AGESA_FAMILY15_TN
// FIXME: Is this piece of code southbridge specific, or // FIXME: Is this piece of code southbridge specific, or
// can it be cleaned up so this include is not required? // can it be cleaned up so this include is not required?

View File

@@ -23,6 +23,8 @@
#include <cpu/x86/msr.h> #include <cpu/x86/msr.h>
#define MCI_STATUS 0x00000401 #define MCI_STATUS 0x00000401
#define MSR_SMM_BASE 0xC0010111
#define MSR_SMM_MASK 0xC0010113
#define HWCR_MSR 0xC0010015 #define HWCR_MSR 0xC0010015
#define NB_CFG_MSR 0xC001001f #define NB_CFG_MSR 0xC001001f