summaryrefslogtreecommitdiff
path: root/src/include/cpu/x86/smm.h
blob: 00a8c7a2188beed2afeb1ace7221528f6e2435de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2008-2009 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 published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

/* AMD64 SMM State-Save Area
 * starts @ 0x7e00
 */

#ifndef CPU_X86_SMM_H
#define CPU_X86_SMM_H

/* used only by C programs so far */
#define SMM_BASE 0xa0000

#define SMM_ENTRY_OFFSET 0x8000
#define SMM_SAVE_STATE_BEGIN(x) (SMM_ENTRY_OFFSET + (x))

#include <types.h>
typedef struct {
	u16	es_selector;
	u16	es_attributes;
	u32	es_limit;
	u64	es_base;

	u16	cs_selector;
	u16	cs_attributcs;
	u32	cs_limit;
	u64	cs_base;

	u16	ss_selector;
	u16	ss_attributss;
	u32	ss_limit;
	u64	ss_base;

	u16	ds_selector;
	u16	ds_attributds;
	u32	ds_limit;
	u64	ds_base;

	u16	fs_selector;
	u16	fs_attributfs;
	u32	fs_limit;
	u64	fs_base;

	u16	gs_selector;
	u16	gs_attributgs;
	u32	gs_limit;
	u64	gs_base;

	u8	reserved0[4];
	u16	gdtr_limit;
	u8	reserved1[2];
	u64	gdtr_base;

	u16	ldtr_selector;
	u16	ldtr_attributes;
	u32	ldtr_limit;
	u64	ldtr_base;

	u8	reserved2[4];
	u16	idtr_limit;
	u8	reserved3[2];
	u64	idtr_base;

	u16	tr_selector;
	u16	tr_attributes;
	u32	tr_limit;
	u64	tr_base;

	u8	reserved4[40];

	u8	io_restart;
	u8	autohalt_restart;

	u8	reserved5[6];

	u64	efer;

	u8	reserved6[36];

	u32	smm_revision;
	u32	smbase;

	u8	reserved7[68];

	u64	cr4;
	u64	cr3;
	u64	cr0;
	u64	dr7;
	u64	dr6;

	u64	rflags;
	u64	rip;
	u64	r15;
	u64	r14;
	u64	r13;
	u64	r12;
	u64	r11;
	u64	r10;
	u64	r9;
	u64	r8;

	u64	rdi;
	u64	rsi;
	u64	rpb;
	u64	rsp;
	u64	rbx;
	u64	rdx;
	u64	rcx;
	u64	rax;
} __attribute__((packed)) amd64_smm_state_save_area_t;


/* Intel Core 2 (EM64T) SMM State-Save Area
 * starts @ 0x7d00
 */
typedef struct {
	u8	reserved0[208];

	u32	gdtr_upper_base;
	u32	ldtr_upper_base;
	u32	idtr_upper_base;

	u8	reserved1[4];

	u64	io_rdi;
	u64	io_rip;
	u64	io_rcx;
	u64	io_rsi;
	u64	cr4;

	u8	reserved2[68];

	u64	gdtr_base;
	u64	idtr_base;
	u64	ldtr_base;

	u8	reserved3[84];

	u32	smm_revision;
	u32	smbase;

	u16	io_restart;
	u16	autohalt_restart;

	u8	reserved4[24];

	u64	r15;
	u64	r14;
	u64	r13;
	u64	r12;
	u64	r11;
	u64	r10;
	u64	r9;
	u64	r8;

	u64	rax;
	u64	rcx;
	u64	rdx;
	u64	rbx;

	u64	rsp;
	u64	rbp;
	u64	rsi;
	u64	rdi;


	u64	io_mem_addr;
	u32	io_misc_info;

	u32	es_sel;
	u32	cs_sel;
	u32	ss_sel;
	u32	ds_sel;
	u32	fs_sel;
	u32	gs_sel;

	u32	ldtr_sel;
	u32	tr_sel;

	u64	dr7;
	u64	dr6;
	u64	rip;
	u64	efer;
	u64	rflags;

	u64	cr3;
	u64	cr0;
} __attribute__((packed)) em64t_smm_state_save_area_t;


/* Intel Revision 30101 SMM State-Save Area
 * The following processor architectures use this:
 * - SandyBridge
 * - IvyBridge
 * - Haswell
 */
#define SMM_EM64T101_ARCH_OFFSET 0x7c00
#define SMM_EM64T101_SAVE_STATE_OFFSET \
	SMM_SAVE_STATE_BEGIN(SMM_EM64T101_ARCH_OFFSET)
