#define BIOS_START_MIN 0x20000U /* 128K, less than this is insane */ #define BIOS_START_MAX 0x9f000U /* 640K, absolute maximum */
/* __pgtable_l5_enabled needs to be in .data to avoid being cleared along with .bss */ unsignedint __section(".data") __pgtable_l5_enabled; unsignedint __section(".data") pgdir_shift = 39; unsignedint __section(".data") ptrs_per_p4d = 1;
/* Buffer to preserve trampoline memory */ staticchar 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().
*/ unsignedlong *trampoline_32bit __section(".data");
/* * 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 = *(unsignedshort *)0x40e << 4;
bios_start = *(unsignedshort *)0x413 << 10;
}
/* * Check if LA57 is desired and supported. * * There are several parts to the check: * - 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
*/ if (!cmdline_find_option_bool("no5lvl") &&
native_cpuid_eax(0) >= 7 && (native_cpuid_ecx(7) & BIT(16))) {
l5_required = true;
/* * 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;
/* 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(unsignedlong),
&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) +=
(unsignedlong)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 { unsignedlong 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 = *(unsignedlong *)__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((unsignedlong)pgtable);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.