Add support to run SMM handler in TSEG instead of ASEG
[coreboot.git] / src / cpu / x86 / smm / smmrelocate.S
index 14fdc639bcec0aa464ca6e0e2701fe2c2cc73a46..bc5b2da41b5ffb9f029fbbd4c9d526dea7f846c2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the coreboot project.
  *
- * Copyright (C) 2008 coresystems GmbH
+ * Copyright (C) 2008-2010 coresystems GmbH
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
 // Make sure no stage 2 code is included:
 #define __PRE_RAM__
 
-// FIXME: Is this piece of code southbridge specific, or 
+/* On AMD's platforms we can set SMBASE by writing an MSR */
+#if !CONFIG_NORTHBRIDGE_AMD_AMDK8 && !CONFIG_NORTHBRIDGE_AMD_AMDFAM10
+
+// FIXME: Is this piece of code southbridge specific, or
 // can it be cleaned up so this include is not required?
-// It's needed right now because we get our PM_BASE from
+// It's needed right now because we get our DEFAULT_PMBASE from
 // here.
+#if CONFIG_SOUTHBRIDGE_INTEL_I82801GX
 #include "../../../southbridge/intel/i82801gx/i82801gx.h"
+#elif CONFIG_SOUTHBRIDGE_INTEL_I82801DX
+#include "../../../southbridge/intel/i82801dx/i82801dx.h"
+#elif CONFIG_SOUTHBRIDGE_INTEL_SCH
+#include "../../../southbridge/intel/sch/sch.h"
+#else
+#error "Southbridge needs SMM handler support."
+#endif
+
+#if CONFIG_SMM_TSEG
+
+#include <cpu/x86/mtrr.h>
 
-#undef DEBUG_SMM_RELOCATION
-//#define DEBUG_SMM_RELOCATION
+#endif /* CONFIG_SMM_TSEG */
 
 #define LAPIC_ID 0xfee00020
 
@@ -73,7 +87,7 @@
  * 0xa0000-0xa0400 and the stub plus stack would need to go
  * at 0xa8000-0xa8100 (example for core 0). That is not enough.
  *
- * This means we're basically limited to 16 cpu cores before 
+ * This means we're basically limited to 16 cpu cores before
  * we need to use the TSEG/HSEG for the actual SMM handler plus stack.
  * When we exceed 32 cores, we also need to put SMBASE to TSEG/HSEG.
  *
@@ -92,6 +106,7 @@ smm_relocation_start:
        /* Check revision to see if AMD64 style SMM_BASE
         *   Intel Core Solo/Duo:  0x30007
         *   Intel Core2 Solo/Duo: 0x30100
+        *   Intel SandyBridge:    0x30101
         *   AMD64:                0x3XX64
         * This check does not make much sense, unless someone ports
         * SMI handling to AMD64 CPUs.
@@ -101,7 +116,7 @@ smm_relocation_start:
        addr32 mov (%ebx), %al
        cmp $0x64, %al
        je 1f
+
        mov $0x38000 + 0x7ef8, %ebx
        jmp smm_relocate
 1:
@@ -112,20 +127,62 @@ smm_relocate:
        movl $LAPIC_ID, %esi
        addr32 movl (%esi), %ecx
        shr  $24, %ecx
-       
-       /* calculate offset by multiplying the 
+
+       /* calculate offset by multiplying the
         * apic ID by 1024 (0x400)
         */
        movl %ecx, %edx
        shl $10, %edx
 
+#if CONFIG_SMM_TSEG
+       movl    $(TSEG_BAR), %ecx       /* Get TSEG base from PCIE */
+       addr32  movl (%ecx), %eax       /* Save TSEG_BAR in %eax */
+       andl    $~1, %eax               /* Remove lock bit */
+#else
        movl $0xa0000, %eax
+#endif
        subl %edx, %eax /* subtract offset, see above */
 
        addr32 movl %eax, (%ebx)
 
+#if CONFIG_SMM_TSEG
+       /* Check for SMRR capability in MTRRCAP[11] */
+       movl    $MTRRcap_MSR, %ecx
+       rdmsr
+       bt      $11, %eax
+       jnc     skip_smrr
+
+       /* TSEG base */
+       movl    $(TSEG_BAR), %ecx       /* Get TSEG base from PCIE */
+       addr32  movl (%ecx), %eax       /* Save TSEG_BAR in %eax */
+       andl    $~1, %eax               /* Remove lock bit */
+       movl    %eax, %ebx
+
+       /* Set SMRR base address. */
+       movl    $SMRRphysBase_MSR, %ecx
+       orl     $MTRR_TYPE_WRBACK, %eax
+       xorl    %edx, %edx
+       wrmsr
+
+       /* Set SMRR mask. */
+       movl    $SMRRphysMask_MSR, %ecx
+       movl    $(~(CONFIG_SMM_TSEG_SIZE - 1) | MTRRphysMaskValid), %eax
+       xorl    %edx, %edx
+       wrmsr
+
+#if CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE || CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE
+       /*
+        * IED base is top 4M of TSEG
+        */
+       addl    $(CONFIG_SMM_TSEG_SIZE - IED_SIZE), %ebx
+       movl    $(0x30000 + 0x8000 + 0x7eec), %eax
+       addr32  movl %ebx, (%eax)
+#endif
+
+skip_smrr:
+#endif
 
-       /* The next section of code is hardware specific */
+       /* The next section of code is potentially southbridge specific */
 
        /* Clear SMI status */
        movw $(DEFAULT_PMBASE + 0x34), %dx
@@ -143,8 +200,9 @@ smm_relocate:
        orl $(1 << 1), %eax
        outl %eax, %dx
 
-       /* End of hardware specific section. */
-#ifdef DEBUG_SMM_RELOCATION
+       /* End of southbridge specific section. */
+
+#if CONFIG_DEBUG_SMM_RELOCATION
        /* print [SMM-x] so we can determine if CPUx went to SMM */
        movw $CONFIG_TTYS0_BASE, %dx
        mov $'[', %al
@@ -158,7 +216,7 @@ smm_relocate:
        outb %al, %dx
        /* calculate ascii of cpu number. More than 9 cores? -> FIXME */
        movb %cl, %al
-       addb $'0', %al 
+       addb $'0', %al
        outb %al, %dx
        mov $']', %al
        outb %al, %dx
@@ -171,4 +229,4 @@ smm_relocate:
        /* That's it. return */
        rsm
 smm_relocation_end:
-
+#endif