]>
Commit | Line | Data |
---|---|---|
08529078 | 1 | #include <asm/processor.h> |
3548e131 | 2 | #include "pgtable.h" |
08529078 KS |
3 | |
4 | /* | |
5 | * __force_order is used by special_insns.h asm code to force instruction | |
6 | * serialization. | |
7 | * | |
8 | * It is not referenced from the code, but GCC < 5 with -fPIE would fail | |
9 | * due to an undefined symbol. Define it to make these ancient GCCs work. | |
10 | */ | |
11 | unsigned long __force_order; | |
12 | ||
3548e131 KS |
13 | #define BIOS_START_MIN 0x20000U /* 128K, less than this is insane */ |
14 | #define BIOS_START_MAX 0x9f000U /* 640K, absolute maximum */ | |
15 | ||
4440977b KS |
16 | struct paging_config { |
17 | unsigned long trampoline_start; | |
18 | unsigned long l5_required; | |
19 | }; | |
08529078 | 20 | |
3548e131 KS |
21 | /* |
22 | * Trampoline address will be printed by extract_kernel() for debugging | |
23 | * purposes. | |
24 | * | |
25 | * Avoid putting the pointer into .bss as it will be cleared between | |
26 | * paging_prepare() and extract_kernel(). | |
27 | */ | |
28 | unsigned long *trampoline_32bit __section(.data); | |
29 | ||
4440977b KS |
30 | struct paging_config paging_prepare(void) |
31 | { | |
32 | struct paging_config paging_config = {}; | |
3548e131 | 33 | unsigned long bios_start, ebda_start; |
08529078 | 34 | |
a403d798 KS |
35 | /* |
36 | * Check if LA57 is desired and supported. | |
37 | * | |
38 | * There are two parts to the check: | |
39 | * - if the kernel supports 5-level paging: CONFIG_X86_5LEVEL=y | |
40 | * - if the machine supports 5-level paging: | |
41 | * + CPUID leaf 7 is supported | |
42 | * + the leaf has the feature bit set | |
43 | * | |
44 | * That's substitute for boot_cpu_has() in early boot code. | |
45 | */ | |
46 | if (IS_ENABLED(CONFIG_X86_5LEVEL) && | |
47 | native_cpuid_eax(0) >= 7 && | |
48 | (native_cpuid_ecx(7) & (1 << (X86_FEATURE_LA57 & 31)))) { | |
4440977b | 49 | paging_config.l5_required = 1; |
a403d798 | 50 | } |
08529078 | 51 | |
3548e131 KS |
52 | /* |
53 | * Find a suitable spot for the trampoline. | |
54 | * This code is based on reserve_bios_regions(). | |
55 | */ | |
56 | ||
57 | ebda_start = *(unsigned short *)0x40e << 4; | |
58 | bios_start = *(unsigned short *)0x413 << 10; | |
59 | ||
60 | if (bios_start < BIOS_START_MIN || bios_start > BIOS_START_MAX) | |
61 | bios_start = BIOS_START_MAX; | |
62 | ||
63 | if (ebda_start > BIOS_START_MIN && ebda_start < bios_start) | |
64 | bios_start = ebda_start; | |
65 | ||
66 | /* Place the trampoline just below the end of low memory, aligned to 4k */ | |
67 | paging_config.trampoline_start = bios_start - TRAMPOLINE_32BIT_SIZE; | |
68 | paging_config.trampoline_start = round_down(paging_config.trampoline_start, PAGE_SIZE); | |
69 | ||
70 | trampoline_32bit = (unsigned long *)paging_config.trampoline_start; | |
71 | ||
4440977b | 72 | return paging_config; |
08529078 | 73 | } |