blob: 230c78d0797335f3717ce66d8e2ace4c95c044e7 [file] [log] [blame]
Stefan Reinauerdebb11f2008-10-29 04:46:52 +00001/*
2 * This file is part of the coreboot project.
3 *
Stefan Reinauerbc0f7a62010-08-01 15:41:14 +00004 * Copyright (C) 2008-2010 coresystems GmbH
Stefan Reinauerdebb11f2008-10-29 04:46:52 +00005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of
9 * the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000015 */
16
Stefan Reinauer4da810b2009-07-21 21:41:42 +000017// Make sure no stage 2 code is included:
Myles Watson1d6d45e2009-11-06 17:02:51 +000018#define __PRE_RAM__
Stefan Reinauer4da810b2009-07-21 21:41:42 +000019
Stefan Reinauer14e22772010-04-27 06:56:47 +000020// FIXME: Is this piece of code southbridge specific, or
Stefan Reinauer4da810b2009-07-21 21:41:42 +000021// can it be cleaned up so this include is not required?
Stefan Reinauerbc0f7a62010-08-01 15:41:14 +000022// It's needed right now because we get our DEFAULT_PMBASE from
Stefan Reinauer5f5436f2010-04-25 20:42:02 +000023// here.
Martin Roth0fa92b32017-06-24 13:53:20 -060024#if IS_ENABLED(CONFIG_SOUTHBRIDGE_INTEL_I82801GX)
Stefan Reinauer4da810b2009-07-21 21:41:42 +000025#include "../../../southbridge/intel/i82801gx/i82801gx.h"
Martin Roth0fa92b32017-06-24 13:53:20 -060026#elif IS_ENABLED(CONFIG_SOUTHBRIDGE_INTEL_I82801DX)
Stefan Reinauerbc0f7a62010-08-01 15:41:14 +000027#include "../../../southbridge/intel/i82801dx/i82801dx.h"
Martin Roth0fa92b32017-06-24 13:53:20 -060028#elif IS_ENABLED(CONFIG_SOC_INTEL_SCH)
Stefan Reinauer4bab6e72016-05-03 15:53:33 -070029#include "../../../soc/intel/sch/sch.h"
Martin Roth0fa92b32017-06-24 13:53:20 -060030#elif IS_ENABLED(CONFIG_SOUTHBRIDGE_INTEL_I82801IX)
Patrick Georgie72a8a32012-11-06 11:05:09 +010031#include "../../../southbridge/intel/i82801ix/i82801ix.h"
Martin Rothb137c132017-07-21 10:23:57 -060032#elif IS_ENABLED(CONFIG_SOUTHBRIDGE_INTEL_I82801JX)
Arthur Heymans349e0852017-04-09 20:48:37 +020033#include "../../../southbridge/intel/i82801jx/i82801jx.h"
34
Stefan Reinauerbc0f7a62010-08-01 15:41:14 +000035#else
36#error "Southbridge needs SMM handler support."
37#endif
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000038
Edward O'Callaghan1104c272017-01-08 19:57:45 +110039// ADDR32() macro
Patrick Georgie8741fe2017-09-04 17:37:31 +020040#include <arch/registers.h>
Edward O'Callaghan1104c272017-01-08 19:57:45 +110041
Martin Roth0fa92b32017-06-24 13:53:20 -060042#if IS_ENABLED(CONFIG_SMM_TSEG)
Vladimir Serbinenko7f464202015-05-28 21:03:51 +020043#error "Don't use this file with TSEG."
Stefan Reinauer3aa067f2012-04-02 13:24:04 -070044
45#endif /* CONFIG_SMM_TSEG */
46
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000047#define LAPIC_ID 0xfee00020
48
49.global smm_relocation_start
50.global smm_relocation_end
51
52/* initially SMM is some sort of real mode. */
53.code16
54
55/**
Stefan Reinauer8c5b58e2012-04-04 10:38:05 -070056 * When starting up, x86 CPUs have their SMBASE set to 0x30000. However,
57 * this is not a good place for the SMM handler to live, so it needs to
58 * be relocated.
59 * Traditionally SMM handlers used to live in the A segment (0xa0000).
60 * With growing SMM handlers, more CPU cores, etc. CPU vendors started
61 * allowing to relocate the handler to the end of physical memory, which
62 * they refer to as TSEG.
63 * This trampoline code relocates SMBASE to base address - ( lapicid * 0x400 )
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000064 *
65 * Why 0x400? It is a safe value to cover the save state area per CPU. On
66 * current AMD CPUs this area is _documented_ to be 0x200 bytes. On Intel
67 * Core 2 CPUs the _documented_ parts of the save state area is 48 bytes
68 * bigger, effectively sizing our data structures 0x300 bytes.
69 *
Stefan Reinauer8c5b58e2012-04-04 10:38:05 -070070 * Example (with SMM handler living at 0xa0000):
71 *
Stefan Reinauerdebb11f2008-10-29 04:46:52 +000072 * LAPICID SMBASE SMM Entry SAVE STATE
73 * 0 0xa0000 0xa8000 0xafd00
74 * 1 0x9fc00 0xa7c00 0xaf900
75 * 2 0x9f800 0xa7800 0xaf500
76 * 3 0x9f400 0xa7400 0xaf100
77 * 4 0x9f000 0xa7000 0xaed00
78 * 5 0x9ec00 0xa6c00 0xae900
79 * 6 0x9e800 0xa6800 0xae500
80 * 7 0x9e400 0xa6400 0xae100
81 * 8 0x9e000 0xa6000 0xadd00
82 * 9 0x9dc00 0xa5c00 0xad900
83 * 10 0x9d800 0xa5800 0xad500
84 * 11 0x9d400 0xa5400 0xad100
85 * 12 0x9d000 0xa5000 0xacd00
86 * 13 0x9cc00 0xa4c00 0xac900
87 * 14 0x9c800 0xa4800 0xac500
88 * 15 0x9c400 0xa4400 0xac100
89 * . . . .
90 * . . . .
91 * . . . .
92 * 31 0x98400 0xa0400 0xa8100
93 *
94 * With 32 cores, the SMM handler would need to fit between
95 * 0xa0000-0xa0400 and the stub plus stack would need to go
96 * at 0xa8000-0xa8100 (example for core 0). That is not enough.
97 *
Elyes HAOUASd82be922016-07-28 18:58:27 +020098 * This means we're basically limited to 16 CPU cores before
Stefan Reinauer8c5b58e2012-04-04 10:38:05 -070099 * we need to move the SMM handler to TSEG.
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000100 *
101 * Note: Some versions of Pentium M need their SMBASE aligned to 32k.
102 * On those the above only works for up to 2 cores. But for now we only
103 * care fore Core (2) Duo/Solo
104 *
105 */
106
107smm_relocation_start:
108 /* Check revision to see if AMD64 style SMM_BASE
109 * Intel Core Solo/Duo: 0x30007
110 * Intel Core2 Solo/Duo: 0x30100
Stefan Reinauer3aa067f2012-04-02 13:24:04 -0700111 * Intel SandyBridge: 0x30101
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000112 * AMD64: 0x3XX64
113 * This check does not make much sense, unless someone ports
114 * SMI handling to AMD64 CPUs.
115 */
116
117 mov $0x38000 + 0x7efc, %ebx
Edward O'Callaghan1104c272017-01-08 19:57:45 +1100118 ADDR32(mov) (%ebx), %al
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000119 cmp $0x64, %al
120 je 1f
Stefan Reinauer14e22772010-04-27 06:56:47 +0000121
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000122 mov $0x38000 + 0x7ef8, %ebx
123 jmp smm_relocate
1241:
125 mov $0x38000 + 0x7f00, %ebx
126
127smm_relocate:
128 /* Get this CPU's LAPIC ID */
129 movl $LAPIC_ID, %esi
Edward O'Callaghan1104c272017-01-08 19:57:45 +1100130 ADDR32(movl) (%esi), %ecx
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000131 shr $24, %ecx
Stefan Reinauer14e22772010-04-27 06:56:47 +0000132
133 /* calculate offset by multiplying the
Elyes HAOUASd6e96862016-08-21 10:12:15 +0200134 * APIC ID by 1024 (0x400)
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000135 */
136 movl %ecx, %edx
137 shl $10, %edx
138
139 movl $0xa0000, %eax
140 subl %edx, %eax /* subtract offset, see above */
141
Edward O'Callaghan1104c272017-01-08 19:57:45 +1100142 ADDR32(movl) %eax, (%ebx)
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000143
Stefan Reinauerbc0f7a62010-08-01 15:41:14 +0000144 /* The next section of code is potentially southbridge specific */
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000145
146 /* Clear SMI status */
147 movw $(DEFAULT_PMBASE + 0x34), %dx
148 inw %dx, %ax
149 outw %ax, %dx
150
151 /* Clear PM1 status */
152 movw $(DEFAULT_PMBASE + 0x00), %dx
153 inw %dx, %ax
154 outw %ax, %dx
155
156 /* Set EOS bit so other SMIs can occur */
157 movw $(DEFAULT_PMBASE + 0x30), %dx
158 inl %dx, %eax
159 orl $(1 << 1), %eax
160 outl %eax, %dx
161
Stefan Reinauerbc0f7a62010-08-01 15:41:14 +0000162 /* End of southbridge specific section. */
163
Martin Roth0fa92b32017-06-24 13:53:20 -0600164#if IS_ENABLED(CONFIG_DEBUG_SMM_RELOCATION)
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000165 /* print [SMM-x] so we can determine if CPUx went to SMM */
Stefan Reinauer08670622009-06-30 15:17:49 +0000166 movw $CONFIG_TTYS0_BASE, %dx
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000167 mov $'[', %al
168 outb %al, %dx
169 mov $'S', %al
170 outb %al, %dx
171 mov $'M', %al
172 outb %al, %dx
173 outb %al, %dx
174 movb $'-', %al
175 outb %al, %dx
Elyes HAOUASd82be922016-07-28 18:58:27 +0200176 /* calculate ascii of CPU number. More than 9 cores? -> FIXME */
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000177 movb %cl, %al
Stefan Reinauer14e22772010-04-27 06:56:47 +0000178 addb $'0', %al
Stefan Reinauerdebb11f2008-10-29 04:46:52 +0000179 outb %al, %dx
180 mov $']', %al
181 outb %al, %dx
182 mov $'\r', %al
183 outb %al, %dx
184 mov $'\n', %al
185 outb %al, %dx
186#endif
187
188 /* That's it. return */
189 rsm
190smm_relocation_end: