Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
2
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
c00b413
Documentation
LICENSES
arch
alpha
arc
arm
arm64
csky
hexagon
loongarch
m68k
microblaze
mips
nios2
openrisc
parisc
powerpc
riscv
s390
sh
sparc
um
x86
boot
compressed
.gitignore
Makefile
acpi.c
cmdline.c
cpuflags.c
early_serial_console.c
efi.c
efi.h
efi_mixed.S
error.c
error.h
head_32.S
head_64.S
ident_map_64.c
idt_64.c
idt_handlers_64.S
kaslr.c
kernel_info.S
mem.c
mem_encrypt.S
misc.c
misc.h
mkpiggy.c
pgtable.h
pgtable_64.c
sev.c
sev.h
string.c
tdcall.S
tdx-shared.c
tdx.c
tdx.h
vmlinux.lds.S
tools
.gitignore
Makefile
a20.c
apm.c
bioscall.S
bitops.h
boot.h
cmdline.c
copy.S
cpu.c
cpucheck.c
cpuflags.c
cpuflags.h
ctype.h
early_serial_console.c
edd.c
genimage.sh
header.S
install.sh
io.h
main.c
memory.c
mkcpustr.c
msr.h
mtools.conf.in
pm.c
pmjump.S
printf.c
regs.c
setup.ld
string.c
string.h
tty.c
version.c
vesa.h
video-bios.c
video-mode.c
video-vesa.c
video-vga.c
video.c
video.h
coco
configs
crypto
entry
events
hyperv
ia32
include
kernel
kvm
lib
math-emu
mm
net
pci
platform
power
purgatory
ras
realmode
tools
um
video
virt
xen
.gitignore
Kbuild
Kconfig
Kconfig.assembler
Kconfig.cpu
Kconfig.debug
Makefile
Makefile.postlink
Makefile.um
Makefile_32.cpu
xtensa
.gitignore
Kconfig
block
certs
crypto
drivers
fs
include
init
io_uring
ipc
kernel
lib
mm
net
rust
samples
scripts
security
sound
tools
usr
virt
.clang-format
.clippy.toml
.cocciconfig
.editorconfig
.get_maintainer.ignore
.gitattributes
.gitignore
.mailmap
.rustfmt.toml
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
Breadcrumbs
linux
/
arch
/
x86
/
boot
/
compressed
/
pgtable_64.c
Copy path
Blame
Blame
Latest commit
History
History
205 lines (168 loc) · 5.88 KB
Breadcrumbs
linux
/
arch
/
x86
/
boot
/
compressed
/
pgtable_64.c
Top
File metadata and controls
Code
Blame
205 lines (168 loc) · 5.88 KB
Raw
// SPDX-License-Identifier: GPL-2.0 #include "misc.h" #include <asm/bootparam.h> #include <asm/bootparam_utils.h> #include <asm/e820/types.h> #include <asm/processor.h> #include "pgtable.h" #include "../string.h" #include "efi.h" #define BIOS_START_MIN 0x20000U /* 128K, less than this is insane */ #define BIOS_START_MAX 0x9f000U /* 640K, absolute maximum */ #ifdef CONFIG_X86_5LEVEL /* __pgtable_l5_enabled needs to be in .data to avoid being cleared along with .bss */ unsigned int __section(".data") __pgtable_l5_enabled; unsigned int __section(".data") pgdir_shift = 39; unsigned int __section(".data") ptrs_per_p4d = 1; #endif /* Buffer to preserve trampoline memory */ static char trampoline_save[TRAMPOLINE_32BIT_SIZE]; /* * Trampoline address will be printed by extract_kernel() for debugging * purposes. * * Avoid putting the pointer into .bss as it will be cleared between * configure_5level_paging() and extract_kernel(). */ unsigned long *trampoline_32bit __section(".data"); int cmdline_find_option_bool(const char *option); static unsigned long find_trampoline_placement(void) { unsigned long bios_start = 0, ebda_start = 0; struct boot_e820_entry *entry; char *signature; int i; /* * Find a suitable spot for the trampoline. * This code is based on reserve_bios_regions(). */ /* * EFI systems may not provide legacy ROM. The memory may not be mapped * at all. * * Only look for values in the legacy ROM for non-EFI system. */ signature = (char *)&boot_params_ptr->efi_info.efi_loader_signature; if (strncmp(signature, EFI32_LOADER_SIGNATURE, 4) && strncmp(signature, EFI64_LOADER_SIGNATURE, 4)) { ebda_start = *(unsigned short *)0x40e << 4; bios_start = *(unsigned short *)0x413 << 10; } if (bios_start < BIOS_START_MIN || bios_start > BIOS_START_MAX) bios_start = BIOS_START_MAX; if (ebda_start > BIOS_START_MIN && ebda_start < bios_start) bios_start = ebda_start; bios_start = round_down(bios_start, PAGE_SIZE); /* Find the first usable memory region under bios_start. */ for (i = boot_params_ptr->e820_entries - 1; i >= 0; i--) { unsigned long new = bios_start; entry = &boot_params_ptr->e820_table[i]; /* Skip all entries above bios_start. */ if (bios_start <= entry->addr) continue; /* Skip non-RAM entries. */ if (entry->type != E820_TYPE_RAM) continue; /* Adjust bios_start to the end of the entry if needed. */ if (bios_start > entry->addr + entry->size) new = entry->addr + entry->size; /* Keep bios_start page-aligned. */ new = round_down(new, PAGE_SIZE); /* Skip the entry if it's too small. */ if (new - TRAMPOLINE_32BIT_SIZE < entry->addr) continue; /* Protect against underflow. */ if (new - TRAMPOLINE_32BIT_SIZE > bios_start) break; bios_start = new; break; } /* Place the trampoline just below the end of low memory */ return bios_start - TRAMPOLINE_32BIT_SIZE; } asmlinkage void configure_5level_paging(struct boot_params *bp, void *pgtable) { void (*toggle_la57)(void *cr3); bool l5_required = false; /* Initialize boot_params. Required for cmdline_find_option_bool(). */ sanitize_boot_params(bp); boot_params_ptr = bp; /* * Check if LA57 is desired and supported. * * There are several parts to the check: * - if the kernel supports 5-level paging: CONFIG_X86_5LEVEL=y * - if user asked to disable 5-level paging: no5lvl in cmdline * - if the machine supports 5-level paging: * + CPUID leaf 7 is supported * + the leaf has the feature bit set * * That's substitute for boot_cpu_has() in early boot code. */ if (IS_ENABLED(CONFIG_X86_5LEVEL) && !cmdline_find_option_bool("no5lvl") && native_cpuid_eax(0) >= 7 && (native_cpuid_ecx(7) & (1 << (X86_FEATURE_LA57 & 31)))) { l5_required = true; /* Initialize variables for 5-level paging */ __pgtable_l5_enabled = 1; pgdir_shift = 48; ptrs_per_p4d = 512; } /* * The trampoline will not be used if the paging mode is already set to * the desired one. */ if (l5_required == !!(native_read_cr4() & X86_CR4_LA57)) return; trampoline_32bit = (unsigned long *)find_trampoline_placement(); /* Preserve trampoline memory */ memcpy(trampoline_save, trampoline_32bit, TRAMPOLINE_32BIT_SIZE); /* Clear trampoline memory first */ memset(trampoline_32bit, 0, TRAMPOLINE_32BIT_SIZE); /* Copy trampoline code in place */ toggle_la57 = memcpy(trampoline_32bit + TRAMPOLINE_32BIT_CODE_OFFSET / sizeof(unsigned long), &trampoline_32bit_src, TRAMPOLINE_32BIT_CODE_SIZE); /* * Avoid the need for a stack in the 32-bit trampoline code, by using * LJMP rather than LRET to return back to long mode. LJMP takes an * immediate absolute address, which needs to be adjusted based on the * placement of the trampoline. */ *(u32 *)((u8 *)toggle_la57 + trampoline_ljmp_imm_offset) += (unsigned long)toggle_la57; /* * The code below prepares page table in trampoline memory. * * The new page table will be used by trampoline code for switching * from 4- to 5-level paging or vice versa. */ if (l5_required) { /* * For 4- to 5-level paging transition, set up current CR3 as * the first and the only entry in a new top-level page table. */ *trampoline_32bit = __native_read_cr3() | _PAGE_TABLE_NOENC; } else { unsigned long src; /* * For 5- to 4-level paging transition, copy page table pointed * by first entry in the current top-level page table as our * new top-level page table. * * We cannot just point to the page table from trampoline as it * may be above 4G. */ src = *(unsigned long *)__native_read_cr3() & PAGE_MASK; memcpy(trampoline_32bit, (void *)src, PAGE_SIZE); } toggle_la57(trampoline_32bit); /* * Move the top level page table out of trampoline memory. */ memcpy(pgtable, trampoline_32bit, PAGE_SIZE); native_write_cr3((unsigned long)pgtable); /* Restore trampoline memory */ memcpy(trampoline_32bit, trampoline_save, TRAMPOLINE_32BIT_SIZE); }
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
You can’t perform that action at this time.