blob: 32b848df9b40db5ef5479da7358c11baa2f46036 [file] [log] [blame]
Martin Roth9df9e9392016-01-12 15:55:28 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
Stefan Reinauer5f5436f2010-04-25 20:42:02 +000014#include <cpu/x86/post_code.h>
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +000015
Aaron Durbin633f1122013-02-06 15:28:40 -060016/* Place the stack in the bss section. It's not necessary to define it in the
17 * the linker script. */
18 .section .bss, "aw", @nobits
19.global _stack
20.global _estack
21
Kyösti Mälkki2fbb6772018-05-15 19:50:20 +030022/* Stack alignment is not enforced with rmodule loader, reserve one
23 * extra CPU such that alignment can be enforced on entry. */
Aaron Durbin633f1122013-02-06 15:28:40 -060024.align CONFIG_STACK_SIZE
25_stack:
Kyösti Mälkki2fbb6772018-05-15 19:50:20 +030026.space (CONFIG_MAX_CPUS+1)*CONFIG_STACK_SIZE
Aaron Durbin633f1122013-02-06 15:28:40 -060027_estack:
Julius Wernercd49cce2019-03-05 16:53:33 -080028#if CONFIG(COOP_MULTITASKING)
Aaron Durbin38c326d2013-05-06 12:22:23 -050029.global thread_stacks
30thread_stacks:
31.space CONFIG_STACK_SIZE*CONFIG_NUM_THREADS
32#endif
Aaron Durbin633f1122013-02-06 15:28:40 -060033
Julius Wernerec5e5e02014-08-20 15:29:56 -070034 .section ".text._start", "ax", @progbits
Stefan Reinauer96938852015-06-18 01:23:48 -070035#ifdef __x86_64__
36 .code64
37#else
Eric Biederman8ca8d762003-04-22 19:02:15 +000038 .code32
Stefan Reinauer96938852015-06-18 01:23:48 -070039#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +000040 .globl _start
41_start:
42 cli
43 lgdt %cs:gdtaddr
Stefan Reinauer96938852015-06-18 01:23:48 -070044#ifndef __x86_64__
Eric Biederman8ca8d762003-04-22 19:02:15 +000045 ljmp $0x10, $1f
Stefan Reinauer96938852015-06-18 01:23:48 -070046#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +0000471: movl $0x18, %eax
48 movl %eax, %ds
49 movl %eax, %es
50 movl %eax, %ss
51 movl %eax, %fs
52 movl %eax, %gs
Stefan Reinauer96938852015-06-18 01:23:48 -070053#ifdef __x86_64__
Elyes HAOUAS2ea751a2018-12-27 09:21:02 +010054 mov $0x48, %ecx
55 call SetCodeSelector
Stefan Reinauer96938852015-06-18 01:23:48 -070056#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +000057
Alexandru Gagniuc5005bb062011-04-11 20:17:22 +000058 post_code(POST_ENTRY_C_START) /* post 13 */
Eric Biederman8ca8d762003-04-22 19:02:15 +000059
arch import user (historical)6ca76362005-07-06 17:17:25 +000060 cld
Eric Biederman8ca8d762003-04-22 19:02:15 +000061
Aaron Durbin633f1122013-02-06 15:28:40 -060062 /** poison the stack. Code should not count on the
63 * stack being full of zeros. This stack poisoning
64 * recently uncovered a bug in the broadcast SIPI
65 * code.
66 */
67 leal _stack, %edi
68 movl $_estack, %ecx
69 subl %edi, %ecx
70 shrl $2, %ecx /* it is 32 bit aligned, right? */
71 movl $0xDEADBEEF, %eax
72 rep
73 stosl
74
Kyösti Mälkki2fbb6772018-05-15 19:50:20 +030075 /* Set new stack with enforced alignment. */
Eric Biederman8ca8d762003-04-22 19:02:15 +000076 movl $_estack, %esp
Kyösti Mälkki2fbb6772018-05-15 19:50:20 +030077 andl $(~(CONFIG_STACK_SIZE-1)), %esp
Eric Biederman8ca8d762003-04-22 19:02:15 +000078
Julius Wernercd49cce2019-03-05 16:53:33 -080079#if CONFIG(COOP_MULTITASKING)
Aaron Durbin38c326d2013-05-06 12:22:23 -050080 /* Push the thread pointer. */
Stefan Reinauer96938852015-06-18 01:23:48 -070081 push $0
Aaron Durbin38c326d2013-05-06 12:22:23 -050082#endif
Elyes HAOUAS777ea892016-07-29 07:40:41 +020083 /* Push the CPU index and struct CPU */
Stefan Reinauer96938852015-06-18 01:23:48 -070084 push $0
85 push $0
Eric Biederman8ca8d762003-04-22 19:02:15 +000086
Eric Biederman8ca8d762003-04-22 19:02:15 +000087 /*
88 * Now we are finished. Memory is up, data is copied and
89 * bss is cleared. Now we call the main routine and
90 * let it do the rest.
Stefan Reinauer607cdf62010-04-26 12:08:51 +000091 */
Alexandru Gagniuc5005bb062011-04-11 20:17:22 +000092 post_code(POST_PRE_HARDWAREMAIN) /* post fe */
Eric Biederman8ca8d762003-04-22 19:02:15 +000093
Kyösti Mälkki4796c322017-03-15 08:07:22 +020094 andl $0xFFFFFFF0, %esp
95
Julius Wernercd49cce2019-03-05 16:53:33 -080096#if CONFIG(GDB_WAIT)
Kyösti Mälkkif2f7f032014-04-04 15:05:28 +030097 call gdb_hw_init
Denis 'GNUtoo' Cariklie4cece02012-06-22 15:56:37 +020098 call gdb_stub_breakpoint
99#endif
Stefan Reinauer6adef082013-05-09 16:30:06 -0700100 call main
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000101 /* NOTREACHED */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000102.Lhlt:
Alexandru Gagniuc5005bb062011-04-11 20:17:22 +0000103 post_code(POST_DEAD_CODE) /* post ee */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000104 hlt
105 jmp .Lhlt
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000106
Julius Wernercd49cce2019-03-05 16:53:33 -0800107#if CONFIG(GDB_WAIT)
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000108
109 .globl gdb_stub_breakpoint
110gdb_stub_breakpoint:
Stefan Reinauer96938852015-06-18 01:23:48 -0700111#ifdef __x86_64__
112 pop %rax /* Return address */
113 pushfl
114 push %cs
115 push %rax /* Return address */
116 push $0 /* No error code */
117 push $32 /* vector 32 is user defined */
118#else
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000119 popl %eax /* Return address */
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000120 pushfl
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000121 pushl %cs
122 pushl %eax /* Return address */
123 pushl $0 /* No error code */
124 pushl $32 /* vector 32 is user defined */
Stefan Reinauer96938852015-06-18 01:23:48 -0700125#endif
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000126 jmp int_hand
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000127#endif
128
Aaron Durbin4b032e42018-04-20 01:39:30 -0600129 .globl gdt, gdt_end
Eric Biederman8ca8d762003-04-22 19:02:15 +0000130
Eric Biederman8ca8d762003-04-22 19:02:15 +0000131gdtaddr:
Aaron Durbina146d582013-02-08 16:56:51 -0600132 .word gdt_end - gdt - 1
Stefan Reinauer96938852015-06-18 01:23:48 -0700133#ifdef __x86_64__
134 .quad gdt
135#else
Li-Ta Lof84926e2004-11-04 18:36:06 +0000136 .long gdt /* we know the offset */
Stefan Reinauer96938852015-06-18 01:23:48 -0700137#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +0000138
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000139 .data
Li-Ta Lof84926e2004-11-04 18:36:06 +0000140
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000141 /* This is the gdt for GCC part of coreboot.
142 * It is different from the gdt in ROMCC/ASM part of coreboot
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000143 * which is defined in entry32.inc
144 *
145 * When the machine is initially started, we use a very simple
Elyes HAOUAS777ea892016-07-29 07:40:41 +0200146 * gdt from ROM (that in entry32.inc) which only contains those
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000147 * entries we need for protected mode.
148 *
149 * When we're executing code from RAM, we want to do more complex
Elyes HAOUAS777ea892016-07-29 07:40:41 +0200150 * stuff, like initializing PCI option ROMs in real mode, or doing
151 * a resume from a suspend to RAM.
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000152 */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000153gdt:
Li-Ta Lof84926e2004-11-04 18:36:06 +0000154 /* selgdt 0, unused */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000155 .word 0x0000, 0x0000 /* dummy */
156 .byte 0x00, 0x00, 0x00, 0x00
157
Li-Ta Lof84926e2004-11-04 18:36:06 +0000158 /* selgdt 8, unused */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000159 .word 0x0000, 0x0000 /* dummy */
160 .byte 0x00, 0x00, 0x00, 0x00
161
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000162 /* selgdt 0x10, flat code segment */
163 .word 0xffff, 0x0000
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700164 .byte 0x00, 0x9b, 0xcf, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for
165 * limit
166 */
Li-Ta Lof84926e2004-11-04 18:36:06 +0000167
168 /* selgdt 0x18, flat data segment */
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000169 .word 0xffff, 0x0000
Stefan Reinauer96938852015-06-18 01:23:48 -0700170#ifdef __x86_64__
171 .byte 0x00, 0x92, 0xcf, 0x00
172#else
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000173 .byte 0x00, 0x93, 0xcf, 0x00
Stefan Reinauer96938852015-06-18 01:23:48 -0700174#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +0000175
Li-Ta Lof84926e2004-11-04 18:36:06 +0000176 /* selgdt 0x20, unused */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000177 .word 0x0000, 0x0000 /* dummy */
178 .byte 0x00, 0x00, 0x00, 0x00
179
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000180 /* The next two entries are used for executing VGA option ROMs */
181
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000182 /* selgdt 0x28 16 bit 64k code at 0x00000000 */
Elyes HAOUAS2ea751a2018-12-27 09:21:02 +0100183 .word 0xffff, 0x0000
184 .byte 0, 0x9a, 0, 0
Stefan Reinauerf8a5c6e2009-05-29 13:08:27 +0000185
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000186 /* selgdt 0x30 16 bit 64k data at 0x00000000 */
Elyes HAOUAS2ea751a2018-12-27 09:21:02 +0100187 .word 0xffff, 0x0000
188 .byte 0, 0x92, 0, 0
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000189
190 /* The next two entries are used for ACPI S3 RESUME */
191
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000192 /* selgdt 0x38, flat data segment 16 bit */
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000193 .word 0x0000, 0x0000 /* dummy */
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700194 .byte 0x00, 0x93, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for
195 * limit
196 */
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000197
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000198 /* selgdt 0x40, flat code segment 16 bit */
199 .word 0xffff, 0x0000
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700200 .byte 0x00, 0x9b, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for
201 * limit
202 */
Stefan Reinauer96938852015-06-18 01:23:48 -0700203
204#ifdef __x86_64__
205 /* selgdt 0x48, flat x64 code segment */
206 .word 0xffff, 0x0000
207 .byte 0x00, 0x9b, 0xaf, 0x00
208#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +0000209gdt_end:
210
Patrick Georgi546f29d2016-01-22 12:43:43 +0100211 .section ".text._start", "ax", @progbits
Stefan Reinauer96938852015-06-18 01:23:48 -0700212#ifdef __x86_64__
213SetCodeSelector:
Martin Rothe3690102016-01-06 15:21:02 -0700214 # save rsp because iret will align it to a 16 byte boundary
Patrick Georgi0302b062016-01-22 12:26:52 +0100215 mov %rsp, %rdx
Stefan Reinauer96938852015-06-18 01:23:48 -0700216
Martin Rothe3690102016-01-06 15:21:02 -0700217 # use iret to jump to a 64-bit offset in a new code segment
218 # iret will pop cs:rip, flags, then ss:rsp
Patrick Georgi0302b062016-01-22 12:26:52 +0100219 mov %ss, %ax # need to push ss..
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700220 push %rax # push ss instuction not valid in x64 mode,
221 # so use ax
Patrick Georgi0302b062016-01-22 12:26:52 +0100222 push %rsp
Martin Rothe3690102016-01-06 15:21:02 -0700223 pushfq
Patrick Georgi0302b062016-01-22 12:26:52 +0100224 push %rcx # cx is code segment selector from caller
225 mov $setCodeSelectorLongJump, %rax
226 push %rax
Stefan Reinauer96938852015-06-18 01:23:48 -0700227
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700228 # the iret will continue at next instruction, with the new cs value
229 # loaded
Martin Rothe3690102016-01-06 15:21:02 -0700230 iretq
Stefan Reinauer96938852015-06-18 01:23:48 -0700231
232setCodeSelectorLongJump:
Martin Rothe3690102016-01-06 15:21:02 -0700233 # restore rsp, it might not have been 16-byte aligned on entry
Patrick Georgi0302b062016-01-22 12:26:52 +0100234 mov %rdx, %rsp
Martin Rothe3690102016-01-06 15:21:02 -0700235 ret
Stefan Reinauer96938852015-06-18 01:23:48 -0700236
237 .previous
238.code64
239#else
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000240 .previous
Eric Biederman8ca8d762003-04-22 19:02:15 +0000241.code32
Stefan Reinauer96938852015-06-18 01:23:48 -0700242#endif