Commit | Line | Data |
---|---|---|
77ad386e | 1 | #include <linux/io.h> |
a9ce6bc1 | 2 | #include <linux/memblock.h> |
77ad386e IM |
3 | |
4 | #include <asm/trampoline.h> | |
4822b7fc | 5 | #include <asm/cacheflush.h> |
fd89a137 | 6 | #include <asm/pgtable.h> |
77ad386e | 7 | |
4822b7fc | 8 | unsigned char *x86_trampoline_base; |
7a4b7e5e | 9 | |
4822b7fc | 10 | void __init setup_trampolines(void) |
3e1e9002 | 11 | { |
a9ce6bc1 | 12 | phys_addr_t mem; |
4822b7fc | 13 | size_t size = PAGE_ALIGN(x86_trampoline_end - x86_trampoline_start); |
893f38d1 | 14 | |
3e1e9002 | 15 | /* Has to be in very low memory so we can execute real-mode AP code. */ |
4822b7fc | 16 | mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE); |
a9ce6bc1 | 17 | if (mem == MEMBLOCK_ERROR) |
893f38d1 YL |
18 | panic("Cannot allocate trampoline\n"); |
19 | ||
4822b7fc PA |
20 | x86_trampoline_base = __va(mem); |
21 | memblock_x86_reserve_range(mem, mem + size, "TRAMPOLINE"); | |
22 | ||
23 | printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n", | |
24 | x86_trampoline_base, (unsigned long long)mem, size); | |
25 | ||
26 | memcpy(x86_trampoline_base, x86_trampoline_start, size); | |
3e1e9002 RW |
27 | } |
28 | ||
77ad386e | 29 | /* |
4822b7fc PA |
30 | * setup_trampolines() gets called very early, to guarantee the |
31 | * availability of low memory. This is before the proper kernel page | |
32 | * tables are set up, so we cannot set page permissions in that | |
33 | * function. Thus, we use an arch_initcall instead. | |
77ad386e | 34 | */ |
4822b7fc | 35 | static int __init configure_trampolines(void) |
77ad386e | 36 | { |
4822b7fc PA |
37 | size_t size = PAGE_ALIGN(x86_trampoline_end - x86_trampoline_start); |
38 | ||
39 | set_memory_x((unsigned long)x86_trampoline_base, size >> PAGE_SHIFT); | |
40 | return 0; | |
77ad386e | 41 | } |
4822b7fc | 42 | arch_initcall(configure_trampolines); |