typedef struct {
	u8	reserved0[256];
	u8	reserved1[208];

	u32	gdtr_upper_base;
	u32	ldtr_upper_base;
	u32	idtr_upper_base;

	u32	io_cf8;

	u64	io_rdi;
	u64	io_rip;
	u64	io_rcx;
	u64	io_rsi;

	u8	reserved2[52];
	u32	shutdown_auto_restart;
	u8	reserved3[8];
	u32	cr4;

	u8	reserved4[72];

	u32	gdtr_base;
	u8	reserved5[4];
	u32	idtr_base;
	u8	reserved6[4];
	u32	ldtr_base;

	u8	reserved7[56];
	/* EPTP fields are only on Haswell according to BWGs, but Intel was
	 * wise and reused the same revision number. */
	u64	eptp;
	u32	eptp_en;
	u32	cs_base;
	u8	reserved8[4];
	u32	iedbase;

	u8	reserved9[8];

	u32	smbase;
	u32	smm_revision;

	u16	io_restart;
	u16	autohalt_restart;

	u8	reserved10[24];

	u64	r15;
	u64	r14;
	u64	r13;
	u64	r12;
	u64	r11;
	u64	r10;
	u64	r9;
	u64	r8;

	u64	rax;
	u64	rcx;
	u64	rdx;
	u64	rbx;

	u64	rsp;
	u64	rbp;
	u64	rsi;
	u64	rdi;


	u64	io_mem_addr;
	u32	io_misc_info;

	u32	es_sel;
	u32	cs_sel;
	u32	ss_sel;
	u32	ds_sel;
	u32	fs_sel;
	u32	gs_sel;

	u32	ldtr_sel;
	u32	tr_sel;

	u64	dr7;
	u64	dr6;
	u64	rip;
	u64	efer;
	u64	rflags;

	u64	cr3;
	u64	cr0;
} __attribute__((packed)) em64t101_smm_state_save_area_t;


/* Legacy x86 SMM State-Save Area
 * starts @ 0x7e00
 */

typedef struct {
	u8	reserved0[248];
	u32	smbase;
	u32	smm_revision;
	u16	io_restart;
	u16	autohalt_restart;
	u8	reserved1[132];
	u32	gdtbase;
	u8	reserved2[8];
	u32	idtbase;
	u8	reserved3[16];
	u32	es;
	u32	cs;
	u32	ss;
	u32	ds;
	u32	fs;
	u32	gs;
	u32	ldtbase;
	u32	tr;
	u32	dr7;
	u32	dr6;
	u32	eax;
	u32	ecx;
	u32	edx;
	u32	ebx;
	u32	esp;
	u32	ebp;
	u32	esi;
	u32	edi;
	u32	eip;
	u32	eflags;
	u32	cr3;
	u32	cr0;
} __attribute__((packed)) legacy_smm_state_save_area_t;

typedef enum {
	AMD64,
	EM64T,
	EM64T101,
	LEGACY
} save_state_type_t;


typedef struct {
	save_state_type_t type;
	union {
	amd64_smm_state_save_area_t *amd64_state_save;
	em64t_smm_state_save_area_t *em64t_state_save;
	em64t101_smm_state_save_area_t *em64t101_state_save;
	legacy_smm_state_save_area_t *legacy_state_save;
	};
} smm_state_save_area_t;

#define APM_CNT		0xb2
#define APM_CNT_CST_CONTROL	0x85
#define APM_CNT_PST_CONTROL	0x80
#define APM_CNT_ACPI_DISABLE	0x1e
#define APM_CNT_ACPI_ENABLE	0xe1
#define APM_CNT_MBI_UPDATE	0xeb
#define APM_CNT_GNVS_UPDATE	0xea
#define APM_STS		0xb3

/* SMI handler function prototypes */
void smi_handler(u32 smm_revision);

void io_trap_handler(int smif);
int southbridge_io_trap_handler(int smif);
int __attribute__((weak)) mainboard_io_trap_handler(int smif);

void southbridge_smi_set_eos(void);

void __attribute__((weak)) cpu_smi_handler(unsigned int node, smm_state_save_area_t *state_save);
void __attribute__((weak)) northbridge_smi_handler(unsigned int node, smm_state_save_area_t *state_save);
void __attribute__((weak)) southbridge_smi_handler(unsigned int node, smm_state_save_area_t *state_save);

void __attribute__((weak)) mainboard_smi_gpi(u16 gpi_sts);
int __attribute__((weak)) mainboard_smi_apmc(u8 data);
void __attribute__((weak)) mainboard_smi_sleep(u8 slp_typ);

#if !CONFIG_SMM_TSEG
void smi_release_lock(void);
#define tseg_relocate(ptr)
#else
/* Return address of TSEG base */
u32 smi_get_tseg_base(void);
/* Adjust pointer with TSEG base */
void tseg_relocate(void **ptr);
#endif

/* Get PMBASE address */
u16 smm_get_pmbase(void);

#endif