1/*
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright © 2021 Mike Haertel and Keith Packard
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above
14 *    copyright notice, this list of conditions and the following
15 *    disclaimer in the documentation and/or other materials provided
16 *    with the distribution.
17 *
18 * 3. Neither the name of the copyright holder nor the names of its
19 *    contributors may be used to endorse or promote products derived
20 *    from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33 * OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36#include <picolibc.h>
37
38#ifndef CONSTRUCTORS
39#define CONSTRUCTORS 1
40#endif
41
42	.text
43	.section	.text.init.enter
44	.globl	_start
45	.type	start, @function
46_start:
47	.code16
48	cs
49	lgdtl	gdt_desc - _start + 0x10
50
51	# enable sse and pae
52	mov	$0x620, %eax
53	mov	%eax, %cr4
54
55	# enable long mode by setting EFER
56	mov	$0x100, %eax
57	xor	%edx, %edx
58	mov	$0xc0000080, %ecx
59	wrmsr
60
61	# set the page table base address
62	mov	$level4pt, %eax
63	mov	%eax, %cr3
64
65	# enable paging and protected mode by setting PG and PE
66	mov	$0x80000001, %eax
67	mov	%eax, %cr0
68
69	ljmpl	$0x10,$_start64
70
71	.code64
72_start64:
73	mov	$0x18, %eax		# selector for 32-bit data segment
74	mov	%eax, %es		# propagate to all data segments
75	mov	%eax, %ss
76	mov	%eax, %ds
77	mov	%eax, %fs
78	mov	%eax, %gs
79
80	/* Initialize the stack */
81	mov	$__stack, %esp
82
83	/* Initialize data segment */
84	mov	$__data_size, %rdx
85	mov	$__data_source, %rsi
86	mov	$__data_start, %rdi
87	call	memcpy
88
89	/* Initialize BSS */
90	mov	$__bss_size, %rdx
91	mov	$0, %rsi
92	mov	$__bss_start, %rdi
93	call	memset
94
95#ifdef PICOLIBC_TLS
96	// call to _set_tls(__tls_base)
97	mov	$__tls_base, %rdi
98	call	_set_tls
99#endif
100
101#if defined(_HAVE_INITFINI_ARRAY) && CONSTRUCTORS
102	call	__libc_init_array
103#endif
104
105	mov	$0, %rdi
106	mov	$0, %rsi
107	mov	$0, %rdx
108	call	main
109
110#ifdef CRT0_EXIT
111	mov	%rax, %rdi
112	call	exit
113#else
1141:
115	jmp	1b
116#endif
117
118gdt_desc:
119	.word gdt_end - gdt - 1
120	.long gdt
121
122gdt:
123	.quad 0x0000000000000000	# unused (null selector)
124	.quad 0x0000000000000000	# 0x08: space for Task State Segment
125	.quad 0x00AF9B000000FFFF        # 0x10: ring 0 64-bit code segment
126	.quad 0x00CF93000000FFFF        # 0x18: ring 0 data segment
127gdt_end:
128
129	.section .rodata
130	/* Page table */
131	.balign 4096, 0
132level4pt:
133	.quad	level3pt + 0x67
134	.balign	4096, 0
135level3pt:
136	.quad	level2pt + 0x67
137	.balign	4096, 0
138level2pt:
139#define page1(base) \
140	((0x00000000000000E7) | ((base) << 21))
141#define page2(base) \
142	page1(base), \
143	page1((base)+1)
144#define page4(base) \
145	page2(base), \
146	page2((base)+2)
147#define page8(base) \
148	page4(base), \
149	page4((base)+4)
150#define page16(base) \
151	page8(base), \
152	page8((base)+8)
153#define page32(base) \
154	page16(base), \
155	page16((base)+16)
156#define page32(base) \
157	page16(base), \
158	page16((base)+16)
159#define page64(base) \
160	page32(base), \
161	page32((base)+32)
162#define page128(base) \
163	page64(base), \
164	page64((base)+64)
165#define page256(base) \
166	page128(base), \
167	page128((base)+128)
168#define page512(base) \
169	page256(base), \
170	page256((base)+256)
171	.quad page512(0)
172
173#if defined(__linux__) && defined(__ELF__)
174.section .note.GNU-stack,"",%progbits
175#endif
176