blob: 94b9bd9fa50925fd6b02b6970b438ecfb775023e [file] [log] [blame]
Patrick Georgi11f00792020-03-04 15:10:45 +01001/* SPDX-License-Identifier: GPL-2.0-only */
Martin Roth9df9e9392016-01-12 15:55:28 -07002
Stefan Reinauer5f5436f2010-04-25 20:42:02 +00003#include <cpu/x86/post_code.h>
Patrick Rudolph776da082019-10-25 08:09:33 +02004#include <arch/ram_segs.h>
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +00005
Elyes HAOUASf79f7752021-12-12 21:43:13 +01006/* Place the stack in the bss section. It's not necessary to define it in
Aaron Durbin633f1122013-02-06 15:28:40 -06007 * the linker script. */
8 .section .bss, "aw", @nobits
9.global _stack
10.global _estack
Julius Werner82d16b12020-12-30 15:51:10 -080011.global _stack_size
Aaron Durbin633f1122013-02-06 15:28:40 -060012
Arthur Heymans4d75dbd2022-11-01 23:57:24 +010013.align 16
Aaron Durbin633f1122013-02-06 15:28:40 -060014_stack:
Arthur Heymans4d75dbd2022-11-01 23:57:24 +010015.space CONFIG_STACK_SIZE
Aaron Durbin633f1122013-02-06 15:28:40 -060016_estack:
Julius Werner82d16b12020-12-30 15:51:10 -080017.set _stack_size, _estack - _stack
Aaron Durbin633f1122013-02-06 15:28:40 -060018
Julius Wernerec5e5e02014-08-20 15:29:56 -070019 .section ".text._start", "ax", @progbits
Patrick Rudolphadcf7822020-08-27 20:50:18 +020020#if ENV_X86_64
Stefan Reinauer96938852015-06-18 01:23:48 -070021 .code64
22#else
Eric Biederman8ca8d762003-04-22 19:02:15 +000023 .code32
Stefan Reinauer96938852015-06-18 01:23:48 -070024#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +000025 .globl _start
26_start:
27 cli
Patrick Rudolphadcf7822020-08-27 20:50:18 +020028#if ENV_X86_64
Patrick Rudolphd0239092021-06-11 21:24:10 +020029 movabs $gdtaddr, %rax
30 lgdt (%rax)
31#else
Eric Biederman8ca8d762003-04-22 19:02:15 +000032 lgdt %cs:gdtaddr
Patrick Rudolph776da082019-10-25 08:09:33 +020033 ljmp $RAM_CODE_SEG, $1f
Stefan Reinauer96938852015-06-18 01:23:48 -070034#endif
Patrick Rudolph776da082019-10-25 08:09:33 +0200351: movl $RAM_DATA_SEG, %eax
Eric Biederman8ca8d762003-04-22 19:02:15 +000036 movl %eax, %ds
37 movl %eax, %es
38 movl %eax, %ss
Raul E Rangelea5c3112021-09-21 10:17:24 -060039 xor %eax, %eax /* zero out the gs and fs segment index */
Eric Biederman8ca8d762003-04-22 19:02:15 +000040 movl %eax, %fs
Raul E Rangelea5c3112021-09-21 10:17:24 -060041 movl %eax, %gs /* Will be used for cpu_info */
Patrick Rudolphadcf7822020-08-27 20:50:18 +020042#if ENV_X86_64
Patrick Rudolph776da082019-10-25 08:09:33 +020043 mov $RAM_CODE_SEG64, %ecx
Elyes HAOUAS2ea751a2018-12-27 09:21:02 +010044 call SetCodeSelector
Stefan Reinauer96938852015-06-18 01:23:48 -070045#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +000046
lilacious40cb3fe2023-06-21 23:24:14 +020047 post_code(POSTCODE_ENTRY_C_START) /* post 13 */
Eric Biederman8ca8d762003-04-22 19:02:15 +000048
arch import user (historical)6ca76362005-07-06 17:17:25 +000049 cld
Eric Biederman8ca8d762003-04-22 19:02:15 +000050
Patrick Rudolphadcf7822020-08-27 20:50:18 +020051#if ENV_X86_64
Patrick Rudolphd0239092021-06-11 21:24:10 +020052 mov %rdi, %rax
53 movabs %rax, _cbmem_top_ptr
54 movabs $_stack, %rdi
Arthur Heymans7c9a0e82019-10-23 17:02:50 +020055#else
56 /* The return argument is at 0(%esp), the calling argument at 4(%esp) */
57 movl 4(%esp), %eax
58 movl %eax, _cbmem_top_ptr
Patrick Rudolphd0239092021-06-11 21:24:10 +020059 leal _stack, %edi
Arthur Heymans7c9a0e82019-10-23 17:02:50 +020060#endif
61
Patrick Rudolph1c4c7ad2021-12-03 17:32:07 +010062#if ENV_X86_64
63 /** 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 movabs $_estack, %rcx
69 sub %rdi, %rcx
70 shr $3, %rcx /* it is 64 bit aligned, right? */
71 movq $0xDEADBEEFDEADBEEF, %rax
72 rep
73 stosq
74
75 /* Set new stack with enforced alignment. */
76 movabs $_estack, %rsp
77 movq $(0xfffffffffffffff0), %rax
78 and %rax, %rsp
79#else
Aaron Durbin633f1122013-02-06 15:28:40 -060080 /** poison the stack. Code should not count on the
81 * stack being full of zeros. This stack poisoning
82 * recently uncovered a bug in the broadcast SIPI
83 * code.
84 */
Aaron Durbin633f1122013-02-06 15:28:40 -060085 movl $_estack, %ecx
86 subl %edi, %ecx
87 shrl $2, %ecx /* it is 32 bit aligned, right? */
88 movl $0xDEADBEEF, %eax
89 rep
90 stosl
91
Kyösti Mälkki2fbb6772018-05-15 19:50:20 +030092 /* Set new stack with enforced alignment. */
Eric Biederman8ca8d762003-04-22 19:02:15 +000093 movl $_estack, %esp
Arthur Heymans4d75dbd2022-11-01 23:57:24 +010094 andl $(0xfffffff0), %esp
Patrick Rudolph1c4c7ad2021-12-03 17:32:07 +010095#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +000096
Eric Biederman8ca8d762003-04-22 19:02:15 +000097 /*
98 * Now we are finished. Memory is up, data is copied and
99 * bss is cleared. Now we call the main routine and
100 * let it do the rest.
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000101 */
lilacious40cb3fe2023-06-21 23:24:14 +0200102 post_code(POSTCODE_PRE_HARDWAREMAIN) /* post 6e */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000103
Patrick Rudolph1c4c7ad2021-12-03 17:32:07 +0100104#if ENV_X86_64
105 movq $0xFFFFFFFFFFFFFFF0, %rax
106 and %rax, %rsp
107#else
Kyösti Mälkki4796c322017-03-15 08:07:22 +0200108 andl $0xFFFFFFF0, %esp
Patrick Rudolph1c4c7ad2021-12-03 17:32:07 +0100109#endif
Kyösti Mälkki4796c322017-03-15 08:07:22 +0200110
Harshit Sharma9c88fb82020-06-17 20:19:00 -0700111#if CONFIG(ASAN_IN_RAMSTAGE)
112 call asan_init
113#endif
114
Julius Wernercd49cce2019-03-05 16:53:33 -0800115#if CONFIG(GDB_WAIT)
Kyösti Mälkkif2f7f032014-04-04 15:05:28 +0300116 call gdb_hw_init
Denis 'GNUtoo' Cariklie4cece02012-06-22 15:56:37 +0200117 call gdb_stub_breakpoint
118#endif
Stefan Reinauer6adef082013-05-09 16:30:06 -0700119 call main
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000120 /* NOTREACHED */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000121.Lhlt:
lilacious40cb3fe2023-06-21 23:24:14 +0200122 post_code(POSTCODE_DEAD_CODE) /* post ee */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000123 hlt
124 jmp .Lhlt
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000125
Julius Wernercd49cce2019-03-05 16:53:33 -0800126#if CONFIG(GDB_WAIT)
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000127
128 .globl gdb_stub_breakpoint
129gdb_stub_breakpoint:
Patrick Rudolphadcf7822020-08-27 20:50:18 +0200130#if ENV_X86_64
Stefan Reinauer96938852015-06-18 01:23:48 -0700131 pop %rax /* Return address */
Arthur Heymansc5e467e2024-03-21 13:58:49 +0100132 pushfq
133 mov %cs, %rbx
134 push %rbx
Stefan Reinauer96938852015-06-18 01:23:48 -0700135 push %rax /* Return address */
136 push $0 /* No error code */
137 push $32 /* vector 32 is user defined */
138#else
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000139 popl %eax /* Return address */
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000140 pushfl
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000141 pushl %cs
142 pushl %eax /* Return address */
143 pushl $0 /* No error code */
144 pushl $32 /* vector 32 is user defined */
Stefan Reinauer96938852015-06-18 01:23:48 -0700145#endif
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000146 jmp int_hand
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000147#endif
148
Aaron Durbin4b032e42018-04-20 01:39:30 -0600149 .globl gdt, gdt_end
Raul E Rangelb2346a52021-09-22 14:56:51 -0600150 .global per_cpu_segment_descriptors, per_cpu_segment_selector
Eric Biederman8ca8d762003-04-22 19:02:15 +0000151
Eric Biederman8ca8d762003-04-22 19:02:15 +0000152gdtaddr:
Aaron Durbina146d582013-02-08 16:56:51 -0600153 .word gdt_end - gdt - 1
Patrick Rudolphadcf7822020-08-27 20:50:18 +0200154#if ENV_X86_64
Stefan Reinauer96938852015-06-18 01:23:48 -0700155 .quad gdt
156#else
Li-Ta Lof84926e2004-11-04 18:36:06 +0000157 .long gdt /* we know the offset */
Stefan Reinauer96938852015-06-18 01:23:48 -0700158#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +0000159
Raul E Rangelb2346a52021-09-22 14:56:51 -0600160 .data
Li-Ta Lof84926e2004-11-04 18:36:06 +0000161
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000162 /* This is the gdt for GCC part of coreboot.
Arthur Heymans1cb9cd52019-11-28 16:05:08 +0100163 * It is different from the gdt in ASM part of coreboot
Kyösti Mälkki97b76f72020-11-19 16:41:28 +0200164 * which is defined in gdt_init.S
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000165 *
166 * When the machine is initially started, we use a very simple
Kyösti Mälkki97b76f72020-11-19 16:41:28 +0200167 * gdt from ROM (that in gdt_init.S) which only contains those
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000168 * entries we need for protected mode.
169 *
170 * When we're executing code from RAM, we want to do more complex
Elyes HAOUAS777ea892016-07-29 07:40:41 +0200171 * stuff, like initializing PCI option ROMs in real mode, or doing
172 * a resume from a suspend to RAM.
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000173 */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000174gdt:
Li-Ta Lof84926e2004-11-04 18:36:06 +0000175 /* selgdt 0, unused */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000176 .word 0x0000, 0x0000 /* dummy */
177 .byte 0x00, 0x00, 0x00, 0x00
178
Li-Ta Lof84926e2004-11-04 18:36:06 +0000179 /* selgdt 8, unused */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000180 .word 0x0000, 0x0000 /* dummy */
181 .byte 0x00, 0x00, 0x00, 0x00
182
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000183 /* selgdt 0x10, flat code segment */
184 .word 0xffff, 0x0000
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700185 .byte 0x00, 0x9b, 0xcf, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for
186 * limit
187 */
Li-Ta Lof84926e2004-11-04 18:36:06 +0000188
189 /* selgdt 0x18, flat data segment */
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000190 .word 0xffff, 0x0000
Patrick Rudolphadcf7822020-08-27 20:50:18 +0200191#if ENV_X86_64
Stefan Reinauer96938852015-06-18 01:23:48 -0700192 .byte 0x00, 0x92, 0xcf, 0x00
193#else
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000194 .byte 0x00, 0x93, 0xcf, 0x00
Stefan Reinauer96938852015-06-18 01:23:48 -0700195#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +0000196
Li-Ta Lof84926e2004-11-04 18:36:06 +0000197 /* selgdt 0x20, unused */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000198 .word 0x0000, 0x0000 /* dummy */
199 .byte 0x00, 0x00, 0x00, 0x00
200
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000201 /* The next two entries are used for executing VGA option ROMs */
202
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000203 /* selgdt 0x28 16 bit 64k code at 0x00000000 */
Elyes HAOUAS2ea751a2018-12-27 09:21:02 +0100204 .word 0xffff, 0x0000
205 .byte 0, 0x9a, 0, 0
Stefan Reinauerf8a5c6e2009-05-29 13:08:27 +0000206
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000207 /* selgdt 0x30 16 bit 64k data at 0x00000000 */
Elyes HAOUAS2ea751a2018-12-27 09:21:02 +0100208 .word 0xffff, 0x0000
209 .byte 0, 0x92, 0, 0
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000210
211 /* The next two entries are used for ACPI S3 RESUME */
212
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000213 /* selgdt 0x38, flat data segment 16 bit */
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000214 .word 0x0000, 0x0000 /* dummy */
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700215 .byte 0x00, 0x93, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for
216 * limit
217 */
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000218
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000219 /* selgdt 0x40, flat code segment 16 bit */
220 .word 0xffff, 0x0000
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700221 .byte 0x00, 0x9b, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for
222 * limit
223 */
Stefan Reinauer96938852015-06-18 01:23:48 -0700224
Patrick Rudolphadcf7822020-08-27 20:50:18 +0200225#if ENV_X86_64
Stefan Reinauer96938852015-06-18 01:23:48 -0700226 /* selgdt 0x48, flat x64 code segment */
227 .word 0xffff, 0x0000
228 .byte 0x00, 0x9b, 0xaf, 0x00
229#endif
Raul E Rangelb2346a52021-09-22 14:56:51 -0600230per_cpu_segment_descriptors:
231 .rept CONFIG_MAX_CPUS
232 /* flat data segment */
233 .word 0xffff, 0x0000
234#if ENV_X86_64
235 .byte 0x00, 0x92, 0xcf, 0x00
236#else
237 .byte 0x00, 0x93, 0xcf, 0x00
238#endif
239 .endr
Eric Biederman8ca8d762003-04-22 19:02:15 +0000240gdt_end:
241
Raul E Rangelb2346a52021-09-22 14:56:51 -0600242/* Segment selector pointing to the first per_cpu_segment_descriptor. */
243per_cpu_segment_selector:
244 .long per_cpu_segment_descriptors - gdt
Raul E Rangelb2346a52021-09-22 14:56:51 -0600245
Patrick Georgi546f29d2016-01-22 12:43:43 +0100246 .section ".text._start", "ax", @progbits
Patrick Rudolphadcf7822020-08-27 20:50:18 +0200247#if ENV_X86_64
Stefan Reinauer96938852015-06-18 01:23:48 -0700248SetCodeSelector:
Martin Rothe3690102016-01-06 15:21:02 -0700249 # save rsp because iret will align it to a 16 byte boundary
Patrick Georgi0302b062016-01-22 12:26:52 +0100250 mov %rsp, %rdx
Stefan Reinauer96938852015-06-18 01:23:48 -0700251
Martin Rothe3690102016-01-06 15:21:02 -0700252 # use iret to jump to a 64-bit offset in a new code segment
253 # iret will pop cs:rip, flags, then ss:rsp
Patrick Georgi0302b062016-01-22 12:26:52 +0100254 mov %ss, %ax # need to push ss..
Martin Roth0949e732021-10-01 14:28:22 -0600255 push %rax # push ss instruction not valid in x64 mode,
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700256 # so use ax
Patrick Georgi0302b062016-01-22 12:26:52 +0100257 push %rsp
Martin Rothe3690102016-01-06 15:21:02 -0700258 pushfq
Patrick Georgi0302b062016-01-22 12:26:52 +0100259 push %rcx # cx is code segment selector from caller
Patrick Rudolphd0239092021-06-11 21:24:10 +0200260 movabs $setCodeSelectorLongJump, %rax
Patrick Georgi0302b062016-01-22 12:26:52 +0100261 push %rax
Stefan Reinauer96938852015-06-18 01:23:48 -0700262
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700263 # the iret will continue at next instruction, with the new cs value
264 # loaded
Martin Rothe3690102016-01-06 15:21:02 -0700265 iretq
Stefan Reinauer96938852015-06-18 01:23:48 -0700266
267setCodeSelectorLongJump:
Martin Rothe3690102016-01-06 15:21:02 -0700268 # restore rsp, it might not have been 16-byte aligned on entry
Patrick Georgi0302b062016-01-22 12:26:52 +0100269 mov %rdx, %rsp
Martin Rothe3690102016-01-06 15:21:02 -0700270 ret
Stefan Reinauer96938852015-06-18 01:23:48 -0700271#endif