mirror of
https://github.com/torvalds/linux.git
synced 2024-12-25 12:21:37 +00:00
4822b7fc6d
Common infrastructure for low memory trampolines. This code installs the trampolines permanently in low memory very early. It also permits multiple pieces of code to be used for this purpose. This code also introduces a standard infrastructure for computing symbol addresses in the trampoline code. The only change to the actual SMP trampolines themselves is that the 64-bit trampoline has been made reusable -- the previous version would overwrite the code with a status variable; this moves the status variable to a separate location. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> LKML-Reference: <4D5DFBE4.7090104@intel.com> Cc: Rafael J. Wysocki <rjw@sisk.pl> Cc: Matthieu Castet <castet.matthieu@free.fr> Cc: Stephen Rothwell <sfr@canb.auug.org.au>
43 lines
1.3 KiB
C
43 lines
1.3 KiB
C
#include <linux/io.h>
|
|
#include <linux/memblock.h>
|
|
|
|
#include <asm/trampoline.h>
|
|
#include <asm/cacheflush.h>
|
|
#include <asm/pgtable.h>
|
|
|
|
unsigned char *x86_trampoline_base;
|
|
|
|
void __init setup_trampolines(void)
|
|
{
|
|
phys_addr_t mem;
|
|
size_t size = PAGE_ALIGN(x86_trampoline_end - x86_trampoline_start);
|
|
|
|
/* Has to be in very low memory so we can execute real-mode AP code. */
|
|
mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE);
|
|
if (mem == MEMBLOCK_ERROR)
|
|
panic("Cannot allocate trampoline\n");
|
|
|
|
x86_trampoline_base = __va(mem);
|
|
memblock_x86_reserve_range(mem, mem + size, "TRAMPOLINE");
|
|
|
|
printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n",
|
|
x86_trampoline_base, (unsigned long long)mem, size);
|
|
|
|
memcpy(x86_trampoline_base, x86_trampoline_start, size);
|
|
}
|
|
|
|
/*
|
|
* setup_trampolines() gets called very early, to guarantee the
|
|
* availability of low memory. This is before the proper kernel page
|
|
* tables are set up, so we cannot set page permissions in that
|
|
* function. Thus, we use an arch_initcall instead.
|
|
*/
|
|
static int __init configure_trampolines(void)
|
|
{
|
|
size_t size = PAGE_ALIGN(x86_trampoline_end - x86_trampoline_start);
|
|
|
|
set_memory_x((unsigned long)x86_trampoline_base, size >> PAGE_SHIFT);
|
|
return 0;
|
|
}
|
|
arch_initcall(configure_trampolines);
|