summaryrefslogtreecommitdiff
path: root/payloads/libpayload/arch/x86/pt.S
blob: 9b085e53ffac0ee95936678dbb7c51e52c918da5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
 *
 * Copyright 2024 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * For reference see "AMD64 Architecture Programmer's Manual Volume 2",
 * Document 24593-Rev. 3.31-July 2019 Chapter 5.3.4
 *
 * Page table attributes: WB, User+Supervisor, Present, Writeable, Accessed, Dirty
 */

.section .bss
#define _PRES (1ULL << 0)
#define _RW   (1ULL << 1)
#define _US   (1ULL << 2)
#define _A    (1ULL << 5)
#define _D    (1ULL << 6)
#define _PS   (1ULL << 7)

.section .bss.pm4le
.global pm4le
.align 4096
pm4le:
.skip 8

.section .bss.main_page_table
.global main_page_table
.align 4096
main_page_table:
.skip 8192

.section .bss.extra_page_table
.global extra_page_table
.align 4096
extra_page_table:
.skip 32

/*
 * WARNING: 32-bit/64-bit Mode Compatibility for Page Table Initialization
 * This `init_page_table` function is designed to work in both 32-bit protected
 * mode AND 64-bit long mode.
 *
 * Key Considerations:
 * - Assembly Instructions:  Use ONLY instructions that have the SAME binary representation
 *                           in both 32-bit and 64-bit modes.
 * - `.code64` Directive:  We're compiling with `.code64` to ensure the assembler uses
 *                         the correct 64-bit version of instructions (e.g., `inc`).
 * - Register Notation:
 *     - Use 64-bit register names (like `%rsi`) for register-indirect addressing to avoid
 *       incorrect address size prefixes.
 *     - It's safe to use `%esi` with `mov` instructions, as the high 32 bits are zeroed
 *       in 64-bit mode.
 *
 * IMPORTANT:
 * Thoroughly test ANY changes to this function in BOTH 32-bit and 64-bit boot environments.
 */

.code64
.section .text.init_page_table
.globl init_page_table
.type init_page_table, @function

init_page_table:
	mov $0x80000001, %eax
	cpuid
	test $(1 << 26), %edx
	jnz setup_1gb

setup_2mb:
	mov $2048, %edi
	mov $(_PRES + _RW + _US + _PS + _A + _D), %eax
	mov $0, %ecx
	mov $main_page_table, %esi

loop_2mb:
	mov %eax, (%rsi, %rcx, 8)
	mov $0, 4(%rsi, %rcx, 8)
	add $0x200000, %eax
	inc %ecx
	cmp %edi, %ecx
	jb loop_2mb

	mov $4, %edi
	mov $main_page_table, %eax
	add $(_PRES + _RW + _US + _A), %eax
	mov $0, %ecx
	mov $extra_page_table, %esi

fill_extra_page_table:
	mov %eax, (%rsi, %rcx, 8)
	mov $0, 4(%rsi, %rcx, 8)
	add $4096, %eax
	inc %ecx
	cmp %edi, %ecx
	jb fill_extra_page_table

	mov $extra_page_table, %eax
	jmp leave

setup_1gb:
	mov $512, %edi
	mov $(_PRES + _RW + _US + _PS + _A + _D), %eax
	mov $0, %ebx
	mov $0, %ecx
	mov $main_page_table, %esi

loop_1gb:
	mov %eax, (%rsi, %rcx, 8)
	mov %ebx, 4(%rsi, %rcx, 8)
	add $0x40000000, %eax
	cmp $0x40000000, %eax
	ja no_overflow_1gb
	inc %ebx
no_overflow_1gb:
	inc %ecx
	cmp %edi, %ecx
	jb loop_1gb

	mov $main_page_table, %eax

leave:
	or $(_PRES + _RW + _US + _A), %eax
	mov %eax, pm4le

	ret