blob: ba66db917995cbf8b0befd3a4ea69ca0a2600dfd [file] [log] [blame]
Aaron Durbin50a34642013-01-03 17:38:47 -06001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2012 ChromeOS Authors
5 *
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.
Aaron Durbin50a34642013-01-03 17:38:47 -060015 */
16
17/*
18 * The stub is a generic wrapper for bootstrapping a C-based SMM handler. Its
19 * primary purpose is to put the CPU into protected mode with a stack and call
20 * into the C handler.
21 *
22 * The stub_entry_params structure needs to correspond to the C structure
23 * found in smm.h.
24 */
25
Aaron Durbin9e01a0b2017-06-16 14:12:55 -050026#include <cpu/x86/cr.h>
27
Aaron Durbin50a34642013-01-03 17:38:47 -060028.code32
29.section ".module_parameters", "aw", @progbits
30stub_entry_params:
31stack_size:
32.long 0
33stack_top:
34.long 0
35c_handler:
36.long 0
37c_handler_arg:
38.long 0
Aaron Durbin8ade68a2017-06-16 15:16:13 -050039fxsave_area:
40.long 0
41fxsave_area_size:
42.long 0
Aaron Durbin50a34642013-01-03 17:38:47 -060043/* struct smm_runtime begins here. */
44smm_runtime:
45smbase:
46.long 0
47save_state_size:
48.long 0
Elyes HAOUASd82be922016-07-28 18:58:27 +020049/* apic_to_cpu_num is a table mapping the default APIC id to CPU num. If the
50 * APIC id is found at the given index, the contiguous CPU number is index
Aaron Durbin50a34642013-01-03 17:38:47 -060051 * into the table. */
52apic_to_cpu_num:
53.fill CONFIG_MAX_CPUS,1,0xff
54/* end struct smm_runtime */
55
56.data
Elyes HAOUASd82be922016-07-28 18:58:27 +020057/* Provide fallback stack to use when a valid CPU number cannot be found. */
Aaron Durbin50a34642013-01-03 17:38:47 -060058fallback_stack_bottom:
59.skip 128
60fallback_stack_top:
61
Aaron Durbin9e01a0b2017-06-16 14:12:55 -050062#define CR0_CLEAR_FLAGS \
63 (CR0_CD | CR0_NW | CR0_PG | CR0_AM | CR0_WP | \
64 CR0_NE | CR0_TS | CR0_EM | CR0_MP)
65
Aaron Durbin50a34642013-01-03 17:38:47 -060066.text
67.code16
Aaron Durbindde76292015-09-05 12:59:26 -050068.global _start
69_start:
Aaron Durbin50a34642013-01-03 17:38:47 -060070 movl $(smm_relocate_gdt), %ebx
Edward O'Callaghan4e2294b2017-01-08 19:14:42 +110071 lgdtl (%ebx)
Aaron Durbin50a34642013-01-03 17:38:47 -060072
73 movl %cr0, %eax
Aaron Durbin9e01a0b2017-06-16 14:12:55 -050074 andl $~CR0_CLEAR_FLAGS, %eax
75 orl $CR0_PE, %eax
Aaron Durbin50a34642013-01-03 17:38:47 -060076 movl %eax, %cr0
77
78 /* Enable protected mode */
Edward O'Callaghan4e2294b2017-01-08 19:14:42 +110079 ljmpl $0x8, $smm_trampoline32
Aaron Durbin50a34642013-01-03 17:38:47 -060080
81.align 4
82smm_relocate_gdt:
83 /* The first GDT entry is used for the lgdt instruction. */
84 .word smm_relocate_gdt_end - smm_relocate_gdt - 1
85 .long smm_relocate_gdt
86 .word 0x0000
87
88 /* gdt selector 0x08, flat code segment */
89 .word 0xffff, 0x0000
90 .byte 0x00, 0x9b, 0xcf, 0x00 /* G=1 and 0x0f, 4GB limit */
91
92 /* gdt selector 0x10, flat data segment */
93 .word 0xffff, 0x0000
94 .byte 0x00, 0x93, 0xcf, 0x00
95smm_relocate_gdt_end:
96
97.align 4
98.code32
99.global smm_trampoline32
100smm_trampoline32:
101 /* Use flat data segment */
102 movw $0x10, %ax
103 movw %ax, %ds
104 movw %ax, %es
105 movw %ax, %ss
106 movw %ax, %fs
107 movw %ax, %gs
108
109 /* The CPU number is calculated by reading the initial APIC id. Since
110 * the OS can maniuplate the APIC id use the non-changing cpuid result
111 * for APIC id (ebx[31:24]). A table is used to handle a discontiguous
112 * APIC id space. */
113 mov $1, %eax
114 cpuid
115 bswap %ebx /* Default APIC id in bl. */
116 mov $(apic_to_cpu_num), %eax
117 xor %ecx, %ecx
118
1191:
120 cmp (%eax, %ecx, 1), %bl
121 je 1f
122 inc %ecx
123 cmp $CONFIG_MAX_CPUS, %ecx
124 jne 1b
Elyes HAOUASd82be922016-07-28 18:58:27 +0200125 /* This is bad. One cannot find a stack entry because a CPU num could
Aaron Durbin50a34642013-01-03 17:38:47 -0600126 * not be assigned. Use the fallback stack and check this condition in
127 * C handler. */
128 movl $(fallback_stack_top), %esp
Aaron Durbin8ade68a2017-06-16 15:16:13 -0500129 /* Clear fxsave location as there will be no saving/restoring. */
130 xor %edi, %edi
Aaron Durbin50a34642013-01-03 17:38:47 -0600131 jmp 2f
1321:
133 movl stack_size, %eax
Raul E Rangel01405412018-06-25 14:22:27 -0600134 mul %ecx /* %eax(stack_size) * %ecx(cpu) = %eax(offset) */
Raul E Rangele18e5ab2018-06-25 14:22:27 -0600135 movl stack_top, %ebx
136 subl %eax, %ebx /* global_stack_top - offset = stack_top */
137 mov %ebx, %esp
Raul E Rangel87115682018-06-25 14:22:27 -0600138
139 /* Create stack frame by pushing a NULL stack base pointer */
140 pushl $0x0
Raul E Rangel01405412018-06-25 14:22:27 -0600141 mov %esp, %ebp
142
143 /* Allocate locals (fxsave) */
144 subl $0x4, %esp
Aaron Durbin50a34642013-01-03 17:38:47 -0600145
Aaron Durbin8ade68a2017-06-16 15:16:13 -0500146 /* calculate fxsave location */
147 mov fxsave_area, %edi
148 test %edi, %edi
149 jz 2f
150 movl fxsave_area_size, %eax
151 mul %ecx
152 add %eax, %edi
153
Aaron Durbin50a34642013-01-03 17:38:47 -06001542:
Aaron Durbin8ade68a2017-06-16 15:16:13 -0500155 /* Save location of fxsave area. */
Raul E Rangel01405412018-06-25 14:22:27 -0600156 mov %edi, -4(%ebp)
Aaron Durbin8ade68a2017-06-16 15:16:13 -0500157 test %edi, %edi
158 jz 1f
159
160 /* Enable sse instructions. */
161 mov %cr4, %eax
162 orl $(CR4_OSFXSR | CR4_OSXMMEXCPT), %eax
163 mov %eax, %cr4
164
165 /* Save FP state. */
166 fxsave (%edi)
167
1681:
169 /* Align stack to 16 bytes. Another 16 bytes are pushed below. */
170 andl $0xfffffff0, %esp
171
Aaron Durbin50a34642013-01-03 17:38:47 -0600172 /* Call into the c-based SMM relocation function with the platform
173 * parameters. Equivalent to:
Raul E Rangel01405412018-06-25 14:22:27 -0600174 * struct arg = { c_handler_params, cpu_num, smm_runtime };
Aaron Durbin3eb8eb72014-03-10 16:13:58 -0500175 * c_handler(&arg)
Aaron Durbin50a34642013-01-03 17:38:47 -0600176 */
177 push $(smm_runtime)
Raul E Rangel01405412018-06-25 14:22:27 -0600178 push %ecx /* int cpu */
179 push c_handler_arg /* void *arg */
180 push %esp /* smm_module_params *arg (allocated on stack). */
Aaron Durbin50a34642013-01-03 17:38:47 -0600181 mov c_handler, %eax
182 call *%eax
183
Aaron Durbin8ade68a2017-06-16 15:16:13 -0500184 /* Retrieve fxsave location. */
Raul E Rangel01405412018-06-25 14:22:27 -0600185 mov -4(%ebp), %edi
Aaron Durbin8ade68a2017-06-16 15:16:13 -0500186 test %edi, %edi
187 jz 1f
188
189 /* Restore FP state. */
190 fxrstor (%edi)
191
1921:
Aaron Durbin50a34642013-01-03 17:38:47 -0600193 /* Exit from SM mode. */
194 rsm