x86: make run-time part of trampoline relocatable
authorJan Beulich <jbeulich@novell.com>
Fri, 19 Aug 2011 08:54:26 +0000 (09:54 +0100)
committerJan Beulich <jbeulich@novell.com>
Fri, 19 Aug 2011 08:54:26 +0000 (09:54 +0100)
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>
xen/arch/x86/boot/Makefile
xen/arch/x86/boot/head.S
xen/arch/x86/boot/trampoline.S
xen/arch/x86/boot/wakeup.S
xen/arch/x86/efi/boot.c
xen/arch/x86/smpboot.c
xen/arch/x86/x86_32/mm.c
xen/arch/x86/x86_64/mm.c
xen/arch/x86/xen.lds.S
xen/include/asm-x86/config.h

index fb921173c25cac3023d462ab4825225967af5a4a..64b5db4c19e81ebd23afc9ff549197c020795764 100644 (file)
@@ -2,8 +2,8 @@ obj-bin-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
index 0c59f2a7508848c3080ce7984ef17832de652132..d0925794620feb592c648eecf737e90e220e43f4 100644 (file)
@@ -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
index e5b4dbef45f7f7a67484c79fd5e915b79a70017d..37f64cf54f4879bfaf9144d380d0c7b960c38075 100644 (file)
@@ -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:
index db367995ab4478e2f8bdf7cd20b8a1474db5e0aa..daf0d7126ac546dd6342ce277c926d5ff7f1e041 100644 (file)
@@ -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:
index 2e9d5532be23f0c340ca34449f956d4084d6f5a7..fcc2db284f6a46bd8919fa7870045281d6061bf1 100644 (file)
@@ -599,6 +599,9 @@ static void __init relocate_image(unsigned long delta)
     }
 }
 
+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_SYSTEM_TABLE *SystemTable)
     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_SYSTEM_TABLE *SystemTable)
         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_SYSTEM_TABLE *SystemTable)
             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_SYSTEM_TABLE *SystemTable)
     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");
index 7f0093bc08c3d84f7f79311bba4dab29078e04a6..b49edb509a38979251deadc39a874ae08f1f324b 100644 (file)
@@ -48,6 +48,8 @@
 
 #define setup_trampoline()    (bootsym_phys(trampoline_realmode_entry))
 
+unsigned long __read_mostly trampoline_phys;
+
 /* representing HT siblings of each logical CPU */
 DEFINE_PER_CPU_READ_MOSTLY(cpumask_t, cpu_sibling_map);
 /* representing HT and core siblings of each logical CPU */
index 59b450cbf9cad1c2428d5e607a77475411635144..9c7a059bfb55da2e8844448a5211c7b6bd04e5f4 100644 (file)
@@ -166,8 +166,9 @@ void __init zap_low_mappings(l2_pgentry_t *dom0_l2)
     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)
index 9ff343b97efe87eafb7e239b6b25592010c8b871..1df64998e8d7f421409bf3894be2bdd3c00e77a5 100644 (file)
@@ -829,7 +829,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);
 }
index 08e7fa027377e01d5eaafc7958df979d4b1f00ab..578d24a17259e9b08c5d64b2cb525379c8624334 100644 (file)
@@ -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 : {
index d82351d9389ac676052129971a69c1f6cba42d0d..5bca0214c54c2b28293e1e1be89144f27c2e2aba 100644 (file)
 /* 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;