364 lines
13 KiB
Diff
364 lines
13 KiB
Diff
|
# HG changeset patch
|
||
|
# User Jan Beulich <jbeulich@novell.com>
|
||
|
# Date 1313744066 -3600
|
||
|
# Node ID 29aeed4979a78f26519f5fde8a405f8438297ab9
|
||
|
# Parent fc2be6cb89ad49efd90fe1b650f7efaab72f61b2
|
||
|
x86: make run-time part of trampoline relocatable
|
||
|
|
||
|
In order to eliminate an initial hack in the EFI boot code (where
|
||
|
memory for the trampoline was just "claimed" instead of properly
|
||
|
allocated), the trampoline code must no longer make assumption on the
|
||
|
address at which it would be located. For the time being, the fixed
|
||
|
address is being retained for the traditional multiboot path.
|
||
|
|
||
|
As an additional benefit (at least from my pov) it allows confining
|
||
|
the visibility of the BOOT_TRAMPOLINE definition to just the boot
|
||
|
code.
|
||
|
|
||
|
Signed-off-by: Jan Beulich <jbeulich@novell.com>
|
||
|
|
||
|
--- a/xen/arch/x86/boot/Makefile
|
||
|
+++ b/xen/arch/x86/boot/Makefile
|
||
|
@@ -2,8 +2,8 @@ obj-y += head.o
|
||
|
|
||
|
head.o: reloc.S
|
||
|
|
||
|
-BOOT_TRAMPOLINE := $(shell sed -n 's,^\#define[[:space:]]\{1\,\}BOOT_TRAMPOLINE[[:space:]]\{1\,\},,p' $(BASEDIR)/include/asm-x86/config.h)
|
||
|
+BOOT_TRAMPOLINE := $(shell sed -n 's,^\#define[[:space:]]\{1\,\}BOOT_TRAMPOLINE[[:space:]]\{1\,\},,p' head.S)
|
||
|
%.S: %.c
|
||
|
RELOC=$(BOOT_TRAMPOLINE) $(MAKE) -f build32.mk $@
|
||
|
|
||
|
-reloc.S: $(BASEDIR)/include/asm-x86/config.h
|
||
|
+reloc.S: head.S
|
||
|
--- a/xen/arch/x86/boot/head.S
|
||
|
+++ b/xen/arch/x86/boot/head.S
|
||
|
@@ -9,7 +9,7 @@
|
||
|
.text
|
||
|
.code32
|
||
|
|
||
|
-#undef bootsym_phys
|
||
|
+#define BOOT_TRAMPOLINE 0x7c000
|
||
|
#define sym_phys(sym) ((sym) - __XEN_VIRT_START)
|
||
|
#define bootsym_phys(sym) ((sym) - trampoline_start + BOOT_TRAMPOLINE)
|
||
|
|
||
|
@@ -189,6 +189,17 @@ __start:
|
||
|
mov %edi,sym_phys(idle_pg_table_l2) + (__PAGE_OFFSET>>18)
|
||
|
#endif
|
||
|
|
||
|
+ /* Apply relocations to bootstrap trampoline. */
|
||
|
+ mov $BOOT_TRAMPOLINE,%edx
|
||
|
+ mov $sym_phys(__trampoline_rel_start),%edi
|
||
|
+ mov %edx,sym_phys(trampoline_phys)
|
||
|
+1:
|
||
|
+ mov (%edi),%eax
|
||
|
+ add %edx,(%edi,%eax)
|
||
|
+ add $4,%edi
|
||
|
+ cmp $sym_phys(__trampoline_rel_stop),%edi
|
||
|
+ jb 1b
|
||
|
+
|
||
|
/* Copy bootstrap trampoline to low memory, below 1MB. */
|
||
|
mov $sym_phys(trampoline_start),%esi
|
||
|
mov $bootsym_phys(trampoline_start),%edi
|
||
|
--- a/xen/arch/x86/boot/trampoline.S
|
||
|
+++ b/xen/arch/x86/boot/trampoline.S
|
||
|
@@ -4,6 +4,13 @@
|
||
|
#undef bootsym
|
||
|
#define bootsym(s) ((s)-trampoline_start)
|
||
|
|
||
|
+#define bootsym_rel(sym, off, opnd...) \
|
||
|
+ bootsym(sym),##opnd; \
|
||
|
+111:; \
|
||
|
+ .pushsection .trampoline_rel, "a"; \
|
||
|
+ .long 111b - (off) - .; \
|
||
|
+ .popsection
|
||
|
+
|
||
|
.globl trampoline_realmode_entry
|
||
|
trampoline_realmode_entry:
|
||
|
mov %cs,%ax
|
||
|
@@ -17,11 +24,11 @@ trampoline_realmode_entry:
|
||
|
xor %ax, %ax
|
||
|
inc %ax
|
||
|
lmsw %ax # CR0.PE = 1 (enter protected mode)
|
||
|
- ljmpl $BOOT_CS32,$bootsym_phys(trampoline_protmode_entry)
|
||
|
+ ljmpl $BOOT_CS32,$bootsym_rel(trampoline_protmode_entry,6)
|
||
|
|
||
|
idt_48: .word 0, 0, 0 # base = limit = 0
|
||
|
gdt_48: .word 6*8-1
|
||
|
- .long bootsym_phys(trampoline_gdt)
|
||
|
+ .long bootsym_rel(trampoline_gdt,4)
|
||
|
trampoline_gdt:
|
||
|
/* 0x0000: unused */
|
||
|
.quad 0x0000000000000000
|
||
|
@@ -32,11 +39,16 @@ trampoline_gdt:
|
||
|
/* 0x0018: ring 0 data */
|
||
|
.quad 0x00cf92000000ffff
|
||
|
/* 0x0020: real-mode code @ BOOT_TRAMPOLINE */
|
||
|
- .long 0x0000ffff | ((BOOT_TRAMPOLINE & 0x00ffff) << 16)
|
||
|
- .long 0x00009a00 | ((BOOT_TRAMPOLINE & 0xff0000) >> 16)
|
||
|
+ .long 0x0000ffff
|
||
|
+ .long 0x00009a00
|
||
|
/* 0x0028: real-mode data @ BOOT_TRAMPOLINE */
|
||
|
- .long 0x0000ffff | ((BOOT_TRAMPOLINE & 0x00ffff) << 16)
|
||
|
- .long 0x00009200 | ((BOOT_TRAMPOLINE & 0xff0000) >> 16)
|
||
|
+ .long 0x0000ffff
|
||
|
+ .long 0x00009200
|
||
|
+
|
||
|
+ .pushsection .trampoline_rel, "a"
|
||
|
+ .long trampoline_gdt + BOOT_PSEUDORM_CS + 2 - .
|
||
|
+ .long trampoline_gdt + BOOT_PSEUDORM_DS + 2 - .
|
||
|
+ .popsection
|
||
|
|
||
|
.globl cpuid_ext_features
|
||
|
cpuid_ext_features:
|
||
|
@@ -66,11 +78,11 @@ trampoline_protmode_entry:
|
||
|
|
||
|
/* Load pagetable base register. */
|
||
|
mov $sym_phys(idle_pg_table),%eax
|
||
|
- add bootsym_phys(trampoline_xen_phys_start),%eax
|
||
|
+ add bootsym_rel(trampoline_xen_phys_start,4,%eax)
|
||
|
mov %eax,%cr3
|
||
|
|
||
|
/* Set up EFER (Extended Feature Enable Register). */
|
||
|
- mov bootsym_phys(cpuid_ext_features),%edi
|
||
|
+ mov bootsym_rel(cpuid_ext_features,4,%edi)
|
||
|
test $0x20100800,%edi /* SYSCALL/SYSRET, No Execute, Long Mode? */
|
||
|
jz .Lskip_efer
|
||
|
movl $MSR_EFER,%ecx
|
||
|
@@ -93,7 +105,7 @@ trampoline_protmode_entry:
|
||
|
#if defined(__x86_64__)
|
||
|
|
||
|
/* Now in compatibility mode. Long-jump into 64-bit mode. */
|
||
|
- ljmp $BOOT_CS64,$bootsym_phys(start64)
|
||
|
+ ljmp $BOOT_CS64,$bootsym_rel(start64,6)
|
||
|
|
||
|
.code64
|
||
|
start64:
|
||
|
--- a/xen/arch/x86/boot/wakeup.S
|
||
|
+++ b/xen/arch/x86/boot/wakeup.S
|
||
|
@@ -42,15 +42,13 @@ ENTRY(wakeup_start)
|
||
|
|
||
|
# boot trampoline is under 1M, and shift its start into
|
||
|
# %fs to reference symbols in that area
|
||
|
- movl $BOOT_TRAMPOLINE, %eax
|
||
|
- shrl $4, %eax
|
||
|
- movl %eax, %fs
|
||
|
+ mov wakesym(trampoline_seg), %fs
|
||
|
lidt %fs:bootsym(idt_48)
|
||
|
lgdt %fs:bootsym(gdt_48)
|
||
|
|
||
|
movw $1, %ax
|
||
|
lmsw %ax # Turn on CR0.PE
|
||
|
- ljmpl $BOOT_CS32, $bootsym_phys(wakeup_32)
|
||
|
+ ljmpl $BOOT_CS32, $bootsym_rel(wakeup_32, 6)
|
||
|
|
||
|
/* This code uses an extended set of video mode numbers. These include:
|
||
|
* Aliases for standard modes
|
||
|
@@ -103,6 +101,10 @@ real_magic: .long 0x12345678
|
||
|
.globl video_mode, video_flags
|
||
|
video_mode: .long 0
|
||
|
video_flags: .long 0
|
||
|
+trampoline_seg: .word BOOT_TRAMPOLINE >> 4
|
||
|
+ .pushsection .trampoline_seg, "a"
|
||
|
+ .long trampoline_seg - .
|
||
|
+ .popsection
|
||
|
|
||
|
.code32
|
||
|
|
||
|
@@ -114,11 +116,11 @@ wakeup_32:
|
||
|
mov $BOOT_DS, %eax
|
||
|
mov %eax, %ds
|
||
|
mov %eax, %ss
|
||
|
- mov $bootsym_phys(early_stack), %esp
|
||
|
+ mov $bootsym_rel(early_stack, 4, %esp)
|
||
|
|
||
|
# check saved magic again
|
||
|
mov $sym_phys(saved_magic), %eax
|
||
|
- add bootsym_phys(trampoline_xen_phys_start), %eax
|
||
|
+ add bootsym_rel(trampoline_xen_phys_start, 4, %eax)
|
||
|
mov (%eax), %eax
|
||
|
cmp $0x9abcdef0, %eax
|
||
|
jne bogus_saved_magic
|
||
|
@@ -131,12 +133,12 @@ wakeup_32:
|
||
|
|
||
|
/* Load pagetable base register */
|
||
|
mov $sym_phys(idle_pg_table),%eax
|
||
|
- add bootsym_phys(trampoline_xen_phys_start),%eax
|
||
|
+ add bootsym_rel(trampoline_xen_phys_start,4,%eax)
|
||
|
mov %eax,%cr3
|
||
|
|
||
|
/* Will cpuid feature change after resume? */
|
||
|
/* Set up EFER (Extended Feature Enable Register). */
|
||
|
- mov bootsym_phys(cpuid_ext_features),%edi
|
||
|
+ mov bootsym_rel(cpuid_ext_features,4,%edi)
|
||
|
test $0x20100800,%edi /* SYSCALL/SYSRET, No Execute, Long Mode? */
|
||
|
jz .Lskip_eferw
|
||
|
movl $MSR_EFER,%ecx
|
||
|
@@ -162,7 +164,7 @@ wakeup_32:
|
||
|
#if defined(__x86_64__)
|
||
|
|
||
|
/* Now in compatibility mode. Long-jump to 64-bit mode */
|
||
|
- ljmp $BOOT_CS64, $bootsym_phys(wakeup_64)
|
||
|
+ ljmp $BOOT_CS64, $bootsym_rel(wakeup_64,6)
|
||
|
|
||
|
.code64
|
||
|
wakeup_64:
|
||
|
--- a/xen/arch/x86/efi/boot.c
|
||
|
+++ b/xen/arch/x86/efi/boot.c
|
||
|
@@ -599,6 +599,9 @@ static void __init relocate_image(unsign
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+extern const s32 __trampoline_rel_start[], __trampoline_rel_stop[];
|
||
|
+extern const s32 __trampoline_seg_start[], __trampoline_seg_stop[];
|
||
|
+
|
||
|
void EFIAPI __init __attribute__((__noreturn__))
|
||
|
efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
|
||
|
{
|
||
|
@@ -614,9 +617,10 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
|
||
|
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
|
||
|
EFI_FILE_HANDLE dir_handle;
|
||
|
union string section = { NULL }, name;
|
||
|
+ const s32 *trampoline_ptr;
|
||
|
struct e820entry *e;
|
||
|
u64 efer;
|
||
|
- bool_t base_video = 0, trampoline_okay = 0;
|
||
|
+ bool_t base_video = 0;
|
||
|
|
||
|
efi_ih = ImageHandle;
|
||
|
efi_bs = SystemTable->BootServices;
|
||
|
@@ -914,15 +918,27 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
|
||
|
dmi_efi_get_table((void *)(long)efi.smbios);
|
||
|
|
||
|
/* Allocate space for trampoline (in first Mb). */
|
||
|
- cfg.addr = BOOT_TRAMPOLINE;
|
||
|
+ cfg.addr = 0x100000;
|
||
|
cfg.size = trampoline_end - trampoline_start;
|
||
|
- status = efi_bs->AllocatePages(AllocateAddress, EfiLoaderData,
|
||
|
+ status = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData,
|
||
|
PFN_UP(cfg.size), &cfg.addr);
|
||
|
if ( EFI_ERROR(status) )
|
||
|
{
|
||
|
cfg.addr = 0;
|
||
|
- PrintErr(L"Note: Trampoline area is in use\r\n");
|
||
|
+ blexit(L"No memory for trampoline\r\n");
|
||
|
}
|
||
|
+ trampoline_phys = cfg.addr;
|
||
|
+ /* Apply relocations to trampoline. */
|
||
|
+ for ( trampoline_ptr = __trampoline_rel_start;
|
||
|
+ trampoline_ptr < __trampoline_rel_stop;
|
||
|
+ ++trampoline_ptr )
|
||
|
+ *(u32 *)(*trampoline_ptr + (long)trampoline_ptr) +=
|
||
|
+ trampoline_phys;
|
||
|
+ for ( trampoline_ptr = __trampoline_seg_start;
|
||
|
+ trampoline_ptr < __trampoline_seg_stop;
|
||
|
+ ++trampoline_ptr )
|
||
|
+ *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) =
|
||
|
+ trampoline_phys >> 4;
|
||
|
|
||
|
/* Initialise L2 identity-map and xen page table entries (16MB). */
|
||
|
for ( i = 0; i < 8; ++i )
|
||
|
@@ -1096,14 +1112,8 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
|
||
|
e->type = type;
|
||
|
++e820nr;
|
||
|
}
|
||
|
- if ( type == E820_RAM && e->addr <= BOOT_TRAMPOLINE &&
|
||
|
- e->addr + e->size >= BOOT_TRAMPOLINE + cfg.size )
|
||
|
- trampoline_okay = 1;
|
||
|
}
|
||
|
|
||
|
- if ( !trampoline_okay )
|
||
|
- blexit(L"Trampoline area unavailable\r\n");
|
||
|
-
|
||
|
status = efi_bs->ExitBootServices(ImageHandle, map_key);
|
||
|
if ( EFI_ERROR(status) )
|
||
|
PrintErrMesg(L"Cannot exit boot services", status);
|
||
|
@@ -1117,7 +1127,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
|
||
|
efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START;
|
||
|
|
||
|
relocate_image(__XEN_VIRT_START - xen_phys_start);
|
||
|
- memcpy((void *)(long)BOOT_TRAMPOLINE, trampoline_start, cfg.size);
|
||
|
+ memcpy((void *)trampoline_phys, trampoline_start, cfg.size);
|
||
|
|
||
|
/* Set system registers and transfer control. */
|
||
|
asm volatile("pushq $0\n\tpopfq");
|
||
|
--- a/xen/arch/x86/smpboot.c
|
||
|
+++ b/xen/arch/x86/smpboot.c
|
||
|
@@ -49,6 +49,8 @@
|
||
|
|
||
|
#define setup_trampoline() (bootsym_phys(trampoline_realmode_entry))
|
||
|
|
||
|
+unsigned long __read_mostly trampoline_phys;
|
||
|
+
|
||
|
/* Set if we find a B stepping CPU */
|
||
|
static int smp_b_stepping;
|
||
|
|
||
|
--- a/xen/arch/x86/x86_32/mm.c
|
||
|
+++ b/xen/arch/x86/x86_32/mm.c
|
||
|
@@ -22,6 +22,7 @@
|
||
|
#include <xen/lib.h>
|
||
|
#include <xen/init.h>
|
||
|
#include <xen/mm.h>
|
||
|
+#include <xen/pfn.h>
|
||
|
#include <xen/sched.h>
|
||
|
#include <xen/guest_access.h>
|
||
|
#include <asm/current.h>
|
||
|
@@ -164,8 +165,9 @@ void __init zap_low_mappings(l2_pgentry_
|
||
|
flush_all(FLUSH_TLB_GLOBAL);
|
||
|
|
||
|
/* Replace with mapping of the boot trampoline only. */
|
||
|
- map_pages_to_xen(BOOT_TRAMPOLINE, BOOT_TRAMPOLINE >> PAGE_SHIFT,
|
||
|
- 0x10, __PAGE_HYPERVISOR);
|
||
|
+ map_pages_to_xen(trampoline_phys, trampoline_phys >> PAGE_SHIFT,
|
||
|
+ PFN_UP(trampoline_end - trampoline_start),
|
||
|
+ __PAGE_HYPERVISOR);
|
||
|
}
|
||
|
|
||
|
void __init subarch_init_memory(void)
|
||
|
--- a/xen/arch/x86/x86_64/mm.c
|
||
|
+++ b/xen/arch/x86/x86_64/mm.c
|
||
|
@@ -828,7 +828,7 @@ void __init zap_low_mappings(void)
|
||
|
flush_local(FLUSH_TLB_GLOBAL);
|
||
|
|
||
|
/* Replace with mapping of the boot trampoline only. */
|
||
|
- map_pages_to_xen(BOOT_TRAMPOLINE, BOOT_TRAMPOLINE >> PAGE_SHIFT,
|
||
|
+ map_pages_to_xen(trampoline_phys, trampoline_phys >> PAGE_SHIFT,
|
||
|
PFN_UP(trampoline_end - trampoline_start),
|
||
|
__PAGE_HYPERVISOR);
|
||
|
}
|
||
|
--- a/xen/arch/x86/xen.lds.S
|
||
|
+++ b/xen/arch/x86/xen.lds.S
|
||
|
@@ -103,6 +103,13 @@ SECTIONS
|
||
|
*(.init.data)
|
||
|
*(.init.data.rel)
|
||
|
*(.init.data.rel.*)
|
||
|
+ . = ALIGN(4);
|
||
|
+ __trampoline_rel_start = .;
|
||
|
+ *(.trampoline_rel)
|
||
|
+ __trampoline_rel_stop = .;
|
||
|
+ __trampoline_seg_start = .;
|
||
|
+ *(.trampoline_seg)
|
||
|
+ __trampoline_seg_stop = .;
|
||
|
} :text
|
||
|
. = ALIGN(32);
|
||
|
.init.setup : {
|
||
|
--- a/xen/include/asm-x86/config.h
|
||
|
+++ b/xen/include/asm-x86/config.h
|
||
|
@@ -95,13 +95,13 @@
|
||
|
/* Primary stack is restricted to 8kB by guard pages. */
|
||
|
#define PRIMARY_STACK_SIZE 8192
|
||
|
|
||
|
-#define BOOT_TRAMPOLINE 0x7c000
|
||
|
+#ifndef __ASSEMBLY__
|
||
|
+extern unsigned long trampoline_phys;
|
||
|
#define bootsym_phys(sym) \
|
||
|
- (((unsigned long)&(sym)-(unsigned long)&trampoline_start)+BOOT_TRAMPOLINE)
|
||
|
+ (((unsigned long)&(sym)-(unsigned long)&trampoline_start)+trampoline_phys)
|
||
|
#define bootsym(sym) \
|
||
|
(*RELOC_HIDE((typeof(&(sym)))__va(__pa(&(sym))), \
|
||
|
- BOOT_TRAMPOLINE-__pa(trampoline_start)))
|
||
|
-#ifndef __ASSEMBLY__
|
||
|
+ trampoline_phys-__pa(trampoline_start)))
|
||
|
extern char trampoline_start[], trampoline_end[];
|
||
|
extern char trampoline_realmode_entry[];
|
||
|
extern unsigned int trampoline_xen_phys_start;
|