Skip to content

Commit 5ff3e2c

Browse files
amlutoIngo Molnar
authored andcommitted
x86/boot: Rework reserve_real_mode() to allow multiple tries
If reserve_real_mode() fails, panicing immediately means we're doomed. Make it safe to try more than once to allocate the trampoline: - Degrade a failure from panic() to pr_info(). (If we make it to setup_real_mode() without reserving the trampoline, we'll panic them.) - Factor out helpers so that platform code can supply a specific address to try. - Warn if reserve_real_mode() is called after we're done with the memblock allocator. If that were to happen, we would behave unpredictably. Signed-off-by: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mario Limonciello <mario_limonciello@dell.com> Cc: Matt Fleming <mfleming@suse.de> Cc: Matthew Garrett <mjg59@srcf.ucam.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/876e383038f3e9971aa72fd20a4f5da05f9d193d.1470821230.git.luto@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent d0de0f6 commit 5ff3e2c

File tree

2 files changed

+30
-8
lines changed

2 files changed

+30
-8
lines changed

arch/x86/include/asm/realmode.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ extern unsigned char boot_gdt[];
5858
extern unsigned char secondary_startup_64[];
5959
#endif
6060

61+
static inline size_t real_mode_size_needed(void)
62+
{
63+
if (real_mode_header)
64+
return 0; /* already allocated. */
65+
66+
return ALIGN(real_mode_blob_end - real_mode_blob, PAGE_SIZE);
67+
}
68+
69+
void set_real_mode_mem(phys_addr_t mem, size_t size);
6170
void reserve_real_mode(void);
6271

6372
#endif /* _ARCH_X86_REALMODE_H */

arch/x86/realmode/init.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <linux/io.h>
2+
#include <linux/slab.h>
23
#include <linux/memblock.h>
34

45
#include <asm/cacheflush.h>
@@ -12,22 +13,34 @@ u32 *trampoline_cr4_features;
1213
/* Hold the pgd entry used on booting additional CPUs */
1314
pgd_t trampoline_pgd_entry;
1415

16+
void __init set_real_mode_mem(phys_addr_t mem, size_t size)
17+
{
18+
void *base = __va(mem);
19+
20+
real_mode_header = (struct real_mode_header *) base;
21+
printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n",
22+
base, (unsigned long long)mem, size);
23+
}
24+
1525
void __init reserve_real_mode(void)
1626
{
1727
phys_addr_t mem;
18-
unsigned char *base;
19-
size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob);
28+
size_t size = real_mode_size_needed();
29+
30+
if (!size)
31+
return;
32+
33+
WARN_ON(slab_is_available());
2034

2135
/* Has to be under 1M so we can execute real-mode AP code. */
2236
mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE);
23-
if (!mem)
24-
panic("Cannot allocate trampoline\n");
37+
if (!mem) {
38+
pr_info("No sub-1M memory is available for the trampoline\n");
39+
return;
40+
}
2541

26-
base = __va(mem);
2742
memblock_reserve(mem, size);
28-
real_mode_header = (struct real_mode_header *) base;
29-
printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n",
30-
base, (unsigned long long)mem, size);
43+
set_real_mode_mem(mem, size);
3144
}
3245

3346
static void __init setup_real_mode(void)

0 commit comments

Comments
 (0)