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 lgdtl	gdt_desc - _start + 0x10
49
50	# enable sse and pae
51	mov	$0x620, %eax
52	mov	%eax, %cr4
53
54	# enable long mode by setting EFER
55	mov	$0x100, %eax
56	xor	%edx, %edx
57	mov	$0xc0000080, %ecx
58	wrmsr
59
60	# set the page table base address
61	mov	$level4pt, %eax
62	mov	%eax, %cr3
63
64	# enable paging and protected mode by setting PG and PE
65	mov	$0x80000001, %eax
66	mov	%eax, %cr0
67
68	ljmpl	$0x10,$_start64
69
70	.code64
71_start64:
72	mov	$0x18, %eax		# selector for 32-bit data segment
73	mov	%eax, %es		# propagate to all data segments
74	mov	%eax, %ss
75	mov	%eax, %ds
76	mov	%eax, %fs
77	mov	%eax, %gs
78
79	/* Initialize the stack */
80	mov	$__stack, %esp
81
82	/* Initialize data segment */
83	mov	$__data_size, %rdx
84	mov	$__data_source, %rsi
85	mov	$__data_start, %rdi
86	call	memcpy
87
88	/* Initialize BSS */
89	mov	$__bss_size, %rdx
90	mov	$0, %rsi
91	mov	$__bss_start, %rdi
92	call	memset
93
94#ifdef PICOLIBC_TLS
95	// call to _set_tls(__tls_base)
96	mov	$__tls_base, %rdi
97	call	_set_tls
98#endif
99
100#if defined(_HAVE_INITFINI_ARRAY) && CONSTRUCTORS
101	call	__libc_init_array
102#endif
103
104	mov	$0, %rdi
105	mov	$0, %rsi
106	mov	$0, %rdx
107	call	main
108
109#ifdef CRT0_EXIT
110	mov	%rax, %rdi
111	call	exit
112#else
1131:
114	jmp	1b
115#endif
116
117gdt_desc:
118	.word gdt_end - gdt - 1
119	.long gdt
120
121gdt:
122	.quad 0x0000000000000000	# unused (null selector)
123	.quad 0x0000000000000000	# 0x08: space for Task State Segment
124	.quad 0x00AF9B000000FFFF        # 0x10: ring 0 64-bit code segment
125	.quad 0x00CF93000000FFFF        # 0x18: ring 0 data segment
126gdt_end:
127
128	.section .rodata
129	/* Page table */
130	.balign 4096, 0
131level4pt:
132	.quad	level3pt + 0x67
133	.balign	4096, 0
134level3pt:
135	.quad	level2pt + 0x67
136	.balign	4096, 0
137level2pt:
138#define page1(base) \
139	((0x00000000000000E7) | ((base) << 21))
140#define page2(base) \
141	page1(base), \
142	page1((base)+1)
143#define page4(base) \
144	page2(base), \
145	page2((base)+2)
146#define page8(base) \
147	page4(base), \
148	page4((base)+4)
149#define page16(base) \
150	page8(base), \
151	page8((base)+8)
152#define page32(base) \
153	page16(base), \
154	page16((base)+16)
155#define page32(base) \
156	page16(base), \
157	page16((base)+16)
158#define page64(base) \
159	page32(base), \
160	page32((base)+32)
161#define page128(base) \
162	page64(base), \
163	page64((base)+64)
164#define page256(base) \
165	page128(base), \
166	page128((base)+128)
167#define page512(base) \
168	page256(base), \
169	page256((base)+256)
170	.quad page512(0)
171
172#if defined(__linux__) && defined(__ELF__)
173.section .note.GNU-stack,"",%progbits
174#endif
175