diff options
-rw-r--r-- | arch/x86/boot/compressed/misc.c | 6 | ||||
-rw-r--r-- | arch/x86/boot/compressed/pgtable.h | 11 | ||||
-rw-r--r-- | arch/x86/boot/compressed/pgtable_64.c | 34 |
3 files changed, 51 insertions, 0 deletions
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index b50c42455e25..8e4b55dd5df9 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include "misc.h" | 15 | #include "misc.h" |
16 | #include "error.h" | 16 | #include "error.h" |
17 | #include "pgtable.h" | ||
17 | #include "../string.h" | 18 | #include "../string.h" |
18 | #include "../voffset.h" | 19 | #include "../voffset.h" |
19 | 20 | ||
@@ -372,6 +373,11 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, | |||
372 | debug_putaddr(output_len); | 373 | debug_putaddr(output_len); |
373 | debug_putaddr(kernel_total_size); | 374 | debug_putaddr(kernel_total_size); |
374 | 375 | ||
376 | #ifdef CONFIG_X86_64 | ||
377 | /* Report address of 32-bit trampoline */ | ||
378 | debug_putaddr(trampoline_32bit); | ||
379 | #endif | ||
380 | |||
375 | /* | 381 | /* |
376 | * The memory hole needed for the kernel is the larger of either | 382 | * The memory hole needed for the kernel is the larger of either |
377 | * the entire decompressed kernel plus relocation table, or the | 383 | * the entire decompressed kernel plus relocation table, or the |
diff --git a/arch/x86/boot/compressed/pgtable.h b/arch/x86/boot/compressed/pgtable.h new file mode 100644 index 000000000000..57722a2fe2a0 --- /dev/null +++ b/arch/x86/boot/compressed/pgtable.h | |||
@@ -0,0 +1,11 @@ | |||
1 | #ifndef BOOT_COMPRESSED_PAGETABLE_H | ||
2 | #define BOOT_COMPRESSED_PAGETABLE_H | ||
3 | |||
4 | #define TRAMPOLINE_32BIT_SIZE (2 * PAGE_SIZE) | ||
5 | |||
6 | #ifndef __ASSEMBLER__ | ||
7 | |||
8 | extern unsigned long *trampoline_32bit; | ||
9 | |||
10 | #endif /* __ASSEMBLER__ */ | ||
11 | #endif /* BOOT_COMPRESSED_PAGETABLE_H */ | ||
diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compressed/pgtable_64.c index 45c76eff2718..21d5cc1cd5fa 100644 --- a/arch/x86/boot/compressed/pgtable_64.c +++ b/arch/x86/boot/compressed/pgtable_64.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #include <asm/processor.h> | 1 | #include <asm/processor.h> |
2 | #include "pgtable.h" | ||
2 | 3 | ||
3 | /* | 4 | /* |
4 | * __force_order is used by special_insns.h asm code to force instruction | 5 | * __force_order is used by special_insns.h asm code to force instruction |
@@ -9,14 +10,27 @@ | |||
9 | */ | 10 | */ |
10 | unsigned long __force_order; | 11 | unsigned long __force_order; |
11 | 12 | ||
13 | #define BIOS_START_MIN 0x20000U /* 128K, less than this is insane */ | ||
14 | #define BIOS_START_MAX 0x9f000U /* 640K, absolute maximum */ | ||
15 | |||
12 | struct paging_config { | 16 | struct paging_config { |
13 | unsigned long trampoline_start; | 17 | unsigned long trampoline_start; |
14 | unsigned long l5_required; | 18 | unsigned long l5_required; |
15 | }; | 19 | }; |
16 | 20 | ||
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 | |||
17 | struct paging_config paging_prepare(void) | 30 | struct paging_config paging_prepare(void) |
18 | { | 31 | { |
19 | struct paging_config paging_config = {}; | 32 | struct paging_config paging_config = {}; |
33 | unsigned long bios_start, ebda_start; | ||
20 | 34 | ||
21 | /* | 35 | /* |
22 | * Check if LA57 is desired and supported. | 36 | * Check if LA57 is desired and supported. |
@@ -35,5 +49,25 @@ struct paging_config paging_prepare(void) | |||
35 | paging_config.l5_required = 1; | 49 | paging_config.l5_required = 1; |
36 | } | 50 | } |
37 | 51 | ||
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 | |||
38 | return paging_config; | 72 | return paging_config; |
39 | } | 73 | } |