blob: c3fdfd9f17697e2568a82fe26b6a726076da85e5 [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
Raul E Rangelda68c9d2021-09-22 10:45:51 -06003#include <cpu/x86/cpu_info.S.inc>
Stefan Reinauer5f5436f2010-04-25 20:42:02 +00004#include <cpu/x86/post_code.h>
Patrick Rudolph776da082019-10-25 08:09:33 +02005#include <arch/ram_segs.h>
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +00006
Aaron Durbin633f1122013-02-06 15:28:40 -06007/* Place the stack in the bss section. It's not necessary to define it in the
8 * the linker script. */
9 .section .bss, "aw", @nobits
10.global _stack
11.global _estack
Julius Werner82d16b12020-12-30 15:51:10 -080012.global _stack_size
Aaron Durbin633f1122013-02-06 15:28:40 -060013
Kyösti Mälkki2fbb6772018-05-15 19:50:20 +030014/* Stack alignment is not enforced with rmodule loader, reserve one
15 * extra CPU such that alignment can be enforced on entry. */
Aaron Durbin633f1122013-02-06 15:28:40 -060016.align CONFIG_STACK_SIZE
17_stack:
Kyösti Mälkki2fbb6772018-05-15 19:50:20 +030018.space (CONFIG_MAX_CPUS+1)*CONFIG_STACK_SIZE
Aaron Durbin633f1122013-02-06 15:28:40 -060019_estack:
Julius Werner82d16b12020-12-30 15:51:10 -080020.set _stack_size, _estack - _stack
Aaron Durbin633f1122013-02-06 15:28:40 -060021
Julius Wernerec5e5e02014-08-20 15:29:56 -070022 .section ".text._start", "ax", @progbits
Patrick Rudolphadcf7822020-08-27 20:50:18 +020023#if ENV_X86_64
Stefan Reinauer96938852015-06-18 01:23:48 -070024 .code64
25#else
Eric Biederman8ca8d762003-04-22 19:02:15 +000026 .code32
Stefan Reinauer96938852015-06-18 01:23:48 -070027#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +000028 .globl _start
29_start:
30 cli
Patrick Rudolphadcf7822020-08-27 20:50:18 +020031#if ENV_X86_64
Patrick Rudolphd0239092021-06-11 21:24:10 +020032 movabs $gdtaddr, %rax
33 lgdt (%rax)
34#else
Eric Biederman8ca8d762003-04-22 19:02:15 +000035 lgdt %cs:gdtaddr
Patrick Rudolph776da082019-10-25 08:09:33 +020036 ljmp $RAM_CODE_SEG, $1f
Stefan Reinauer96938852015-06-18 01:23:48 -070037#endif
Patrick Rudolph776da082019-10-25 08:09:33 +0200381: movl $RAM_DATA_SEG, %eax
Eric Biederman8ca8d762003-04-22 19:02:15 +000039 movl %eax, %ds
40 movl %eax, %es
41 movl %eax, %ss
Raul E Rangelea5c3112021-09-21 10:17:24 -060042 xor %eax, %eax /* zero out the gs and fs segment index */
Eric Biederman8ca8d762003-04-22 19:02:15 +000043 movl %eax, %fs
Raul E Rangelea5c3112021-09-21 10:17:24 -060044 movl %eax, %gs /* Will be used for cpu_info */
Patrick Rudolphadcf7822020-08-27 20:50:18 +020045#if ENV_X86_64
Patrick Rudolph776da082019-10-25 08:09:33 +020046 mov $RAM_CODE_SEG64, %ecx
Elyes HAOUAS2ea751a2018-12-27 09:21:02 +010047 call SetCodeSelector
Stefan Reinauer96938852015-06-18 01:23:48 -070048#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +000049
Alexandru Gagniuc5005bb062011-04-11 20:17:22 +000050 post_code(POST_ENTRY_C_START) /* post 13 */
Eric Biederman8ca8d762003-04-22 19:02:15 +000051
arch import user (historical)6ca76362005-07-06 17:17:25 +000052 cld
Eric Biederman8ca8d762003-04-22 19:02:15 +000053
Patrick Rudolphadcf7822020-08-27 20:50:18 +020054#if ENV_X86_64
Patrick Rudolphd0239092021-06-11 21:24:10 +020055 mov %rdi, %rax
56 movabs %rax, _cbmem_top_ptr
57 movabs $_stack, %rdi
Arthur Heymans7c9a0e82019-10-23 17:02:50 +020058#else
59 /* The return argument is at 0(%esp), the calling argument at 4(%esp) */
60 movl 4(%esp), %eax
61 movl %eax, _cbmem_top_ptr
Patrick Rudolphd0239092021-06-11 21:24:10 +020062 leal _stack, %edi
Arthur Heymans7c9a0e82019-10-23 17:02:50 +020063#endif
64
Aaron Durbin633f1122013-02-06 15:28:40 -060065 /** poison the stack. Code should not count on the
66 * stack being full of zeros. This stack poisoning
67 * recently uncovered a bug in the broadcast SIPI
68 * code.
69 */
Aaron Durbin633f1122013-02-06 15:28:40 -060070 movl $_estack, %ecx
71 subl %edi, %ecx
72 shrl $2, %ecx /* it is 32 bit aligned, right? */
73 movl $0xDEADBEEF, %eax
74 rep
75 stosl
76
Kyösti Mälkki2fbb6772018-05-15 19:50:20 +030077 /* Set new stack with enforced alignment. */
Eric Biederman8ca8d762003-04-22 19:02:15 +000078 movl $_estack, %esp
Kyösti Mälkki2fbb6772018-05-15 19:50:20 +030079 andl $(~(CONFIG_STACK_SIZE-1)), %esp
Eric Biederman8ca8d762003-04-22 19:02:15 +000080
Raul E Rangelda68c9d2021-09-22 10:45:51 -060081 push_cpu_info
Eric Biederman8ca8d762003-04-22 19:02:15 +000082
Raul E Rangelb2346a52021-09-22 14:56:51 -060083#if CONFIG(CPU_INFO_V2)
84 /* Allocate the per_cpu_segment_data on the stack */
85 push_per_cpu_segment_data
86
87 /*
88 * Update the BSP's per_cpu_segment_descriptor to point to the
89 * per_cpu_segment_data that was allocated on the stack.
90 */
91 set_segment_descriptor_base $per_cpu_segment_descriptors, %esp
92
Raul E Rangel1eae39f2021-10-08 13:10:38 -060093 mov $per_cpu_segment_selector, %eax
94 movl (%eax), %eax
Raul E Rangelb2346a52021-09-22 14:56:51 -060095 mov %eax, %gs
96#endif
97
Eric Biederman8ca8d762003-04-22 19:02:15 +000098 /*
99 * Now we are finished. Memory is up, data is copied and
100 * bss is cleared. Now we call the main routine and
101 * let it do the rest.
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000102 */
Subrata Banik38e4a2d2021-05-05 19:34:07 +0530103 post_code(POST_PRE_HARDWAREMAIN) /* post 6e */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000104
Kyösti Mälkki4796c322017-03-15 08:07:22 +0200105 andl $0xFFFFFFF0, %esp
106
Harshit Sharma9c88fb82020-06-17 20:19:00 -0700107#if CONFIG(ASAN_IN_RAMSTAGE)
108 call asan_init
109#endif
110
Julius Wernercd49cce2019-03-05 16:53:33 -0800111#if CONFIG(GDB_WAIT)
Kyösti Mälkkif2f7f032014-04-04 15:05:28 +0300112 call gdb_hw_init
Denis 'GNUtoo' Cariklie4cece02012-06-22 15:56:37 +0200113 call gdb_stub_breakpoint
114#endif
Stefan Reinauer6adef082013-05-09 16:30:06 -0700115 call main
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000116 /* NOTREACHED */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000117.Lhlt:
Alexandru Gagniuc5005bb062011-04-11 20:17:22 +0000118 post_code(POST_DEAD_CODE) /* post ee */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000119 hlt
120 jmp .Lhlt
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000121
Julius Wernercd49cce2019-03-05 16:53:33 -0800122#if CONFIG(GDB_WAIT)
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000123
124 .globl gdb_stub_breakpoint
125gdb_stub_breakpoint:
Patrick Rudolphadcf7822020-08-27 20:50:18 +0200126#if ENV_X86_64
Stefan Reinauer96938852015-06-18 01:23:48 -0700127 pop %rax /* Return address */
128 pushfl
129 push %cs
130 push %rax /* Return address */
131 push $0 /* No error code */
132 push $32 /* vector 32 is user defined */
133#else
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000134 popl %eax /* Return address */
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000135 pushfl
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000136 pushl %cs
137 pushl %eax /* Return address */
138 pushl $0 /* No error code */
139 pushl $32 /* vector 32 is user defined */
Stefan Reinauer96938852015-06-18 01:23:48 -0700140#endif
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000141 jmp int_hand
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000142#endif
143
Aaron Durbin4b032e42018-04-20 01:39:30 -0600144 .globl gdt, gdt_end
Raul E Rangelb2346a52021-09-22 14:56:51 -0600145 .global per_cpu_segment_descriptors, per_cpu_segment_selector
Eric Biederman8ca8d762003-04-22 19:02:15 +0000146
Eric Biederman8ca8d762003-04-22 19:02:15 +0000147gdtaddr:
Aaron Durbina146d582013-02-08 16:56:51 -0600148 .word gdt_end - gdt - 1
Patrick Rudolphadcf7822020-08-27 20:50:18 +0200149#if ENV_X86_64
Stefan Reinauer96938852015-06-18 01:23:48 -0700150 .quad gdt
151#else
Li-Ta Lof84926e2004-11-04 18:36:06 +0000152 .long gdt /* we know the offset */
Stefan Reinauer96938852015-06-18 01:23:48 -0700153#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +0000154
Raul E Rangelb2346a52021-09-22 14:56:51 -0600155 .data
Li-Ta Lof84926e2004-11-04 18:36:06 +0000156
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000157 /* This is the gdt for GCC part of coreboot.
Arthur Heymans1cb9cd52019-11-28 16:05:08 +0100158 * It is different from the gdt in ASM part of coreboot
Kyösti Mälkki97b76f72020-11-19 16:41:28 +0200159 * which is defined in gdt_init.S
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000160 *
161 * When the machine is initially started, we use a very simple
Kyösti Mälkki97b76f72020-11-19 16:41:28 +0200162 * gdt from ROM (that in gdt_init.S) which only contains those
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000163 * entries we need for protected mode.
164 *
165 * When we're executing code from RAM, we want to do more complex
Elyes HAOUAS777ea892016-07-29 07:40:41 +0200166 * stuff, like initializing PCI option ROMs in real mode, or doing
167 * a resume from a suspend to RAM.
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000168 */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000169gdt:
Li-Ta Lof84926e2004-11-04 18:36:06 +0000170 /* selgdt 0, unused */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000171 .word 0x0000, 0x0000 /* dummy */
172 .byte 0x00, 0x00, 0x00, 0x00
173
Li-Ta Lof84926e2004-11-04 18:36:06 +0000174 /* selgdt 8, unused */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000175 .word 0x0000, 0x0000 /* dummy */
176 .byte 0x00, 0x00, 0x00, 0x00
177
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000178 /* selgdt 0x10, flat code segment */
179 .word 0xffff, 0x0000
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700180 .byte 0x00, 0x9b, 0xcf, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for
181 * limit
182 */
Li-Ta Lof84926e2004-11-04 18:36:06 +0000183
184 /* selgdt 0x18, flat data segment */
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000185 .word 0xffff, 0x0000
Patrick Rudolphadcf7822020-08-27 20:50:18 +0200186#if ENV_X86_64
Stefan Reinauer96938852015-06-18 01:23:48 -0700187 .byte 0x00, 0x92, 0xcf, 0x00
188#else
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000189 .byte 0x00, 0x93, 0xcf, 0x00
Stefan Reinauer96938852015-06-18 01:23:48 -0700190#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +0000191
Li-Ta Lof84926e2004-11-04 18:36:06 +0000192 /* selgdt 0x20, unused */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000193 .word 0x0000, 0x0000 /* dummy */
194 .byte 0x00, 0x00, 0x00, 0x00
195
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000196 /* The next two entries are used for executing VGA option ROMs */
197
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000198 /* selgdt 0x28 16 bit 64k code at 0x00000000 */
Elyes HAOUAS2ea751a2018-12-27 09:21:02 +0100199 .word 0xffff, 0x0000
200 .byte 0, 0x9a, 0, 0
Stefan Reinauerf8a5c6e2009-05-29 13:08:27 +0000201
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000202 /* selgdt 0x30 16 bit 64k data at 0x00000000 */
Elyes HAOUAS2ea751a2018-12-27 09:21:02 +0100203 .word 0xffff, 0x0000
204 .byte 0, 0x92, 0, 0
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000205
206 /* The next two entries are used for ACPI S3 RESUME */
207
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000208 /* selgdt 0x38, flat data segment 16 bit */
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000209 .word 0x0000, 0x0000 /* dummy */
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700210 .byte 0x00, 0x93, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for
211 * limit
212 */
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000213
Stefan Reinauer607cdf62010-04-26 12:08:51 +0000214 /* selgdt 0x40, flat code segment 16 bit */
215 .word 0xffff, 0x0000
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700216 .byte 0x00, 0x9b, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for
217 * limit
218 */
Stefan Reinauer96938852015-06-18 01:23:48 -0700219
Patrick Rudolphadcf7822020-08-27 20:50:18 +0200220#if ENV_X86_64
Stefan Reinauer96938852015-06-18 01:23:48 -0700221 /* selgdt 0x48, flat x64 code segment */
222 .word 0xffff, 0x0000
223 .byte 0x00, 0x9b, 0xaf, 0x00
224#endif
Raul E Rangelb2346a52021-09-22 14:56:51 -0600225#if CONFIG(CPU_INFO_V2)
226per_cpu_segment_descriptors:
227 .rept CONFIG_MAX_CPUS
228 /* flat data segment */
229 .word 0xffff, 0x0000
230#if ENV_X86_64
231 .byte 0x00, 0x92, 0xcf, 0x00
232#else
233 .byte 0x00, 0x93, 0xcf, 0x00
234#endif
235 .endr
236#endif /* CPU_INFO_V2 */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000237gdt_end:
238
Raul E Rangelb2346a52021-09-22 14:56:51 -0600239#if CONFIG(CPU_INFO_V2)
240/* Segment selector pointing to the first per_cpu_segment_descriptor. */
241per_cpu_segment_selector:
242 .long per_cpu_segment_descriptors - gdt
243#endif /* CPU_INFO_V2 */
244
Patrick Georgi546f29d2016-01-22 12:43:43 +0100245 .section ".text._start", "ax", @progbits
Patrick Rudolphadcf7822020-08-27 20:50:18 +0200246#if ENV_X86_64
Stefan Reinauer96938852015-06-18 01:23:48 -0700247SetCodeSelector:
Martin Rothe3690102016-01-06 15:21:02 -0700248 # save rsp because iret will align it to a 16 byte boundary
Patrick Georgi0302b062016-01-22 12:26:52 +0100249 mov %rsp, %rdx
Stefan Reinauer96938852015-06-18 01:23:48 -0700250
Martin Rothe3690102016-01-06 15:21:02 -0700251 # use iret to jump to a 64-bit offset in a new code segment
252 # iret will pop cs:rip, flags, then ss:rsp
Patrick Georgi0302b062016-01-22 12:26:52 +0100253 mov %ss, %ax # need to push ss..
Martin Roth0949e732021-10-01 14:28:22 -0600254 push %rax # push ss instruction not valid in x64 mode,
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700255 # so use ax
Patrick Georgi0302b062016-01-22 12:26:52 +0100256 push %rsp
Martin Rothe3690102016-01-06 15:21:02 -0700257 pushfq
Patrick Georgi0302b062016-01-22 12:26:52 +0100258 push %rcx # cx is code segment selector from caller
Patrick Rudolphd0239092021-06-11 21:24:10 +0200259 movabs $setCodeSelectorLongJump, %rax
Patrick Georgi0302b062016-01-22 12:26:52 +0100260 push %rax
Stefan Reinauer96938852015-06-18 01:23:48 -0700261
Lee Leahy6f80ccc2017-03-16 15:18:22 -0700262 # the iret will continue at next instruction, with the new cs value
263 # loaded
Martin Rothe3690102016-01-06 15:21:02 -0700264 iretq
Stefan Reinauer96938852015-06-18 01:23:48 -0700265
266setCodeSelectorLongJump:
Martin Rothe3690102016-01-06 15:21:02 -0700267 # restore rsp, it might not have been 16-byte aligned on entry
Patrick Georgi0302b062016-01-22 12:26:52 +0100268 mov %rdx, %rsp
Martin Rothe3690102016-01-06 15:21:02 -0700269 ret
Stefan Reinauer96938852015-06-18 01:23:48 -0700270#endif