blob: 43d78020e1d1bc118eed4f31584784386e285f92 [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>
Patrick Rudolph776da082019-10-25 08:09:33 +020015#include <arch/ram_segs.h>
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +000016
Aaron Durbin633f1122013-02-06 15:28:40 -060017/* Place the stack in the bss section. It's not necessary to define it in the
18 * the linker script. */
19 .section .bss, "aw", @nobits
20.global _stack
21.global _estack
22
Kyösti Mälkki2fbb6772018-05-15 19:50:20 +030023/* Stack alignment is not enforced with rmodule loader, reserve one
24 * extra CPU such that alignment can be enforced on entry. */
Aaron Durbin633f1122013-02-06 15:28:40 -060025.align CONFIG_STACK_SIZE
26_stack:
Kyösti Mälkki2fbb6772018-05-15 19:50:20 +030027.space (CONFIG_MAX_CPUS+1)*CONFIG_STACK_SIZE
Aaron Durbin633f1122013-02-06 15:28:40 -060028_estack:
Julius Wernercd49cce2019-03-05 16:53:33 -080029#if CONFIG(COOP_MULTITASKING)
Aaron Durbin38c326d2013-05-06 12:22:23 -050030.global thread_stacks
31thread_stacks:
32.space CONFIG_STACK_SIZE*CONFIG_NUM_THREADS
33#endif
Aaron Durbin633f1122013-02-06 15:28:40 -060034
Julius Wernerec5e5e02014-08-20 15:29:56 -070035 .section ".text._start", "ax", @progbits
Stefan Reinauer96938852015-06-18 01:23:48 -070036#ifdef __x86_64__
37 .code64
38#else
Eric Biederman8ca8d762003-04-22 19:02:15 +000039 .code32
Stefan Reinauer96938852015-06-18 01:23:48 -070040#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +000041 .globl _start
42_start:
43 cli
44 lgdt %cs:gdtaddr
Stefan Reinauer96938852015-06-18 01:23:48 -070045#ifndef __x86_64__
Patrick Rudolph776da082019-10-25 08:09:33 +020046 ljmp $RAM_CODE_SEG, $1f
Stefan Reinauer96938852015-06-18 01:23:48 -070047#endif
Patrick Rudolph776da082019-10-25 08:09:33 +0200481: movl $RAM_DATA_SEG, %eax
Eric Biederman8ca8d762003-04-22 19:02:15 +000049 movl %eax, %ds
50 movl %eax, %es
51 movl %eax, %ss
52 movl %eax, %fs
53 movl %eax, %gs
Stefan Reinauer96938852015-06-18 01:23:48 -070054#ifdef __x86_64__
Patrick Rudolph776da082019-10-25 08:09:33 +020055 mov $RAM_CODE_SEG64, %ecx
Elyes HAOUAS2ea751a2018-12-27 09:21:02 +010056 call SetCodeSelector
Stefan Reinauer96938852015-06-18 01:23:48 -070057#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +000058
Alexandru Gagniuc5005bb062011-04-11 20:17:22 +000059 post_code(POST_ENTRY_C_START) /* post 13 */
Eric Biederman8ca8d762003-04-22 19:02:15 +000060
arch import user (historical)6ca76362005-07-06 17:17:25 +000061 cld
Eric Biederman8ca8d762003-04-22 19:02:15 +000062
Aaron Durbin633f1122013-02-06 15:28:40 -060063 /** poison the stack. Code should not count on the
64 * stack being full of zeros. This stack poisoning
65 * recently uncovered a bug in the broadcast SIPI
66 * code.
67 */
68 leal _stack, %edi
69 movl $_estack, %ecx
70 subl %edi, %ecx
71 shrl $2, %ecx /* it is 32 bit aligned, right? */
72 movl $0xDEADBEEF, %eax
73 rep
74 stosl
75
Kyösti Mälkki2fbb6772018-05-15 19:50:20 +030076 /* Set new stack with enforced alignment. */
Eric Biederman8ca8d762003-04-22 19:02:15 +000077 movl $_estack, %esp
Kyösti Mälkki2fbb6772018-05-15 19:50:20 +030078 andl $(~(CONFIG_STACK_SIZE-1)), %esp
Eric Biederman8ca8d762003-04-22 19:02:15 +000079
Julius Wernercd49cce2019-03-05 16:53:33 -080080#if CONFIG(COOP_MULTITASKING)
Aaron Durbin38c326d2013-05-06 12:22:23 -050081 /* Push the thread pointer. */
Stefan Reinauer96938852015-06-18 01:23:48 -070082 push $0
Aaron Durbin38c326d2013-05-06 12:22:23 -050083#endif
Elyes HAOUAS777ea892016-07-29 07:40:41 +020084 /* Push the CPU index and struct CPU */
Stefan Reinauer96938852015-06-18 01:23:48 -070085 push $0
86 push $0
Eric Biederman8ca8d762003-04-22 19:02:15 +000087
Eric Biederman8ca8d762003-04-22 19:02:15 +000088 /*
89 * Now we are finished. Memory is up, data is copied and
90 * bss is cleared. Now we call the main routine and
91 * let it do the rest.
Stefan Reinauer607cdf62010-04-26 12:08:51 +000092 */
Alexandru Gagniuc5005bb062011-04-11 20:17:22 +000093 post_code(POST_PRE_HARDWAREMAIN) /* post fe */
Eric Biederman8ca8d762003-04-22 19:02:15 +000094
Kyösti Mälkki4796c322017-03-15 08:07:22 +020095 andl $0xFFFFFFF0, %esp
96
Julius Wernercd49cce2019-03-05 16:53:33 -080097#if CONFIG(GDB_WAIT)
Kyösti Mälkkif2f7f032014-04-04 15:05:28 +030098 call gdb_hw_init
Denis 'GNUtoo' Cariklie4cece02012-06-22 15:56:37 +020099 call gdb_stub_breakpoint
100#endif
Stefan Reinauer6adef082013-05-09 16:30:06 -0700101 call main
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000102 /* NOTREACHED */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000103.Lhlt:
Alexandru Gagniuc5005bb062011-04-11 20:17:22 +0000104 post_code(POST_DEAD_CODE) /* post ee */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000105 hlt
106 jmp .Lhlt
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000107
Julius Wernercd49cce2019-03-05 16:53:33 -0800108#if CONFIG(GDB_WAIT)
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000109
110 .globl gdb_stub_breakpoint
111gdb_stub_breakpoint:
Stefan Reinauer96938852015-06-18 01:23:48 -0700112#ifdef __x86_64__
113 pop %rax /* Return address */
114 pushfl
115 push %cs
116 push %rax /* Return address */
117 push $0 /* No error code */
118 push $32 /* vector 32 is user defined */
119#else
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000120 popl %eax /* Return address */
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000121 pushfl
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000122 pushl %cs
123 pushl %eax /* Return address */
124 pushl $0 /* No error code */
125 pushl $32 /* vector 32 is user defined */
Stefan Reinauer96938852015-06-18 01:23:48 -0700126#endif
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000127 jmp int_hand
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000128#endif
129
Aaron Durbin4b032e42018-04-20 01:39:30 -0600130 .globl gdt, gdt_end
Eric Biederman8ca8d762003-04-22 19:02:15 +0000131
Eric Biederman8ca8d762003-04-22 19:02:15 +0000132gdtaddr:
Aaron Durbina146d582013-02-08 16:56:51 -0600133 .word gdt_end - gdt - 1
Stefan Reinauer96938852015-06-18 01:23:48 -0700134#ifdef __x86_64__
135 .quad gdt
136#else
Li-Ta Lof84926e2004-11-04 18:36:06 +0000137 .long gdt /* we know the offset */
Stefan Reinauer96938852015-06-18 01:23:48 -0700138#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +0000139
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000140 .data
Li-Ta Lof84926e2004-11-04 18:36:06 +0000141
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000142 /* This is the gdt for GCC part of coreboot.
143 * It is different from the gdt in ROMCC/ASM part of coreboot
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000144 * which is defined in entry32.inc
145 *
146 * When the machine is initially started, we use a very simple
Elyes HAOUAS777ea892016-07-29 07:40:41 +0200147 * gdt from ROM (that in entry32.inc) which only contains those
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000148 * entries we need for protected mode.
149 *
150 * When we're executing code from RAM, we want to do more complex
Elyes HAOUAS777ea892016-07-29 07:40:41 +0200151 * stuff, like initializing PCI option ROMs in real mode, or doing
152 * a resume from a suspend to RAM.
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000153 */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000154gdt:
Li-Ta Lof84926e2004-11-04 18:36:06 +0000155 /* selgdt 0, unused */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000156 .word 0x0000, 0x0000 /* dummy */
157 .byte 0x00, 0x00, 0x00, 0x00
158
Li-Ta Lof84926e2004-11-04 18:36:06 +0000159 /* selgdt 8, unused */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000160 .word 0x0000, 0x0000 /* dummy */
161 .byte 0x00, 0x00, 0x00, 0x00
162
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000163 /* selgdt 0x10, flat code segment */
164 .word 0xffff, 0x0000
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700165 .byte 0x00, 0x9b, 0xcf, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for
166 * limit
167 */
Li-Ta Lof84926e2004-11-04 18:36:06 +0000168
169 /* selgdt 0x18, flat data segment */
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000170 .word 0xffff, 0x0000
Stefan Reinauer96938852015-06-18 01:23:48 -0700171#ifdef __x86_64__
172 .byte 0x00, 0x92, 0xcf, 0x00
173#else
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000174 .byte 0x00, 0x93, 0xcf, 0x00
Stefan Reinauer96938852015-06-18 01:23:48 -0700175#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +0000176
Li-Ta Lof84926e2004-11-04 18:36:06 +0000177 /* selgdt 0x20, unused */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000178 .word 0x0000, 0x0000 /* dummy */
179 .byte 0x00, 0x00, 0x00, 0x00
180
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000181 /* The next two entries are used for executing VGA option ROMs */
182
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000183 /* selgdt 0x28 16 bit 64k code at 0x00000000 */
Elyes HAOUAS2ea751a2018-12-27 09:21:02 +0100184 .word 0xffff, 0x0000
185 .byte 0, 0x9a, 0, 0
Stefan Reinauerf8a5c6e2009-05-29 13:08:27 +0000186
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000187 /* selgdt 0x30 16 bit 64k data at 0x00000000 */
Elyes HAOUAS2ea751a2018-12-27 09:21:02 +0100188 .word 0xffff, 0x0000
189 .byte 0, 0x92, 0, 0
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000190
191 /* The next two entries are used for ACPI S3 RESUME */
192
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000193 /* selgdt 0x38, flat data segment 16 bit */
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000194 .word 0x0000, 0x0000 /* dummy */
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700195 .byte 0x00, 0x93, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for
196 * limit
197 */
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000198
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000199 /* selgdt 0x40, flat code segment 16 bit */
200 .word 0xffff, 0x0000
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700201 .byte 0x00, 0x9b, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for
202 * limit
203 */
Stefan Reinauer96938852015-06-18 01:23:48 -0700204
205#ifdef __x86_64__
206 /* selgdt 0x48, flat x64 code segment */
207 .word 0xffff, 0x0000
208 .byte 0x00, 0x9b, 0xaf, 0x00
209#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +0000210gdt_end:
211
Patrick Georgi546f29d2016-01-22 12:43:43 +0100212 .section ".text._start", "ax", @progbits
Stefan Reinauer96938852015-06-18 01:23:48 -0700213#ifdef __x86_64__
214SetCodeSelector:
Martin Rothe3690102016-01-06 15:21:02 -0700215 # save rsp because iret will align it to a 16 byte boundary
Patrick Georgi0302b062016-01-22 12:26:52 +0100216 mov %rsp, %rdx
Stefan Reinauer96938852015-06-18 01:23:48 -0700217
Martin Rothe3690102016-01-06 15:21:02 -0700218 # use iret to jump to a 64-bit offset in a new code segment
219 # iret will pop cs:rip, flags, then ss:rsp
Patrick Georgi0302b062016-01-22 12:26:52 +0100220 mov %ss, %ax # need to push ss..
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700221 push %rax # push ss instuction not valid in x64 mode,
222 # so use ax
Patrick Georgi0302b062016-01-22 12:26:52 +0100223 push %rsp
Martin Rothe3690102016-01-06 15:21:02 -0700224 pushfq
Patrick Georgi0302b062016-01-22 12:26:52 +0100225 push %rcx # cx is code segment selector from caller
226 mov $setCodeSelectorLongJump, %rax
227 push %rax
Stefan Reinauer96938852015-06-18 01:23:48 -0700228
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700229 # the iret will continue at next instruction, with the new cs value
230 # loaded
Martin Rothe3690102016-01-06 15:21:02 -0700231 iretq
Stefan Reinauer96938852015-06-18 01:23:48 -0700232
233setCodeSelectorLongJump:
Martin Rothe3690102016-01-06 15:21:02 -0700234 # restore rsp, it might not have been 16-byte aligned on entry
Patrick Georgi0302b062016-01-22 12:26:52 +0100235 mov %rdx, %rsp
Martin Rothe3690102016-01-06 15:21:02 -0700236 ret
Stefan Reinauer96938852015-06-18 01:23:48 -0700237
238 .previous
239.code64
240#else
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000241 .previous
Eric Biederman8ca8d762003-04-22 19:02:15 +0000242.code32
Stefan Reinauer96938852015-06-18 01:23:48 -0700243#endif